stillmade-sdk 0.1.42 → 0.1.43

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 (262) hide show
  1. package/.stillmade/sdk-baseline.json +6 -8
  2. package/AGENTS.md +15 -10
  3. package/FRAME_VIEWS.md +113 -0
  4. package/INTERFACE_DESIGN.md +62 -22
  5. package/MOBILE_UI.md +4 -2
  6. package/MODULES.md +152 -6
  7. package/PASTE_TO_LLM.md +35 -25
  8. package/README.md +3 -2
  9. package/SDK.md +994 -550
  10. package/UI_AESTHETIC.md +22 -2
  11. package/blocks/generate/package.js +1 -0
  12. package/blocks/generate/versions/1.0.0/package.js +463 -0
  13. package/docs/build/audio-to-editor.md +36 -0
  14. package/docs/build/block-builder-contract.md +150 -0
  15. package/docs/build/comfyui.md +227 -0
  16. package/docs/build/concepts.md +40 -0
  17. package/docs/build/context.md +159 -0
  18. package/docs/build/cookbook.md +57 -0
  19. package/docs/build/custom-interface.md +617 -0
  20. package/docs/build/data-types.md +83 -0
  21. package/docs/build/frame-views.md +259 -0
  22. package/docs/build/generate-media.md +59 -0
  23. package/docs/build/github-applications.md +314 -0
  24. package/docs/build/hosted-images.md +214 -0
  25. package/docs/build/hosted-music.md +39 -0
  26. package/docs/build/hosted-speech.md +157 -0
  27. package/docs/build/hosted-text.md +246 -0
  28. package/docs/build/image-description.md +49 -0
  29. package/docs/build/interface-design.md +343 -0
  30. package/docs/build/javascript.md +63 -0
  31. package/docs/build/local-preview.md +61 -0
  32. package/docs/build/media-analysis.md +27 -0
  33. package/docs/build/media.md +400 -0
  34. package/docs/build/mobile-ui.md +106 -0
  35. package/docs/build/modules.md +487 -0
  36. package/docs/build/original-blocks.md +70 -0
  37. package/docs/build/outside-apis.md +128 -0
  38. package/docs/build/production-context-templates.md +12 -0
  39. package/docs/build/project-storage.md +94 -0
  40. package/docs/build/quickstart.md +48 -0
  41. package/docs/build/recipes.md +103 -0
  42. package/docs/build/script-handoff.md +45 -0
  43. package/docs/build/script-writer.md +34 -0
  44. package/docs/build/state.md +223 -0
  45. package/docs/build/testing.md +112 -0
  46. package/docs/build/timeline-edits.md +116 -0
  47. package/docs/build/timeline-proposals.md +76 -0
  48. package/docs/build/transcription.md +59 -0
  49. package/docs/build/triggers.md +59 -0
  50. package/docs/build/tutorial.md +52 -0
  51. package/docs/build/typescript.md +34 -0
  52. package/docs/build/video-generation.md +61 -0
  53. package/docs/build/web-reading.md +37 -0
  54. package/docs/build/with-your-ai.md +27 -0
  55. package/docs/changelog.md +9 -0
  56. package/docs/creators.md +21 -0
  57. package/docs/distribute/discovery.md +43 -0
  58. package/docs/distribute/imports.md +58 -0
  59. package/docs/distribute/publishing.md +29 -0
  60. package/docs/distribute/sdk-versions.md +36 -0
  61. package/docs/distribute/selling.md +14 -0
  62. package/docs/distribute/teams.md +60 -0
  63. package/docs/distribute/versioning.md +28 -0
  64. package/docs/examples.md +23 -0
  65. package/docs/gallery.md +26 -0
  66. package/docs/index.md +50 -0
  67. package/docs/native-mcp.md +307 -0
  68. package/docs/project-types/automation.md +43 -0
  69. package/docs/project-types/batches.md +50 -0
  70. package/docs/project-types/build.md +42 -0
  71. package/docs/project-types/completion.md +15 -0
  72. package/docs/project-types/conditions.md +21 -0
  73. package/docs/project-types/hosted-review.md +115 -0
  74. package/docs/project-types/onboarding.md +75 -0
  75. package/docs/project-types/running.md +309 -0
  76. package/docs/project-types/testing.md +72 -0
  77. package/docs/reference/application-artifacts.md +87 -0
  78. package/docs/reference/authoring-guide.md +134 -0
  79. package/docs/reference/browser-applications.md +267 -0
  80. package/docs/reference/capabilities.md +45 -0
  81. package/docs/reference/cli.md +71 -0
  82. package/docs/reference/connection-api.md +59 -0
  83. package/docs/reference/cooperative-jobs.md +13 -0
  84. package/docs/reference/desktop-capabilities.md +172 -0
  85. package/docs/reference/desktop-execution.md +77 -0
  86. package/docs/reference/errors.md +233 -0
  87. package/docs/reference/execution.md +800 -0
  88. package/docs/reference/first-party-blocks.md +40 -0
  89. package/docs/reference/generation-models.md +59 -0
  90. package/docs/reference/limits.md +306 -0
  91. package/docs/reference/manifest-kinds-controls.md +36 -0
  92. package/docs/reference/manifest.md +181 -0
  93. package/docs/reference/operations.md +36 -0
  94. package/docs/reference/package-jobs.md +35 -0
  95. package/docs/reference/parity.md +55 -0
  96. package/docs/reference/permissions.md +86 -0
  97. package/docs/reference/ports.md +26 -0
  98. package/docs/reference/types.md +268 -0
  99. package/docs/reference/universal-resolver.md +303 -0
  100. package/docs/reference/view-bridge.md +60 -0
  101. package/docs/reference/view-rules.md +15 -0
  102. package/docs/reference/workspace-sync.md +25 -0
  103. package/docs/sdk.md +34 -0
  104. package/docs/tools/block-remix.md +211 -0
  105. package/docs/tools/llm.md +2213 -0
  106. package/docs/tools/repository-adaptation.md +613 -0
  107. package/examples/check-clip.stillmade.json +4 -1
  108. package/examples/generate-video.stillmade.json +6 -2
  109. package/examples/research-topic.stillmade.json +5 -1
  110. package/examples/text-workflow.stillmade.json +3 -32
  111. package/examples/timeline-polish.stillmade.json +11 -3
  112. package/examples/transcribe-audio.stillmade.json +11 -3
  113. package/package.json +1 -1
  114. package/packages/block-cli/cli.js +13 -6
  115. package/packages/block-cli/dev-host/assets/host.js +76 -38
  116. package/packages/block-cli/dev-host/assets/index.css +1 -1
  117. package/packages/block-cli/format.js +1 -1
  118. package/packages/block-cli/templates.js +31 -13
  119. package/packages/block-cli/type-packages.js +119 -0
  120. package/packages/block-platform/block-readiness.js +5 -0
  121. package/packages/block-platform/canvas.js +2 -1
  122. package/packages/block-platform/catalog.js +27 -48
  123. package/packages/block-platform/native-host-inventory.js +0 -226
  124. package/packages/block-platform/plain-descriptions.js +1 -25
  125. package/packages/block-platform/project-type-starters.js +13 -53
  126. package/packages/block-platform/script-handoff.js +2 -4
  127. package/packages/block-platform/type-workspace.js +2 -0
  128. package/packages/block-sdk/appearance.js +3 -1
  129. package/packages/block-sdk/block-tier.js +1 -1
  130. package/packages/block-sdk/builder-contract.js +10 -8
  131. package/packages/block-sdk/capabilities.js +1 -1
  132. package/packages/block-sdk/contracts.js +6 -2
  133. package/packages/block-sdk/first-party-identities.js +1 -84
  134. package/packages/block-sdk/first-party-packages.js +3 -85
  135. package/packages/block-sdk/generation-catalog.js +15 -3
  136. package/packages/block-sdk/index.d.ts +2 -1
  137. package/packages/block-sdk/media-analysis-example.js +1 -1
  138. package/packages/block-sdk/mock-host.js +7 -1
  139. package/packages/block-sdk/module-host-calls.js +35 -10
  140. package/packages/block-sdk/module-hosted.js +15 -2
  141. package/packages/block-sdk/module-media-access.js +71 -0
  142. package/packages/block-sdk/module-node.js +1 -1
  143. package/packages/block-sdk/portable-media-actions.js +1 -1
  144. package/packages/block-sdk/runtime.js +1 -1
  145. package/packages/block-sdk/timeline-proposal-example.js +1 -1
  146. package/packages/block-sdk/transcription-example.js +1 -1
  147. package/packages/block-sdk/video-generation-example.js +1 -1
  148. package/packages/block-sdk/view-bridge.js +4 -1
  149. package/packages/block-sdk/view-design.js +17 -14
  150. package/packages/block-sdk/web-example.js +1 -1
  151. package/packages/design-system/block-kit.css +48 -12
  152. package/packages/design-system/block-kit.html +3 -2
  153. package/blocks/mcp-motion-planner/versions/1.1.0/package.js +0 -97
  154. package/blocks/motion-designer/versions/1.0.1/package.js +0 -173318
  155. package/blocks/motion-designer/versions/1.0.2/package.js +0 -173318
  156. package/blocks/motion-frame-review/versions/1.1.1/package.js +0 -465
  157. package/blocks/motion-frame-review/versions/1.1.2/package.snapshot.js +0 -572
  158. package/blocks/narration/package.js +0 -1
  159. package/blocks/narration/versions/1.0.0/package.js +0 -221
  160. package/blocks/narration/versions/1.0.1/package.js +0 -221
  161. package/blocks/native/sm.animated-scene/versions/2.0.0/package.js +0 -475
  162. package/blocks/native/sm.animated-scene/versions/2.1.0/package.js +0 -498
  163. package/blocks/native/sm.animated-scene/versions/2.2.0/package.js +0 -524
  164. package/blocks/native/sm.animated-scene/versions/2.3.0/package.js +0 -618
  165. package/blocks/native/sm.animated-scene/versions/2.3.1/package.js +0 -618
  166. package/blocks/native/sm.animated-scene/versions/2.3.2/package.js +0 -723
  167. package/blocks/native/sm.animated-scene/versions/2.3.3/package.js +0 -723
  168. package/blocks/native/sm.animated-scene/versions/2.3.4/package.js +0 -676
  169. package/blocks/native/sm.animated-scene/versions/2.3.5/package.js +0 -693
  170. package/blocks/native/sm.animated-scene/versions/2.3.6/package.js +0 -700
  171. package/blocks/native/sm.animated-scene/versions/2.3.7/package.js +0 -747
  172. package/blocks/native/sm.animated-scene/versions/2.3.8/package.js +0 -769
  173. package/blocks/native/sm.animated-scene/versions/2.3.9/package.js +0 -769
  174. package/blocks/native/sm.animated-scene-assistant/versions/1.0.0/package.js +0 -183
  175. package/blocks/native/sm.blueprint/versions/2.0.0/package.js +0 -358
  176. package/blocks/native/sm.blueprint/versions/2.1.0/package.js +0 -358
  177. package/blocks/native/sm.blueprint/versions/2.1.1/package.js +0 -358
  178. package/blocks/native/sm.blueprint/versions/2.1.2/package.js +0 -358
  179. package/blocks/native/sm.blueprint/versions/2.1.3/package.js +0 -381
  180. package/blocks/native/sm.blueprint/versions/2.1.4/package.js +0 -381
  181. package/blocks/native/sm.blueprint/versions/2.1.5/package.js +0 -339
  182. package/blocks/native/sm.blueprint/versions/2.1.6/package.js +0 -356
  183. package/blocks/native/sm.blueprint/versions/2.1.7/package.js +0 -363
  184. package/blocks/native/sm.blueprint/versions/2.1.8/package.js +0 -410
  185. package/blocks/native/sm.blueprint/versions/2.1.9/package.js +0 -422
  186. package/blocks/native/sm.blueprint-assistant/versions/1.0.0/package.js +0 -172
  187. package/blocks/native/sm.chat/versions/2.0.0/package.js +0 -144
  188. package/blocks/native/sm.chat/versions/2.0.1/package.js +0 -97
  189. package/blocks/native/sm.chat/versions/2.0.2/package.js +0 -100
  190. package/blocks/native/sm.chat/versions/2.0.3/package.js +0 -100
  191. package/blocks/native/sm.continue-if/versions/1.0.0/package.js +0 -168
  192. package/blocks/native/sm.describe-media/versions/2.0.0/package.js +0 -153
  193. package/blocks/native/sm.describe-media/versions/2.0.1/package.js +0 -156
  194. package/blocks/native/sm.describe-media/versions/2.1.0/package.js +0 -140
  195. package/blocks/native/sm.image-editor/versions/2.0.0/package.js +0 -183
  196. package/blocks/native/sm.image-editor/versions/2.0.1/package.js +0 -190
  197. package/blocks/native/sm.new-items/versions/1.0.0/package.js +0 -191
  198. package/blocks/native/sm.pick-photos/versions/1.0.0/package.js +0 -334
  199. package/blocks/native/sm.quality-audit/versions/1.0.0/package.js +0 -192
  200. package/blocks/native/sm.quality-audit/versions/1.0.1/package.js +0 -192
  201. package/blocks/native/sm.quality-audit/versions/1.0.2/package.js +0 -195
  202. package/blocks/native/sm.research/versions/2.0.0/package.js +0 -175
  203. package/blocks/native/sm.research/versions/2.0.1/package.js +0 -184
  204. package/blocks/native/sm.research/versions/2.0.2/package.js +0 -187
  205. package/blocks/native/sm.script/versions/2.0.0/package.js +0 -144
  206. package/blocks/native/sm.script/versions/2.1.0/package.js +0 -144
  207. package/blocks/native/sm.script/versions/2.1.1/package.js +0 -144
  208. package/blocks/native/sm.script/versions/2.1.2/package.js +0 -105
  209. package/blocks/native/sm.script/versions/2.1.3/package.js +0 -152
  210. package/blocks/native/sm.script/versions/2.1.4/package.js +0 -156
  211. package/blocks/native/sm.script/versions/2.1.5/package.js +0 -156
  212. package/blocks/native/sm.shot-plan/versions/2.0.0/package.js +0 -301
  213. package/blocks/native/sm.shot-plan/versions/2.1.0/package.js +0 -528
  214. package/blocks/native/sm.shot-plan/versions/2.1.1/package.js +0 -528
  215. package/blocks/native/sm.shot-plan/versions/2.1.2/package.js +0 -528
  216. package/blocks/native/sm.shot-plan/versions/2.1.3/package.js +0 -536
  217. package/blocks/native/sm.shot-plan/versions/2.2.0/package.js +0 -800
  218. package/blocks/native/sm.shot-plan/versions/2.2.1/package.js +0 -920
  219. package/blocks/native/sm.shot-plan-assistant/versions/1.0.0/package.js +0 -173
  220. package/blocks/native/sm.stock-search/versions/2.0.0/package.js +0 -174
  221. package/blocks/native/sm.thumbnail/versions/2.0.0/package.js +0 -137
  222. package/blocks/native/sm.thumbnail/versions/2.0.1/package.js +0 -140
  223. package/blocks/native/sm.transcribe/versions/2.0.0/package.js +0 -163
  224. package/blocks/native/sm.transcribe/versions/2.0.1/package.js +0 -168
  225. package/blocks/native/sm.whiteboard-assistant/versions/1.0.0/package.js +0 -175
  226. package/blocks/native/sm.youtube/versions/2.0.0/package.js +0 -217
  227. package/blocks/occasion-story/package.js +0 -1
  228. package/blocks/occasion-story/versions/1.0.0/package.js +0 -1658
  229. package/blocks/occasion-story/versions/1.0.1/package.js +0 -1699
  230. package/blocks/occasion-story/versions/1.0.2/package.js +0 -1682
  231. package/blocks/photo-reel-composer/versions/1.0.0/package.js +0 -3043
  232. package/blocks/photo-reel-composer/versions/1.0.1/package.js +0 -3026
  233. package/blocks/photo-reel-composer/versions/1.0.2/package.js +0 -4149
  234. package/blocks/product-ad-variants/versions/1.0.0/package.js +0 -2911
  235. package/blocks/product-launch-director/versions/1.0.0/package.js +0 -103
  236. package/blocks/release-visuals/package.js +0 -1
  237. package/blocks/release-visuals/versions/1.0.0/package.js +0 -1492
  238. package/blocks/release-visuals/versions/1.0.1/package.js +0 -1517
  239. package/blocks/release-visuals/versions/1.0.2/package.js +0 -1500
  240. package/blocks/screen-recorder/package.js +0 -1
  241. package/blocks/screen-recorder/versions/1.0.0/package.js +0 -223
  242. package/blocks/screen-recorder/versions/1.0.1/package.js +0 -223
  243. package/blocks/short-form-finish/package.js +0 -1
  244. package/blocks/short-form-finish/versions/1.0.0/package.js +0 -1043
  245. package/blocks/short-form-finish/versions/1.0.1/package.js +0 -1043
  246. package/blocks/short-form-finish/versions/1.0.2/package.js +0 -1043
  247. package/blocks/short-form-finish/versions/1.0.3/package.js +0 -1026
  248. package/examples/saas-product-launch-reviewed-source.stillmade.json +0 -383
  249. package/examples/saas-product-launch.stillmade.json +0 -304
  250. package/packages/block-platform/dealer-inventory-video-project-type.js +0 -38
  251. package/packages/block-platform/first-revenue-project-types.js +0 -46
  252. package/packages/block-platform/fixture-starters.js +0 -13
  253. package/packages/block-platform/launch-project-source.js +0 -10
  254. package/packages/block-platform/launch-project.js +0 -30
  255. package/packages/block-platform/motion-project-types.js +0 -55
  256. package/packages/block-platform/motion-starters.js +0 -14
  257. package/packages/block-platform/product-ad-variants-project-type.js +0 -30
  258. package/packages/block-platform/product-launch-updated.js +0 -90
  259. package/packages/block-platform/revenue-review-project-types.js +0 -36
  260. package/packages/block-platform/revenue-review-starters.js +0 -13
  261. package/packages/block-platform/script-writer.js +0 -29
  262. package/packages/block-platform/website-source-block.js +0 -14
