@nodetool-ai/agents 0.8.2 → 0.8.4-a24.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (323) hide show
  1. package/dist/.nodetool-build-stamp +1 -1
  2. package/dist/apify/assets.d.ts.map +1 -1
  3. package/dist/apify/assets.js +4 -0
  4. package/dist/apify/assets.js.map +1 -1
  5. package/dist/capabilities/agent-activity.js +1 -1
  6. package/dist/capabilities/agentic-storyboard-finish.d.ts.map +1 -1
  7. package/dist/capabilities/agentic-storyboard-finish.js +2 -1
  8. package/dist/capabilities/agentic-storyboard-finish.js.map +1 -1
  9. package/dist/capabilities/apps.specs.d.ts.map +1 -1
  10. package/dist/capabilities/apps.specs.js +4 -3
  11. package/dist/capabilities/apps.specs.js.map +1 -1
  12. package/dist/capabilities/assets.d.ts.map +1 -1
  13. package/dist/capabilities/assets.js +40 -10
  14. package/dist/capabilities/assets.js.map +1 -1
  15. package/dist/capabilities/code-grading.d.ts +4 -0
  16. package/dist/capabilities/code-grading.d.ts.map +1 -1
  17. package/dist/capabilities/code-grading.js +8 -1
  18. package/dist/capabilities/code-grading.js.map +1 -1
  19. package/dist/capabilities/code.d.ts.map +1 -1
  20. package/dist/capabilities/code.js +13 -7
  21. package/dist/capabilities/code.js.map +1 -1
  22. package/dist/capabilities/collections.d.ts +4 -6
  23. package/dist/capabilities/collections.d.ts.map +1 -1
  24. package/dist/capabilities/collections.js +16 -11
  25. package/dist/capabilities/collections.js.map +1 -1
  26. package/dist/capabilities/derive-shot.d.ts +45 -0
  27. package/dist/capabilities/derive-shot.d.ts.map +1 -0
  28. package/dist/capabilities/derive-shot.js +83 -0
  29. package/dist/capabilities/derive-shot.js.map +1 -0
  30. package/dist/capabilities/dispatcher.js +2 -2
  31. package/dist/capabilities/dispatcher.js.map +1 -1
  32. package/dist/capabilities/documents.d.ts +2 -1
  33. package/dist/capabilities/documents.d.ts.map +1 -1
  34. package/dist/capabilities/documents.js +12 -6
  35. package/dist/capabilities/documents.js.map +1 -1
  36. package/dist/capabilities/email.d.ts +2 -1
  37. package/dist/capabilities/email.d.ts.map +1 -1
  38. package/dist/capabilities/email.js +5 -3
  39. package/dist/capabilities/email.js.map +1 -1
  40. package/dist/capabilities/files.d.ts.map +1 -1
  41. package/dist/capabilities/files.js +3 -7
  42. package/dist/capabilities/files.js.map +1 -1
  43. package/dist/capabilities/files.specs.d.ts.map +1 -1
  44. package/dist/capabilities/files.specs.js +2 -1
  45. package/dist/capabilities/files.specs.js.map +1 -1
  46. package/dist/capabilities/flow.d.ts +3 -0
  47. package/dist/capabilities/flow.d.ts.map +1 -1
  48. package/dist/capabilities/flow.js +7 -0
  49. package/dist/capabilities/flow.js.map +1 -1
  50. package/dist/capabilities/game-asset-browser.d.ts +3 -0
  51. package/dist/capabilities/game-asset-browser.d.ts.map +1 -0
  52. package/dist/capabilities/game-asset-browser.js +153 -0
  53. package/dist/capabilities/game-asset-browser.js.map +1 -0
  54. package/dist/capabilities/game.d.ts +30 -0
  55. package/dist/capabilities/game.d.ts.map +1 -1
  56. package/dist/capabilities/game.js +266 -149
  57. package/dist/capabilities/game.js.map +1 -1
  58. package/dist/capabilities/game.specs.d.ts +2 -0
  59. package/dist/capabilities/game.specs.d.ts.map +1 -1
  60. package/dist/capabilities/game.specs.js +21 -6
  61. package/dist/capabilities/game.specs.js.map +1 -1
  62. package/dist/capabilities/game3d.d.ts.map +1 -1
  63. package/dist/capabilities/game3d.js +24 -10
  64. package/dist/capabilities/game3d.js.map +1 -1
  65. package/dist/capabilities/generations.d.ts.map +1 -1
  66. package/dist/capabilities/generations.js +7 -21
  67. package/dist/capabilities/generations.js.map +1 -1
  68. package/dist/capabilities/invoke.d.ts.map +1 -1
  69. package/dist/capabilities/invoke.js +15 -2
  70. package/dist/capabilities/invoke.js.map +1 -1
  71. package/dist/capabilities/jobs.d.ts +7 -2
  72. package/dist/capabilities/jobs.d.ts.map +1 -1
  73. package/dist/capabilities/jobs.js +13 -3
  74. package/dist/capabilities/jobs.js.map +1 -1
  75. package/dist/capabilities/lazy-tool-core.d.ts +23 -0
  76. package/dist/capabilities/lazy-tool-core.d.ts.map +1 -0
  77. package/dist/capabilities/lazy-tool-core.js +56 -0
  78. package/dist/capabilities/lazy-tool-core.js.map +1 -0
  79. package/dist/capabilities/lazy-tool.d.ts +2 -21
  80. package/dist/capabilities/lazy-tool.d.ts.map +1 -1
  81. package/dist/capabilities/lazy-tool.js +3 -55
  82. package/dist/capabilities/lazy-tool.js.map +1 -1
  83. package/dist/capabilities/legacy-tools.js +1 -1
  84. package/dist/capabilities/legacy-tools.js.map +1 -1
  85. package/dist/capabilities/media.d.ts.map +1 -1
  86. package/dist/capabilities/media.js +26 -1
  87. package/dist/capabilities/media.js.map +1 -1
  88. package/dist/capabilities/media.specs.d.ts.map +1 -1
  89. package/dist/capabilities/media.specs.js +17 -0
  90. package/dist/capabilities/media.specs.js.map +1 -1
  91. package/dist/capabilities/metadata.d.ts +62 -0
  92. package/dist/capabilities/metadata.d.ts.map +1 -0
  93. package/dist/capabilities/metadata.js +114 -0
  94. package/dist/capabilities/metadata.js.map +1 -0
  95. package/dist/capabilities/model3d.d.ts.map +1 -1
  96. package/dist/capabilities/model3d.js +6 -1
  97. package/dist/capabilities/model3d.js.map +1 -1
  98. package/dist/capabilities/nodes.specs.js +1 -1
  99. package/dist/capabilities/nodes.specs.js.map +1 -1
  100. package/dist/capabilities/registry.d.ts +4 -19
  101. package/dist/capabilities/registry.d.ts.map +1 -1
  102. package/dist/capabilities/registry.js +48 -117
  103. package/dist/capabilities/registry.js.map +1 -1
  104. package/dist/capabilities/run-agent.js +1 -1
  105. package/dist/capabilities/scripts.js +2 -2
  106. package/dist/capabilities/scripts.js.map +1 -1
  107. package/dist/capabilities/settings.d.ts.map +1 -1
  108. package/dist/capabilities/settings.js +4 -2
  109. package/dist/capabilities/settings.js.map +1 -1
  110. package/dist/capabilities/storyboard-layout-check.d.ts.map +1 -1
  111. package/dist/capabilities/storyboard-layout-check.js +2 -1
  112. package/dist/capabilities/storyboard-layout-check.js.map +1 -1
  113. package/dist/capabilities/storyboard-measured-sources.d.ts +1 -1
  114. package/dist/capabilities/storyboard-measured-sources.d.ts.map +1 -1
  115. package/dist/capabilities/storyboard-measured-sources.js +2 -1
  116. package/dist/capabilities/storyboard-measured-sources.js.map +1 -1
  117. package/dist/capabilities/storyboards.d.ts +11 -1
  118. package/dist/capabilities/storyboards.d.ts.map +1 -1
  119. package/dist/capabilities/storyboards.js +467 -5
  120. package/dist/capabilities/storyboards.js.map +1 -1
  121. package/dist/capabilities/storyboards.specs.d.ts +6 -0
  122. package/dist/capabilities/storyboards.specs.d.ts.map +1 -1
  123. package/dist/capabilities/storyboards.specs.js +139 -3
  124. package/dist/capabilities/storyboards.specs.js.map +1 -1
  125. package/dist/capabilities/threads.js +1 -1
  126. package/dist/capabilities/threads.js.map +1 -1
  127. package/dist/capabilities/timeline-asset-ids.d.ts +27 -0
  128. package/dist/capabilities/timeline-asset-ids.d.ts.map +1 -0
  129. package/dist/capabilities/timeline-asset-ids.js +88 -0
  130. package/dist/capabilities/timeline-asset-ids.js.map +1 -0
  131. package/dist/capabilities/timeline-bake.d.ts.map +1 -1
  132. package/dist/capabilities/timeline-bake.js +2 -1
  133. package/dist/capabilities/timeline-bake.js.map +1 -1
  134. package/dist/capabilities/timeline-bridge.d.ts +9 -0
  135. package/dist/capabilities/timeline-bridge.d.ts.map +1 -1
  136. package/dist/capabilities/timeline-bridge.js +60 -68
  137. package/dist/capabilities/timeline-bridge.js.map +1 -1
  138. package/dist/capabilities/timeline-clip-frames.d.ts.map +1 -1
  139. package/dist/capabilities/timeline-clip-frames.js +2 -1
  140. package/dist/capabilities/timeline-clip-frames.js.map +1 -1
  141. package/dist/capabilities/timeline-operations.d.ts +52 -0
  142. package/dist/capabilities/timeline-operations.d.ts.map +1 -0
  143. package/dist/capabilities/timeline-operations.js +413 -0
  144. package/dist/capabilities/timeline-operations.js.map +1 -0
  145. package/dist/capabilities/timelines.d.ts +4 -39
  146. package/dist/capabilities/timelines.d.ts.map +1 -1
  147. package/dist/capabilities/timelines.js +45 -414
  148. package/dist/capabilities/timelines.js.map +1 -1
  149. package/dist/capabilities/timelines.specs.d.ts.map +1 -1
  150. package/dist/capabilities/timelines.specs.js +8 -3
  151. package/dist/capabilities/timelines.specs.js.map +1 -1
  152. package/dist/capabilities/web.d.ts.map +1 -1
  153. package/dist/capabilities/web.js +5 -1
  154. package/dist/capabilities/web.js.map +1 -1
  155. package/dist/capabilities/web.specs.js +1 -1
  156. package/dist/capabilities/web.specs.js.map +1 -1
  157. package/dist/capabilities/workflows.d.ts +3 -23
  158. package/dist/capabilities/workflows.d.ts.map +1 -1
  159. package/dist/capabilities/workflows.js +197 -15
  160. package/dist/capabilities/workflows.js.map +1 -1
  161. package/dist/capabilities/workflows.specs.d.ts +2 -0
  162. package/dist/capabilities/workflows.specs.d.ts.map +1 -1
  163. package/dist/capabilities/workflows.specs.js +65 -1
  164. package/dist/capabilities/workflows.specs.js.map +1 -1
  165. package/dist/codeact/nodetool-api.d.ts +17 -1
  166. package/dist/codeact/nodetool-api.d.ts.map +1 -1
  167. package/dist/codeact/nodetool-api.js +168 -48
  168. package/dist/codeact/nodetool-api.js.map +1 -1
  169. package/dist/codeact/sandbox-packages.d.ts +0 -7
  170. package/dist/codeact/sandbox-packages.d.ts.map +1 -1
  171. package/dist/codeact/sandbox-packages.js +1 -10
  172. package/dist/codeact/sandbox-packages.js.map +1 -1
  173. package/dist/codeact/tool-api.d.ts.map +1 -1
  174. package/dist/codeact/tool-api.js +6 -2
  175. package/dist/codeact/tool-api.js.map +1 -1
  176. package/dist/evals/app-build-plan.d.ts.map +1 -1
  177. package/dist/evals/app-build-plan.js +3 -0
  178. package/dist/evals/app-build-plan.js.map +1 -1
  179. package/dist/evals/codeact-api-core.d.ts.map +1 -1
  180. package/dist/evals/codeact-api-core.js +6 -0
  181. package/dist/evals/codeact-api-core.js.map +1 -1
  182. package/dist/evals/surfaces/creative-pipeline.d.ts +1 -1
  183. package/dist/evals/surfaces/creative-pipeline.d.ts.map +1 -1
  184. package/dist/evals/surfaces/creative-pipeline.js +2 -2
  185. package/dist/evals/surfaces/creative-pipeline.js.map +1 -1
  186. package/dist/evals/surfaces/game.d.ts +9 -2
  187. package/dist/evals/surfaces/game.d.ts.map +1 -1
  188. package/dist/evals/surfaces/game.js +714 -2
  189. package/dist/evals/surfaces/game.js.map +1 -1
  190. package/dist/evals/surfaces/sketch.d.ts +1 -1
  191. package/dist/evals/surfaces/sketch.d.ts.map +1 -1
  192. package/dist/evals/surfaces/sketch.js +6 -13
  193. package/dist/evals/surfaces/sketch.js.map +1 -1
  194. package/dist/evals/tool-loop-eval.d.ts +1 -1
  195. package/dist/evals/tool-loop-eval.d.ts.map +1 -1
  196. package/dist/evals/tool-loop-eval.js +1 -1
  197. package/dist/evals/tool-loop-eval.js.map +1 -1
  198. package/dist/game-authoring.d.ts +18868 -3824
  199. package/dist/game-authoring.d.ts.map +1 -1
  200. package/dist/game-build.d.ts +3 -0
  201. package/dist/game-build.d.ts.map +1 -0
  202. package/dist/game-build.js +3 -0
  203. package/dist/game-build.js.map +1 -0
  204. package/dist/game-examples.d.ts +5310 -1056
  205. package/dist/game-examples.d.ts.map +1 -1
  206. package/dist/generation-cancel.d.ts +31 -0
  207. package/dist/generation-cancel.d.ts.map +1 -0
  208. package/dist/generation-cancel.js +28 -0
  209. package/dist/generation-cancel.js.map +1 -0
  210. package/dist/host-access-gate.d.ts +29 -0
  211. package/dist/host-access-gate.d.ts.map +1 -0
  212. package/dist/host-access-gate.js +39 -0
  213. package/dist/host-access-gate.js.map +1 -0
  214. package/dist/host-modules/dispatcher.d.ts +7 -1
  215. package/dist/host-modules/dispatcher.d.ts.map +1 -1
  216. package/dist/host-modules/dispatcher.js +13 -2
  217. package/dist/host-modules/dispatcher.js.map +1 -1
  218. package/dist/host-modules/docx.d.ts.map +1 -1
  219. package/dist/host-modules/docx.js +2 -2
  220. package/dist/host-modules/docx.js.map +1 -1
  221. package/dist/host-modules/epub.d.ts.map +1 -1
  222. package/dist/host-modules/epub.js +2 -2
  223. package/dist/host-modules/epub.js.map +1 -1
  224. package/dist/host-modules/fabric.d.ts.map +1 -1
  225. package/dist/host-modules/fabric.js +1 -1
  226. package/dist/host-modules/fabric.js.map +1 -1
  227. package/dist/host-modules/limits.d.ts +10 -8
  228. package/dist/host-modules/limits.d.ts.map +1 -1
  229. package/dist/host-modules/limits.js +14 -9
  230. package/dist/host-modules/limits.js.map +1 -1
  231. package/dist/host-modules/mammoth.d.ts.map +1 -1
  232. package/dist/host-modules/mammoth.js +2 -2
  233. package/dist/host-modules/mammoth.js.map +1 -1
  234. package/dist/host-modules/ocr.d.ts.map +1 -1
  235. package/dist/host-modules/ocr.js +1 -1
  236. package/dist/host-modules/ocr.js.map +1 -1
  237. package/dist/host-modules/pdf.d.ts.map +1 -1
  238. package/dist/host-modules/pdf.js +2 -2
  239. package/dist/host-modules/pdf.js.map +1 -1
  240. package/dist/host-modules/pdflib.d.ts.map +1 -1
  241. package/dist/host-modules/pdflib.js +2 -2
  242. package/dist/host-modules/pdflib.js.map +1 -1
  243. package/dist/host-modules/pptx.d.ts.map +1 -1
  244. package/dist/host-modules/pptx.js +2 -2
  245. package/dist/host-modules/pptx.js.map +1 -1
  246. package/dist/host-modules/pptxgen.d.ts.map +1 -1
  247. package/dist/host-modules/pptxgen.js +2 -2
  248. package/dist/host-modules/pptxgen.js.map +1 -1
  249. package/dist/host-modules/tfjs.d.ts.map +1 -1
  250. package/dist/host-modules/tfjs.js +4 -4
  251. package/dist/host-modules/tfjs.js.map +1 -1
  252. package/dist/host-modules/tokens.js +2 -2
  253. package/dist/host-modules/tokens.js.map +1 -1
  254. package/dist/host-modules/xlsx.d.ts.map +1 -1
  255. package/dist/host-modules/xlsx.js +2 -2
  256. package/dist/host-modules/xlsx.js.map +1 -1
  257. package/dist/index.d.ts +3 -0
  258. package/dist/index.d.ts.map +1 -1
  259. package/dist/index.js +4 -0
  260. package/dist/index.js.map +1 -1
  261. package/dist/js-sandbox.d.ts +8 -1
  262. package/dist/js-sandbox.d.ts.map +1 -1
  263. package/dist/js-sandbox.js +27 -4
  264. package/dist/js-sandbox.js.map +1 -1
  265. package/dist/jtbd/registry.d.ts.map +1 -1
  266. package/dist/jtbd/registry.js +16 -3
  267. package/dist/jtbd/registry.js.map +1 -1
  268. package/dist/jtbd/run.d.ts +2 -2
  269. package/dist/jtbd/run.d.ts.map +1 -1
  270. package/dist/jtbd/run.js +3 -3
  271. package/dist/jtbd/run.js.map +1 -1
  272. package/dist/jtbd/types.d.ts +1 -1
  273. package/dist/jtbd/types.d.ts.map +1 -1
  274. package/dist/model-prompting-skills.d.ts +8 -7
  275. package/dist/model-prompting-skills.d.ts.map +1 -1
  276. package/dist/model-prompting-skills.js +35 -16
  277. package/dist/model-prompting-skills.js.map +1 -1
  278. package/dist/sandbox-media.d.ts +1 -1
  279. package/dist/sandbox-media.d.ts.map +1 -1
  280. package/dist/sandbox-media.js +10 -9
  281. package/dist/sandbox-media.js.map +1 -1
  282. package/dist/skill-prompt.d.ts.map +1 -1
  283. package/dist/skill-prompt.js +1 -1
  284. package/dist/skill-prompt.js.map +1 -1
  285. package/dist/system-skills.d.ts +4 -3
  286. package/dist/system-skills.d.ts.map +1 -1
  287. package/dist/system-skills.js +4 -3
  288. package/dist/system-skills.js.map +1 -1
  289. package/dist/task-planner.js +1 -1
  290. package/dist/timeline-code-bake.js +2 -2
  291. package/dist/timeline-code-bake.js.map +1 -1
  292. package/dist/timeline-preview/compare.d.ts.map +1 -1
  293. package/dist/timeline-preview/compare.js +4 -1
  294. package/dist/timeline-preview/compare.js.map +1 -1
  295. package/dist/timeline-preview/frames.d.ts.map +1 -1
  296. package/dist/timeline-preview/frames.js +7 -4
  297. package/dist/timeline-preview/frames.js.map +1 -1
  298. package/dist/timeline-preview/model3d.d.ts +1 -1
  299. package/dist/timeline-preview/model3d.d.ts.map +1 -1
  300. package/dist/timeline-preview/model3d.js +4 -23
  301. package/dist/timeline-preview/model3d.js.map +1 -1
  302. package/dist/timeline-preview/rasterize.d.ts +4 -2
  303. package/dist/timeline-preview/rasterize.d.ts.map +1 -1
  304. package/dist/timeline-preview/rasterize.js +10 -4
  305. package/dist/timeline-preview/rasterize.js.map +1 -1
  306. package/dist/timeline-preview/sheet.d.ts.map +1 -1
  307. package/dist/timeline-preview/sheet.js +3 -2
  308. package/dist/timeline-preview/sheet.js.map +1 -1
  309. package/dist/tools/builtin-tools.d.ts +4 -3
  310. package/dist/tools/builtin-tools.d.ts.map +1 -1
  311. package/dist/tools/builtin-tools.js +11 -3
  312. package/dist/tools/builtin-tools.js.map +1 -1
  313. package/dist/tools/graph-validation-registry.d.ts.map +1 -1
  314. package/dist/tools/graph-validation-registry.js +3 -0
  315. package/dist/tools/graph-validation-registry.js.map +1 -1
  316. package/dist/tools/mcp-tool-support.js +1 -1
  317. package/dist/tools/mcp-tool-support.js.map +1 -1
  318. package/dist/tools/mcp-tools.d.ts.map +1 -1
  319. package/dist/tools/mcp-tools.js +4 -0
  320. package/dist/tools/mcp-tools.js.map +1 -1
  321. package/dist/utils/json-parser.js +1 -1
  322. package/dist/utils/json-parser.js.map +1 -1
  323. package/package.json +131 -47
