@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.
- package/dist/.nodetool-build-stamp +1 -1
- package/dist/analysis/audio-dsp.d.ts +3 -2
- package/dist/analysis/audio-dsp.d.ts.map +1 -1
- package/dist/analysis/audio-dsp.js +11 -8
- package/dist/analysis/audio-dsp.js.map +1 -1
- package/dist/analysis/media-decode.d.ts +13 -0
- package/dist/analysis/media-decode.d.ts.map +1 -1
- package/dist/analysis/media-decode.js +33 -6
- package/dist/analysis/media-decode.js.map +1 -1
- package/dist/apify/assets.d.ts.map +1 -1
- package/dist/apify/assets.js +4 -0
- package/dist/apify/assets.js.map +1 -1
- package/dist/author-graph.d.ts +2 -3
- package/dist/author-graph.d.ts.map +1 -1
- package/dist/author-graph.js +3 -5
- package/dist/author-graph.js.map +1 -1
- package/dist/browser-gate.d.ts +2 -2
- package/dist/browser-gate.js +2 -2
- package/dist/capabilities/GamePublishRequest.d.ts +14 -0
- package/dist/capabilities/GamePublishRequest.d.ts.map +1 -0
- package/dist/capabilities/GamePublishRequest.js +2 -0
- package/dist/capabilities/GamePublishRequest.js.map +1 -0
- package/dist/capabilities/adapters.d.ts +4 -13
- package/dist/capabilities/adapters.d.ts.map +1 -1
- package/dist/capabilities/adapters.js +9 -14
- package/dist/capabilities/adapters.js.map +1 -1
- package/dist/capabilities/agent-activity.d.ts +27 -0
- package/dist/capabilities/agent-activity.d.ts.map +1 -0
- package/dist/capabilities/agent-activity.js +103 -0
- package/dist/capabilities/agent-activity.js.map +1 -0
- package/dist/capabilities/agentic-storyboard-finish.d.ts +67 -0
- package/dist/capabilities/agentic-storyboard-finish.d.ts.map +1 -0
- package/dist/capabilities/agentic-storyboard-finish.js +1321 -0
- package/dist/capabilities/agentic-storyboard-finish.js.map +1 -0
- package/dist/capabilities/agents.d.ts +5 -2
- package/dist/capabilities/agents.d.ts.map +1 -1
- package/dist/capabilities/agents.js +14 -4
- package/dist/capabilities/agents.js.map +1 -1
- package/dist/capabilities/agents.specs.d.ts +3 -0
- package/dist/capabilities/agents.specs.d.ts.map +1 -1
- package/dist/capabilities/agents.specs.js +71 -1
- package/dist/capabilities/agents.specs.js.map +1 -1
- package/dist/capabilities/analysis.d.ts.map +1 -1
- package/dist/capabilities/analysis.js +33 -22
- package/dist/capabilities/analysis.js.map +1 -1
- package/dist/capabilities/analysis.specs.js +2 -2
- package/dist/capabilities/analysis.specs.js.map +1 -1
- package/dist/capabilities/apps.d.ts.map +1 -1
- package/dist/capabilities/apps.js +5 -3
- package/dist/capabilities/apps.js.map +1 -1
- package/dist/capabilities/args.d.ts +2 -5
- package/dist/capabilities/args.d.ts.map +1 -1
- package/dist/capabilities/args.js +2 -5
- package/dist/capabilities/args.js.map +1 -1
- package/dist/capabilities/assets.d.ts.map +1 -1
- package/dist/capabilities/assets.js +40 -10
- package/dist/capabilities/assets.js.map +1 -1
- package/dist/capabilities/browser.d.ts +1 -1
- package/dist/capabilities/browser.js +1 -1
- package/dist/capabilities/browser.specs.d.ts +1 -1
- package/dist/capabilities/browser.specs.js +1 -1
- package/dist/capabilities/code.d.ts +5 -0
- package/dist/capabilities/code.d.ts.map +1 -1
- package/dist/capabilities/code.js +128 -89
- package/dist/capabilities/code.js.map +1 -1
- package/dist/capabilities/collections.d.ts +4 -6
- package/dist/capabilities/collections.d.ts.map +1 -1
- package/dist/capabilities/collections.js +16 -11
- package/dist/capabilities/collections.js.map +1 -1
- package/dist/capabilities/derive-shot.d.ts +45 -0
- package/dist/capabilities/derive-shot.d.ts.map +1 -0
- package/dist/capabilities/derive-shot.js +82 -0
- package/dist/capabilities/derive-shot.js.map +1 -0
- package/dist/capabilities/documents.d.ts +2 -1
- package/dist/capabilities/documents.d.ts.map +1 -1
- package/dist/capabilities/documents.js +12 -6
- package/dist/capabilities/documents.js.map +1 -1
- package/dist/capabilities/email.d.ts +2 -1
- package/dist/capabilities/email.d.ts.map +1 -1
- package/dist/capabilities/email.js +5 -3
- package/dist/capabilities/email.js.map +1 -1
- package/dist/capabilities/errors.d.ts +19 -0
- package/dist/capabilities/errors.d.ts.map +1 -0
- package/dist/capabilities/errors.js +109 -0
- package/dist/capabilities/errors.js.map +1 -0
- package/dist/capabilities/errors.specs.d.ts +11 -0
- package/dist/capabilities/errors.specs.d.ts.map +1 -0
- package/dist/capabilities/errors.specs.js +100 -0
- package/dist/capabilities/errors.specs.js.map +1 -0
- package/dist/capabilities/example-timelines.d.ts.map +1 -1
- package/dist/capabilities/example-timelines.js +52 -10
- package/dist/capabilities/example-timelines.js.map +1 -1
- package/dist/capabilities/example-timelines.specs.d.ts +1 -0
- package/dist/capabilities/example-timelines.specs.d.ts.map +1 -1
- package/dist/capabilities/example-timelines.specs.js +21 -3
- package/dist/capabilities/example-timelines.specs.js.map +1 -1
- package/dist/capabilities/finish-storyboard.d.ts +5 -0
- package/dist/capabilities/finish-storyboard.d.ts.map +1 -0
- package/dist/capabilities/finish-storyboard.js +278 -0
- package/dist/capabilities/finish-storyboard.js.map +1 -0
- package/dist/capabilities/game-asset-browser.d.ts +11 -0
- package/dist/capabilities/game-asset-browser.d.ts.map +1 -0
- package/dist/capabilities/game-asset-browser.js +152 -0
- package/dist/capabilities/game-asset-browser.js.map +1 -0
- package/dist/capabilities/game-asset-source.js +1 -1
- package/dist/capabilities/game-asset-source.js.map +1 -1
- package/dist/capabilities/game.d.ts +44 -2
- package/dist/capabilities/game.d.ts.map +1 -1
- package/dist/capabilities/game.js +408 -160
- package/dist/capabilities/game.js.map +1 -1
- package/dist/capabilities/game.specs.d.ts +4 -0
- package/dist/capabilities/game.specs.d.ts.map +1 -1
- package/dist/capabilities/game.specs.js +42 -13
- package/dist/capabilities/game.specs.js.map +1 -1
- package/dist/capabilities/game3d.d.ts +17 -0
- package/dist/capabilities/game3d.d.ts.map +1 -0
- package/dist/capabilities/game3d.js +434 -0
- package/dist/capabilities/game3d.js.map +1 -0
- package/dist/capabilities/gate-from-context.d.ts +1 -1
- package/dist/capabilities/gate-from-context.js +1 -1
- package/dist/capabilities/generations.d.ts +2 -0
- package/dist/capabilities/generations.d.ts.map +1 -1
- package/dist/capabilities/generations.js +14 -23
- package/dist/capabilities/generations.js.map +1 -1
- package/dist/capabilities/index.d.ts +2 -2
- package/dist/capabilities/index.d.ts.map +1 -1
- package/dist/capabilities/index.js +2 -2
- package/dist/capabilities/index.js.map +1 -1
- package/dist/capabilities/invoke.d.ts +14 -25
- package/dist/capabilities/invoke.d.ts.map +1 -1
- package/dist/capabilities/invoke.js +72 -35
- package/dist/capabilities/invoke.js.map +1 -1
- package/dist/capabilities/jobs.d.ts.map +1 -1
- package/dist/capabilities/jobs.js +47 -3
- package/dist/capabilities/jobs.js.map +1 -1
- package/dist/capabilities/jobs.specs.d.ts.map +1 -1
- package/dist/capabilities/jobs.specs.js +3 -1
- package/dist/capabilities/jobs.specs.js.map +1 -1
- package/dist/capabilities/js-scripts.d.ts +19 -1
- package/dist/capabilities/js-scripts.d.ts.map +1 -1
- package/dist/capabilities/js-scripts.js +109 -2
- package/dist/capabilities/js-scripts.js.map +1 -1
- package/dist/capabilities/js-scripts.specs.d.ts +2 -0
- package/dist/capabilities/js-scripts.specs.d.ts.map +1 -1
- package/dist/capabilities/js-scripts.specs.js +50 -0
- package/dist/capabilities/js-scripts.specs.js.map +1 -1
- package/dist/capabilities/lazy-tool-core.d.ts +23 -0
- package/dist/capabilities/lazy-tool-core.d.ts.map +1 -0
- package/dist/capabilities/lazy-tool-core.js +56 -0
- package/dist/capabilities/lazy-tool-core.js.map +1 -0
- package/dist/capabilities/lazy-tool.d.ts +3 -23
- package/dist/capabilities/lazy-tool.d.ts.map +1 -1
- package/dist/capabilities/lazy-tool.js +6 -64
- package/dist/capabilities/lazy-tool.js.map +1 -1
- package/dist/capabilities/legacy-tools.d.ts +15 -0
- package/dist/capabilities/legacy-tools.d.ts.map +1 -0
- package/dist/capabilities/legacy-tools.js +98 -0
- package/dist/capabilities/legacy-tools.js.map +1 -0
- package/dist/capabilities/media.d.ts +0 -9
- package/dist/capabilities/media.d.ts.map +1 -1
- package/dist/capabilities/media.js +314 -261
- package/dist/capabilities/media.js.map +1 -1
- package/dist/capabilities/media.specs.d.ts.map +1 -1
- package/dist/capabilities/media.specs.js +17 -0
- package/dist/capabilities/media.specs.js.map +1 -1
- package/dist/capabilities/metadata.d.ts +62 -0
- package/dist/capabilities/metadata.d.ts.map +1 -0
- package/dist/capabilities/metadata.js +114 -0
- package/dist/capabilities/metadata.js.map +1 -0
- package/dist/capabilities/model3d.d.ts.map +1 -1
- package/dist/capabilities/model3d.js +4 -0
- package/dist/capabilities/model3d.js.map +1 -1
- package/dist/capabilities/models.d.ts +2 -2
- package/dist/capabilities/models.d.ts.map +1 -1
- package/dist/capabilities/models.js +5 -3
- package/dist/capabilities/models.js.map +1 -1
- package/dist/capabilities/registry.d.ts +6 -19
- package/dist/capabilities/registry.d.ts.map +1 -1
- package/dist/capabilities/registry.js +72 -113
- package/dist/capabilities/registry.js.map +1 -1
- package/dist/capabilities/run-agent.d.ts +19 -0
- package/dist/capabilities/run-agent.d.ts.map +1 -0
- package/dist/capabilities/run-agent.js +183 -0
- package/dist/capabilities/run-agent.js.map +1 -0
- package/dist/capabilities/runs.d.ts +9 -0
- package/dist/capabilities/runs.d.ts.map +1 -0
- package/dist/capabilities/runs.js +46 -0
- package/dist/capabilities/runs.js.map +1 -0
- package/dist/capabilities/runs.specs.d.ts +39 -0
- package/dist/capabilities/runs.specs.d.ts.map +1 -0
- package/dist/capabilities/runs.specs.js +52 -0
- package/dist/capabilities/runs.specs.js.map +1 -0
- package/dist/capabilities/scripts.d.ts.map +1 -1
- package/dist/capabilities/scripts.js +11 -5
- package/dist/capabilities/scripts.js.map +1 -1
- package/dist/capabilities/settings.d.ts.map +1 -1
- package/dist/capabilities/settings.js +4 -2
- package/dist/capabilities/settings.js.map +1 -1
- package/dist/capabilities/sketches.d.ts.map +1 -1
- package/dist/capabilities/sketches.js +4 -2
- package/dist/capabilities/sketches.js.map +1 -1
- package/dist/capabilities/skills.d.ts.map +1 -1
- package/dist/capabilities/skills.js +22 -2
- package/dist/capabilities/skills.js.map +1 -1
- package/dist/capabilities/storyboard-layout-check.d.ts +33 -0
- package/dist/capabilities/storyboard-layout-check.d.ts.map +1 -0
- package/dist/capabilities/storyboard-layout-check.js +229 -0
- package/dist/capabilities/storyboard-layout-check.js.map +1 -0
- package/dist/capabilities/storyboard-measured-sources.d.ts +10 -0
- package/dist/capabilities/storyboard-measured-sources.d.ts.map +1 -0
- package/dist/capabilities/storyboard-measured-sources.js +67 -0
- package/dist/capabilities/storyboard-measured-sources.js.map +1 -0
- package/dist/capabilities/storyboard-review-times.d.ts +4 -0
- package/dist/capabilities/storyboard-review-times.d.ts.map +1 -0
- package/dist/capabilities/storyboard-review-times.js +39 -0
- package/dist/capabilities/storyboard-review-times.js.map +1 -0
- package/dist/capabilities/storyboards.d.ts +12 -18
- package/dist/capabilities/storyboards.d.ts.map +1 -1
- package/dist/capabilities/storyboards.js +779 -96
- package/dist/capabilities/storyboards.js.map +1 -1
- package/dist/capabilities/storyboards.specs.d.ts +9 -0
- package/dist/capabilities/storyboards.specs.d.ts.map +1 -1
- package/dist/capabilities/storyboards.specs.js +173 -5
- package/dist/capabilities/storyboards.specs.js.map +1 -1
- package/dist/capabilities/threads.js +1 -1
- package/dist/capabilities/threads.js.map +1 -1
- package/dist/capabilities/timeline-bridge.d.ts +368 -0
- package/dist/capabilities/timeline-bridge.d.ts.map +1 -0
- package/dist/capabilities/timeline-bridge.js +1008 -0
- package/dist/capabilities/timeline-bridge.js.map +1 -0
- package/dist/capabilities/timeline-clip-frames.d.ts +17 -0
- package/dist/capabilities/timeline-clip-frames.d.ts.map +1 -0
- package/dist/capabilities/timeline-clip-frames.js +84 -0
- package/dist/capabilities/timeline-clip-frames.js.map +1 -0
- package/dist/capabilities/timeline-media-edit.d.ts +8 -0
- package/dist/capabilities/timeline-media-edit.d.ts.map +1 -0
- package/dist/capabilities/timeline-media-edit.js +94 -0
- package/dist/capabilities/timeline-media-edit.js.map +1 -0
- package/dist/capabilities/timeline-native-media.d.ts.map +1 -1
- package/dist/capabilities/timeline-native-media.js +40 -0
- package/dist/capabilities/timeline-native-media.js.map +1 -1
- package/dist/capabilities/timeline-operations.d.ts +52 -0
- package/dist/capabilities/timeline-operations.d.ts.map +1 -0
- package/dist/capabilities/timeline-operations.js +413 -0
- package/dist/capabilities/timeline-operations.js.map +1 -0
- package/dist/capabilities/timelines.d.ts +28 -3
- package/dist/capabilities/timelines.d.ts.map +1 -1
- package/dist/capabilities/timelines.js +410 -294
- package/dist/capabilities/timelines.js.map +1 -1
- package/dist/capabilities/timelines.specs.d.ts +8 -0
- package/dist/capabilities/timelines.specs.d.ts.map +1 -1
- package/dist/capabilities/timelines.specs.js +178 -9
- package/dist/capabilities/timelines.specs.js.map +1 -1
- package/dist/capabilities/types.d.ts +3 -1
- package/dist/capabilities/types.d.ts.map +1 -1
- package/dist/capabilities/types.js.map +1 -1
- package/dist/capabilities/ui.d.ts.map +1 -1
- package/dist/capabilities/ui.js +24 -2
- package/dist/capabilities/ui.js.map +1 -1
- package/dist/capabilities/web.d.ts.map +1 -1
- package/dist/capabilities/web.js +4 -0
- package/dist/capabilities/web.js.map +1 -1
- package/dist/capabilities/workflows.d.ts +3 -1
- package/dist/capabilities/workflows.d.ts.map +1 -1
- package/dist/capabilities/workflows.js +244 -39
- package/dist/capabilities/workflows.js.map +1 -1
- package/dist/capabilities/workflows.specs.d.ts +2 -0
- package/dist/capabilities/workflows.specs.d.ts.map +1 -1
- package/dist/capabilities/workflows.specs.js +72 -2
- package/dist/capabilities/workflows.specs.js.map +1 -1
- package/dist/codeact/action-diagnostics.d.ts.map +1 -1
- package/dist/codeact/action-diagnostics.js +51 -1
- package/dist/codeact/action-diagnostics.js.map +1 -1
- package/dist/codeact/codeact-executor.d.ts.map +1 -1
- package/dist/codeact/codeact-executor.js +16 -8
- package/dist/codeact/codeact-executor.js.map +1 -1
- package/dist/codeact/compact-ids.d.ts.map +1 -1
- package/dist/codeact/compact-ids.js +5 -1
- package/dist/codeact/compact-ids.js.map +1 -1
- package/dist/codeact/graph-model.d.ts +1 -1
- package/dist/codeact/graph-model.d.ts.map +1 -1
- package/dist/codeact/graph-model.js +2 -3
- package/dist/codeact/graph-model.js.map +1 -1
- package/dist/codeact/nodetool-api.d.ts +1 -1
- package/dist/codeact/nodetool-api.d.ts.map +1 -1
- package/dist/codeact/nodetool-api.js +202 -284
- package/dist/codeact/nodetool-api.js.map +1 -1
- package/dist/codeact/sandbox-packages.d.ts +0 -7
- package/dist/codeact/sandbox-packages.d.ts.map +1 -1
- package/dist/codeact/sandbox-packages.js +1 -10
- package/dist/codeact/sandbox-packages.js.map +1 -1
- package/dist/codeact/tool-api.d.ts +6 -3
- package/dist/codeact/tool-api.d.ts.map +1 -1
- package/dist/codeact/tool-api.js +22 -15
- package/dist/codeact/tool-api.js.map +1 -1
- package/dist/evals/codeact-api-cases.d.ts.map +1 -1
- package/dist/evals/codeact-api-cases.js +2 -0
- package/dist/evals/codeact-api-cases.js.map +1 -1
- package/dist/evals/codeact-api-runs.d.ts +3 -0
- package/dist/evals/codeact-api-runs.d.ts.map +1 -0
- package/dist/evals/codeact-api-runs.js +33 -0
- package/dist/evals/codeact-api-runs.js.map +1 -0
- package/dist/evals/surfaces/game.d.ts +8 -2
- package/dist/evals/surfaces/game.d.ts.map +1 -1
- package/dist/evals/surfaces/game.js +460 -2
- package/dist/evals/surfaces/game.js.map +1 -1
- package/dist/evals/surfaces/sketch.d.ts +2 -0
- package/dist/evals/surfaces/sketch.d.ts.map +1 -1
- package/dist/evals/surfaces/sketch.js +11 -3
- package/dist/evals/surfaces/sketch.js.map +1 -1
- package/dist/evals/surfaces/timeline.d.ts +4 -357
- package/dist/evals/surfaces/timeline.d.ts.map +1 -1
- package/dist/evals/surfaces/timeline.js +9 -2621
- package/dist/evals/surfaces/timeline.js.map +1 -1
- package/dist/evals/tool-loop-bridge.d.ts +4 -0
- package/dist/evals/tool-loop-bridge.d.ts.map +1 -1
- package/dist/evals/tool-loop-bridge.js.map +1 -1
- package/dist/evals/tool-loop-eval.d.ts +2 -0
- package/dist/evals/tool-loop-eval.d.ts.map +1 -1
- package/dist/evals/tool-loop-eval.js +6 -1
- package/dist/evals/tool-loop-eval.js.map +1 -1
- package/dist/evals/tool-loop-permission.d.ts +1 -15
- package/dist/evals/tool-loop-permission.d.ts.map +1 -1
- package/dist/evals/tool-loop-permission.js +23 -41
- package/dist/evals/tool-loop-permission.js.map +1 -1
- package/dist/game-authoring.d.ts +9573 -0
- package/dist/game-authoring.d.ts.map +1 -0
- package/dist/game-authoring.js +146 -0
- package/dist/game-authoring.js.map +1 -0
- package/dist/game-build.d.ts +3 -0
- package/dist/game-build.d.ts.map +1 -0
- package/dist/game-build.js +3 -0
- package/dist/game-build.js.map +1 -0
- package/dist/game-code-bake.d.ts +26 -0
- package/dist/game-code-bake.d.ts.map +1 -0
- package/dist/game-code-bake.js +98 -0
- package/dist/game-code-bake.js.map +1 -0
- package/dist/game-examples.d.ts +2227 -18
- package/dist/game-examples.d.ts.map +1 -1
- package/dist/game-examples.js +5 -4
- package/dist/game-examples.js.map +1 -1
- package/dist/generation-cancel.d.ts +31 -0
- package/dist/generation-cancel.d.ts.map +1 -0
- package/dist/generation-cancel.js +28 -0
- package/dist/generation-cancel.js.map +1 -0
- package/dist/host-access-gate.d.ts +29 -0
- package/dist/host-access-gate.d.ts.map +1 -0
- package/dist/host-access-gate.js +39 -0
- package/dist/host-access-gate.js.map +1 -0
- package/dist/host-modules/dispatcher.d.ts +7 -1
- package/dist/host-modules/dispatcher.d.ts.map +1 -1
- package/dist/host-modules/dispatcher.js +13 -2
- package/dist/host-modules/dispatcher.js.map +1 -1
- package/dist/host-modules/docx.d.ts.map +1 -1
- package/dist/host-modules/docx.js +2 -2
- package/dist/host-modules/docx.js.map +1 -1
- package/dist/host-modules/epub.d.ts.map +1 -1
- package/dist/host-modules/epub.js +2 -2
- package/dist/host-modules/epub.js.map +1 -1
- package/dist/host-modules/fabric.d.ts.map +1 -1
- package/dist/host-modules/fabric.js +1 -1
- package/dist/host-modules/fabric.js.map +1 -1
- package/dist/host-modules/limits.d.ts +10 -8
- package/dist/host-modules/limits.d.ts.map +1 -1
- package/dist/host-modules/limits.js +14 -9
- package/dist/host-modules/limits.js.map +1 -1
- package/dist/host-modules/mammoth.d.ts.map +1 -1
- package/dist/host-modules/mammoth.js +2 -2
- package/dist/host-modules/mammoth.js.map +1 -1
- package/dist/host-modules/ocr.d.ts.map +1 -1
- package/dist/host-modules/ocr.js +1 -1
- package/dist/host-modules/ocr.js.map +1 -1
- package/dist/host-modules/pdf.d.ts.map +1 -1
- package/dist/host-modules/pdf.js +2 -2
- package/dist/host-modules/pdf.js.map +1 -1
- package/dist/host-modules/pdflib.d.ts.map +1 -1
- package/dist/host-modules/pdflib.js +2 -2
- package/dist/host-modules/pdflib.js.map +1 -1
- package/dist/host-modules/pptx.d.ts.map +1 -1
- package/dist/host-modules/pptx.js +2 -2
- package/dist/host-modules/pptx.js.map +1 -1
- package/dist/host-modules/pptxgen.d.ts.map +1 -1
- package/dist/host-modules/pptxgen.js +2 -2
- package/dist/host-modules/pptxgen.js.map +1 -1
- package/dist/host-modules/tfjs.d.ts.map +1 -1
- package/dist/host-modules/tfjs.js +4 -4
- package/dist/host-modules/tfjs.js.map +1 -1
- package/dist/host-modules/xlsx.d.ts.map +1 -1
- package/dist/host-modules/xlsx.js +2 -2
- package/dist/host-modules/xlsx.js.map +1 -1
- package/dist/index.d.ts +18 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +17 -3
- package/dist/index.js.map +1 -1
- package/dist/js-sandbox-worker/engine.d.ts +4 -0
- package/dist/js-sandbox-worker/engine.d.ts.map +1 -0
- package/dist/js-sandbox-worker/engine.js +45 -0
- package/dist/js-sandbox-worker/engine.js.map +1 -0
- package/dist/js-sandbox-worker/host.js +1 -1
- package/dist/js-sandbox-worker/host.js.map +1 -1
- package/dist/js-sandbox-worker/interpreter.d.ts +1 -1
- package/dist/js-sandbox-worker/interpreter.d.ts.map +1 -1
- package/dist/js-sandbox-worker/interpreter.js +94 -2
- package/dist/js-sandbox-worker/interpreter.js.map +1 -1
- package/dist/js-sandbox-worker/worker-entry.d.ts.map +1 -1
- package/dist/js-sandbox-worker/worker-entry.js +3 -2
- package/dist/js-sandbox-worker/worker-entry.js.map +1 -1
- package/dist/js-sandbox.d.ts +9 -1
- package/dist/js-sandbox.d.ts.map +1 -1
- package/dist/js-sandbox.js +76 -15
- package/dist/js-sandbox.js.map +1 -1
- package/dist/js-script-app-runner.d.ts +2 -0
- package/dist/js-script-app-runner.d.ts.map +1 -1
- package/dist/js-script-app-runner.js +8 -3
- package/dist/js-script-app-runner.js.map +1 -1
- package/dist/js-script-sandbox.d.ts +12 -18
- package/dist/js-script-sandbox.d.ts.map +1 -1
- package/dist/js-script-sandbox.js +3 -49
- package/dist/js-script-sandbox.js.map +1 -1
- package/dist/prompts/product-knowledge.d.ts +1 -1
- package/dist/prompts/product-knowledge.d.ts.map +1 -1
- package/dist/prompts/product-knowledge.js +82 -41
- package/dist/prompts/product-knowledge.js.map +1 -1
- package/dist/sandbox-pack-resolution.d.ts +21 -0
- package/dist/sandbox-pack-resolution.d.ts.map +1 -0
- package/dist/sandbox-pack-resolution.js +42 -0
- package/dist/sandbox-pack-resolution.js.map +1 -0
- package/dist/sandbox-toolbelt.d.ts +3 -1
- package/dist/sandbox-toolbelt.d.ts.map +1 -1
- package/dist/sandbox-toolbelt.js +8 -2
- package/dist/sandbox-toolbelt.js.map +1 -1
- package/dist/skill-prompt.d.ts +11 -1
- package/dist/skill-prompt.d.ts.map +1 -1
- package/dist/skill-prompt.js +17 -6
- package/dist/skill-prompt.js.map +1 -1
- package/dist/system-skills.d.ts +7 -1
- package/dist/system-skills.d.ts.map +1 -1
- package/dist/system-skills.js +2 -2
- package/dist/system-skills.js.map +1 -1
- package/dist/timeline-capture.d.ts +21 -0
- package/dist/timeline-capture.d.ts.map +1 -0
- package/dist/timeline-capture.js +564 -0
- package/dist/timeline-capture.js.map +1 -0
- package/dist/timeline-code-bake.d.ts +75 -0
- package/dist/timeline-code-bake.d.ts.map +1 -0
- package/dist/timeline-code-bake.js +327 -0
- package/dist/timeline-code-bake.js.map +1 -0
- package/dist/timeline-preview/frames.d.ts +26 -0
- package/dist/timeline-preview/frames.d.ts.map +1 -1
- package/dist/timeline-preview/frames.js +155 -70
- package/dist/timeline-preview/frames.js.map +1 -1
- package/dist/tools/base-tool.d.ts +1 -0
- package/dist/tools/base-tool.d.ts.map +1 -1
- package/dist/tools/base-tool.js +1 -1
- package/dist/tools/base-tool.js.map +1 -1
- package/dist/tools/builtin-tools.d.ts +4 -3
- package/dist/tools/builtin-tools.d.ts.map +1 -1
- package/dist/tools/builtin-tools.js +24 -3
- package/dist/tools/builtin-tools.js.map +1 -1
- package/dist/tools/external-capability-tools.d.ts +1 -1
- package/dist/tools/external-capability-tools.js +1 -1
- package/dist/tools/mcp-tool-support.d.ts +10 -9
- package/dist/tools/mcp-tool-support.d.ts.map +1 -1
- package/dist/tools/mcp-tool-support.js +14 -13
- package/dist/tools/mcp-tool-support.js.map +1 -1
- package/dist/tools/mcp-tools.d.ts +6 -4
- package/dist/tools/mcp-tools.d.ts.map +1 -1
- package/dist/tools/mcp-tools.js +65 -62
- package/dist/tools/mcp-tools.js.map +1 -1
- package/dist/tools/tool-permissions.d.ts +1 -1
- package/dist/tools/tool-permissions.js +1 -1
- package/package.json +124 -41
- package/dist/capabilities/gate-tools.d.ts +0 -18
- package/dist/capabilities/gate-tools.d.ts.map +0 -1
- package/dist/capabilities/gate-tools.js +0 -66
- package/dist/capabilities/gate-tools.js.map +0 -1
- 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 {
|
|
21
|
-
|
|
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:
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
1514
|
-
|
|
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
|
|
1526
|
-
const
|
|
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
|
-
|
|
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(
|
|
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(
|
|
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
|