@@ -1,22 +1,5 @@
1
- import shortFormFinishV100 from '../../blocks/short-form-finish/versions/1.0.0/package.js';
2
- import shortFormFinishV101 from '../../blocks/short-form-finish/versions/1.0.1/package.js';
3
- import shortFormFinishV102 from '../../blocks/short-form-finish/versions/1.0.2/package.js';
4
- import shortFormFinish from '../../blocks/short-form-finish/package.js';
5
- import screenRecorderV100 from '../../blocks/screen-recorder/versions/1.0.0/package.js';
6
- import screenRecorder from '../../blocks/screen-recorder/package.js';
7
- import narrationV100 from '../../blocks/narration/versions/1.0.0/package.js';
8
- import narration from '../../blocks/narration/package.js';
9
- import occasionStoryV100 from '../../blocks/occasion-story/versions/1.0.0/package.js';
10
- import releaseVisualsV100 from '../../blocks/release-visuals/versions/1.0.0/package.js';
11
- import occasionStoryV101 from '../../blocks/occasion-story/versions/1.0.1/package.js';
12
- import releaseVisualsV101 from '../../blocks/release-visuals/versions/1.0.1/package.js';
13
- import occasionStory from '../../blocks/occasion-story/package.js';
14
- import releaseVisuals from '../../blocks/release-visuals/package.js';
1
+ import generate from '../../blocks/generate/package.js';
15
2
  import importMedia from '../../blocks/native/sm.import-media/versions/2.0.0/package.js';
16
- import photoReelComposerV100 from '../../blocks/photo-reel-composer/versions/1.0.0/package.js';
17
- import photoReelComposerV101 from '../../blocks/photo-reel-composer/versions/1.0.1/package.js';
18
- import photoReelComposer from '../../blocks/photo-reel-composer/versions/1.0.2/package.js';
19
- import productAdVariants from '../../blocks/product-ad-variants/versions/1.0.0/package.js';
20
3
  import importMediaV201 from '../../blocks/native/sm.import-media/versions/2.0.1/package.js';
21
4
  import importMediaV202 from '../../blocks/native/sm.import-media/versions/2.0.2/package.js';
22
5
  import editorV229 from '../../blocks/native/sm.editor/versions/2.2.9/package.js';
@@ -34,9 +17,6 @@ import gradeV202 from '../../blocks/native/sm.grade/versions/2.0.2/package.js';
34
17
  import compare from '../../blocks/native/sm.compare/versions/2.0.0/package.js';