@@ -17,17 +17,14 @@
17
17
  *
18
18
  * Design: docs/tool-class-retirement-design.md § "Migration".
19
19
  */
20
- import { z } from "zod";
21
- import { applyTimelineTrackOp } from "@nodetool-ai/timeline/ops";
22
- import { STAGGER_UNITS, ANIMATED_PROPERTIES, DEFAULT_BEAT_TOLERANCE_MS } from "@nodetool-ai/timeline";
23
- import { buildTimelineToolContracts } from "@nodetool-ai/protocol/api-schemas/timeline-tool-contracts.js";
24
- import { resolveMoveTrackArgs, resolveDeleteTrackArgs } from "@nodetool-ai/protocol/api-schemas/timeline-tool-params.js";
25
- import { parseWithTypeCoercion } from "@nodetool-ai/runtime";
20
+ import { parseOps, applyOps, TOOL_PREFIX, READ_ONLY_OPS, timelineModel3DBaker } from "./timeline-operations.js";
21
+ export { parseOps, applyOps } from "./timeline-operations.js";
26
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";
27
23
  import { AUDIO_BAKED_ANIMATION_KIND, normalizeAuthoredDocument, hashSceneSubtree, mergeTimelineSource } from "@nodetool-ai/timeline";
28
24
  import { bakeTimelineCode, bakedDocumentMatchesSaved } from "../timeline-code-bake.js";
29
25
  import { applyJsScriptEditOps, parseJsScriptEditOps } from "./js-scripts.js";
30
26
  import { clipSourceWindowMs } from "./timeline-audio-bake.js";
27
+ import { canonicalizeTimelineAssetIds, userAssetFinder } from "./timeline-asset-ids.js";
31
28
  import { TIMELINE_NATIVE_MEDIA_CAPABILITIES } from "./timeline-native-media.js";
32
29
  import { isFiniteNumber, isRecord, isString } from "../utils/type-guards.js";
33
30
  import { resolveProjectId } from "./project-scope.js";
@@ -372,400 +369,6 @@ const deleteTimelineVersion = {
372
369
  // ---------------------------------------------------------------------------
373
370
  /** Attempts to land the document write before reporting a conflict. */
374
371
  const CAS_ATTEMPTS = 2;
375
- /** Operations one call may apply, so a runaway script cannot rewrite a cut. */
376
- const MAX_OPS = 60;
377
- const TOOL_PREFIX = "ui_timeline_";
378
- /** Browser generation without a real provider adapter remains excluded. */
379
- const EXCLUDED_OPS = new Set([`${TOOL_PREFIX}generate_clip`]);
380
- const READ_ONLY_OPS = new Set([`${TOOL_PREFIX}get_clip_frames`]);
381
- /** `add_track`, `ui_add_track`, and `ui_timeline_add_track` all name one tool. */
382
- function normalizeOpName(name) {
383
- const trimmed = name.trim();
384
- if (trimmed.startsWith(TOOL_PREFIX))
385
- return trimmed;
386
- const bare = trimmed.startsWith("ui_")
387
- ? trimmed.slice("ui_".length)
388
- : trimmed;
389
- return `${TOOL_PREFIX}${bare}`;
390
- }
391
- /** An op is `{op, ...args}` — the arguments sit alongside the verb. */
392
- export function parseOps(raw) {
393
- if (!Array.isArray(raw) || raw.length === 0) {
394
- return {
395
- error: 'ops must be a non-empty array, e.g. [{"op": "add_track", "type": "audio"}].'
396
- };
397
- }
398
- if (raw.length > MAX_OPS) {
399
- return {
400
- error: `ops holds ${raw.length} entries; at most ${MAX_OPS} per call.`
401
- };
402
- }
403
- const parsed = [];
404
- for (const [index, entry] of raw.entries()) {
405
- if (!isRecord(entry)) {
406
- return { error: `ops[${index}] must be an object.` };
407
- }
408
- const { op, ...input } = entry;
409
- if (!isString(op) || op.trim() === "") {
410
- return { error: `ops[${index}] has no \`op\` name.` };
411
- }
412
- parsed.push({ op: normalizeOpName(op), input });
413
- }
414
- return parsed;
415
- }
416
- /**
417
- * Read one of the caller's assets for `add_media_clip`.
418
- *
419
- * The ref a model has in hand is whatever `list_assets` printed — a bare id or
420
- * an `asset://<id>.<ext>` URI — so both resolve here.
421
- */
422
- async function resolveTimelineAsset(run, ref) {
423
- const id = ref.startsWith("asset://")
424
- ? ref.slice("asset://".length).replace(/\.[A-Za-z0-9]{1,8}$/, "")
425
- : ref;
426
- if (!id)
427
- return null;
428
- const userId = run.context.userId;
429
- if (!userId)
430
- return null;
431
- const { Asset } = await import("@nodetool-ai/models");
432
- // `find` is already user-scoped: someone else's asset reads as missing.
433
- const asset = await Asset.find(userId, id);
434
- if (!asset)
435
- return null;
436
- const thumbnails = isRecord(asset.metadata)
437
- ? asset.metadata["thumbnails"]
438
- : undefined;
439
- const thumbnailAssetId = Array.isArray(thumbnails) && isString(thumbnails[0])
440
- ? thumbnails[0]
441
- : undefined;
442
- const resolved = {
443
- id: asset.id,
444
- name: asset.name,
445
- contentType: asset.content_type
446
- };
447
- let duration = asset.duration;
448
- if ((!isFiniteNumber(duration) || duration <= 0) &&
449
- (asset.content_type.startsWith("audio/") || asset.content_type.startsWith("video/"))) {
450
- try {
451
- const { loadMediaRefBytes, probeVideoDurationSeconds } = await import("@nodetool-ai/runtime");
452
- const bytes = await loadMediaRefBytes({ asset_id: asset.id }, run.context);
453
- if (bytes) {
454
- duration = await probeVideoDurationSeconds(bytes, new AbortController().signal);
455
- if (isFiniteNumber(duration) && duration > 0) {
456
- asset.duration = duration;
457
- await asset.save();
458
- }
459
- }
460
- }
461
- catch {
462
- // An explicit clip duration remains usable when the source cannot be probed.
463
- }
464
- }
465
- if (isFiniteNumber(duration) && duration > 0) {
466
- resolved.durationMs = Math.round(duration * 1000);
467
- }
468
- if (thumbnailAssetId)
469
- resolved.thumbnailAssetId = thumbnailAssetId;
470
- return resolved;
471
- }
472
- /**
473
- * Run a custom animation's body once and return its curves.
474
- *
475
- * The bake is the only place that code runs — the curves are stored and every
476
- * render site samples them — so it goes through `bakeCustomAnimation`, the
477
- * same hermetic path `POST /api/timelines/animations/bake` uses. Imported
478
- * lazily: the sandbox is a heavy dependency for a capability most calls never
479
- * reach.
480
- */
481
- async function bakeTimelineAnimation(run, request) {
482
- const { bakeCustomAnimation } = await import("../custom-animation-bake.js");
483
- const params = {
484
- code: request.code,
485
- role: request.role,
486
- durationMs: request.durationMs,
487
- clipDurationMs: request.clipDurationMs,
488
- canvas: request.canvas
489
- };
490
- if (request.params !== undefined)
491
- params.params = request.params;
492
- if (request.staggerCount !== undefined) {
493
- params.staggerCount = request.staggerCount;
494
- }
495
- const baked = await bakeCustomAnimation(run.context, params);
496
- const result = { ok: baked.ok };
497
- if (baked.curves !== undefined)
498
- result.curves = baked.curves;
499
- if (baked.mask !== undefined)
500
- result.mask = baked.mask;
501
- if (baked.error !== undefined)
502
- result.error = baked.error;
503
- return result;
504
- }
505
- /**
506
- * The bridge hooks that write outside the document: a Blender render of a 3D
507
- * clip, and the new sequence `retarget_format` creates.
508
- */
509
- function writingHooks(run, sequence) {
510
- return {
511
- bakeModel3DClip: async (request) => {
512
- const { bakeModel3DClipOnServer } = await import("./timeline-bake.js");
513
- return bakeModel3DClipOnServer(run.context, request);
514
- },
515
- retargetFormat: async (adapted) => {
516
- const { TimelineSequence } = await import("@nodetool-ai/models");
517
- const derivedDocument = {
518
- tracks: adapted.tracks,
519
- clips: adapted.clips,
520
- markers: adapted.markers
521
- };
522
- if (adapted.transcript !== undefined) {
523
- derivedDocument.transcript = adapted.transcript;
524
- }
525
- if (adapted.scriptEnabled !== undefined) {
526
- derivedDocument.scriptEnabled = adapted.scriptEnabled;
527
- }
528
- if (adapted.tempo !== undefined)
529
- derivedDocument.tempo = adapted.tempo;
530
- if (adapted.camera2d !== undefined)
531
- derivedDocument.camera2d = adapted.camera2d;
532
- if (adapted.setup !== undefined)
533
- derivedDocument.setup = adapted.setup;
534
- if (adapted.templateId !== undefined) {
535
- derivedDocument.templateId = adapted.templateId;
536
- }
537
- if (adapted.mediaTracks !== undefined) {
538
- derivedDocument.mediaTracks = adapted.mediaTracks;
539
- }
540
- const name = `${sequence.name} (${adapted.width}×${adapted.height})`;
541
- const created = await TimelineSequence.create({
542
- user_id: run.context.userId,
543
- project_id: sequence.project_id,
544
- workflow_id: sequence.workflow_id,
545
- name,
546
- fps: adapted.fps,
547
- width: adapted.width,
548
- height: adapted.height,
549
- duration_ms: adapted.durationMs,
550
- document: JSON.stringify(derivedDocument)
551
- });
552
- return { sequenceId: created.id, name };
553
- }
554
- };
555
- }
556
- /** Track-only batches need no simulated editor or external hooks. */
557
- function applyTrackOps(sequence, document, ops) {
558
- const contracts = buildTimelineToolContracts({
559
- staggerUnits: STAGGER_UNITS,
560
- animatedProperties: ANIMATED_PROPERTIES,
561
- beatToleranceMs: DEFAULT_BEAT_TOLERANCE_MS
562
- });
563
- let state = {
564
- fps: sequence.fps,
565
- width: sequence.width,
566
- height: sequence.height,
567
- tracks: document.tracks,
568
- clips: document.clips,
569
- markers: document.markers,
570
- mediaTracks: document.mediaTracks,
571
- tempo: document.tempo,
572
- playheadMs: 0,
573
- selectedClipIds: []
574
- };
575
- const usedIds = new Set([
576
- ...[
577
- ...document.tracks,
578
- ...document.clips,
579
- ...document.markers,
580
- ...(document.mediaTracks ?? [])
581
- ].map((unit) => unit.id),
582
- ...document.clips.flatMap((clip) => (clip.animations ?? []).map((animation) => animation.id))
583
- ]);
584
- let nextId = 0;
585
- const newId = () => {
586
- let id;
587
- do {
588
- id = `track_${++nextId}`;
589
- } while (usedIds.has(id));
590
- usedIds.add(id);
591
- return id;
592
- };
593
- const records = [];
594
- for (const entry of ops) {
595
- try {
596
- let op;
597
- if (entry.op === "ui_timeline_add_track") {
598
- const args = parseWithTypeCoercion(z.object(contracts.ui_timeline_add_track.shape), entry.input);
599
- op = { op: "add_track", ...args };
600
- }
601
- else if (entry.op === "ui_timeline_move_track") {
602
- const args = parseWithTypeCoercion(z.object(contracts.ui_timeline_move_track.shape), entry.input);
603
- op = { op: "move_track", ...resolveMoveTrackArgs(args) };
604
- }
605
- else {
606
- const args = parseWithTypeCoercion(z.object(contracts.ui_timeline_delete_track.shape), entry.input);
607
- op = { op: "delete_track", ...resolveDeleteTrackArgs(args) };
608
- }
609
- const outcome = applyTimelineTrackOp(state, op, { newId });
610
- if (outcome.error)
611
- throw new Error(outcome.error);
612
- state = outcome.state;
613
- records.push({ op: entry.op, ok: true, result: outcome.result });
614
- }
615
- catch (error) {
616
- records.push({
617
- op: entry.op,
618
- ok: false,
619
- error: error instanceof Error ? error.message : String(error)
620
- });
621
- }
622
- }
623
- return {
624
- records,
625
- state: {
626
- fps: state.fps,
627
- width: state.width,
628
- height: state.height,
629
- durationMs: state.clips.reduce((end, clip) => Math.max(end, clip.startMs + clip.durationMs), 0),
630
- playheadMs: state.playheadMs,
631
- tracks: state.tracks.map(({ id, name, type, index }) => ({
632
- id,
633
- name,
634
- type,
635
- index
636
- })),
637
- clips: state.clips.map((clip) => ({
638
- id: clip.id,
639
- name: clip.name,
640
- trackId: clip.trackId,
641
- mediaType: clip.mediaType,
642
- startMs: clip.startMs,
643
- durationMs: clip.durationMs,
644
- prompt: clip.prompt,
645
- animations: (clip.animations ?? []).map(({ role, preset }) => ({
646
- role,
647
- preset
648
- }))
649
- })),
650
- documentTracks: state.tracks,
651
- documentClips: state.clips,
652
- markers: state.markers,
653
- mediaTracks: state.mediaTracks ?? [],
654
- derivedSequences: [],
655
- tempo: state.tempo,
656
- camera2d: document.camera2d ?? null,
657
- setup: document.setup ?? null,
658
- transitionCandidates: [],
659
- appliedTransitionCandidates: [],
660
- toolLog: ops.map((entry) => entry.op),
661
- previewTimesMs: [],
662
- previewedLayerKinds: []
663
- }
664
- };
665
- }
666
- /**
667
- * Run `ops` against a bridge seeded from `document`.
668
- *
669
- * A failing op is recorded and the script continues: stopping at the first
670
- * error hides every problem behind it, and the caller wants the whole picture.
671
- *
672
- * `hermetic` leaves out the hooks that write outside the document: the 3D
673
- * render and the new sequence a retarget creates. A code bake sets it. The
674
- * bridge then uses its in-memory fallbacks for those ops.
675
- */
676
- export async function applyOps(run, sequence, document, ops, options = {}) {
677
- if (ops.every(({ op }) => op === "ui_timeline_add_track" || op === "ui_timeline_move_track" || op === "ui_timeline_delete_track")) {
678
- return applyTrackOps(sequence, document, ops);
679
- }
680
- const { createTimelineToolBridge } = await import("./timeline-bridge.js");
681
- let operationIndex = 0;
682
- const init = {
683
- sequenceId: sequence.id,
684
- sequenceName: sequence.name,
685
- projectId: sequence.project_id,
686
- sequence: {
687
- fps: sequence.fps,
688
- width: sequence.width,
689
- height: sequence.height,
690
- tracks: document.tracks,
691
- clips: document.clips,
692
- markers: document.markers,
693
- transcript: document.transcript,
694
- scriptEnabled: document.scriptEnabled,
695
- templateId: document.templateId,
696
- tempo: document.tempo,
697
- camera2d: document.camera2d,
698
- setup: document.setup,
699
- mediaTracks: document.mediaTracks
700
- },
701
- resolveAsset: (ref) => resolveTimelineAsset(run, ref),
702
- bakeAnimation: (request) => bakeTimelineAnimation(run, request),
703
- loadComposition: {
704
- get: async (id) => {
705
- const { loadComposition } = await import("./compositions.js");
706
- const found = await loadComposition(run, id);
707
- return found ? found.composition : null;
708
- },
709
- listIds: async () => {
710
- const { loadShippedCompositions, loadUserCompositions } = await import("./compositions.js");
711
- const mine = await loadUserCompositions(run);
712
- return [
713
- ...loadShippedCompositions().map((comp) => comp.id),
714
- ...(Array.isArray(mine) ? mine.map((comp) => comp.id) : [])
715
- ];
716
- }
717
- }
718
- };
719
- if (!options.hermetic) {
720
- Object.assign(init, writingHooks(run, sequence));
721
- const { timelineMediaEditGenerator } = await import("./timeline-media-edit.js");
722
- const generate = options.generateMediaEdit ?? timelineMediaEditGenerator(run);
723
- init.generateMediaEdit = (request) => generate(request, operationIndex);
724
- init.getClipFrames = async (clip, frameOptions) => {
725
- const current = bridge.finalState();
726
- const { inspectTimelineClipFrames } = await import("./timeline-clip-frames.js");
727
- return inspectTimelineClipFrames(run.context, { ...sequence.toDocument(),
728
- tracks: current.documentTracks, clips: current.documentClips, markers: current.markers,
729
- mediaTracks: current.mediaTracks, tempo: current.tempo, camera2d: current.camera2d,
730
- id: sequence.id, projectId: sequence.project_id ?? "default", name: sequence.name,
731
- fps: sequence.fps, width: sequence.width, height: sequence.height,
732
- durationMs: sequence.duration_ms, createdAt: sequence.created_at, updatedAt: sequence.updated_at
733
- }, clip, frameOptions);
734
- };
735
- }
736
- const bridge = createTimelineToolBridge(init);
737
- const byName = new Map(bridge.tools
738
- .filter((tool) => !EXCLUDED_OPS.has(tool.name) && !(options.hermetic && (tool.name === `${TOOL_PREFIX}generatively_edit_clip` || READ_ONLY_OPS.has(tool.name))))
739
- .map((tool) => [tool.name, tool]));
740
- const records = [];
741
- for (const [index, { op, input }] of ops.entries()) {
742
- operationIndex = index;
743
- const tool = byName.get(op);
744
- if (!tool) {
745
- const known = [...byName.keys()]
746
- .map((name) => name.slice(TOOL_PREFIX.length))
747
- .sort()
748
- .join(", ");
749
- records.push({
750
- op,
751
- ok: false,
752
- error: `No timeline operation named "${op.slice(TOOL_PREFIX.length)}". Available: ${known}.`
753
- });
754
- continue;
755
- }
756
- try {
757
- records.push({ op, ok: true, result: await tool.execute(input) });
758
- }
759
- catch (e) {
760
- records.push({
761
- op,
762
- ok: false,
763
- error: e instanceof Error ? e.message : String(e)
764
- });
765
- }
766
- }
767
- return { records, state: bridge.finalState() };
768
- }
769
372
  /**
770
373
  * The keys an op names its unit under, and which list each one means.
771
374
  *
@@ -886,6 +489,9 @@ const editTimeline = {
886
489
  const { TimelineSequence, TimelineSequenceVersion } = await import("@nodetool-ai/models");
887
490
  const { timelineMediaEditGenerator } = await import("./timeline-media-edit.js");
888
491
  const generateMediaEdit = timelineMediaEditGenerator(run);
492
+ // Shared across retries, like the media edit generator: a retry re-applies
493
+ // every op, and a 3D bake already rendered must not render again.
494
+ const bakeModel3DClip = timelineModel3DBaker(run);
889
495
  for (let attempt = 0; attempt < CAS_ATTEMPTS; attempt++) {
890
496
  const sequence = await TimelineSequence.findById(timelineId);
891
497
  // A sequence owned by someone else reads as missing — the rule the tRPC
@@ -894,7 +500,7 @@ const editTimeline = {
894
500
  return { error: `Timeline ${timelineId} was not found.` };
895
501
  }
896
502
  const document = sequence.toDocument();
897
- const { records, state } = await applyOps(run, sequence, document, ops, { generateMediaEdit });
503
+ const { records, state } = await applyOps(run, sequence, document, ops, { generateMediaEdit, bakeModel3DClip });
898
504
  // The transcript rides along untouched — no timeline operation edits it,
899
505
  // so the stored copy stays authoritative. Markers come back from the
900
506
  // bridge, which seeded them and which the marker ops write to.
@@ -1134,7 +740,11 @@ const validateTimeline = {
1134
740
  * whole-document write is that what was sent is what the sequence becomes.
1135
741
  */
1136
742
  function documentToStore(raw) {
1137
- return normalizeAuthoredDocument(raw);
743
+ const { name, id: _id, projectId: _projectId, workflowId: _workflowId, durationMs: _durationMs, createdAt: _createdAt, updatedAt: _updatedAt, ...document } = raw;
744
+ return {
745
+ ...normalizeAuthoredDocument(document),
746
+ name: isString(name) && name.trim() ? name.trim() : undefined
747
+ };
1138
748
  }
1139
749
  /** The end of the last clip — what the sequence's stored duration means. */
1140
750
  function documentDurationMs(document) {
@@ -1201,7 +811,19 @@ const setTimelineDocument = {
1201
811
  };
1202
812
  }
1203
813
  }