35
18
  import compareV201 from '../../blocks/native/sm.compare/versions/2.0.1/package.js';
36
19
  import compareV202 from '../../blocks/native/sm.compare/versions/2.0.2/package.js';
37
- import qualityAuditV102 from '../../blocks/native/sm.quality-audit/versions/1.0.2/package.js';
38
- import stockSearch from '../../blocks/native/sm.stock-search/versions/2.0.0/package.js';
39
- import youtubePublication from '../../blocks/native/sm.youtube/versions/2.0.0/package.js';
40
20
  import exportVideo from '../../blocks/native/sm.export-video/versions/2.0.0/package.js';
41
21
  import exportVideoV210 from '../../blocks/native/sm.export-video/versions/2.1.0/package.js';
42
22
  import exportAudio from '../../blocks/native/sm.export-audio/versions/2.0.0/package.js';
@@ -44,14 +24,10 @@ import motionGraphics from '../../blocks/native/sm.motion-graphics/versions/2.0.
44
24
  import audioScore from '../../blocks/native/sm.score/versions/2.0.0/package.js';
45
25
  import generateImage from '../../blocks/native/sm.generate-image/versions/2.0.0/package.js';
46
26
  import generateImageV210 from '../../blocks/native/sm.generate-image/versions/2.1.0/package.js';
47
- import thumbnail from '../../blocks/native/sm.thumbnail/versions/2.0.0/package.js';
48
- import thumbnailV201 from '../../blocks/native/sm.thumbnail/versions/2.0.1/package.js';
49
27
  import writeSummary from '../../blocks/native/sm.write-summary/versions/1.0.0/package.js';
50
28
  import automationWhen from '../../blocks/native/sm.when/versions/1.0.0/package.js';
51
29
  import automationV110 from '../../blocks/native/sm.when/versions/1.1.0/package.js';
52
- import automationNewItems from '../../blocks/native/sm.new-items/versions/1.0.0/package.js';
53
30
  import automationAiDecide from '../../blocks/native/sm.ai-decide/versions/1.0.0/package.js';
54
- import automationContinueIf from '../../blocks/native/sm.continue-if/versions/1.0.0/package.js';
55
31
  import connectApp from '../../blocks/native/sm.connect-app/versions/1.0.0/package.js';
56
32
  import automationAiWrite from '../../blocks/native/sm.ai-write/versions/1.0.0/package.js';
57
33
  import automationMetaCreative from '../../blocks/native/sm.meta-creative/versions/1.0.0/package.js';
@@ -64,35 +40,16 @@ import voiceoverV213 from '../../blocks/native/sm.voiceover/versions/2.1.3/packa
64
40
  import voiceoverV214 from '../../blocks/native/sm.voiceover/versions/2.1.4/package.js';
65
41
  import voiceoverV215 from '../../blocks/native/sm.voiceover/versions/2.1.5/package.js';
66
42
  import voiceoverV216 from '../../blocks/native/sm.voiceover/versions/2.1.6/package.js';
67
- import script from '../../blocks/native/sm.script/versions/2.0.0/package.js';
68
- import scriptV210 from '../../blocks/native/sm.script/versions/2.1.0/package.js';
69
- import scriptV211 from '../../blocks/native/sm.script/versions/2.1.1/package.js';
70
- import scriptV212 from '../../blocks/native/sm.script/versions/2.1.2/package.js';
71
- import scriptV213 from '../../blocks/native/sm.script/versions/2.1.3/package.js';
72
- import scriptV214 from '../../blocks/native/sm.script/versions/2.1.4/package.js';
73
- import scriptV215 from '../../blocks/native/sm.script/versions/2.1.5/package.js';
74
43
  import generateVideo from '../../blocks/native/sm.generate-video/versions/2.0.0/package.js';
75
44
  import generateVideoV201 from '../../blocks/native/sm.generate-video/versions/2.0.1/package.js';
76
- import chat from '../../blocks/native/sm.chat/versions/2.0.0/package.js';
77
- import chatV201 from '../../blocks/native/sm.chat/versions/2.0.1/package.js';
78
- import chatV202 from '../../blocks/native/sm.chat/versions/2.0.2/package.js';
79
- import chatV203 from '../../blocks/native/sm.chat/versions/2.0.3/package.js';
80
45
  import character from '../../blocks/native/sm.character/versions/2.0.0/package.js';
81
46
  import characterV201 from '../../blocks/native/sm.character/versions/2.0.1/package.js';
82
47
  import location from '../../blocks/native/sm.location/versions/2.0.0/package.js';
83
48
  import locationV201 from '../../blocks/native/sm.location/versions/2.0.1/package.js';
84
49
  import style from '../../blocks/native/sm.style/versions/2.0.0/package.js';
85
50
  import styleV201 from '../../blocks/native/sm.style/versions/2.0.1/package.js';
86
- import research from '../../blocks/native/sm.research/versions/2.0.0/package.js';
87
- import researchV201 from '../../blocks/native/sm.research/versions/2.0.1/package.js';
88
- import researchV202 from '../../blocks/native/sm.research/versions/2.0.2/package.js';
89
- import imageEditor from '../../blocks/native/sm.image-editor/versions/2.0.0/package.js';
90
- import imageEditorV201 from '../../blocks/native/sm.image-editor/versions/2.0.1/package.js';
91
- import describeMedia from '../../blocks/native/sm.describe-media/versions/2.0.0/package.js';
92
- import describeMediaV201 from '../../blocks/native/sm.describe-media/versions/2.0.1/package.js';
93
51
  // October 29, 2026: StillMade credits stopped paying for image.describe on September 13, so Describe media 2.1.0
94
52
  // and Photo notes 1.1.0 run on media.analyze (credits, per image); the image.describe releases stay for exact pins.
95
- import describeMediaV210 from '../../blocks/native/sm.describe-media/versions/2.1.0/package.js';
96
53
  import videoAssets from '../../blocks/native/sm.video-assets/versions/2.0.0/package.js';
97
54
  import videoAssetsV210 from '../../blocks/native/sm.video-assets/versions/2.1.0/package.js';
98
55
  import videoAssetsV211 from '../../blocks/native/sm.video-assets/versions/2.1.1/package.js';
@@ -108,31 +65,9 @@ import finalEditV202 from '../../blocks/native/sm.final-edit/versions/2.0.2/pack
108
65
  import editAssistant from '../../blocks/native/sm.edit-assistant/versions/2.0.0/package.js';
109
66
  import editAssistantV201 from '../../blocks/native/sm.edit-assistant/versions/2.0.1/package.js';
110
67
  import editAssistantV202 from '../../blocks/native/sm.edit-assistant/versions/2.0.2/package.js';
111
- import transcribe from '../../blocks/native/sm.transcribe/versions/2.0.0/package.js';
112
- import transcribeV201 from '../../blocks/native/sm.transcribe/versions/2.0.1/package.js';
113
- import blueprint from '../../blocks/native/sm.blueprint/versions/2.0.0/package.js';
114
- import blueprintV210 from '../../blocks/native/sm.blueprint/versions/2.1.0/package.js';
115
- import blueprintV211 from '../../blocks/native/sm.blueprint/versions/2.1.1/package.js';
116
- import blueprintV212 from '../../blocks/native/sm.blueprint/versions/2.1.2/package.js';
117
- import blueprintV213 from '../../blocks/native/sm.blueprint/versions/2.1.3/package.js';
118
- import blueprintV214 from '../../blocks/native/sm.blueprint/versions/2.1.4/package.js';
119
- import blueprintV215 from '../../blocks/native/sm.blueprint/versions/2.1.5/package.js';
120
- import blueprintV216 from '../../blocks/native/sm.blueprint/versions/2.1.6/package.js';
121
- import blueprintV218 from '../../blocks/native/sm.blueprint/versions/2.1.8/package.js';
122
- import blueprintV219 from '../../blocks/native/sm.blueprint/versions/2.1.9/package.js';
123
- import blueprintV217 from '../../blocks/native/sm.blueprint/versions/2.1.7/package.js';
124
- import shotPlan from '../../blocks/native/sm.shot-plan/versions/2.0.0/package.js';
125
- import shotPlanV210 from '../../blocks/native/sm.shot-plan/versions/2.1.0/package.js';
126
- import shotPlanV211 from '../../blocks/native/sm.shot-plan/versions/2.1.1/package.js';
127
- import shotPlanV212 from '../../blocks/native/sm.shot-plan/versions/2.1.2/package.js';
128
- import shotPlanV213 from '../../blocks/native/sm.shot-plan/versions/2.1.3/package.js';
129
- import shotPlanV220 from '../../blocks/native/sm.shot-plan/versions/2.2.0/package.js';
130
- import shotPlanV221 from '../../blocks/native/sm.shot-plan/versions/2.2.1/package.js';
131
68
  import boardEditor from '../../blocks/native/sm.board-editor/versions/2.0.0/package.js';
132
69
  import panelStripV200 from '../../blocks/native/sm.panel-strip/versions/2.0.0/package.js';
133
70
  import panelStrip from '../../blocks/native/sm.panel-strip/versions/2.1.0/package.js';
134
- import animatedSceneV200 from '../../blocks/native/sm.animated-scene/versions/2.0.0/package.js';
135
- import animatedScene from '../../blocks/native/sm.animated-scene/versions/2.1.0/package.js';
136
71
  import editor from '../../blocks/native/sm.editor/versions/2.0.0/package.js';
137
72
  import pipelineV200 from '../../blocks/native/sm.pipeline/versions/2.0.0/package.js';
138
73
  import pipeline from '../../blocks/native/sm.pipeline/versions/2.1.0/package.js';
@@ -143,11 +78,6 @@ import pipelineV225 from '../../blocks/native/sm.pipeline/versions/2.2.5/package
143
78
  import pipelineV226 from '../../blocks/native/sm.pipeline/versions/2.2.6/package.js';
144
79
  import pipelineV224 from '../../blocks/native/sm.pipeline/versions/2.2.4/package.js';
145
80
  import pipelineV222 from '../../blocks/native/sm.pipeline/versions/2.2.2/package.js';