1204
- const { document, settings } = documentToStore(raw);
814
+ // `get_timeline` returns the sequence row's fields beside the document.
815
+ // A caller that sends that object back renames the sequence with `name`.
816
+ // The other row fields are owned by the row, so they are dropped rather
817
+ // than reported as stripped document fields.
818
+ const stored = documentToStore(raw);
819
+ const { settings, name } = stored;
820
+ // Sandbox code holds the `asset://<short id>.<ext>` form the asset tools
821
+ // print; the stored clip holds the asset row's full id.
822
+ const canonical = await canonicalizeTimelineAssetIds(stored.document, userAssetFinder(sequence.user_id));
823
+ if ("error" in canonical) {
824
+ return { error: canonical.error, written: false, timeline_id: sequence.id };
825
+ }
826
+ const { document } = canonical;
1205
827
  // Document-level fps/width/height are sequence settings, so opts win and a
1206
828
  // document that carries them configures the sequence instead of having
1207
829
  // them stripped with a `field_stripped` warning.
@@ -1237,16 +859,19 @@ const setTimelineDocument = {
1237
859
  saveType: "manual",
1238
860
  name: snapshotName
1239
861
  });
1240
- const durationMs = documentDurationMs(document);
862
+ const fields = {
863
+ document: JSON.stringify(document),
864
+ fps,
865
+ width,
866
+ height,
867
+ duration_ms: documentDurationMs(document)
868
+ };
869
+ if (name !== undefined) {
870
+ fields.name = name;
871
+ }
1241
872
  let saved;