146
- import shotPlanAssistant from '../../blocks/native/sm.shot-plan-assistant/versions/1.0.0/package.js';
147
- import animatedSceneAssistant from '../../blocks/native/sm.animated-scene-assistant/versions/1.0.0/package.js';
148
- import whiteboardAssistant from '../../blocks/native/sm.whiteboard-assistant/versions/1.0.0/package.js';
149
- import qualityAudit from '../../blocks/native/sm.quality-audit/versions/1.0.0/package.js';
150
- import qualityAuditV101 from '../../blocks/native/sm.quality-audit/versions/1.0.1/package.js';
151
81
  import editorV210 from '../../blocks/native/sm.editor/versions/2.1.0/package.js';
152
82
  import editorV220 from '../../blocks/native/sm.editor/versions/2.2.0/package.js';
153
83
  import editorV221 from '../../blocks/native/sm.editor/versions/2.2.1/package.js';
@@ -183,24 +113,12 @@ import boardEditorV228 from '../../blocks/native/sm.board-editor/versions/2.2.8/
183
113
  import boardEditorV229 from '../../blocks/native/sm.board-editor/versions/2.2.9/package.js';
184
114
  import boardEditorV2210 from '../../blocks/native/sm.board-editor/versions/2.2.10/package.js';
185
115
  import boardEditorV2211 from '../../blocks/native/sm.board-editor/versions/2.2.11/package.js';
186
- import animatedSceneV220 from '../../blocks/native/sm.animated-scene/versions/2.2.0/package.js';
187
- import animatedSceneV230 from '../../blocks/native/sm.animated-scene/versions/2.3.0/package.js';
188
- import animatedSceneV231 from '../../blocks/native/sm.animated-scene/versions/2.3.1/package.js';
189
- import animatedSceneV232 from '../../blocks/native/sm.animated-scene/versions/2.3.2/package.js';
190
- import animatedSceneV233 from '../../blocks/native/sm.animated-scene/versions/2.3.3/package.js';
191
- import animatedSceneV234 from '../../blocks/native/sm.animated-scene/versions/2.3.4/package.js';
192
- import animatedSceneV235 from '../../blocks/native/sm.animated-scene/versions/2.3.5/package.js';
193
- import animatedSceneV236 from '../../blocks/native/sm.animated-scene/versions/2.3.6/package.js';
194
- import animatedSceneV237 from '../../blocks/native/sm.animated-scene/versions/2.3.7/package.js';
195
- import animatedSceneV238 from '../../blocks/native/sm.animated-scene/versions/2.3.8/package.js';
196
- import animatedSceneV239 from '../../blocks/native/sm.animated-scene/versions/2.3.9/package.js';
197
- import blueprintAssistant from '../../blocks/native/sm.blueprint-assistant/versions/1.0.0/package.js';
116
+
198
117
  import photoNotes from '../../blocks/native/sm.photo-notes/versions/1.0.0/package.js';
199
118
  import photoNotesV110 from '../../blocks/native/sm.photo-notes/versions/1.1.0/package.js';
200
- import pickPhotos from '../../blocks/native/sm.pick-photos/versions/1.0.0/package.js';
201
119
 
202
120
  // Exact, independently executable first-party releases. Host workspaces do not
203
121
  // belong here. Changing implementation requires a new immutable version.
204
122
  const freeze=value=>{if(value&&typeof value==='object'&&!Object.isFrozen(value)){Object.values(value).forEach(freeze);Object.freeze(value);}return value;};
205
- export const FIRST_PARTY_SDK_PACKAGES = Object.freeze([freeze(productAdVariants),freeze(pickPhotos),freeze(photoNotesV110),freeze(photoNotes),freeze(youtubePublication),freeze(stockSearch),freeze(exportVideoV210),freeze(exportVideo),freeze(exportAudio),freeze(motionGraphics),freeze(audioScore),freeze(shortFormFinish),freeze(screenRecorder),freeze(screenRecorderV100),freeze(narration),freeze(narrationV100),freeze(shortFormFinishV102),freeze(shortFormFinishV101),freeze(shortFormFinishV100),freeze(occasionStory),freeze(occasionStoryV101),freeze(occasionStoryV100),freeze(releaseVisuals),freeze(releaseVisualsV101),freeze(releaseVisualsV100),freeze(photoReelComposer),freeze(photoReelComposerV101),freeze(photoReelComposerV100),freeze(importMediaV202),freeze(importMediaV201),freeze(editorV2212),freeze(editorV2211),freeze(editorV2210),freeze(editorV229),freeze(editorV228),freeze(panelStripV242),freeze(panelStripV241),freeze(panelStripV240),freeze(panelStripV237),freeze(panelStripV236),freeze(boardEditorV2211),freeze(boardEditorV2210),freeze(boardEditorV229),freeze(animatedSceneV239),freeze(animatedSceneV238),freeze(animatedSceneV237),freeze(pipelineV226),freeze(pipelineV225),freeze(pipelineV224),freeze(blueprintV219),freeze(blueprintV218),freeze(videoAssetsV214),freeze(videoAssetsV213),freeze(chatV203),freeze(chatV202),freeze(chatV201),freeze(shotPlanV221),freeze(shotPlanV220),freeze(shotPlanV213),freeze(shotPlanV212),freeze(voiceoverV216),freeze(voiceoverV215),freeze(voiceoverV214),freeze(voiceoverV213),freeze(scriptV215),freeze(scriptV214),freeze(scriptV213),freeze(roughCutV202),freeze(roughCutV201),freeze(finalEditV202),freeze(finalEditV201),freeze(editAssistantV202),freeze(editAssistantV201),freeze(gradeV202),freeze(gradeV201),freeze(transitionV202),freeze(transitionV201),freeze(qualityAuditV102),freeze(qualityAuditV101),freeze(compareV202),freeze(compareV201),freeze(compare),freeze(grade),freeze(transition),freeze(exportTimeline),freeze(captions),freeze(importMedia),freeze(generateImageV210),freeze(generateImage),freeze(thumbnailV201),freeze(thumbnail),freeze(writeSummary),freeze(automationV110),freeze(automationWhen),freeze(automationNewItems),freeze(automationAiDecide),freeze(automationContinueIf),freeze(connectApp),freeze(automationContactFields),freeze(automationAiWrite),freeze(automationMetaCreative),freeze(voiceover),freeze(voiceoverV210),freeze(voiceoverV211),freeze(voiceoverV212),freeze(script),freeze(scriptV210),freeze(scriptV211),freeze(scriptV212),freeze(generateVideoV201),freeze(generateVideo),freeze(chat),freeze(characterV201),freeze(character),freeze(locationV201),freeze(location),freeze(styleV201),freeze(style),freeze(researchV202),freeze(researchV201),freeze(research),freeze(imageEditorV201),freeze(imageEditor),freeze(describeMediaV210),freeze(describeMediaV201),freeze(describeMedia),freeze(videoAssets),freeze(videoAssetsV210),freeze(videoAssetsV211),freeze(videoAssetsV212),freeze(roughCut),freeze(finalEdit),freeze(editAssistant),freeze(transcribeV201),freeze(transcribe),freeze(blueprint),freeze(blueprintV210),freeze(blueprintV211),freeze(blueprintV212),freeze(blueprintV213),freeze(blueprintV214),freeze(blueprintV215),freeze(blueprintV216),freeze(blueprintV217),freeze(shotPlan),freeze(shotPlanV210),freeze(shotPlanV211),freeze(boardEditor),freeze(boardEditorV210),freeze(boardEditorV220),freeze(boardEditorV221),freeze(boardEditorV222),freeze(boardEditorV223),freeze(boardEditorV224),freeze(boardEditorV225),freeze(boardEditorV226),freeze(boardEditorV227),freeze(boardEditorV228),freeze(panelStripV200),freeze(panelStrip),freeze(panelStripV220),freeze(panelStripV230),freeze(panelStripV231),freeze(panelStripV232),freeze(panelStripV233),freeze(panelStripV234),freeze(panelStripV235),freeze(animatedSceneV200),freeze(animatedScene),freeze(animatedSceneV220),freeze(animatedSceneV230),freeze(animatedSceneV231),freeze(animatedSceneV232),freeze(animatedSceneV233),freeze(animatedSceneV234),freeze(animatedSceneV235),freeze(animatedSceneV236),freeze(editor),freeze(editorV210),freeze(editorV220),freeze(editorV221),freeze(editorV222),freeze(editorV223),freeze(editorV224),freeze(editorV225),freeze(editorV226),freeze(editorV227),freeze(pipelineV200),freeze(pipeline),freeze(pipelineV220),freeze(pipelineV221),freeze(pipelineV223),freeze(pipelineV222),freeze(shotPlanAssistant),freeze(animatedSceneAssistant),freeze(blueprintAssistant),freeze(whiteboardAssistant),freeze(qualityAudit)]);
123
+ export const FIRST_PARTY_SDK_PACKAGES = Object.freeze([freeze(generate),freeze(photoNotesV110),freeze(photoNotes),freeze(exportVideoV210),freeze(exportVideo),freeze(exportAudio),freeze(motionGraphics),freeze(audioScore),freeze(importMediaV202),freeze(importMediaV201),freeze(editorV2212),freeze(editorV2211),freeze(editorV2210),freeze(editorV229),freeze(editorV228),freeze(panelStripV242),freeze(panelStripV241),freeze(panelStripV240),freeze(panelStripV237),freeze(panelStripV236),freeze(boardEditorV2211),freeze(boardEditorV2210),freeze(boardEditorV229),freeze(pipelineV226),freeze(pipelineV225),freeze(pipelineV224),freeze(videoAssetsV214),freeze(videoAssetsV213),freeze(voiceoverV216),freeze(voiceoverV215),freeze(voiceoverV214),freeze(voiceoverV213),freeze(roughCutV202),freeze(roughCutV201),freeze(finalEditV202),freeze(finalEditV201),freeze(editAssistantV202),freeze(editAssistantV201),freeze(gradeV202),freeze(gradeV201),freeze(transitionV202),freeze(transitionV201),freeze(compareV202),freeze(compareV201),freeze(compare),freeze(grade),freeze(transition),freeze(exportTimeline),freeze(captions),freeze(importMedia),freeze(generateImageV210),freeze(generateImage),freeze(writeSummary),freeze(automationV110),freeze(automationWhen),freeze(automationAiDecide),freeze(connectApp),freeze(automationContactFields),freeze(automationAiWrite),freeze(automationMetaCreative),freeze(voiceover),freeze(voiceoverV210),freeze(voiceoverV211),freeze(voiceoverV212),freeze(generateVideoV201),freeze(generateVideo),freeze(characterV201),freeze(character),freeze(locationV201),freeze(location),freeze(styleV201),freeze(style),freeze(videoAssets),freeze(videoAssetsV210),freeze(videoAssetsV211),freeze(videoAssetsV212),freeze(roughCut),freeze(finalEdit),freeze(editAssistant),freeze(boardEditor),freeze(boardEditorV210),freeze(boardEditorV220),freeze(boardEditorV221),freeze(boardEditorV222),freeze(boardEditorV223),freeze(boardEditorV224),freeze(boardEditorV225),freeze(boardEditorV226),freeze(boardEditorV227),freeze(boardEditorV228),freeze(panelStripV200),freeze(panelStrip),freeze(panelStripV220),freeze(panelStripV230),freeze(panelStripV231),freeze(panelStripV232),freeze(panelStripV233),freeze(panelStripV234),freeze(panelStripV235),freeze(editor),freeze(editorV210),freeze(editorV220),freeze(editorV221),freeze(editorV222),freeze(editorV223),freeze(editorV224),freeze(editorV225),freeze(editorV226),freeze(editorV227),freeze(pipelineV200),freeze(pipeline),freeze(pipelineV220),freeze(pipelineV221),freeze(pipelineV223),freeze(pipelineV222) ]);
206
124
  export const firstPartySdkPackage = manifest => FIRST_PARTY_SDK_PACKAGES.find(pkg => pkg.manifest.id === manifest?.id && pkg.manifest.version === manifest?.version);
@@ -64,10 +64,22 @@ export function imageSettings(value,{strict=false}={}){
64
64
  return {model,aspectRatio:axis('aspectRatio',entry.aspectRatios,entry.aspectRatios.includes('1:1')?'1:1':undefined),resolution:axis('resolution',entry.resolutions),quality:axis('quality',entry.qualities,entry.qualities.includes('medium')?'medium':undefined)};
65
65
  }
66
66
 
67
- /** Fill and check video settings, including Veo's 1080p-is-8-seconds rule. */
68
- export function videoSettings(value,{strict=false,firstFrame=false}={}){
67
+ // November 3, 2026: a listing Block asked for a 9:16 clip and named no model, and the default (Vidu Q3 Turbo) takes no
68
+ // aspect ratio. With no model named, a shape the default cannot make picks the cheapest model here that makes it and
69
+ // takes the frames and the duration asked (prices in server/services/tiers.js); a named model is always kept.
70
+ export const VIDEO_SHAPE_MODELS=Object.freeze(['wan-2.6-flash','veo-3.1-lite','seedance-2.0-mini','kling-v3-turbo','seedance-2.0-fast','seedance-2.0']);
71
+ function defaultVideoModel(raw,{firstFrame,lastFrame}){
72
+ const shape=raw.aspectRatio;
73
+ if(shape===undefined||shape===DEFAULT_SETTING||shape==='auto'||VIDEO_GENERATION_MODELS[DEFAULT_VIDEO_MODEL].aspectRatios.includes(shape))return DEFAULT_VIDEO_MODEL;
74
+ const fits=entry=>entry.aspectRatios.includes(shape)&&(firstFrame||!entry.requiresFirstFrame)&&(!lastFrame||entry.lastFrame)&&(raw.duration===undefined||entry.durations.includes(raw.duration));
75
+ return VIDEO_SHAPE_MODELS.find(model=>fits(VIDEO_GENERATION_MODELS[model]))??DEFAULT_VIDEO_MODEL;
76
+ }
77
+
78
+ /** Fill and check video settings, including Veo's 1080p-is-8-seconds rule. With no model named, the default model is
79
+ * the one that makes the asked aspect ratio (VIDEO_SHAPE_MODELS). */
80
+ export function videoSettings(value,{strict=false,firstFrame=false,lastFrame=false}={}){
69
81
  const raw=settingsObject(value,VIDEO_SETTING_KEYS,'Video');
70
- const model=raw.model??DEFAULT_VIDEO_MODEL,entry=VIDEO_GENERATION_MODELS[model];
82
+ const model=raw.model??defaultVideoModel(raw,{firstFrame,lastFrame}),entry=VIDEO_GENERATION_MODELS[model];
71
83
  assert(entry,'CAPABILITY_SETTINGS',`Choose a video model from: ${Object.keys(VIDEO_GENERATION_MODELS).join(', ')}`);
72
84
  const axis=(name,allowed,fallback)=>{
73
85
  const chosen=pick(allowed,raw[name],fallback);
@@ -278,7 +278,8 @@ export const GENERATION_LIMITS: Readonly<{references:8;negativePrompt:2000;seed:
278
278
  /** Fill and check image settings; `strict` rejects values the model does not accept. */
279
279
  export function imageSettings(value?:Partial<ImageSettings>,options?:{strict?:boolean}):ImageSettings;
280
280
  /** Fill and check video settings, including Veo's 1080p-is-8-seconds rule. */
281
- export function videoSettings(value?:Partial<VideoSettings>,options?:{strict?:boolean;firstFrame?:boolean}):VideoSettings;
281
+ /** With no model named, the default is the cheapest model that makes the asked aspect ratio and takes the frames given. */
282
+ export function videoSettings(value?:Partial<VideoSettings>,options?:{strict?:boolean;firstFrame?:boolean;lastFrame?:boolean}):VideoSettings;
282
283
  export function validateSeed(seed:number):number;
283
284
  export const MEDIA_GENERATE_LIMITS: Readonly<{items:50;prompt:4000}>;
284
285
  export const MEDIA_GENERATE_OPERATIONS: readonly ['image','video','speech','music','sfx'];
@@ -4,7 +4,7 @@ import {EXAMPLE_PROVENANCE} from './example-license.js';
4
4
  export const mediaAnalysis={
5
5
  manifest:{schemaVersion:1,sdkVersion:'0.1.0',id:'example.check-clip',action:{label:'Check clip',running:'Checking clip…'},version:'1.0.0',name:'Check a clip',description:'Answer a production question about a saved video clip, with timestamps.',kind:'task',runtime:'capability',entry:'src/capability.json',license:'MIT',provenance:EXAMPLE_PROVENANCE,
6
6
  inputs:{clip:{type:'video',primary:true,semantic:'source_video',required:true,description:'Saved video to check.'},start:{type:'number',required:false,min:0,semantic:'range_start',description:'Optional start of the range to look at closely, in seconds.'},end:{type:'number',required:false,min:0,semantic:'range_end',description:'Optional end of the range, in seconds (at most 12 seconds after the start).'}},
7
- outputs:{report:{type:'json',primary:true,semantic:'media_findings',description:'Summary, timeline, on-screen text and issues found.'}},
7
+ outputs:{report:{type:'json',primary:true,semantic:'media_findings',description:'Summary, timeline, on-screen text and issues found.',schema:{items:'json[]'}}},
8
8
  permissions:{project:[],capabilities:['media.analyze'],network:[],filesystem:[],secrets:[]},ui:[{control:'asset',port:'clip'},{control:'number',port:'start'},{control:'number',port:'end'}]},
9
9
  capability:{schemaVersion:1,operation:'media.analyze',media:{$input:'clip'},question:'Is the product logo clearly visible, and when? List any on-screen text and visible defects.',range:{start:{$input:'start'},end:{$input:'end'}},output:'report'},
10
10
  tests:[{name:'A saved clip',input:{clip:{kind:'video',assetId:'clip-1',versionId:'v1',url:'/api/media/owner/clip.mp4'}},expectations:{report:{kind:'json',includes:['summary']}}}],
@@ -13,6 +13,7 @@ import {createMemoryStorage,storageKey} from './cloud-storage.js';
13
13
  import {mediaTransformRequest,decodeWav} from './media-transform.js';
14
14
  import {FILE_FORMATS} from './data-values.js';
15
15
  import {mockPng,mockWav,mockMp4,MOCK_IMAGE_SIZE,MOCK_VIDEO_SIZE} from './mock-media.js';
16
+ import {videoSettings,audioSettings} from './generation-catalog.js';
16
17
  // The words of a simple PDF whose pages are uncompressed text, such as the example lesson.pdf, page by page; null for
17
18
  // anything else. StillMade reads real PDFs on the person's device; a local test of another PDF mocks document.text
18
19
  // (November 1, 2026: the stand-in read a PDF's own code as its words).
@@ -201,7 +202,12 @@ export function createMockHost({mocks:given={},readLocalFile,manifest,pickedMedi
201
202
  const operation=action?.operation;
202
203
  if(recorded('actions',operation)){note('actions.run',operation,'mocks');return pick(mocks.actions[operation],count(`action:${operation}`));}
203
204
  note('actions.run',operation,'recorded');
204
- if(operation==='media.generate')return {value:action.request.items.map(item=>{const made=reference[item.operation==='image'||item.operation==='video'?item.operation:'audio']();return {key:item.key,kind:made.kind,assetId:made.assetId,versionId:made.versionId,url:made.url};}),failures:[]};
205
+ // As in StillMade: a video, music or sound effect carries the length it asked for; speech carries none (decode it).
206
+ if(operation==='media.generate')return {value:action.request.items.map(item=>{
207
+ const seconds=item.operation==='video'?videoSettings(item.settings,{firstFrame:item.firstFrame!==undefined,lastFrame:item.lastFrame!==undefined}).duration:['music','sfx'].includes(item.operation)?audioSettings(item.operation,item.settings).durationSec:undefined;
208
+ const made=item.operation==='image'||item.operation==='video'?reference[item.operation]():reference.audio(seconds?{seconds,sampleRate:8000}:undefined);
209
+ return {key:item.key,kind:made.kind,assetId:made.assetId,versionId:made.versionId,url:made.url,...(Number.isFinite(seconds)?{duration:seconds}:{})};
210
+ }),failures:[]};
205
211
  if(operation==='stock.search')return {results:[]};
206
212
  fail(`There is no recorded stand-in for the ${operation} action. Add one under actions["${operation}"] in ${MOCKS_FILE}.`);
207
213
  },
@@ -4,20 +4,45 @@
4
4
  import {networkDeclarations,networkRequest,connectionDeclarations,connectionCall} from './network.js';
5
5
  import {storageHostHandlers} from './cloud-storage.js';
6
6
  import {projectReadSnapshot} from './context.js';
7
+ import {mediaReferences,moduleMediaAccess,MEDIA_RESULT_OPERATIONS} from './module-media-access.js';
7
8
 
8
- /** {api: args => Promise} for one run of `pkg` against `host` (see createNodeModuleExecutor). */
9
- export function moduleHostCalls(pkg,host,storage){
9
+ /**
10
+ * {api: args => Promise} for one run of `pkg` against `host` (see createNodeModuleExecutor). `input` is the run's input:
11
+ * files, transforms, actions, hosted calls and asset changes use only files the run received or the host made in it,
12
+ * the rule StillMade's own host applies (module-media-access.js).
13
+ */
14
+ export function moduleHostCalls(pkg,host,storage,input){
15
+ const access=moduleMediaAccess(input);
16
+ const made=async pending=>access.remember(await pending);
10
17
  return {
11
- 'files.read':args=>host.readFile?host.readFile(args.ref):Promise.reject(Object.assign(new Error('files.read needs a host file reader in local runs.'),{code:'MODULE_HOST_UNAVAILABLE'})),
12
- 'files.write':args=>host.writeFile?host.writeFile(args.buffer,args.options):Promise.reject(Object.assign(new Error('files.write saves to the StillMade library; pass a host writer in local runs.'),{code:'MODULE_HOST_UNAVAILABLE'})),
13
- 'media.transform':args=>host.transformMedia?host.transformMedia(args.request):Promise.reject(Object.assign(new Error('Media transforms run in StillMade; pass a host transformMedia in local runs.'),{code:'MODULE_HOST_UNAVAILABLE'})),
14
- 'actions.run':args=>host.runAction?host.runAction(args.action):Promise.reject(Object.assign(new Error('Actions run in StillMade.'),{code:'MODULE_HOST_UNAVAILABLE'})),
15
- 'hosted.run':args=>host.runHosted?host.runHosted(args.operation,args.request):Promise.reject(Object.assign(new Error('Hosted operations run in StillMade.'),{code:'MODULE_HOST_UNAVAILABLE'})),
18
+ 'files.read':async args=>{access.checkFile(args.ref,'files.read reads');return host.readFile?host.readFile(args.ref):Promise.reject(Object.assign(new Error('files.read needs a host file reader in local runs.'),{code:'MODULE_HOST_UNAVAILABLE'}));},
19
+ 'files.write':args=>host.writeFile?made(host.writeFile(args.buffer,args.options)):Promise.reject(Object.assign(new Error('files.write saves to the StillMade library; pass a host writer in local runs.'),{code:'MODULE_HOST_UNAVAILABLE'})),
20
+ 'media.transform':async args=>{access.check(args.request,'Media transforms');return host.transformMedia?made(host.transformMedia(args.request)):Promise.reject(Object.assign(new Error('Media transforms run in StillMade; pass a host transformMedia in local runs.'),{code:'MODULE_HOST_UNAVAILABLE'}));},
21
+ 'actions.run':async args=>{
22
+ access.check(args.action,'Actions');
23
+ if(!host.runAction)throw Object.assign(new Error('Actions run in StillMade.'),{code:'MODULE_HOST_UNAVAILABLE'});
24
+ const result=await host.runAction(args.action);
25
+ if(args.action?.operation==='media.generate')for(const ref of mediaReferences(result?.value))access.remember(ref);
26
+ return result;
27
+ },
28
+ 'hosted.run':async args=>{
29
+ access.check(args.request,'Hosted operations');
30
+ if(!host.runHosted)throw Object.assign(new Error('Hosted operations run in StillMade.'),{code:'MODULE_HOST_UNAVAILABLE'});
31
+ const result=await host.runHosted(args.operation,args.request);
32
+ return MEDIA_RESULT_OPERATIONS.includes(args.operation)?access.remember(result):result;
33
+ },
16
34
  'connections.call':async args=>{const request=connectionCall(args.request,connectionDeclarations(pkg.manifest.permissions?.connections));return host.callConnection?host.callConnection(request):Promise.reject(Object.assign(new Error('Connections run through StillMade, which adds your account; pass a host callConnection in local runs.'),{code:'MODULE_HOST_UNAVAILABLE'}));},
17
35
  ...storageHostHandlers(storage),
18
- 'project.read':async args=>{if(!host.project)throw Object.assign(new Error('project.read needs a project snapshot; pass host.project in local runs.'),{code:'MODULE_HOST_UNAVAILABLE'});return projectReadSnapshot(pkg.manifest,host.project,args.fields);},
19
- 'assets.create':async args=>{if(!(pkg.manifest.permissions?.project||[]).includes('asset.create'))throw Object.assign(new Error('Declare asset.create to add project assets.'),{code:'MODULE_PERMISSION'});return host.createAsset?host.createAsset(args.file,args.options||{}):Promise.reject(Object.assign(new Error('Project assets are saved in StillMade; pass a host createAsset in local runs.'),{code:'MODULE_HOST_UNAVAILABLE'}));},
20
- 'assets.appendVersion':async args=>{if(!(pkg.manifest.permissions?.project||[]).includes('asset.version.append'))throw Object.assign(new Error('Declare asset.version.append to add asset versions.'),{code:'MODULE_PERMISSION'});return host.appendAssetVersion?host.appendAssetVersion(args.asset,args.file):Promise.reject(Object.assign(new Error('Project assets are saved in StillMade; pass a host appendAssetVersion in local runs.'),{code:'MODULE_HOST_UNAVAILABLE'}));},
36
+ // Only the host-built media indexes make media usable, as in StillMade: free-form documents can hold media-shaped values.
37
+ 'project.read':async args=>{
38
+ if(!host.project)throw Object.assign(new Error('project.read needs a project snapshot; pass host.project in local runs.'),{code:'MODULE_HOST_UNAVAILABLE'});
39
+ const snapshot=projectReadSnapshot(pkg.manifest,host.project,args.fields);
40
+ for(const field of ['assets','files'])for(const ref of mediaReferences(snapshot[field]))access.add(ref);
41
+ for(const shot of Array.isArray(snapshot.shots)?snapshot.shots:[])if(shot?.selectedImage)access.remember(shot.selectedImage);
42
+ return snapshot;
43
+ },
44
+ 'assets.create':async args=>{if(!(pkg.manifest.permissions?.project||[]).includes('asset.create'))throw Object.assign(new Error('Declare asset.create to add project assets.'),{code:'MODULE_PERMISSION'});access.checkFile(args.file,'assets.create adds');return host.createAsset?made(host.createAsset(args.file,args.options||{})):Promise.reject(Object.assign(new Error('Project assets are saved in StillMade; pass a host createAsset in local runs.'),{code:'MODULE_HOST_UNAVAILABLE'}));},
45
+ 'assets.appendVersion':async args=>{if(!(pkg.manifest.permissions?.project||[]).includes('asset.version.append'))throw Object.assign(new Error('Declare asset.version.append to add asset versions.'),{code:'MODULE_PERMISSION'});access.checkFile(args.file,'assets.appendVersion adds');return host.appendAssetVersion?made(host.appendAssetVersion(args.asset,args.file)):Promise.reject(Object.assign(new Error('Project assets are saved in StillMade; pass a host appendAssetVersion in local runs.'),{code:'MODULE_HOST_UNAVAILABLE'}));},
21
46
  'net.fetch':async args=>{const request=networkRequest(args.request,networkDeclarations(pkg.manifest.permissions?.network));return host.netFetch?host.netFetch(request):Promise.reject(Object.assign(new Error('Network calls run through StillMade, which adds your key; pass a host netFetch in local runs.'),{code:'MODULE_HOST_UNAVAILABLE'}));},
22
47
  };
23
48
  }
@@ -5,7 +5,7 @@
5
5
  // operation in `permissions.capabilities`.
6
6
  import {assert,plain,stableStringify} from './contracts.js';
7
7
  import {defaultCapabilityExpectations,MEDIA_ANALYZE_LIMITS} from './capabilities.js';
8
- import {GENERATION_LIMITS,IMAGE_GENERATION_MODELS} from './generation-catalog.js';
8
+ import {GENERATION_LIMITS,IMAGE_GENERATION_MODELS,VIDEO_GENERATION_MODELS} from './generation-catalog.js';
9
9
 
10
10
  const text=(value,max)=>typeof value==='string'&&value.trim().length>0&&value.length<=max;
11
11
  const media=(value,kind)=>plain(value)&&value.kind===kind&&['assetId','versionId','url'].every(key=>typeof value[key]==='string'&&value[key].trim());
@@ -32,7 +32,20 @@ const SHAPES={
32
32
  },
33
33
  'video.generate':request=>{
34
34
  if(!text(request.prompt,32000))fail('video.generate needs a prompt');
35
- return {inputs:{prompt:port('text','Video prompt')},outputs:{result:port('video','Generated video')},capability:{prompt:{$input:'prompt'},output:'result',...(request.settings?{settings:request.settings}:{})},input:{prompt:request.prompt}};
35
+ // firstFrame and lastFrame: saved images the video starts and ends on, bound as a capability Block binds them; and the
36
+ // negativePrompt (November 3, 2026: they were dropped, so a listing video's camera move over each photo was made from
37
+ // the words alone, and the stand-in host passed it).
38
+ const {firstFrame,lastFrame,negativePrompt}=request;
39
+ for(const [name,frame] of [['firstFrame',firstFrame],['lastFrame',lastFrame]])if(frame!==undefined&&!media(frame,'image'))fail(`video.generate ${name} is one saved image`);
40
+ if(lastFrame!==undefined&&firstFrame===undefined)fail('video.generate lastFrame needs a firstFrame');
41
+ if(negativePrompt!==undefined&&!(typeof negativePrompt==='string'&&negativePrompt.length<=GENERATION_LIMITS.negativePrompt))fail(`video.generate negativePrompt is text of at most ${GENERATION_LIMITS.negativePrompt.toLocaleString('en-US')} characters`);
42
+ // A model named in settings must take those frames (every model takes a first frame; Kling 3.0 Turbo and Wan 2.6 Flash
43
+ // take no last frame; Wan 2.6 Flash and Wan 2.7 need a first frame).
44
+ const model=VIDEO_GENERATION_MODELS[request.settings?.model];
45
+ if(model&&firstFrame&&!model.firstFrame)fail(`${model.label} takes no first frame: choose a model that does, or leave the model to the person`);
46
+ if(model&&lastFrame&&!model.lastFrame)fail(`${model.label} takes no last frame: choose a model that does, or leave the model to the person`);
47
+ if(model?.requiresFirstFrame&&!firstFrame)fail(`${model.label} needs a firstFrame`);
48
+ return {inputs:{prompt:port('text','Video prompt'),...(firstFrame?{firstFrame:port('image','First frame')}:{}),...(lastFrame?{lastFrame:port('image','Last frame')}:{})},outputs:{result:port('video','Generated video')},capability:{prompt:{$input:'prompt'},output:'result',...(firstFrame?{firstFrame:{$input:'firstFrame'}}:{}),...(lastFrame?{lastFrame:{$input:'lastFrame'}}:{}),...(request.settings?{settings:request.settings}:{}),...(negativePrompt?{negativePrompt}:{})},input:{prompt:request.prompt,...(firstFrame?{firstFrame}:{}),...(lastFrame?{lastFrame}:{})}};
36
49
  },
37
50
  'audio.speech':request=>{
38
51
  if(!text(request.text,3800))fail('audio.speech needs text of up to 3,800 characters');
@@ -0,0 +1,71 @@
1
+ // Which saved files a module Block may use in one run: the references it
2
+ // received as input, and those the host made during the run (files it wrote,
3
+ // transform results, generated media, project media it read). files.read,
4
+ // transforms, actions, hosted calls and project asset changes use only these.
5
+ // StillMade's browser host (client/src/blocks/moduleRuntimeHost.js) and the
6
+ // SDK's local runners (module-host-calls.js: `test --mock`, `ready`, `gate`,
7
+ // and the QuickJS runner for Blocks built in StillMade) apply this one rule, so
8
+ // a Block gets the same verdict on a creator's machine and in the import review.
9
+ import {stableStringify} from './contracts.js';
10
+
11
+ const fail=(message,code)=>Object.assign(new Error(message),{code});
12
+ export const MODULE_MEDIA_KINDS=Object.freeze(['image','video','audio','asset','file']);
13
+ // Hosted operations whose result is media the host generated and checked.
14
+ export const MEDIA_RESULT_OPERATIONS=Object.freeze(['image.generate','video.generate','audio.speech','audio.music','audio.sfx']);
15
+ // A reference names its file by these fields. Its other fields describe the
16
+ // file (a media.generate item's key, a duration, a name) and may be dropped or
17
+ // added (November 3, 2026: a listing video Block rebuilt each generated clip as
18
+ // {kind, assetId, versionId, url}, without the result item's `key`, and every
19
+ // render was refused although the clips were generated in that run).
20
+ export const MEDIA_REFERENCE_FIELDS=Object.freeze(['kind','assetId','versionId','url']);
21
+ const isReference=value=>MODULE_MEDIA_KINDS.includes(value.kind)&&(typeof value.url==='string'||typeof value.assetId==='string');
22
+
23
+ /**
24
+ * Saved references in a value: anything shaped like media (a media kind with a
25
+ * url or assetId), at any depth. With `strict`, a value too large to inspect is
26
+ * refused. With `within`, the other fields of a reference are searched too, so
27
+ * a reference cannot carry another file past the check.
28
+ */
29
+ export function mediaReferences(input,{strict=false,within=false}={}){
30
+ const found=[];let visited=0;
31
+ const visit=(value,depth)=>{
32
+ if(!value||typeof value!=='object'||value instanceof ArrayBuffer||ArrayBuffer.isView(value))return;
33
+ if(++visited>20000||depth>16){if(strict)throw fail('This request is too large or too deeply nested to check.','MODULE_HOST');return;}
34
+ if(Array.isArray(value)){for(const item of value)visit(item,depth+1);return;}
35
+ if(isReference(value)){
36
+ found.push(value);
37
+ if(within)for(const [key,item] of Object.entries(value))if(!MEDIA_REFERENCE_FIELDS.includes(key))visit(item,depth+1);
38
+ return;
39
+ }
40
+ for(const item of Object.values(value))visit(item,depth+1);
41
+ };
42
+ visit(input,0);return found;
43
+ }
44
+
45
+ /** The file a reference names, as a comparable string. */
46
+ export function mediaReferenceKey(ref){
47
+ return stableStringify(MEDIA_REFERENCE_FIELDS.map(key=>typeof ref?.[key]==='string'?ref[key]:null));
48
+ }
49
+
50
+ const RULE='this Block received, wrote or generated in this run';
51
+ const FIX='Pass the reference the Block received as input, or the one StillMade returned in this run (files.write, a transform, hosted.run or actions.run media.generate), keeping its kind, assetId, versionId and url.';
52
+
53
+ /**
54
+ * The run's usable files, starting from its input. `remember` adds a value the
55
+ * host made when the value is itself a reference (a text, JSON or web result
56
+ * can contain media-shaped values chosen by a model or a web page, so only
57
+ * references the host returned count); `add` adds a reference the host
58
+ * vouches for (project media it read). The checks throw MODULE_FILE_READ.
59
+ */
60
+ export function moduleMediaAccess(input){
61
+ const usable=new Set(mediaReferences(input).map(mediaReferenceKey));
62
+ const allowed=ref=>!!ref&&typeof ref==='object'&&usable.has(mediaReferenceKey(ref));
63
+ return {
64
+ allowed,
65
+ add(ref){usable.add(mediaReferenceKey(ref));},
66
+ remember(value){if(value&&typeof value==='object'&&mediaReferences(value)[0]===value)usable.add(mediaReferenceKey(value));return value;},
67
+ // Every reference in a request, and inside its references, must be usable.
68
+ check(value,what){if(!mediaReferences(value,{strict:true,within:true}).every(allowed))throw fail(`${what} use only files ${RULE}. ${FIX}`,'MODULE_FILE_READ');},
69
+ checkFile(ref,call){if(!allowed(ref))throw fail(`${call} only files ${RULE}. ${FIX}`,'MODULE_FILE_READ');},
70
+ };
71
+ }
@@ -43,7 +43,7 @@ export function createNodeModuleExecutor({files,host={},onProgress,onLog,now=()=
43
43
  try{declared=networkDeclarations(pkg.manifest.permissions?.network);}catch{/* no valid origins */}
44
44
  const sockets=createModuleSockets({declarations:declared,open:host.netConnect,post:(message,transfer)=>worker.postMessage(message,transfer)});
45
45
  // The shared host calls (files, media, hosted operations, connections, storage, project, assets, net.fetch) plus live connections.
46
- const handlers={...sockets.handlers,...moduleHostCalls(pkg,host,storage)};
46
+ const handlers={...sockets.handlers,...moduleHostCalls(pkg,host,storage,input)};
47
47
  try{
48
48
  return await new Promise((resolve,reject)=>{
49
49
  const stop=error=>{clearInterval(timer);reject(error);};
@@ -37,7 +37,7 @@ export function mediaGenerateRequest(request){
37
37
  if(item.references!==undefined)assert(Array.isArray(item.references)&&item.references.length>0&&item.references.length<=Math.min(GENERATION_LIMITS.references,IMAGE_GENERATION_MODELS[settings.model].references)&&item.references.every(asset),'PORTABLE_ACTION',`${IMAGE_GENERATION_MODELS[settings.model].label} accepts up to ${IMAGE_GENERATION_MODELS[settings.model].references} saved reference images.`);
38
38
  }else{
39
39
  assert(item.references===undefined,'PORTABLE_ACTION','References apply to image items; use firstFrame and lastFrame for video.');
40
- const settings=videoSettings(item.settings,{strict:true,firstFrame:item.firstFrame!==undefined}),entry=VIDEO_GENERATION_MODELS[settings.model];
40
+ const settings=videoSettings(item.settings,{strict:true,firstFrame:item.firstFrame!==undefined,lastFrame:item.lastFrame!==undefined}),entry=VIDEO_GENERATION_MODELS[settings.model];
41
41
  if(item.firstFrame!==undefined)assert(entry.firstFrame&&asset(item.firstFrame),'PORTABLE_ACTION',`${entry.label} needs a saved image as its first frame.`);
42
42
  if(item.lastFrame!==undefined)assert(entry.lastFrame&&item.firstFrame!==undefined&&asset(item.lastFrame),'PORTABLE_ACTION',`${entry.label} cannot use this last frame.`);
43
43
  }
@@ -58,7 +58,7 @@ export async function runPackageAsync(pkg, values, options = {}) {
58
58
  // A module runs only through an injected executor: StillMade's sandboxed
59
59
  // browser Worker, or the CLI's local Node worker for the creator's own tests.
60
60
  const pinned=structuredClone(pkg),input=validateValues(pinned.manifest.inputs,values);
61
- assert(typeof options.module==='function','RUNTIME_UNAVAILABLE','Module Blocks run in StillMade in the browser, or locally with the SDK CLI. They cannot run unattended: StillMade has no server sandbox for module Blocks.');
61
+ assert(typeof options.module==='function','RUNTIME_UNAVAILABLE','Module Blocks run in StillMade in the browser, or on your own machine with the SDK CLI (test, preview and pack for a Block or a Project Type, and ready for a Block), which passes them a local module executor; code calling the SDK directly passes options.module (createNodeModuleExecutor in module-node.js). They cannot run unattended: StillMade has no server sandbox for module Blocks.');
62
62
  const result=await executeHostCall(structuredClone(pinned),input,{signal:options.signal,execute:options.module});
63
63
  assert(!options.signal?.aborted,'CANCELLED','Run cancelled');
64
64
  assert(result&&typeof result==='object'&&Object.keys(result).every(key=>['outputs','logs'].includes(key)),'MODULE_RESULT','The module host returned an unexpected result');
@@ -1,7 +1,7 @@
1
1
  import {EXAMPLE_PROVENANCE} from './example-license.js';
2
2
 
3
3
  export const timelinePolish={
4
- manifest:{schemaVersion:1,sdkVersion:'0.1.0',id:'example.timeline-polish',action:{label:'Suggest edit',running:'Suggesting edit…'},version:'1.0.0',name:'Timeline polish',description:'Turn a timeline and editing direction into a bounded proposal that remains reviewable before Apply.',kind:'task',runtime:'capability',entry:'src/capability.json',license:'MIT',provenance:EXAMPLE_PROVENANCE,inputs:{timeline:{type:'timeline',context:'timeline',primary:true},direction:{type:'text',default:'Polish this cut conservatively.'}},outputs:{edit:{type:'timeline-edit',primary:true}},permissions:{project:['context.timeline.read','timeline.propose'],capabilities:['timeline.propose'],network:[],filesystem:[],secrets:[]},ui:[{control:'text',port:'direction'}]},
4
+ manifest:{schemaVersion:1,sdkVersion:'0.1.0',id:'example.timeline-polish',action:{label:'Suggest edit',running:'Suggesting edit…'},version:'1.0.0',name:'Timeline polish',description:'Turn a timeline and editing direction into a bounded proposal that remains reviewable before Apply.',kind:'task',runtime:'capability',entry:'src/capability.json',license:'MIT',provenance:EXAMPLE_PROVENANCE,inputs:{timeline:{type:'timeline',context:'timeline',primary:true,required:true,semantic:'edit_timeline',description:'The cut to improve.'},direction:{type:'text',default:'Polish this cut conservatively.',required:false,semantic:'edit_direction',description:'How to change the cut, in a sentence.'}},outputs:{edit:{type:'timeline-edit',primary:true,semantic:'timeline_edit',description:'The proposed changes to review before they apply.'}},permissions:{project:['context.timeline.read','timeline.propose'],capabilities:['timeline.propose'],network:[],filesystem:[],secrets:[]},ui:[{control:'text',port:'direction'}]},
5
5
  capability:{schemaVersion:1,operation:'timeline.propose',context:{timeline:{$input:'timeline'},direction:{$input:'direction'}},instruction:'Use only supported timeline-edit commands, exact before snapshots, and the current activeTimelineId. Preserve media and locked items. Return strict JSON only.',maxTokens:2000,output:'edit'},
6
6
  tests:[{name:'one restrained edit',input:{timeline:{schemaVersion:1,activeTimelineId:'timeline-1',tracks:[{id:'video'}],clips:[{id:'clip-1',trackId:'video',start:0,duration:4}],audioItems:[],captions:[]},direction:'Add a soft transition.'},expectations:{edit:{kind:'timeline-edit',minCommands:1,maxCommands:10}}}],
7
7
  };
@@ -1,7 +1,7 @@
1
1
  import {EXAMPLE_PROVENANCE} from './example-license.js';
2
2
 
3
3
  export const audioTranscription={
4
- manifest:{schemaVersion:1,sdkVersion:'0.1.0',id:'example.transcribe-audio',action:{label:'Transcribe audio',running:'Transcribing…'},version:'1.0.0',name:'Transcribe audio',description:'Turn one persistent audio file into reviewed text with word timings.',kind:'task',runtime:'capability',entry:'src/capability.json',license:'MIT',provenance:EXAMPLE_PROVENANCE,inputs:{audio:{type:'audio',primary:true},language:{type:'text',default:'auto'}},outputs:{transcript:{type:'transcript',primary:true}},permissions:{project:[],capabilities:['audio.transcribe'],network:[],filesystem:[],secrets:[]},ui:[{control:'asset',port:'audio'},{control:'select',port:'language',options:['auto','en','es','fr','de','it','pt','ja','ko','zh']}]},
4
+ manifest:{schemaVersion:1,sdkVersion:'0.1.0',id:'example.transcribe-audio',action:{label:'Transcribe audio',running:'Transcribing…'},version:'1.0.0',name:'Transcribe audio',description:'Turn one persistent audio file into reviewed text with word timings.',kind:'task',runtime:'capability',entry:'src/capability.json',license:'MIT',provenance:EXAMPLE_PROVENANCE,inputs:{audio:{type:'audio',primary:true,required:true,semantic:'source_audio',description:'The recording to turn into text.'},language:{type:'text',default:'auto',required:false,semantic:'language_code',description:'auto, or a two-letter language code such as en.'}},outputs:{transcript:{type:'transcript',primary:true,semantic:'timed_transcript',description:'The spoken words with their timings.'}},permissions:{project:[],capabilities:['audio.transcribe'],network:[],filesystem:[],secrets:[]},ui:[{control:'asset',port:'audio'},{control:'select',port:'language',options:['auto','en','es','fr','de','it','pt','ja','ko','zh']}]},
5
5
  capability:{schemaVersion:1,operation:'audio.transcribe',audio:{$input:'audio'},language:{$input:'language'},output:'transcript'},
6
6
  tests:[{name:'timed speech',input:{audio:{kind:'audio',assetId:'audio-1',versionId:'version-1',url:'/api/media/example/audio.mp3',mimeType:'audio/mpeg'},language:'en'},expectations:{transcript:{kind:'transcript',minWords:1,maxWords:1000}}}]
7
7
  };
@@ -2,7 +2,7 @@ import {EXAMPLE_PROVENANCE} from './example-license.js';
2
2
  // Declarative request; the host chooses provider, model, duration, payment and
3
3
  // storage. This fixture is executed only after explicit host approval.
4
4
  export const videoGenerate={
5
- manifest:{schemaVersion:1,id:'example.generate-video',action:{label:'Generate video',running:'Generating video…'},name:'Generate video',version:'1.0.0',sdkVersion:'0.1.0',description:'Turn a production prompt into a short video using an approved host provider.',kind:'task',runtime:'capability',entry:'src/capability.json',license:'MIT',provenance:EXAMPLE_PROVENANCE,inputs:{prompt:{type:'text',primary:true,required:true}},outputs:{video:{type:'video',primary:true}},permissions:{project:[],capabilities:['video.generate'],network:[],filesystem:[],secrets:[]},ui:[{port:'prompt',control:'text'}]},
5
+ manifest:{schemaVersion:1,id:'example.generate-video',action:{label:'Generate video',running:'Generating video…'},name:'Generate video',version:'1.0.0',sdkVersion:'0.1.0',description:'Turn a production prompt into a short video using an approved host provider.',kind:'task',runtime:'capability',entry:'src/capability.json',license:'MIT',provenance:EXAMPLE_PROVENANCE,inputs:{prompt:{type:'text',primary:true,required:true,semantic:'video_prompt',description:'What the clip shows: subject, action, setting and camera, in a sentence or two.'}},outputs:{video:{type:'video',primary:true,semantic:'generated_video',description:'The generated clip.'}},permissions:{project:[],capabilities:['video.generate'],network:[],filesystem:[],secrets:[]},ui:[{port:'prompt',control:'text'}]},
6
6
  capability:{schemaVersion:1,operation:'video.generate',prompt:{$input:'prompt'},output:'video'},
7
7
  tests:[{name:'Produces a bounded MP4 sample',input:{prompt:'A paper boat floating across a calm blue pond. Gentle camera movement.'},expectations:{video:{kind:'video',format:'mp4',minDuration:1,maxDuration:60,minBytes:32,maxBytes:67108864,minWidth:1,maxWidth:3840,minHeight:1,maxHeight:3840}}}],
8
8
  };
@@ -11,7 +11,10 @@ export const VIEW_BRIDGE=Object.freeze([
11
11
  // Inputs and runs
12
12
  {name:'input',group:'Inputs and runs',signature:'readonly input: Partial<In>',summary:'A copy of the current input values. Read it after `onInput` first fires.',where:all},
13
13
  {name:'onInput',group:'Inputs and runs',signature:'onInput(callback: (input: Partial<In>) => void): () => void',summary:'Receives the input when the view starts and each time the host changes it. Returns a function that stops listening. Initialize controls here.',where:all},
14
- {name:'run',group:'Inputs and runs',signature:'run(values: In): Promise<Out>',summary:'Checks the named input values, runs the Block (its recipe, JavaScript, module or hosted operation, after any approval the host asks for) and resolves to the checked outputs. One run at a time, 30 a minute.',where:all},
14
+ {name:'addFiles',group:'Inputs and runs',signature:'addFiles(port: string): Promise<{added: number}>',summary:'Opens StillMade\'s own file picker for a declared `image`, `video`, `audio`, `asset` or `file` input (or a list of them) and saves what the person chooses through StillMade\'s upload, as the Step\'s own tiles do. Call it from a click or key press in the view; a list gets the files added, a single input the first. The saved values arrive through `onInput`; the view never receives a File. A `<button class="sm-add" data-stillmade-add="port">` does this with no code. Refused for an undeclared or non-file input, an input an earlier Step fills, a viewer, and without a gesture.',where:`${saved} and the SDK preview`},
15
+ {name:'removeFile',group:'Inputs and runs',signature:'removeFile(port: string, index: number): Promise<{files: number}>',summary:'Removes the file at `index` (from 0) of a declared list input (`image[]`, `video[]`, `audio[]`, `asset[]` or `file[]`), as the remove button on the Step\'s own tile does, and resolves to how many files the list now holds. Call it from a click or key press in the view; the new list arrives through `onInput`. A `<button data-stillmade-remove="port" data-index="2">` does this with no code. Refused for an undeclared, non-file or single input, an input an earlier Step fills, a viewer, Chat, a file that changed since the view was given it, and without a gesture.',where:`${saved} and the SDK preview`},
16
+ {name:'moveFile',group:'Inputs and runs',signature:'moveFile(port: string, from: number, to: number): Promise<{files: number}>',summary:'Moves the file at `from` to the place `to` (both from 0) in a declared list input, as the Step\'s own move earlier and move later buttons do, so the person sets the order (a tour, a slideshow) on the Block\'s own screen. Same gesture and refusals as `removeFile`. A `<button data-stillmade-move="port" data-index="2" data-to="1">` does this with no code; a `data-to` past either end does nothing.',where:`${saved} and the SDK preview`},
17
+ {name:'run',group:'Inputs and runs',signature:'run(values: In): Promise<Out>',summary:'Checks the named input values, runs the Block (its recipe, JavaScript, module or hosted operation, after any approval the host asks for) and resolves to the checked outputs. On a project Step and in the SDK preview, inputs it leaves out run with the Step\'s current values (its photos, an earlier Step\'s result), so a view passes only what it sets; what it passes is kept as the Step\'s input. One run at a time, 30 a minute.',where:all},
15
18
  {name:'useOutput',group:'Inputs and runs',signature:'useOutput(outputs: Partial<Out>): Promise<Record<string, unknown>>',summary:'Chooses media the view already holds (input media or a desktop recording) as the Block outputs without running. Only complete references the host issued are accepted.',where:saved},
16
19
  {name:'schemaFields',group:'Inputs and runs',signature:'readonly schemaFields: Readonly<Record<string, unknown>>',summary:'Helpers that build form fields from the input ports and their schemas, honoring inputs the host locked.',where:all},
17
20
  // Shared state