1242
873
  try {
1243
- saved = await TimelineSequence.updateFieldsIfUnchanged(sequence.id, sequence.updated_at, {
1244
- document: JSON.stringify(document),
1245
- fps,
1246
- width,
1247
- height,
1248
- duration_ms: durationMs
1249
- });
874
+ saved = await TimelineSequence.updateFieldsIfUnchanged(sequence.id, sequence.updated_at, fields);
1250
875
  }
1251
876
  catch (error) {
1252
877
  // The model rejects a document without tracks/clips/markers arrays. The
@@ -1273,6 +898,7 @@ const setTimelineDocument = {
1273
898
  ok: true,
1274
899
  written: true,
1275
900
  timeline_id: saved.id,
901
+ name: saved.name,
1276
902
  updated_at: saved.updated_at,
1277
903
  undo_version: undo.version,
1278
904
  fps: saved.fps,
@@ -2294,7 +1920,7 @@ const isolateSubject = {
2294
1920
  let expectedUpdatedAt = sequence.updated_at;
2295
1921
  const persist = async (next) => {
2296
1922
  const clips = document.clips.map((c) => (c.id === next.id ? next : c));
2297
- const saved = await TimelineSequence.updateDocumentIfUnchanged(timelineId, expectedUpdatedAt, { ...document, clips }, {
1923
+ const saved = await TimelineSequence.updateDocumentIfUnchanged(sequence.id, expectedUpdatedAt, { ...document, clips }, {
2298
1924
  ops: [
2299
1925
  {
2300
1926
  tool: `${TOOL_PREFIX}set_generated_matte`,
@@ -2416,7 +2042,7 @@ const trackObject = {
2416
2042
  let expectedUpdatedAt = sequence.updated_at;
2417
2043
  let mediaTracks = document.mediaTracks ?? [];
2418
2044
  const persist = async (next) => {
2419
- const saved = await TimelineSequence.updateDocumentIfUnchanged(timelineId, expectedUpdatedAt, { ...document, mediaTracks: next }, { ops: [{ tool: "track_object", input: { clip_id: clip.id, track_id: trackId } }] });
2045
+ const saved = await TimelineSequence.updateDocumentIfUnchanged(sequence.id, expectedUpdatedAt, { ...document, mediaTracks: next }, { ops: [{ tool: "track_object", input: { clip_id: clip.id, track_id: trackId } }] });
2420
2046
  if (!saved)
2421
2047
  return false;
2422
2048
  mediaTracks = next;
@@ -2495,7 +2121,12 @@ function normalizeForceOption(value) {
2495
2121
  * state being replaced so the write is undoable, then a CAS write so a
2496
2122
  * concurrent edit is reported rather than clobbered.
2497
2123
  */
2498
- export async function writeTimelineCodeDocument(sequence, document, snapshotName) {
2124
+ export async function writeTimelineCodeDocument(sequence, authored, snapshotName) {
2125
+ const canonical = await canonicalizeTimelineAssetIds(authored, userAssetFinder(sequence.user_id));
2126
+ if ("error" in canonical) {
2127
+ return { written: false, error: canonical.error, errors: [], warnings: [] };
2128
+ }
2129
+ const { document } = canonical;
2499
2130
  const { validateTimelineSequence } = await import("@nodetool-ai/execution/timeline-debug");
2500
2131
  const before = validateTimelineSequence(document, { fps: sequence.fps, width: sequence.width, height: sequence.height });
2501
2132
  const errors = before.errors.map((issue) => issue.message);