@hypit/hypit 0.0.1 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (961) hide show
  1. package/LICENSE +26 -0
  2. package/README.md +142 -0
  3. package/bin/hypit.mjs +46 -0
  4. package/dist/public/artifact.d.ts +75 -0
  5. package/dist/public/author-kit.d.ts +559 -0
  6. package/dist/public/browser-capture.d.ts +56 -0
  7. package/dist/public/caption.d.ts +751 -0
  8. package/dist/public/composition.d.ts +672 -0
  9. package/dist/public/endpoint-kit.d.ts +366 -0
  10. package/dist/public/generation.d.ts +591 -0
  11. package/dist/public/hyperframes.d.ts +774 -0
  12. package/dist/public/media.d.ts +708 -0
  13. package/dist/public/model-kit.d.ts +523 -0
  14. package/dist/public/narrative.d.ts +315 -0
  15. package/dist/public/program-space.d.ts +193 -0
  16. package/dist/public/runtime-kit.d.ts +427 -0
  17. package/dist/public/semantic-track.d.ts +418 -0
  18. package/dist/public/spatial.d.ts +1193 -0
  19. package/dist/public/speech.d.ts +391 -0
  20. package/dist/public/studio-adapter.d.ts +686 -0
  21. package/dist/public/svs.d.ts +311 -0
  22. package/dist/public/temporal-markup.d.ts +343 -0
  23. package/dist/public/temporal.d.ts +497 -0
  24. package/dist/public/text.d.ts +817 -0
  25. package/dist/public/visual-ir.d.ts +98 -0
  26. package/docs/public/hypit-logo-dark.svg +36 -0
  27. package/docs/public/hypit-logo-light.svg +38 -0
  28. package/examples/README.md +24 -0
  29. package/examples/minimal-author-package/README.md +18 -0
  30. package/examples/minimal-author-package/packages/example-component/README.md +44 -0
  31. package/examples/minimal-author-package/packages/example-component/package.json +27 -0
  32. package/examples/minimal-author-package/packages/example-component/preview/Box.png +0 -0
  33. package/examples/minimal-author-package/packages/example-component/preview/build.svrun +6 -0
  34. package/examples/minimal-author-package/packages/example-component/preview/preview.svml +47 -0
  35. package/examples/minimal-author-package/packages/example-component/preview/recipes.svs +8 -0
  36. package/examples/minimal-author-package/packages/example-component/src/activation.ts +10 -0
  37. package/examples/minimal-author-package/packages/example-component/src/component.ts +44 -0
  38. package/examples/minimal-author-package/packages/example-component/src/fragment.ts +32 -0
  39. package/examples/minimal-author-package/packages/example-component/src/index.ts +6 -0
  40. package/examples/minimal-author-package/packages/example-component/src/manifest.ts +82 -0
  41. package/examples/minimal-author-package/packages/example-component/src/style.ts +13 -0
  42. package/examples/minimal-author-package/packages/example-component/src/surface.ts +41 -0
  43. package/examples/minimal-author-package/packages/example-component/src/temporal.ts +6 -0
  44. package/examples/minimal-author-package/packages/example-component/tsconfig.json +18 -0
  45. package/examples/semantic-composition/README.md +35 -0
  46. package/examples/semantic-composition/chat.svml +25 -0
  47. package/examples/semantic-composition/chat.svrun +6 -0
  48. package/examples/semantic-composition/chat.svs +4 -0
  49. package/examples/semantic-composition/hypit.runtime.json +8 -0
  50. package/examples/semantic-composition/packages/chat-scene/README.md +29 -0
  51. package/examples/semantic-composition/packages/chat-scene/package.json +11 -0
  52. package/examples/semantic-composition/packages/chat-scene/src/activation.ts +112 -0
  53. package/examples/semantic-composition/packages/chat-scene/src/render.ts +64 -0
  54. package/examples/semantic-composition/packages/chat-scene/tsconfig.json +18 -0
  55. package/examples/semantic-composition/packages/responsive-explainer/README.md +45 -0
  56. package/examples/semantic-composition/packages/responsive-explainer/package.json +11 -0
  57. package/examples/semantic-composition/packages/responsive-explainer/src/activation.ts +90 -0
  58. package/examples/semantic-composition/packages/responsive-explainer/src/render.ts +68 -0
  59. package/examples/semantic-composition/packages/responsive-explainer/tsconfig.json +18 -0
  60. package/package.json +263 -5
  61. package/packages/artifact/README.md +10 -0
  62. package/packages/artifact/package.json +16 -0
  63. package/packages/artifact/src/activation.ts +8 -0
  64. package/packages/artifact/src/index.ts +24 -0
  65. package/packages/audio-track/README.md +43 -0
  66. package/packages/audio-track/package.json +36 -0
  67. package/packages/audio-track/src/activation.ts +20 -0
  68. package/packages/audio-track/src/component.ts +40 -0
  69. package/packages/audio-track/src/fragment.ts +63 -0
  70. package/packages/audio-track/src/index.ts +7 -0
  71. package/packages/audio-track/src/manifest.ts +151 -0
  72. package/packages/audio-track/src/program.ts +254 -0
  73. package/packages/audio-track/src/surface.ts +187 -0
  74. package/packages/audio-track/src/types.ts +62 -0
  75. package/packages/audio-track-studio/README.md +3 -0
  76. package/packages/audio-track-studio/package.json +14 -0
  77. package/packages/audio-track-studio/src/activation.ts +7 -0
  78. package/packages/audio-track-studio/src/index.ts +72 -0
  79. package/packages/author-kit/README.md +31 -0
  80. package/packages/author-kit/package.json +16 -0
  81. package/packages/author-kit/src/index.ts +59 -0
  82. package/packages/background-removal/README.md +29 -0
  83. package/packages/background-removal/package.json +16 -0
  84. package/packages/background-removal/src/activation.ts +18 -0
  85. package/packages/background-removal/src/component.ts +32 -0
  86. package/packages/background-removal/src/fragment.ts +18 -0
  87. package/packages/background-removal/src/index.ts +6 -0
  88. package/packages/background-removal/src/manifest.ts +45 -0
  89. package/packages/background-removal/src/program.ts +19 -0
  90. package/packages/background-removal/src/surface.ts +27 -0
  91. package/packages/background-removal/src/types.ts +5 -0
  92. package/packages/browser-capture/README.md +82 -0
  93. package/packages/browser-capture/package.json +15 -0
  94. package/packages/browser-capture/src/browser.ts +19 -0
  95. package/packages/browser-capture/src/index.ts +198 -0
  96. package/packages/build-result/package.json +13 -0
  97. package/packages/build-result/src/decode.ts +286 -0
  98. package/packages/build-result/src/index.ts +25 -0
  99. package/packages/build-result/src/store.ts +505 -0
  100. package/packages/build-result/src/types.ts +354 -0
  101. package/packages/build-result/src/writer.ts +184 -0
  102. package/packages/build-result-fs/README.md +29 -0
  103. package/packages/build-result-fs/package.json +17 -0
  104. package/packages/build-result-fs/src/activation.ts +62 -0
  105. package/packages/build-result-fs/src/index.ts +1 -0
  106. package/packages/build-result-kit/README.md +10 -0
  107. package/packages/build-result-kit/package.json +15 -0
  108. package/packages/build-result-kit/src/index.ts +144 -0
  109. package/packages/build-result-s3/README.md +49 -0
  110. package/packages/build-result-s3/package.json +19 -0
  111. package/packages/build-result-s3/src/activation.ts +71 -0
  112. package/packages/build-result-s3/src/client.ts +254 -0
  113. package/packages/build-result-s3/src/index.ts +4 -0
  114. package/packages/build-result-s3/src/repository.ts +361 -0
  115. package/packages/caption/README.md +77 -0
  116. package/packages/caption/package.json +28 -0
  117. package/packages/caption/src/activation.ts +17 -0
  118. package/packages/caption/src/component.ts +38 -0
  119. package/packages/caption/src/display.ts +111 -0
  120. package/packages/caption/src/error.ts +9 -0
  121. package/packages/caption/src/fragment.ts +26 -0
  122. package/packages/caption/src/index.ts +33 -0
  123. package/packages/caption/src/manifest.ts +97 -0
  124. package/packages/caption/src/style.ts +170 -0
  125. package/packages/caption/src/surface.ts +96 -0
  126. package/packages/caption/src/temporalize.ts +124 -0
  127. package/packages/caption/src/types.ts +71 -0
  128. package/packages/caption-fine/README.md +108 -0
  129. package/packages/caption-fine/package.json +30 -0
  130. package/packages/caption-fine/preview/Track.png +0 -0
  131. package/packages/caption-fine/src/activation.ts +32 -0
  132. package/packages/caption-fine/src/component.ts +58 -0
  133. package/packages/caption-fine/src/fragment.ts +112 -0
  134. package/packages/caption-fine/src/index.ts +19 -0
  135. package/packages/caption-fine/src/manifest.ts +383 -0
  136. package/packages/caption-fine/src/recipe.ts +120 -0
  137. package/packages/caption-fine/src/render.ts +1133 -0
  138. package/packages/caption-fine/src/schedule.ts +126 -0
  139. package/packages/caption-fine/src/spacing.ts +69 -0
  140. package/packages/caption-fine/src/style.ts +370 -0
  141. package/packages/caption-fine/src/surface.ts +152 -0
  142. package/packages/caption-fine/src/types.ts +191 -0
  143. package/packages/caption-fine-studio/README.md +3 -0
  144. package/packages/caption-fine-studio/package.json +15 -0
  145. package/packages/caption-fine-studio/src/activation.ts +7 -0
  146. package/packages/caption-fine-studio/src/index.ts +163 -0
  147. package/packages/cli/README.md +51 -0
  148. package/packages/cli/package.json +33 -0
  149. package/packages/cli/src/arguments.ts +605 -0
  150. package/packages/cli/src/build-planning.ts +460 -0
  151. package/packages/cli/src/command.ts +202 -0
  152. package/packages/cli/src/commands/environment.ts +391 -0
  153. package/packages/cli/src/commands/execution.ts +321 -0
  154. package/packages/cli/src/commands/results.ts +187 -0
  155. package/packages/cli/src/commands/types.ts +9 -0
  156. package/packages/cli/src/distribution.ts +74 -0
  157. package/packages/cli/src/index.ts +30 -0
  158. package/packages/cli/src/machine-view.ts +28 -0
  159. package/packages/cli/src/main.ts +654 -0
  160. package/packages/cli/src/oauth.ts +228 -0
  161. package/packages/cli/src/observation.ts +203 -0
  162. package/packages/cli/src/output.ts +1007 -0
  163. package/packages/cli/src/paths.ts +7 -0
  164. package/packages/cli/src/project-context.ts +38 -0
  165. package/packages/cli/src/reachability.ts +91 -0
  166. package/packages/cli/src/result-export.ts +148 -0
  167. package/packages/cli/src/result-query.ts +46 -0
  168. package/packages/cli/src/run-file.ts +186 -0
  169. package/packages/cli/src/runtime-port.ts +13 -0
  170. package/packages/cli/src/runtime-selection.ts +94 -0
  171. package/packages/cli/src/runtime-view.ts +15 -0
  172. package/packages/cli/src/source-discovery.ts +150 -0
  173. package/packages/cli/src/source-packages.ts +91 -0
  174. package/packages/cli/src/view.ts +228 -0
  175. package/packages/comment-sticker/README.md +41 -0
  176. package/packages/comment-sticker/package.json +29 -0
  177. package/packages/comment-sticker/preview/Track.png +0 -0
  178. package/packages/comment-sticker/src/activation.ts +32 -0
  179. package/packages/comment-sticker/src/author.ts +148 -0
  180. package/packages/comment-sticker/src/component.ts +97 -0
  181. package/packages/comment-sticker/src/fragment.ts +124 -0
  182. package/packages/comment-sticker/src/index.ts +8 -0
  183. package/packages/comment-sticker/src/manifest.ts +373 -0
  184. package/packages/comment-sticker/src/program.ts +610 -0
  185. package/packages/comment-sticker/src/surface.ts +172 -0
  186. package/packages/comment-sticker/src/types.ts +109 -0
  187. package/packages/comment-sticker-studio/README.md +3 -0
  188. package/packages/comment-sticker-studio/package.json +14 -0
  189. package/packages/comment-sticker-studio/src/activation.ts +7 -0
  190. package/packages/comment-sticker-studio/src/index.ts +132 -0
  191. package/packages/compiler-markup-node/README.md +12 -0
  192. package/packages/compiler-markup-node/package.json +22 -0
  193. package/packages/compiler-markup-node/src/index.ts +59 -0
  194. package/packages/compiler-node/README.md +60 -0
  195. package/packages/compiler-node/package.json +25 -0
  196. package/packages/compiler-node/src/compiler.ts +207 -0
  197. package/packages/compiler-node/src/error.ts +11 -0
  198. package/packages/compiler-node/src/graph-query.ts +51 -0
  199. package/packages/compiler-node/src/index.ts +27 -0
  200. package/packages/compiler-node/src/modules.ts +107 -0
  201. package/packages/compiler-node/src/run.ts +355 -0
  202. package/packages/component-kit/README.md +97 -0
  203. package/packages/component-kit/package.json +13 -0
  204. package/packages/component-kit/src/index.ts +155 -0
  205. package/packages/composition/README.md +53 -0
  206. package/packages/composition/package.json +29 -0
  207. package/packages/composition/src/activation.ts +3 -0
  208. package/packages/composition/src/component.ts +10 -0
  209. package/packages/composition/src/index.ts +18 -0
  210. package/packages/composition/src/manifest.ts +13 -0
  211. package/packages/composition/src/schema.ts +194 -0
  212. package/packages/composition/src/track.ts +1403 -0
  213. package/packages/core/README.md +22 -0
  214. package/packages/core/package.json +13 -0
  215. package/packages/core/src/error.ts +12 -0
  216. package/packages/core/src/graph.ts +341 -0
  217. package/packages/core/src/index.ts +32 -0
  218. package/packages/core/src/link.ts +240 -0
  219. package/packages/core/src/machine.ts +60 -0
  220. package/packages/core/src/plan.ts +504 -0
  221. package/packages/core/src/reducer.ts +428 -0
  222. package/packages/core/src/reference.ts +25 -0
  223. package/packages/core/src/slice.ts +108 -0
  224. package/packages/credential-store-env/README.md +11 -0
  225. package/packages/credential-store-env/package.json +17 -0
  226. package/packages/credential-store-env/src/activation.ts +25 -0
  227. package/packages/credential-store-env/src/index.ts +23 -0
  228. package/packages/credential-store-os/README.md +13 -0
  229. package/packages/credential-store-os/package.json +22 -0
  230. package/packages/credential-store-os/runtime/windows-credential.ps1 +59 -0
  231. package/packages/credential-store-os/src/activation.ts +32 -0
  232. package/packages/credential-store-os/src/index.ts +2 -0
  233. package/packages/credential-store-os/src/store.ts +196 -0
  234. package/packages/deck-track/README.md +52 -0
  235. package/packages/deck-track/package.json +35 -0
  236. package/packages/deck-track/preview/DepthStack.png +0 -0
  237. package/packages/deck-track/src/activation.ts +32 -0
  238. package/packages/deck-track/src/author.ts +217 -0
  239. package/packages/deck-track/src/component.ts +86 -0
  240. package/packages/deck-track/src/fragment.ts +148 -0
  241. package/packages/deck-track/src/index.ts +16 -0
  242. package/packages/deck-track/src/lower.ts +370 -0
  243. package/packages/deck-track/src/manifest.ts +438 -0
  244. package/packages/deck-track/src/program.ts +367 -0
  245. package/packages/deck-track/src/surface.ts +286 -0
  246. package/packages/deck-track/src/types.ts +119 -0
  247. package/packages/deck-track-studio/README.md +3 -0
  248. package/packages/deck-track-studio/package.json +14 -0
  249. package/packages/deck-track-studio/src/activation.ts +7 -0
  250. package/packages/deck-track-studio/src/index.ts +134 -0
  251. package/packages/driver-node/README.md +23 -0
  252. package/packages/driver-node/package.json +18 -0
  253. package/packages/driver-node/src/driver.ts +616 -0
  254. package/packages/driver-node/src/index.ts +10 -0
  255. package/packages/driver-node/src/planning.ts +67 -0
  256. package/packages/driver-node/src/registry.ts +234 -0
  257. package/packages/driver-node/src/resources.ts +36 -0
  258. package/packages/driver-node/src/types.ts +69 -0
  259. package/packages/elaborator/README.md +74 -0
  260. package/packages/elaborator/package.json +16 -0
  261. package/packages/elaborator/src/author.ts +308 -0
  262. package/packages/elaborator/src/fragment.ts +505 -0
  263. package/packages/elaborator/src/frontend-facet.ts +30 -0
  264. package/packages/elaborator/src/index.ts +78 -0
  265. package/packages/elaborator/src/source.ts +608 -0
  266. package/packages/endpoint-kit/README.md +111 -0
  267. package/packages/endpoint-kit/package.json +14 -0
  268. package/packages/endpoint-kit/src/index.ts +488 -0
  269. package/packages/estimate/README.md +32 -0
  270. package/packages/estimate/package.json +20 -0
  271. package/packages/estimate/src/activation.ts +11 -0
  272. package/packages/estimate/src/index.ts +16 -0
  273. package/packages/estimate/src/manifest.ts +34 -0
  274. package/packages/estimate/src/policy.ts +70 -0
  275. package/packages/estimate/src/program.ts +196 -0
  276. package/packages/estimate/src/types.ts +15 -0
  277. package/packages/film/README.md +49 -0
  278. package/packages/film/package.json +34 -0
  279. package/packages/film/src/activation.ts +16 -0
  280. package/packages/film/src/component.ts +61 -0
  281. package/packages/film/src/fragment.ts +83 -0
  282. package/packages/film/src/index.ts +11 -0
  283. package/packages/film/src/manifest.ts +152 -0
  284. package/packages/film/src/program.ts +110 -0
  285. package/packages/film/src/recipe.ts +24 -0
  286. package/packages/film/src/surface.ts +146 -0
  287. package/packages/film/src/types.ts +26 -0
  288. package/packages/film-studio/package.json +16 -0
  289. package/packages/film-studio/src/activation.ts +8 -0
  290. package/packages/film-studio/src/index.ts +17 -0
  291. package/packages/fonts-open/README.md +77 -0
  292. package/packages/fonts-open/package.json +130 -0
  293. package/packages/fonts-open/src/activation.ts +30 -0
  294. package/packages/fonts-open/src/catalog.ts +317 -0
  295. package/packages/fonts-open/src/index.ts +13 -0
  296. package/packages/fonts-open/src/manifest.ts +83 -0
  297. package/packages/fonts-open/src/surface.ts +239 -0
  298. package/packages/generation/README.md +19 -0
  299. package/packages/generation/package.json +23 -0
  300. package/packages/generation/src/activation.ts +9 -0
  301. package/packages/generation/src/component.ts +77 -0
  302. package/packages/generation/src/identity.ts +80 -0
  303. package/packages/generation/src/index.ts +79 -0
  304. package/packages/generation/src/manifest.ts +65 -0
  305. package/packages/generation/src/mapping.ts +231 -0
  306. package/packages/generation/src/ports.ts +222 -0
  307. package/packages/generation/src/request.ts +427 -0
  308. package/packages/generation/src/schema.ts +62 -0
  309. package/packages/generation/src/types.ts +17 -0
  310. package/packages/gpt-image/README.md +54 -0
  311. package/packages/gpt-image/package.json +34 -0
  312. package/packages/gpt-image/src/activation.ts +39 -0
  313. package/packages/gpt-image/src/fragment.ts +101 -0
  314. package/packages/gpt-image/src/index.ts +203 -0
  315. package/packages/gpt-image/src/surface.ts +194 -0
  316. package/packages/gpt-image-kits/README.md +44 -0
  317. package/packages/gpt-image-kits/kits/phone-ugc-v1.svs +34 -0
  318. package/packages/gpt-image-kits/package.json +15 -0
  319. package/packages/grok-imagine/README.md +21 -0
  320. package/packages/grok-imagine/package.json +21 -0
  321. package/packages/grok-imagine/src/activation.ts +29 -0
  322. package/packages/grok-imagine/src/index.ts +174 -0
  323. package/packages/grok-imagine/src/surface.ts +149 -0
  324. package/packages/host/README.md +5 -0
  325. package/packages/host/package.json +10 -0
  326. package/packages/host/src/facet.ts +6 -0
  327. package/packages/host/src/frontend.ts +56 -0
  328. package/packages/host/src/index.ts +9 -0
  329. package/packages/hyperframes/README.md +69 -0
  330. package/packages/hyperframes/package.json +36 -0
  331. package/packages/hyperframes/src/activation.ts +8 -0
  332. package/packages/hyperframes/src/browser-program.ts +79 -0
  333. package/packages/hyperframes/src/component.ts +32 -0
  334. package/packages/hyperframes/src/document.ts +827 -0
  335. package/packages/hyperframes/src/fragment.ts +32 -0
  336. package/packages/hyperframes/src/index.ts +13 -0
  337. package/packages/hyperframes/src/manifest.ts +67 -0
  338. package/packages/hyperframes/src/project.ts +118 -0
  339. package/packages/hyperframes/src/text.ts +1179 -0
  340. package/packages/hyperframes/src/types.ts +38 -0
  341. package/packages/image-compose/README.md +25 -0
  342. package/packages/image-compose/package.json +18 -0
  343. package/packages/image-compose/src/activation.ts +21 -0
  344. package/packages/image-compose/src/component.ts +100 -0
  345. package/packages/image-compose/src/fragment.ts +54 -0
  346. package/packages/image-compose/src/index.ts +10 -0
  347. package/packages/image-compose/src/manifest.ts +119 -0
  348. package/packages/image-compose/src/program.ts +75 -0
  349. package/packages/image-compose/src/surface.ts +83 -0
  350. package/packages/image-compose/src/types.ts +22 -0
  351. package/packages/image-transform/README.md +29 -0
  352. package/packages/image-transform/package.json +21 -0
  353. package/packages/image-transform/src/activation.ts +33 -0
  354. package/packages/image-transform/src/component.ts +67 -0
  355. package/packages/image-transform/src/fragment.ts +25 -0
  356. package/packages/image-transform/src/index.ts +13 -0
  357. package/packages/image-transform/src/manifest.ts +209 -0
  358. package/packages/image-transform/src/program.ts +23 -0
  359. package/packages/image-transform/src/surface.ts +216 -0
  360. package/packages/image-transform/src/types.ts +20 -0
  361. package/packages/interview-emoji-reveal/README.md +39 -0
  362. package/packages/interview-emoji-reveal/package.json +23 -0
  363. package/packages/interview-emoji-reveal/preview/Track.png +0 -0
  364. package/packages/interview-emoji-reveal/src/activation.ts +14 -0
  365. package/packages/interview-emoji-reveal/src/component.ts +45 -0
  366. package/packages/interview-emoji-reveal/src/fragment.ts +62 -0
  367. package/packages/interview-emoji-reveal/src/index.ts +16 -0
  368. package/packages/interview-emoji-reveal/src/manifest.ts +174 -0
  369. package/packages/interview-emoji-reveal/src/program.ts +242 -0
  370. package/packages/interview-emoji-reveal/src/style.ts +47 -0
  371. package/packages/interview-emoji-reveal/src/surface.ts +110 -0
  372. package/packages/interview-emoji-reveal/src/types.ts +52 -0
  373. package/packages/markup/README.md +81 -0
  374. package/packages/markup/package.json +16 -0
  375. package/packages/markup/src/element.ts +39 -0
  376. package/packages/markup/src/error.ts +20 -0
  377. package/packages/markup/src/frontend.ts +518 -0
  378. package/packages/markup/src/host-facet.ts +115 -0
  379. package/packages/markup/src/index.ts +25 -0
  380. package/packages/markup/src/registry.ts +83 -0
  381. package/packages/markup/src/syntax.ts +271 -0
  382. package/packages/markup/src/types.ts +246 -0
  383. package/packages/media/README.md +37 -0
  384. package/packages/media/package.json +19 -0
  385. package/packages/media/src/activation.ts +38 -0
  386. package/packages/media/src/component.ts +16 -0
  387. package/packages/media/src/frame-range.ts +33 -0
  388. package/packages/media/src/identity.ts +227 -0
  389. package/packages/media/src/index.ts +15 -0
  390. package/packages/media/src/manifest.ts +122 -0
  391. package/packages/media/src/render.ts +140 -0
  392. package/packages/media/src/schema.ts +69 -0
  393. package/packages/media/src/surface.ts +150 -0
  394. package/packages/media/src/types.ts +121 -0
  395. package/packages/media-execution/README.md +28 -0
  396. package/packages/media-execution/package.json +17 -0
  397. package/packages/media-execution/src/execute.ts +1322 -0
  398. package/packages/media-execution/src/index.ts +16 -0
  399. package/packages/media-execution/src/probe.ts +315 -0
  400. package/packages/media-execution/src/surface.ts +286 -0
  401. package/packages/media-execution/src/toolchain.ts +81 -0
  402. package/packages/media-execution/src/webp.ts +200 -0
  403. package/packages/media-pipeline/README.md +113 -0
  404. package/packages/media-pipeline/package.json +27 -0
  405. package/packages/media-pipeline/src/activation.ts +47 -0
  406. package/packages/media-pipeline/src/audio-plan.ts +113 -0
  407. package/packages/media-pipeline/src/component.ts +373 -0
  408. package/packages/media-pipeline/src/fragment.ts +167 -0
  409. package/packages/media-pipeline/src/index.ts +46 -0
  410. package/packages/media-pipeline/src/manifest.ts +653 -0
  411. package/packages/media-pipeline/src/operations.ts +248 -0
  412. package/packages/media-pipeline/src/selection.ts +110 -0
  413. package/packages/media-pipeline/src/surface.ts +389 -0
  414. package/packages/media-pipeline/src/types.ts +175 -0
  415. package/packages/media-track/README.md +197 -0
  416. package/packages/media-track/package.json +29 -0
  417. package/packages/media-track/preview/Track.png +0 -0
  418. package/packages/media-track/preview/build.svrun +5 -0
  419. package/packages/media-track/preview/flush.png +0 -0
  420. package/packages/media-track/preview/preview.svml +47 -0
  421. package/packages/media-track/preview/recipes.svs +23 -0
  422. package/packages/media-track/preview/rounded.png +0 -0
  423. package/packages/media-track/src/activation.ts +20 -0
  424. package/packages/media-track/src/author.ts +317 -0
  425. package/packages/media-track/src/component.ts +162 -0
  426. package/packages/media-track/src/fragment.ts +57 -0
  427. package/packages/media-track/src/index.ts +65 -0
  428. package/packages/media-track/src/layers.ts +308 -0
  429. package/packages/media-track/src/lower.ts +335 -0
  430. package/packages/media-track/src/manifest.ts +624 -0
  431. package/packages/media-track/src/motion.ts +387 -0
  432. package/packages/media-track/src/performance.ts +37 -0
  433. package/packages/media-track/src/presentation.ts +35 -0
  434. package/packages/media-track/src/program.ts +565 -0
  435. package/packages/media-track/src/sampling.ts +118 -0
  436. package/packages/media-track/src/sequence.ts +403 -0
  437. package/packages/media-track/src/sounds.ts +71 -0
  438. package/packages/media-track/src/surface.ts +668 -0
  439. package/packages/media-track/src/types.ts +311 -0
  440. package/packages/media-track-studio/README.md +3 -0
  441. package/packages/media-track-studio/package.json +15 -0
  442. package/packages/media-track-studio/src/activation.ts +7 -0
  443. package/packages/media-track-studio/src/index.ts +235 -0
  444. package/packages/mimo-speech/README.md +33 -0
  445. package/packages/mimo-speech/package.json +21 -0
  446. package/packages/mimo-speech/src/activation.ts +32 -0
  447. package/packages/mimo-speech/src/fragment.ts +11 -0
  448. package/packages/mimo-speech/src/index.ts +160 -0
  449. package/packages/mimo-speech/src/surface.ts +193 -0
  450. package/packages/minimax-h3/README.md +21 -0
  451. package/packages/minimax-h3/package.json +21 -0
  452. package/packages/minimax-h3/src/activation.ts +14 -0
  453. package/packages/minimax-h3/src/index.ts +188 -0
  454. package/packages/minimax-h3/src/surface.ts +87 -0
  455. package/packages/model-kit/README.md +52 -0
  456. package/packages/model-kit/package.json +19 -0
  457. package/packages/model-kit/src/index.ts +728 -0
  458. package/packages/nano-banana/README.md +23 -0
  459. package/packages/nano-banana/package.json +21 -0
  460. package/packages/nano-banana/src/activation.ts +14 -0
  461. package/packages/nano-banana/src/index.ts +172 -0
  462. package/packages/nano-banana/src/surface.ts +120 -0
  463. package/packages/narrative/README.md +7 -0
  464. package/packages/narrative/package.json +17 -0
  465. package/packages/narrative/src/activation.ts +7 -0
  466. package/packages/narrative/src/component.ts +33 -0
  467. package/packages/narrative/src/identity.ts +131 -0
  468. package/packages/narrative/src/index.ts +11 -0
  469. package/packages/narrative/src/manifest.ts +30 -0
  470. package/packages/narrative/src/schema.ts +89 -0
  471. package/packages/narrative/src/types.ts +141 -0
  472. package/packages/package-loader-node/README.md +23 -0
  473. package/packages/package-loader-node/package.json +15 -0
  474. package/packages/package-loader-node/src/contribution.ts +97 -0
  475. package/packages/package-loader-node/src/distribution-resolution.ts +146 -0
  476. package/packages/package-loader-node/src/index.ts +27 -0
  477. package/packages/package-loader-node/src/loader.ts +301 -0
  478. package/packages/package-loader-node/src/location.ts +279 -0
  479. package/packages/package-loader-node/src/types.ts +60 -0
  480. package/packages/program-space/README.md +20 -0
  481. package/packages/program-space/package.json +17 -0
  482. package/packages/program-space/src/activation.ts +19 -0
  483. package/packages/program-space/src/index.ts +107 -0
  484. package/packages/program-space/src/surface.ts +55 -0
  485. package/packages/protocol/README.md +11 -0
  486. package/packages/protocol/package.json +10 -0
  487. package/packages/protocol/src/build-id.ts +52 -0
  488. package/packages/protocol/src/build.ts +265 -0
  489. package/packages/protocol/src/canonical.ts +37 -0
  490. package/packages/protocol/src/error.ts +11 -0
  491. package/packages/protocol/src/identity.ts +59 -0
  492. package/packages/protocol/src/index.ts +9 -0
  493. package/packages/protocol/src/module.ts +67 -0
  494. package/packages/protocol/src/value.ts +88 -0
  495. package/packages/provider-hyperframes-aws-lambda/README.md +30 -0
  496. package/packages/provider-hyperframes-aws-lambda/package.json +30 -0
  497. package/packages/provider-hyperframes-aws-lambda/src/activation.ts +97 -0
  498. package/packages/provider-hyperframes-aws-lambda/src/client.ts +114 -0
  499. package/packages/provider-hyperframes-aws-lambda/src/index.ts +21 -0
  500. package/packages/provider-hyperframes-aws-lambda/src/provider.ts +522 -0
  501. package/packages/provider-hyperframes-local/README.md +129 -0
  502. package/packages/provider-hyperframes-local/package.json +34 -0
  503. package/packages/provider-hyperframes-local/src/activation.ts +107 -0
  504. package/packages/provider-hyperframes-local/src/capture-process.ts +110 -0
  505. package/packages/provider-hyperframes-local/src/capture-worker.ts +17 -0
  506. package/packages/provider-hyperframes-local/src/capture.ts +184 -0
  507. package/packages/provider-hyperframes-local/src/index.ts +10 -0
  508. package/packages/provider-hyperframes-local/src/options.ts +19 -0
  509. package/packages/provider-hyperframes-local/src/output.ts +73 -0
  510. package/packages/provider-hyperframes-local/src/process.ts +83 -0
  511. package/packages/provider-hyperframes-local/src/program.ts +58 -0
  512. package/packages/provider-hyperframes-local/src/provider.ts +62 -0
  513. package/packages/provider-hyperframes-local/src/render.ts +114 -0
  514. package/packages/provider-hyperframes-local/src/sampling.ts +89 -0
  515. package/packages/provider-hypihub/README.md +143 -0
  516. package/packages/provider-hypihub/package.json +26 -0
  517. package/packages/provider-hypihub/src/activation.ts +91 -0
  518. package/packages/provider-hypihub/src/index.ts +2 -0
  519. package/packages/provider-hypihub/src/mapping.ts +145 -0
  520. package/packages/provider-hypihub/src/oauth.ts +113 -0
  521. package/packages/provider-hypihub/src/provider.ts +566 -0
  522. package/packages/provider-hypihub/src/routes.ts +134 -0
  523. package/packages/provider-hypihub/src/upload.ts +402 -0
  524. package/packages/provider-image-opencv-local/README.md +16 -0
  525. package/packages/provider-image-opencv-local/package.json +27 -0
  526. package/packages/provider-image-opencv-local/runtime/raster_execute.py +299 -0
  527. package/packages/provider-image-opencv-local/src/activation.ts +61 -0
  528. package/packages/provider-image-opencv-local/src/deployment.ts +68 -0
  529. package/packages/provider-image-opencv-local/src/index.ts +2 -0
  530. package/packages/provider-image-opencv-local/src/program.ts +60 -0
  531. package/packages/provider-image-opencv-local/src/provider.ts +155 -0
  532. package/packages/provider-kie/README.md +134 -0
  533. package/packages/provider-kie/package.json +43 -0
  534. package/packages/provider-kie/src/activation.ts +71 -0
  535. package/packages/provider-kie/src/index.ts +10 -0
  536. package/packages/provider-kie/src/mapping.ts +182 -0
  537. package/packages/provider-kie/src/provider.ts +657 -0
  538. package/packages/provider-kie/src/routes.ts +150 -0
  539. package/packages/provider-media-local/README.md +58 -0
  540. package/packages/provider-media-local/package.json +28 -0
  541. package/packages/provider-media-local/src/activation.ts +65 -0
  542. package/packages/provider-media-local/src/index.ts +2 -0
  543. package/packages/provider-media-local/src/program.ts +19 -0
  544. package/packages/provider-media-local/src/provider.ts +150 -0
  545. package/packages/provider-whisperx-local/README.md +44 -0
  546. package/packages/provider-whisperx-local/package.json +27 -0
  547. package/packages/provider-whisperx-local/src/activation.ts +93 -0
  548. package/packages/provider-whisperx-local/src/index.ts +5 -0
  549. package/packages/provider-whisperx-local/src/program.ts +157 -0
  550. package/packages/provider-whisperx-local/src/provider.ts +191 -0
  551. package/packages/provider-xiaomi-mimo/README.md +32 -0
  552. package/packages/provider-xiaomi-mimo/package.json +24 -0
  553. package/packages/provider-xiaomi-mimo/src/activation.ts +57 -0
  554. package/packages/provider-xiaomi-mimo/src/index.ts +5 -0
  555. package/packages/provider-xiaomi-mimo/src/provider.ts +214 -0
  556. package/packages/ranking/README.md +67 -0
  557. package/packages/ranking/package.json +33 -0
  558. package/packages/ranking/preview/Column.svg +29 -0
  559. package/packages/ranking/preview/TierBoard.png +0 -0
  560. package/packages/ranking/preview/TierBoard.svg +36 -0
  561. package/packages/ranking/preview/TopThree.png +0 -0
  562. package/packages/ranking/src/activation.ts +38 -0
  563. package/packages/ranking/src/component.ts +271 -0
  564. package/packages/ranking/src/fragment.ts +206 -0
  565. package/packages/ranking/src/index.ts +26 -0
  566. package/packages/ranking/src/manifest.ts +807 -0
  567. package/packages/ranking/src/render.ts +698 -0
  568. package/packages/ranking/src/schedule.ts +895 -0
  569. package/packages/ranking/src/style.ts +272 -0
  570. package/packages/ranking/src/surface.ts +322 -0
  571. package/packages/ranking/src/tier.ts +176 -0
  572. package/packages/ranking/src/types.ts +277 -0
  573. package/packages/ranking-studio/README.md +3 -0
  574. package/packages/ranking-studio/package.json +14 -0
  575. package/packages/ranking-studio/src/activation.ts +7 -0
  576. package/packages/ranking-studio/src/index.ts +255 -0
  577. package/packages/raster/README.md +7 -0
  578. package/packages/raster/package.json +14 -0
  579. package/packages/raster/src/activation.ts +7 -0
  580. package/packages/raster/src/index.ts +7 -0
  581. package/packages/raster/src/manifest.ts +14 -0
  582. package/packages/raster/src/program.ts +128 -0
  583. package/packages/raster/src/schema.ts +53 -0
  584. package/packages/raster/src/types.ts +61 -0
  585. package/packages/render-hyperframes/README.md +58 -0
  586. package/packages/render-hyperframes/package.json +33 -0
  587. package/packages/render-hyperframes/src/activation.ts +18 -0
  588. package/packages/render-hyperframes/src/component.ts +37 -0
  589. package/packages/render-hyperframes/src/fragment.ts +73 -0
  590. package/packages/render-hyperframes/src/index.ts +6 -0
  591. package/packages/render-hyperframes/src/manifest.ts +100 -0
  592. package/packages/render-hyperframes/src/product.ts +29 -0
  593. package/packages/render-hyperframes/src/surface.ts +65 -0
  594. package/packages/resource-store-fs/README.md +13 -0
  595. package/packages/resource-store-fs/package.json +14 -0
  596. package/packages/resource-store-fs/src/index.ts +2 -0
  597. package/packages/resource-store-fs/src/store.ts +154 -0
  598. package/packages/resource-store-s3/README.md +15 -0
  599. package/packages/resource-store-s3/package.json +15 -0
  600. package/packages/resource-store-s3/src/client.ts +138 -0
  601. package/packages/resource-store-s3/src/index.ts +10 -0
  602. package/packages/resource-store-s3/src/store.ts +258 -0
  603. package/packages/run/README.md +23 -0
  604. package/packages/run/package.json +16 -0
  605. package/packages/run/src/candidate.ts +33 -0
  606. package/packages/run/src/facet.ts +59 -0
  607. package/packages/run/src/frontend-facet.ts +23 -0
  608. package/packages/run/src/frontend.ts +62 -0
  609. package/packages/run/src/graph.ts +65 -0
  610. package/packages/run/src/index.ts +33 -0
  611. package/packages/run/src/registry.ts +24 -0
  612. package/packages/run/src/resolve.ts +213 -0
  613. package/packages/run/src/types.ts +147 -0
  614. package/packages/run-markup/README.md +60 -0
  615. package/packages/run-markup/package.json +22 -0
  616. package/packages/run-markup/src/activation.ts +10 -0
  617. package/packages/run-markup/src/frontend.ts +16 -0
  618. package/packages/run-markup/src/index.ts +5 -0
  619. package/packages/run-markup/src/syntax.ts +304 -0
  620. package/packages/runtime/README.md +39 -0
  621. package/packages/runtime/package.json +15 -0
  622. package/packages/runtime/src/capacity.ts +51 -0
  623. package/packages/runtime/src/catalog.ts +30 -0
  624. package/packages/runtime/src/credentials.ts +124 -0
  625. package/packages/runtime/src/environment.ts +6 -0
  626. package/packages/runtime/src/execution.ts +125 -0
  627. package/packages/runtime/src/index.ts +24 -0
  628. package/packages/runtime/src/operations.ts +99 -0
  629. package/packages/runtime/src/scheduler.ts +281 -0
  630. package/packages/runtime/src/submission.ts +24 -0
  631. package/packages/runtime/src/types.ts +157 -0
  632. package/packages/runtime-host-node/README.md +25 -0
  633. package/packages/runtime-host-node/package.json +19 -0
  634. package/packages/runtime-host-node/src/index.ts +421 -0
  635. package/packages/runtime-host-node/src/packages.ts +158 -0
  636. package/packages/runtime-kit/README.md +42 -0
  637. package/packages/runtime-kit/package.json +16 -0
  638. package/packages/runtime-kit/src/index.ts +307 -0
  639. package/packages/runtime-kit/src/request-deadline.ts +17 -0
  640. package/packages/runtime-local/README.md +119 -0
  641. package/packages/runtime-local/package.json +33 -0
  642. package/packages/runtime-local/src/actions.ts +20 -0
  643. package/packages/runtime-local/src/config.ts +1229 -0
  644. package/packages/runtime-local/src/control.ts +120 -0
  645. package/packages/runtime-local/src/credentials.ts +61 -0
  646. package/packages/runtime-local/src/host.ts +174 -0
  647. package/packages/runtime-local/src/index.ts +36 -0
  648. package/packages/runtime-local/src/process-control.ts +59 -0
  649. package/packages/runtime-local/src/process-logs.ts +33 -0
  650. package/packages/runtime-local/src/programs.ts +441 -0
  651. package/packages/runtime-local/src/result-writer.ts +246 -0
  652. package/packages/runtime-local/src/runtime.ts +342 -0
  653. package/packages/runtime-local/src/types.ts +100 -0
  654. package/packages/runtime-local/src/worker-process.ts +343 -0
  655. package/packages/runtime-local/src/worker.ts +449 -0
  656. package/packages/screen-overlay/README.md +17 -0
  657. package/packages/screen-overlay/package.json +31 -0
  658. package/packages/screen-overlay/preview/Track.png +0 -0
  659. package/packages/screen-overlay/src/activation.ts +15 -0
  660. package/packages/screen-overlay/src/component.ts +20 -0
  661. package/packages/screen-overlay/src/fragment.ts +40 -0
  662. package/packages/screen-overlay/src/index.ts +7 -0
  663. package/packages/screen-overlay/src/manifest.ts +305 -0
  664. package/packages/screen-overlay/src/program.ts +321 -0
  665. package/packages/screen-overlay/src/surface.ts +90 -0
  666. package/packages/screen-overlay/src/types.ts +69 -0
  667. package/packages/screen-overlay-studio/README.md +3 -0
  668. package/packages/screen-overlay-studio/package.json +14 -0
  669. package/packages/screen-overlay-studio/src/activation.ts +7 -0
  670. package/packages/screen-overlay-studio/src/index.ts +80 -0
  671. package/packages/script/README.md +137 -0
  672. package/packages/script/package.json +22 -0
  673. package/packages/script/src/activation.ts +20 -0
  674. package/packages/script/src/edit.ts +174 -0
  675. package/packages/script/src/error.ts +13 -0
  676. package/packages/script/src/format.ts +83 -0
  677. package/packages/script/src/index.ts +20 -0
  678. package/packages/script/src/lexical.ts +133 -0
  679. package/packages/script/src/manifest.ts +95 -0
  680. package/packages/script/src/narrative.ts +232 -0
  681. package/packages/script/src/parser.ts +850 -0
  682. package/packages/script/src/surface.ts +132 -0
  683. package/packages/script/src/types.ts +125 -0
  684. package/packages/script-studio/package.json +13 -0
  685. package/packages/script-studio/src/activation.ts +8 -0
  686. package/packages/script-studio/src/index.ts +61 -0
  687. package/packages/seedance/README.md +19 -0
  688. package/packages/seedance/package.json +22 -0
  689. package/packages/seedance/src/activation.ts +38 -0
  690. package/packages/seedance/src/fragment.ts +46 -0
  691. package/packages/seedance/src/index.ts +329 -0
  692. package/packages/seedance/src/surface.ts +355 -0
  693. package/packages/seedance-kits/README.md +153 -0
  694. package/packages/seedance-kits/kits/broll-v1.svs +52 -0
  695. package/packages/seedance-kits/kits/call-v1.svs +55 -0
  696. package/packages/seedance-kits/kits/camera-reference-v1.svs +9 -0
  697. package/packages/seedance-kits/kits/motion-reference-v1.svs +9 -0
  698. package/packages/seedance-kits/kits/podcast-v1.svs +55 -0
  699. package/packages/seedance-kits/kits/speaker-v1.svs +136 -0
  700. package/packages/seedance-kits/kits/street-interview-v1.svs +49 -0
  701. package/packages/seedance-kits/package.json +24 -0
  702. package/packages/seedream/README.md +21 -0
  703. package/packages/seedream/package.json +21 -0
  704. package/packages/seedream/src/activation.ts +12 -0
  705. package/packages/seedream/src/index.ts +162 -0
  706. package/packages/seedream/src/surface.ts +84 -0
  707. package/packages/semantic-take-adjust/package.json +21 -0
  708. package/packages/semantic-take-adjust/src/activation.ts +22 -0
  709. package/packages/semantic-take-adjust/src/component.ts +31 -0
  710. package/packages/semantic-take-adjust/src/fragment.ts +24 -0
  711. package/packages/semantic-take-adjust/src/index.ts +12 -0
  712. package/packages/semantic-take-adjust/src/manifest.ts +57 -0
  713. package/packages/semantic-take-adjust/src/program.ts +49 -0
  714. package/packages/semantic-take-adjust/src/surface.ts +96 -0
  715. package/packages/semantic-take-adjust/src/types.ts +9 -0
  716. package/packages/semantic-track/README.md +21 -0
  717. package/packages/semantic-track/package.json +22 -0
  718. package/packages/semantic-track/src/activation.ts +8 -0
  719. package/packages/semantic-track/src/component.ts +24 -0
  720. package/packages/semantic-track/src/identity.ts +58 -0
  721. package/packages/semantic-track/src/index.ts +6 -0
  722. package/packages/semantic-track/src/location.ts +81 -0
  723. package/packages/semantic-track/src/manifest.ts +38 -0
  724. package/packages/semantic-track/src/projection.ts +71 -0
  725. package/packages/semantic-track/src/types.ts +26 -0
  726. package/packages/source/README.md +13 -0
  727. package/packages/source/package.json +13 -0
  728. package/packages/source/src/header.ts +80 -0
  729. package/packages/source/src/index.ts +17 -0
  730. package/packages/source/src/unit.ts +38 -0
  731. package/packages/spatial/README.md +77 -0
  732. package/packages/spatial/package.json +24 -0
  733. package/packages/spatial/src/activation.ts +43 -0
  734. package/packages/spatial/src/author.ts +59 -0
  735. package/packages/spatial/src/component.ts +45 -0
  736. package/packages/spatial/src/fragment.ts +36 -0
  737. package/packages/spatial/src/geometry.ts +238 -0
  738. package/packages/spatial/src/index.ts +37 -0
  739. package/packages/spatial/src/manifest.ts +341 -0
  740. package/packages/spatial/src/region-timeline.ts +69 -0
  741. package/packages/spatial/src/schema.ts +47 -0
  742. package/packages/spatial/src/surface.ts +319 -0
  743. package/packages/spatial/src/types.ts +101 -0
  744. package/packages/speech/README.md +16 -0
  745. package/packages/speech/package.json +19 -0
  746. package/packages/speech/src/activation.ts +7 -0
  747. package/packages/speech/src/component.ts +43 -0
  748. package/packages/speech/src/identity.ts +73 -0
  749. package/packages/speech/src/index.ts +6 -0
  750. package/packages/speech/src/manifest.ts +30 -0
  751. package/packages/speech/src/materialize.ts +103 -0
  752. package/packages/speech/src/schema.ts +42 -0
  753. package/packages/speech/src/types.ts +54 -0
  754. package/packages/speech-alignment/README.md +29 -0
  755. package/packages/speech-alignment/package.json +25 -0
  756. package/packages/speech-alignment/src/activation.ts +8 -0
  757. package/packages/speech-alignment/src/align.ts +235 -0
  758. package/packages/speech-alignment/src/component.ts +37 -0
  759. package/packages/speech-alignment/src/error.ts +9 -0
  760. package/packages/speech-alignment/src/index.ts +7 -0
  761. package/packages/speech-alignment/src/local.ts +64 -0
  762. package/packages/speech-alignment/src/locate.ts +473 -0
  763. package/packages/speech-alignment/src/manifest.ts +37 -0
  764. package/packages/speech-alignment/src/normalize.ts +79 -0
  765. package/packages/speech-alignment/src/types.ts +30 -0
  766. package/packages/speech-evidence/README.md +3 -0
  767. package/packages/speech-evidence/package.json +16 -0
  768. package/packages/speech-evidence/src/activation.ts +3 -0
  769. package/packages/speech-evidence/src/index.ts +102 -0
  770. package/packages/speech-track/README.md +51 -0
  771. package/packages/speech-track/package.json +28 -0
  772. package/packages/speech-track/preview/Track.png +0 -0
  773. package/packages/speech-track/src/activation.ts +19 -0
  774. package/packages/speech-track/src/component.ts +45 -0
  775. package/packages/speech-track/src/fragment.ts +74 -0
  776. package/packages/speech-track/src/index.ts +7 -0
  777. package/packages/speech-track/src/manifest.ts +73 -0
  778. package/packages/speech-track/src/program.ts +64 -0
  779. package/packages/speech-track/src/surface.ts +35 -0
  780. package/packages/speech-track/src/types.ts +6 -0
  781. package/packages/speech-track-studio/README.md +3 -0
  782. package/packages/speech-track-studio/package.json +14 -0
  783. package/packages/speech-track-studio/src/activation.ts +7 -0
  784. package/packages/speech-track-studio/src/index.ts +40 -0
  785. package/packages/store-sqlite/README.md +14 -0
  786. package/packages/store-sqlite/package.json +18 -0
  787. package/packages/store-sqlite/src/index.ts +2 -0
  788. package/packages/store-sqlite/src/store.ts +1101 -0
  789. package/packages/studio/README.md +125 -0
  790. package/packages/studio/index.html +10 -0
  791. package/packages/studio/package.json +50 -0
  792. package/packages/studio/src/build-library.ts +281 -0
  793. package/packages/studio/src/companion-assembly.ts +39 -0
  794. package/packages/studio/src/compile.ts +166 -0
  795. package/packages/studio/src/domain.ts +139 -0
  796. package/packages/studio/src/execute.ts +57 -0
  797. package/packages/studio/src/fallback-companions.ts +98 -0
  798. package/packages/studio/src/observe.ts +202 -0
  799. package/packages/studio/src/parameter-values.ts +81 -0
  800. package/packages/studio/src/parameters.ts +550 -0
  801. package/packages/studio/src/preview/render.ts +51 -0
  802. package/packages/studio/src/preview/runtime-shim.ts +184 -0
  803. package/packages/studio/src/programme.ts +276 -0
  804. package/packages/studio/src/run.ts +85 -0
  805. package/packages/studio/src/server.ts +725 -0
  806. package/packages/studio/src/session.ts +111 -0
  807. package/packages/studio/src/shared.ts +315 -0
  808. package/packages/studio/src/snapshot.ts +454 -0
  809. package/packages/studio/src/source-transaction.ts +57 -0
  810. package/packages/studio/src/storyboard.ts +133 -0
  811. package/packages/studio/src/studio-preflight.ts +198 -0
  812. package/packages/studio/src/studio-registry.ts +406 -0
  813. package/packages/studio/src/studio-trace.ts +136 -0
  814. package/packages/studio/src/style.css +1525 -0
  815. package/packages/studio/src/surface-preview.ts +35 -0
  816. package/packages/studio/src/temporal-graph.ts +227 -0
  817. package/packages/studio/src/ui/code.ts +450 -0
  818. package/packages/studio/src/ui/icons.ts +51 -0
  819. package/packages/studio/src/ui/library.ts +378 -0
  820. package/packages/studio/src/ui/main.ts +1001 -0
  821. package/packages/studio/src/ui/markers.ts +152 -0
  822. package/packages/studio/src/ui/material-preview.ts +176 -0
  823. package/packages/studio/src/ui/overlay.ts +144 -0
  824. package/packages/studio/src/ui/resize.ts +74 -0
  825. package/packages/studio/src/ui/selection.ts +178 -0
  826. package/packages/studio/src/ui/stage.ts +231 -0
  827. package/packages/studio/src/ui/syntax.ts +195 -0
  828. package/packages/studio/src/ui/timeline.ts +1041 -0
  829. package/packages/studio/src/ui/writeback.ts +10 -0
  830. package/packages/studio/src/ui/zoom.ts +129 -0
  831. package/packages/studio/start.ts +143 -0
  832. package/packages/studio-adapter/README.md +186 -0
  833. package/packages/studio-adapter/package.json +14 -0
  834. package/packages/studio-adapter/src/index.ts +850 -0
  835. package/packages/svs/README.md +37 -0
  836. package/packages/svs/package.json +21 -0
  837. package/packages/svs/src/activation.ts +11 -0
  838. package/packages/svs/src/format.ts +16 -0
  839. package/packages/svs/src/frontend.ts +33 -0
  840. package/packages/svs/src/index.ts +5 -0
  841. package/packages/svs/src/manifest.ts +17 -0
  842. package/packages/svs/src/parser.ts +279 -0
  843. package/packages/svs/src/types.ts +26 -0
  844. package/packages/temporal/README.md +31 -0
  845. package/packages/temporal/package.json +20 -0
  846. package/packages/temporal/src/activation.ts +9 -0
  847. package/packages/temporal/src/component.ts +68 -0
  848. package/packages/temporal/src/index.ts +110 -0
  849. package/packages/temporal/src/location.ts +67 -0
  850. package/packages/temporal/src/projection.ts +280 -0
  851. package/packages/temporal/src/rational.ts +80 -0
  852. package/packages/temporal/src/sample.ts +43 -0
  853. package/packages/temporal/src/schedule.ts +52 -0
  854. package/packages/temporal/src/types.ts +124 -0
  855. package/packages/temporal-markup/README.md +75 -0
  856. package/packages/temporal-markup/package.json +18 -0
  857. package/packages/temporal-markup/src/index.ts +537 -0
  858. package/packages/temporal-markup/src/space.ts +59 -0
  859. package/packages/text/README.md +59 -0
  860. package/packages/text/package.json +21 -0
  861. package/packages/text/src/activation.ts +33 -0
  862. package/packages/text/src/component.ts +72 -0
  863. package/packages/text/src/fragment.ts +57 -0
  864. package/packages/text/src/frontend.ts +39 -0
  865. package/packages/text/src/index.ts +27 -0
  866. package/packages/text/src/manifest.ts +170 -0
  867. package/packages/text/src/program.ts +418 -0
  868. package/packages/text/src/surface.ts +212 -0
  869. package/packages/text/src/svs.ts +189 -0
  870. package/packages/text/src/types.ts +82 -0
  871. package/packages/transport-aws-lambda/README.md +20 -0
  872. package/packages/transport-aws-lambda/package.json +14 -0
  873. package/packages/transport-aws-lambda/src/index.ts +131 -0
  874. package/packages/typography-track/README.md +50 -0
  875. package/packages/typography-track/package.json +34 -0
  876. package/packages/typography-track/preview/Mask.png +0 -0
  877. package/packages/typography-track/preview/Track.png +0 -0
  878. package/packages/typography-track/src/activation.ts +36 -0
  879. package/packages/typography-track/src/component.ts +93 -0
  880. package/packages/typography-track/src/fragment.ts +30 -0
  881. package/packages/typography-track/src/index.ts +11 -0
  882. package/packages/typography-track/src/manifest.ts +556 -0
  883. package/packages/typography-track/src/program.ts +622 -0
  884. package/packages/typography-track/src/surface.ts +842 -0
  885. package/packages/typography-track/src/types.ts +109 -0
  886. package/packages/typography-track-studio/README.md +3 -0
  887. package/packages/typography-track-studio/package.json +14 -0
  888. package/packages/typography-track-studio/src/activation.ts +7 -0
  889. package/packages/typography-track-studio/src/index.ts +116 -0
  890. package/packages/validation/README.md +11 -0
  891. package/packages/validation/package.json +15 -0
  892. package/packages/validation/src/index.ts +100 -0
  893. package/packages/video-cli/README.md +181 -0
  894. package/packages/video-cli/package.json +37 -0
  895. package/packages/video-cli/src/capture.ts +174 -0
  896. package/packages/video-cli/src/cli.ts +109 -0
  897. package/packages/video-cli/src/compiler.ts +32 -0
  898. package/packages/video-cli/src/creation.ts +449 -0
  899. package/packages/video-cli/src/distribution.ts +88 -0
  900. package/packages/video-cli/src/index.ts +50 -0
  901. package/packages/video-cli/src/media.ts +701 -0
  902. package/packages/video-cli/src/package-selection.ts +34 -0
  903. package/packages/video-cli/src/process.ts +71 -0
  904. package/packages/video-cli/src/studio-distribution.ts +19 -0
  905. package/packages/video-cli/src/transcript.ts +71 -0
  906. package/packages/video-cli/src/vocabulary.ts +386 -0
  907. package/packages/visual-ir/README.md +36 -0
  908. package/packages/visual-ir/package.json +16 -0
  909. package/packages/visual-ir/src/activation.ts +3 -0
  910. package/packages/visual-ir/src/index.ts +7 -0
  911. package/packages/visual-ir/src/style.ts +222 -0
  912. package/packages/volcengine-matting/README.md +89 -0
  913. package/packages/volcengine-matting/package.json +16 -0
  914. package/packages/volcengine-matting/src/activation.ts +13 -0
  915. package/packages/volcengine-matting/src/index.ts +45 -0
  916. package/packages/volcengine-matting/src/surface.ts +48 -0
  917. package/packages/whisperx/README.md +34 -0
  918. package/packages/whisperx/package.json +28 -0
  919. package/packages/whisperx/src/activation.ts +18 -0
  920. package/packages/whisperx/src/component.ts +64 -0
  921. package/packages/whisperx/src/evidence.ts +69 -0
  922. package/packages/whisperx/src/fragment.ts +76 -0
  923. package/packages/whisperx/src/index.ts +14 -0
  924. package/packages/whisperx/src/manifest.ts +92 -0
  925. package/packages/whisperx/src/surface.ts +90 -0
  926. package/packages/whisperx/src/transcript.ts +97 -0
  927. package/packages/whisperx/src/types.ts +9 -0
  928. package/packages/workspace/README.md +4 -0
  929. package/packages/workspace/package.json +14 -0
  930. package/packages/workspace/src/index.ts +38 -0
  931. package/packages/workspace-fs-node/README.md +13 -0
  932. package/packages/workspace-fs-node/package.json +15 -0
  933. package/packages/workspace-fs-node/src/index.ts +6 -0
  934. package/packages/workspace-fs-node/src/workspace.ts +226 -0
  935. package/packages/yt-dlp/README.md +31 -0
  936. package/packages/yt-dlp/package.json +10 -0
  937. package/packages/yt-dlp/src/download.ts +104 -0
  938. package/packages/yt-dlp/src/index.ts +1 -0
  939. package/services/image-opencv/README.md +33 -0
  940. package/services/image-opencv/package.json +14 -0
  941. package/services/image-opencv/pyproject.toml +13 -0
  942. package/services/image-opencv/uv.lock +56 -0
  943. package/services/whisperx/README.md +82 -0
  944. package/services/whisperx/package.json +15 -0
  945. package/services/whisperx/pyproject.toml +26 -0
  946. package/services/whisperx/src/hypit_whisperx_service/__init__.py +6 -0
  947. package/services/whisperx/src/hypit_whisperx_service/__main__.py +29 -0
  948. package/services/whisperx/src/hypit_whisperx_service/application.py +88 -0
  949. package/services/whisperx/src/hypit_whisperx_service/audio.py +66 -0
  950. package/services/whisperx/src/hypit_whisperx_service/check.py +35 -0
  951. package/services/whisperx/src/hypit_whisperx_service/config.py +81 -0
  952. package/services/whisperx/src/hypit_whisperx_service/engine.py +173 -0
  953. package/services/whisperx/src/hypit_whisperx_service/prepare.py +19 -0
  954. package/services/whisperx/src/hypit_whisperx_service/resources.py +41 -0
  955. package/services/whisperx/src/hypit_whisperx_service/server.py +101 -0
  956. package/services/whisperx/uv.lock +3381 -0
  957. package/services/yt-dlp/README.md +19 -0
  958. package/services/yt-dlp/package.json +14 -0
  959. package/services/yt-dlp/pyproject.toml +13 -0
  960. package/services/yt-dlp/uv.lock +23 -0
  961. package/index.js +0 -1
@@ -0,0 +1,1403 @@
1
+ import { canonicalStringify, isResourceId } from "@hypit/protocol";
2
+ import type { BlobRef, CanonicalValue } from "@hypit/protocol";
3
+
4
+ import {
5
+ assertVisualStyleV1,
6
+ VISUAL_IR_V1,
7
+ } from "@hypit/visual-ir";
8
+ import {
9
+ assertProgramSpaceIdentity,
10
+ programSpaceFrameCount,
11
+ programSpaceSampleFrames,
12
+ } from "@hypit/program-space";
13
+ import type { ProgramSpace } from "@hypit/program-space";
14
+ import { assertCompositableSurfaceRef, assertFontArtifactRef } from "@hypit/media";
15
+ import type { CompositableSurfaceRef, FontArtifactRef } from "@hypit/media";
16
+
17
+ export type FrameSpan = {
18
+ readonly startFrame: number;
19
+ readonly endFrameExclusive: number;
20
+ };
21
+
22
+ /** One inline style declaration inside a Present-owned element tree. */
23
+ export type VisualStyleDeclaration = {
24
+ readonly name: string;
25
+ readonly value: string | number;
26
+ };
27
+
28
+ export type VisualAttribute = {
29
+ readonly name: string;
30
+ readonly value: string;
31
+ };
32
+
33
+ export type VisualEasing = "linear" | "ease-in" | "ease-out" | "ease-in-out";
34
+
35
+ /**
36
+ * A frame-exact, code-free animation owned by one element. Keyframe offsets
37
+ * are relative to the containing Present and therefore remain deterministic
38
+ * under local and hosted rendering.
39
+ */
40
+ export type VisualKeyframe = {
41
+ readonly atFrame: number;
42
+ readonly easing?: VisualEasing;
43
+ readonly style: readonly VisualStyleDeclaration[];
44
+ };
45
+
46
+ export type VisualAnimation = {
47
+ readonly keyframes: readonly VisualKeyframe[];
48
+ };
49
+
50
+ export type VisualElementBase = {
51
+ readonly id: string;
52
+ readonly parent?: string;
53
+ readonly order: number;
54
+ readonly style: readonly VisualStyleDeclaration[];
55
+ readonly attributes?: readonly VisualAttribute[];
56
+ readonly animation?: VisualAnimation;
57
+ };
58
+
59
+ export type VisualBoxElement = VisualElementBase & {
60
+ readonly kind: "box";
61
+ };
62
+
63
+ /** A renderer-interpreted local program. Its format and payload belong to its rendering package. */
64
+ export type VisualProgramElement = VisualElementBase & {
65
+ readonly kind: "program";
66
+ readonly program: {
67
+ readonly format: string;
68
+ readonly payload: { readonly [key: string]: CanonicalValue };
69
+ readonly artifacts: readonly BlobRef[];
70
+ };
71
+ };
72
+
73
+ /** A strictly local two-input mask. Both roots are direct owned children in the same Present. */
74
+ export type VisualMaskElement = VisualElementBase & {
75
+ readonly kind: "mask";
76
+ readonly mode: "alpha" | "luminance";
77
+ readonly maskElement: string;
78
+ readonly contentElement: string;
79
+ };
80
+
81
+ export type VisualTextElement = VisualElementBase & {
82
+ readonly kind: "text";
83
+ readonly text: string;
84
+ /** Exact ordered fallback faces. Terminal Visual IR never depends on environment fonts. */
85
+ readonly fonts: readonly FontArtifactRef[];
86
+ /**
87
+ * Ordered glyph Paint, in the same vocabulary Text Flow uses.
88
+ *
89
+ * Style alone can only say `-webkit-text-stroke`, which centres an outline on the glyph edge and
90
+ * therefore spends half its width inside the letter. An outline that is asked to sit outside the
91
+ * letter cannot be expressed that way at all. Declaring the Paint instead lets the renderer build
92
+ * the placement that was asked for, and `stroke` before `fill` orders them.
93
+ */
94
+ readonly paints?: readonly VisualTextPaintLayer[];
95
+ };
96
+
97
+ export type VisualTextDirection = "auto" | "ltr" | "rtl";
98
+ export type VisualTextWritingMode = "horizontal-tb" | "vertical-rl" | "vertical-lr";
99
+
100
+ export type VisualTextTypography = {
101
+ /** Exact ordered faces. Author-package prototype families must resolve before this boundary. */
102
+ readonly fonts: readonly FontArtifactRef[];
103
+ readonly sizePx: number;
104
+ readonly weight: number;
105
+ readonly style: "normal" | "italic" | "oblique";
106
+ readonly axes: readonly { readonly tag: string; readonly value: number }[];
107
+ readonly features: readonly { readonly tag: string; readonly enabled: boolean }[];
108
+ readonly synthesis: "none" | "weight" | "style" | "weight-style";
109
+ readonly kerning: "auto" | "normal" | "none";
110
+ readonly trackingPx: number;
111
+ readonly wordSpacingPx: number;
112
+ readonly lineHeight: number;
113
+ readonly language?: string;
114
+ readonly direction: VisualTextDirection;
115
+ readonly writingMode: VisualTextWritingMode;
116
+ readonly baselineShiftPx: number;
117
+ readonly tabSize: number;
118
+ readonly indentationPx: number;
119
+ readonly paragraphBeforePx: number;
120
+ readonly paragraphAfterPx: number;
121
+ readonly transform: "none" | "uppercase" | "lowercase" | "capitalize";
122
+ readonly variantCaps: "normal" | "small-caps" | "all-small-caps";
123
+ readonly verticalAlign: "baseline" | "super" | "sub";
124
+ readonly decorations: readonly VisualTextDecoration[];
125
+ readonly cjk: {
126
+ readonly textSpacing: "normal" | "none";
127
+ readonly punctuationTrim: "none" | "start" | "end" | "adjacent" | "all";
128
+ };
129
+ };
130
+
131
+ /** Explicit run override. Omitted properties inherit; authored text never changes. */
132
+ export type VisualTextRunStyle = {
133
+ readonly typography?: Partial<VisualTextTypography>;
134
+ readonly paints?: readonly VisualTextPaintLayer[];
135
+ };
136
+
137
+ export type VisualTextInline =
138
+ | {
139
+ readonly kind: "text";
140
+ readonly id: string;
141
+ readonly text: string;
142
+ readonly style?: VisualTextRunStyle;
143
+ readonly language?: string;
144
+ readonly direction?: VisualTextDirection;
145
+ }
146
+ | { readonly kind: "break"; readonly id: string };
147
+
148
+ export type VisualTextDocument = {
149
+ readonly paragraphs: readonly {
150
+ readonly id: string;
151
+ readonly inlines: readonly VisualTextInline[];
152
+ readonly style?: VisualTextRunStyle;
153
+ }[];
154
+ };
155
+
156
+ export type VisualColorPaint =
157
+ | { readonly kind: "solid"; readonly color: string }
158
+ | {
159
+ readonly kind: "linear-gradient";
160
+ readonly angleDeg: number;
161
+ readonly stops: readonly { readonly offset: number; readonly color: string; readonly opacity: number }[];
162
+ }
163
+ | {
164
+ readonly kind: "radial-gradient";
165
+ readonly center: { readonly x: number; readonly y: number };
166
+ readonly stops: readonly { readonly offset: number; readonly color: string; readonly opacity: number }[];
167
+ };
168
+
169
+ export type VisualTextDecoration = {
170
+ readonly line: "underline" | "overline" | "line-through";
171
+ readonly paint: VisualColorPaint;
172
+ readonly style: "solid" | "double" | "dotted" | "dashed" | "wavy";
173
+ readonly thicknessPx?: number;
174
+ readonly offsetPx?: number;
175
+ readonly skipInk: boolean;
176
+ };
177
+
178
+ export type VisualTextBoxDecoration = {
179
+ readonly fill?: VisualColorPaint;
180
+ readonly border?: {
181
+ readonly paint: VisualColorPaint;
182
+ readonly widthsPx: { readonly top: number; readonly right: number; readonly bottom: number; readonly left: number };
183
+ readonly style: "solid" | "dashed" | "dotted";
184
+ };
185
+ readonly paddingPx: { readonly top: number; readonly right: number; readonly bottom: number; readonly left: number };
186
+ readonly radiiPx: { readonly topLeft: number; readonly topRight: number; readonly bottomRight: number; readonly bottomLeft: number };
187
+ readonly shadows: readonly {
188
+ readonly paint: VisualColorPaint;
189
+ readonly offsetX: number;
190
+ readonly offsetY: number;
191
+ readonly blurPx: number;
192
+ readonly spreadPx: number;
193
+ }[];
194
+ readonly tail?: {
195
+ readonly side: "top" | "right" | "bottom" | "left";
196
+ readonly offset: number;
197
+ readonly widthPx: number;
198
+ readonly heightPx: number;
199
+ readonly paint: VisualColorPaint;
200
+ };
201
+ };
202
+
203
+ export type VisualTextPaintTarget = "frame" | "content" | "paragraph" | "line" | "run" | "word" | "grapheme";
204
+
205
+ /** Ordered renderer-neutral text Paint. Repetition and array order are semantic. */
206
+ export type VisualTextPaintLayer =
207
+ | { readonly kind: "fill"; readonly paint: VisualColorPaint }
208
+ | {
209
+ readonly kind: "stroke";
210
+ readonly paint: VisualColorPaint;
211
+ readonly widthPx: number;
212
+ readonly placement: "inside" | "center" | "outside";
213
+ }
214
+ | {
215
+ readonly kind: "shadow";
216
+ readonly paint: VisualColorPaint;
217
+ readonly offsetX: number;
218
+ readonly offsetY: number;
219
+ readonly blurPx: number;
220
+ readonly spreadPx: number;
221
+ }
222
+ | { readonly kind: "glow"; readonly paint: VisualColorPaint; readonly blurPx: number; readonly spreadPx: number }
223
+ | {
224
+ readonly kind: "box";
225
+ readonly target: VisualTextPaintTarget;
226
+ readonly continuity: "isolated" | "joined";
227
+ readonly decoration: VisualTextBoxDecoration;
228
+ };
229
+
230
+ export type VisualTextFlow = {
231
+ readonly form:
232
+ | {
233
+ readonly kind: "point";
234
+ readonly anchorInline: "start" | "center" | "end";
235
+ readonly anchorBlock: "start" | "center" | "end";
236
+ }
237
+ | { readonly kind: "area" };
238
+ readonly inlineSize: "hug" | "fixed";
239
+ readonly blockSize: "hug" | "fixed";
240
+ readonly paddingPx: { readonly inlineStart: number; readonly inlineEnd: number; readonly blockStart: number; readonly blockEnd: number };
241
+ readonly inlineAlign: "start" | "center" | "end" | "justify";
242
+ readonly blockAlign: "start" | "center" | "end";
243
+ readonly wrap: "none" | "word" | "grapheme";
244
+ readonly overflow: "visible" | "clip" | "ellipsis" | "shrink";
245
+ readonly maxLines?: number;
246
+ readonly minimumScale?: number;
247
+ readonly clipToFrame: boolean;
248
+ readonly columns: number;
249
+ readonly columnGapPx: number;
250
+ readonly metricEdge: "line-box" | "cap-height" | "ink";
251
+ };
252
+
253
+ export type VisualTextSequenceAnimation = {
254
+ readonly id: string;
255
+ readonly unit: "paragraph" | "line" | "run" | "word" | "grapheme";
256
+ readonly range: { readonly start: number; readonly endExclusive: number };
257
+ readonly order: "forward" | "reverse" | "random";
258
+ readonly startFrame: number;
259
+ readonly unitDurationFrames: number;
260
+ readonly staggerFrames: number;
261
+ readonly cycles: number;
262
+ readonly seed?: number;
263
+ readonly keyframes: readonly {
264
+ readonly atProgress: number;
265
+ readonly easing?: VisualEasing;
266
+ readonly style: readonly VisualStyleDeclaration[];
267
+ }[];
268
+ };
269
+
270
+ /** Exact terminal text flow. It contains no author Style/Recipe reference or renderer callback. */
271
+ export type VisualTextFlowElement = VisualElementBase & {
272
+ readonly kind: "text-flow";
273
+ readonly document: VisualTextDocument;
274
+ readonly typography: VisualTextTypography;
275
+ readonly paints: readonly VisualTextPaintLayer[];
276
+ readonly flow: VisualTextFlow;
277
+ readonly sequences: readonly VisualTextSequenceAnimation[];
278
+ };
279
+
280
+ export type VisualVectorPathCommand =
281
+ | { readonly kind: "move" | "line"; readonly x: number; readonly y: number }
282
+ | { readonly kind: "quadratic"; readonly controlX: number; readonly controlY: number; readonly x: number; readonly y: number }
283
+ | { readonly kind: "cubic"; readonly control1X: number; readonly control1Y: number; readonly control2X: number; readonly control2Y: number; readonly x: number; readonly y: number }
284
+ | { readonly kind: "close" };
285
+
286
+ export type VisualPathTextElement = VisualElementBase & {
287
+ readonly kind: "path-text";
288
+ readonly document: VisualTextDocument;
289
+ readonly typography: VisualTextTypography;
290
+ readonly paints: readonly VisualTextPaintLayer[];
291
+ readonly path: readonly VisualVectorPathCommand[];
292
+ readonly side: "left" | "right";
293
+ readonly orientation: "follow" | "upright";
294
+ readonly startMarginPx: number;
295
+ readonly endMarginPx: number;
296
+ readonly align: "start" | "center" | "end";
297
+ readonly reverse: boolean;
298
+ readonly overflow: "visible" | "clip";
299
+ readonly sequences: readonly VisualTextSequenceAnimation[];
300
+ readonly marginAnimation?: {
301
+ readonly keyframes: readonly {
302
+ readonly atFrame: number;
303
+ readonly startMarginPx: number;
304
+ readonly easing?: VisualEasing;
305
+ }[];
306
+ };
307
+ };
308
+
309
+ export type VisualSamplingRational = {
310
+ readonly numerator: number;
311
+ readonly denominator: number;
312
+ };
313
+
314
+ /**
315
+ * One exact piece of a timed visual's source-time function. Target frames are
316
+ * relative to the containing Present. A gap means the material is invisible.
317
+ */
318
+ export type VisualSamplingSegment = {
319
+ readonly target: FrameSpan;
320
+ /** Absolute source-frame position at target.startFrame. */
321
+ readonly sourceFrame: VisualSamplingRational;
322
+ /** Source frames advanced per Program frame; zero is an exact held frame. */
323
+ readonly rate: VisualSamplingRational;
324
+ readonly loop?: FrameSpan;
325
+ };
326
+
327
+ export type VisualTimedSampling = {
328
+ readonly sourceFrameRate: VisualSamplingRational;
329
+ readonly sourceFrameCount: number;
330
+ readonly segments: readonly VisualSamplingSegment[];
331
+ };
332
+
333
+ export type VisualMediaElement = VisualElementBase & {
334
+ readonly kind: "image" | "video";
335
+ readonly artifact: BlobRef;
336
+ /** Exact frame-domain mapping for timed media. */
337
+ readonly sampling?: VisualTimedSampling;
338
+ readonly muted?: boolean;
339
+ };
340
+
341
+ /** A package-materialized visual surface with content-bound compositing metadata, not an untyped media guess. */
342
+ export type VisualSurfaceElement = VisualElementBase & {
343
+ readonly kind: "surface";
344
+ readonly surface: CompositableSurfaceRef;
345
+ readonly sampling?: VisualTimedSampling;
346
+ };
347
+
348
+ /**
349
+ * Structural elements and explicit renderer programs compose in one owned tree.
350
+ *
351
+ * A Present holds exactly one root; everything else names a `parent`, which can be a box,
352
+ * mask or program. **Position is measured from that parent, not from the Canvas.** A component that computes
353
+ * its layout in Canvas pixels and then nests its elements has to subtract the parent's own origin,
354
+ * or every child lands offset by it — which draws without complaint and is wrong by exactly the
355
+ * distance the parent sits from the corner.
356
+ */
357
+ export type VisualElement = VisualBoxElement | VisualProgramElement | VisualMaskElement | VisualTextElement | VisualTextFlowElement | VisualPathTextElement | VisualMediaElement | VisualSurfaceElement;
358
+
359
+ export type VisualPresent = {
360
+ readonly id: string;
361
+ /** Optional domain entity implemented by this renderer Present. */
362
+ readonly subjectId?: string;
363
+ readonly span: FrameSpan;
364
+ /** Absolute paint position for this Present, not for its authoring Track. */
365
+ readonly stacking: {
366
+ readonly order: number;
367
+ readonly tieBreak: string;
368
+ };
369
+ readonly elements: readonly VisualElement[];
370
+ };
371
+
372
+ export type VisualTrack = {
373
+ readonly kind: "visual";
374
+ /** ProgramSpace identity this terminal placement was rendered against. */
375
+ readonly programSpaceId: string;
376
+ /** The one terminal visual language shared by official video components. */
377
+ readonly visualIr: typeof VISUAL_IR_V1;
378
+ readonly id: string;
379
+ /** Author-owned contributions that Composition may interleave by absolute z. */
380
+ readonly presents: readonly VisualPresent[];
381
+ };
382
+
383
+ export type AudioClip = {
384
+ readonly id: string;
385
+ /** Optional domain entity implemented by this renderer Clip. */
386
+ readonly subjectId?: string;
387
+ /** Bytes only. Exact duration belongs to source.sampleFrames, not duplicated floating metadata. */
388
+ readonly artifact: BlobRef;
389
+ /** Exact audible placement in the canonical 48 kHz ProgramSpace sample domain. */
390
+ readonly target: {
391
+ readonly startSample: number;
392
+ readonly endSampleExclusive: number;
393
+ };
394
+ /** Exact sampling interval in one canonical 48 kHz stereo WAV Artifact. */
395
+ readonly source: {
396
+ readonly sampleFrames: number;
397
+ readonly startSample: number;
398
+ readonly endSampleExclusive: number;
399
+ readonly loop: boolean;
400
+ /** Offset inside the effective source interval used only when looping. */
401
+ readonly phaseSample: number;
402
+ };
403
+ readonly playbackRate: number;
404
+ readonly pitch: "preserve";
405
+ readonly gain: number;
406
+ readonly fadeInSamples: number;
407
+ readonly fadeOutSamples: number;
408
+ };
409
+
410
+ export type AudioTrack = {
411
+ readonly kind: "audio";
412
+ /** ProgramSpace identity this terminal placement was rendered against. */
413
+ readonly programSpaceId: string;
414
+ readonly id: string;
415
+ readonly clips: readonly AudioClip[];
416
+ };
417
+
418
+ export type Track = VisualTrack | AudioTrack;
419
+
420
+ export type Composition = {
421
+ readonly id: string;
422
+ readonly canvas: {
423
+ readonly width: number;
424
+ readonly height: number;
425
+ /** Structural clear color beneath every VisualTrack. */
426
+ readonly clearColor: string;
427
+ };
428
+ readonly tracks: readonly Track[];
429
+ };
430
+
431
+ /** The only local style properties accepted in element keyframes. */
432
+ export const animatableLocalStyles = [
433
+ "backdrop-filter",
434
+ "clip-path",
435
+ "filter",
436
+ "opacity",
437
+ "transform",
438
+ ] as const;
439
+ const ANIMATABLE_LOCAL_STYLES = new Set<string>(animatableLocalStyles);
440
+
441
+ const ANIMATABLE_TEXT_UNIT_STYLES = new Set([
442
+ "-webkit-text-fill-color",
443
+ "-webkit-text-stroke-color",
444
+ "background-color",
445
+ "color",
446
+ "filter",
447
+ "opacity",
448
+ "transform",
449
+ ]);
450
+
451
+ function assertNonEmpty(value: string, label: string): void {
452
+ if (!value) throw new Error(`${label} must not be empty.`);
453
+ }
454
+
455
+ function assertFrameSpan(span: FrameSpan, totalFrames: number, label: string): void {
456
+ if (
457
+ !Number.isSafeInteger(span.startFrame)
458
+ || !Number.isSafeInteger(span.endFrameExclusive)
459
+ || span.startFrame < 0
460
+ || span.endFrameExclusive <= span.startFrame
461
+ || span.endFrameExclusive > totalFrames
462
+ ) {
463
+ throw new Error(`${label} is outside ProgramSpace.`);
464
+ }
465
+ }
466
+
467
+ function assertMediaArtifact(artifact: BlobRef, label: string): void {
468
+ if (
469
+ artifact.kind !== "blob"
470
+ || !isResourceId(artifact.resource)
471
+ || !Number.isSafeInteger(artifact.size)
472
+ || artifact.size < 0
473
+ || !artifact.mediaType
474
+ ) {
475
+ throw new Error(`${label} is invalid.`);
476
+ }
477
+ }
478
+
479
+ function assertRational(value: VisualSamplingRational, label: string, allowZero: boolean): void {
480
+ if (!Number.isSafeInteger(value.numerator) || (!allowZero && value.numerator <= 0) || (allowZero && value.numerator < 0)
481
+ || !Number.isSafeInteger(value.denominator) || value.denominator <= 0) {
482
+ throw new Error(`${label} must be a non-negative safe rational.`);
483
+ }
484
+ }
485
+
486
+ function compareRationalToInteger(value: VisualSamplingRational, integer: number): number {
487
+ const difference = BigInt(value.numerator) - BigInt(integer) * BigInt(value.denominator);
488
+ return difference < 0n ? -1 : difference > 0n ? 1 : 0;
489
+ }
490
+
491
+ function sourceAt(segment: VisualSamplingSegment, targetOffset: number): VisualSamplingRational {
492
+ const denominator = BigInt(segment.sourceFrame.denominator) * BigInt(segment.rate.denominator);
493
+ const numerator = BigInt(segment.sourceFrame.numerator) * BigInt(segment.rate.denominator)
494
+ + BigInt(targetOffset) * BigInt(segment.rate.numerator) * BigInt(segment.sourceFrame.denominator);
495
+ if (numerator > BigInt(Number.MAX_SAFE_INTEGER) || denominator > BigInt(Number.MAX_SAFE_INTEGER)) {
496
+ throw new Error("Visual sampling arithmetic exceeds the safe wire domain.");
497
+ }
498
+ return { numerator: Number(numerator), denominator: Number(denominator) };
499
+ }
500
+
501
+ function assertSampling(value: VisualTimedSampling, durationFrames: number, label: string): void {
502
+ assertRational(value.sourceFrameRate, `${label}.sourceFrameRate`, false);
503
+ if (!Number.isSafeInteger(value.sourceFrameCount) || value.sourceFrameCount <= 0 || value.segments.length === 0) {
504
+ throw new Error(`${label} source frame domain is invalid.`);
505
+ }
506
+ let previousEnd = 0;
507
+ for (const [index, segment] of value.segments.entries()) {
508
+ const item = `${label}.segments.${index}`;
509
+ if (!Number.isSafeInteger(segment.target.startFrame) || !Number.isSafeInteger(segment.target.endFrameExclusive)
510
+ || segment.target.startFrame < previousEnd || segment.target.endFrameExclusive <= segment.target.startFrame
511
+ || segment.target.endFrameExclusive > durationFrames) throw new Error(`${item} target interval is invalid.`);
512
+ assertRational(segment.sourceFrame, `${item}.sourceFrame`, true);
513
+ assertRational(segment.rate, `${item}.rate`, true);
514
+ if (segment.loop !== undefined) {
515
+ if (!Number.isSafeInteger(segment.loop.startFrame) || !Number.isSafeInteger(segment.loop.endFrameExclusive)
516
+ || segment.loop.startFrame < 0 || segment.loop.endFrameExclusive <= segment.loop.startFrame
517
+ || segment.loop.endFrameExclusive > value.sourceFrameCount
518
+ || compareRationalToInteger(segment.sourceFrame, segment.loop.startFrame) < 0
519
+ || compareRationalToInteger(segment.sourceFrame, segment.loop.endFrameExclusive) >= 0) {
520
+ throw new Error(`${item} loop interval or phase is invalid.`);
521
+ }
522
+ } else {
523
+ const last = sourceAt(segment, segment.target.endFrameExclusive - segment.target.startFrame - 1);
524
+ if (compareRationalToInteger(segment.sourceFrame, 0) < 0
525
+ || compareRationalToInteger(segment.sourceFrame, value.sourceFrameCount) >= 0
526
+ || compareRationalToInteger(last, 0) < 0
527
+ || compareRationalToInteger(last, value.sourceFrameCount) >= 0) {
528
+ throw new Error(`${item} samples outside its source frame domain.`);
529
+ }
530
+ }
531
+ previousEnd = segment.target.endFrameExclusive;
532
+ }
533
+ }
534
+
535
+ function assertAudioArtifact(artifact: BlobRef, label: string): void {
536
+ if (
537
+ artifact.kind !== "blob"
538
+ || !isResourceId(artifact.resource)
539
+ || !Number.isSafeInteger(artifact.size)
540
+ || artifact.size < 0
541
+ || artifact.mediaType !== "audio/wav"
542
+ ) {
543
+ throw new Error(`${label} must be a canonical WAV BlobRef.`);
544
+ }
545
+ }
546
+
547
+ function assertStyle(style: readonly VisualStyleDeclaration[], label: string): void {
548
+ const names = new Set<string>();
549
+ for (const declaration of style) {
550
+ if (names.has(declaration.name)) {
551
+ throw new Error(`${label} contains duplicate style ${declaration.name}.`);
552
+ }
553
+ names.add(declaration.name);
554
+ assertVisualStyleV1(declaration.name, declaration.value, label);
555
+ }
556
+ }
557
+
558
+ function assertAttributes(attributes: readonly VisualAttribute[] | undefined, label: string): void {
559
+ const names = new Set<string>();
560
+ for (const attribute of attributes ?? []) {
561
+ if (!/^(?:data-[a-z0-9-]+|aria-[a-z0-9-]+|role|title|lang|dir)$/u.test(attribute.name)) {
562
+ throw new Error(`${label} contains unsafe attribute ${attribute.name}.`);
563
+ }
564
+ if (attribute.name === "lang" && !/^[A-Za-z0-9]+(?:-[A-Za-z0-9]+)*$/u.test(attribute.value)) {
565
+ throw new Error(`${label} contains invalid lang ${attribute.value}.`);
566
+ }
567
+ if (attribute.name === "dir" && !["ltr", "rtl", "auto"].includes(attribute.value)) {
568
+ throw new Error(`${label} contains invalid dir ${attribute.value}.`);
569
+ }
570
+ if (names.has(attribute.name)) {
571
+ throw new Error(`${label} contains duplicate attribute ${attribute.name}.`);
572
+ }
573
+ names.add(attribute.name);
574
+ }
575
+ }
576
+
577
+ function assertExactFonts(fonts: readonly FontArtifactRef[], label: string): void {
578
+ if (fonts.length === 0) throw new Error(`${label} has an empty font stack.`);
579
+ const faces = new Set<string>();
580
+ for (const [index, font] of fonts.entries()) {
581
+ assertFontArtifactRef(font, `${label}.${index}`);
582
+ const face = canonicalStringify(font);
583
+ if (faces.has(face)) throw new Error(`${label} has a duplicate font face.`);
584
+ faces.add(face);
585
+ }
586
+ }
587
+
588
+ function finite(value: number, label: string): void {
589
+ if (!Number.isFinite(value)) throw new Error(`${label} must be finite.`);
590
+ }
591
+
592
+ function nonNegative(value: number, label: string): void {
593
+ finite(value, label);
594
+ if (value < 0) throw new Error(`${label} must not be negative.`);
595
+ }
596
+
597
+ function assertColor(value: string, label: string): void {
598
+ assertNonEmpty(value, label);
599
+ if (value.length > 256
600
+ || /[;{}<>"'\\]|!important|[\u0000-\u001f\u007f]/iu.test(value)
601
+ || /(?:url|var|env|attr|image-set)\s*\(/iu.test(value)) {
602
+ throw new Error(`${label} contains an unsafe or environment-dependent color.`);
603
+ }
604
+ }
605
+
606
+ function assertColorPaint(paint: VisualColorPaint, label: string): void {
607
+ if (paint.kind === "solid") {
608
+ assertColor(paint.color, `${label}.color`);
609
+ return;
610
+ }
611
+ if (paint.kind !== "linear-gradient" && paint.kind !== "radial-gradient") {
612
+ throw new Error(`${label} has an unsupported Paint kind.`);
613
+ }
614
+ if (paint.kind === "linear-gradient") finite(paint.angleDeg, `${label}.angleDeg`);
615
+ else {
616
+ finite(paint.center.x, `${label}.center.x`);
617
+ finite(paint.center.y, `${label}.center.y`);
618
+ if (paint.center.x < 0 || paint.center.x > 1 || paint.center.y < 0 || paint.center.y > 1) {
619
+ throw new Error(`${label}.center must be normalized.`);
620
+ }
621
+ }
622
+ if (paint.stops.length < 2) throw new Error(`${label} requires at least two gradient stops.`);
623
+ let previous = -1;
624
+ for (const [index, stop] of paint.stops.entries()) {
625
+ finite(stop.offset, `${label}.stops.${index}.offset`);
626
+ finite(stop.opacity, `${label}.stops.${index}.opacity`);
627
+ assertColor(stop.color, `${label}.stops.${index}.color`);
628
+ if (stop.offset < 0 || stop.offset > 1 || stop.offset < previous || stop.opacity < 0 || stop.opacity > 1) {
629
+ throw new Error(`${label} has invalid gradient stops.`);
630
+ }
631
+ previous = stop.offset;
632
+ }
633
+ }
634
+
635
+ function assertTypography(typography: VisualTextTypography, label: string): void {
636
+ assertExactFonts(typography.fonts, `${label}.fonts`);
637
+ finite(typography.sizePx, `${label}.sizePx`);
638
+ if (typography.sizePx <= 0 || !Number.isSafeInteger(typography.weight) || typography.weight < 1 || typography.weight > 1_000) {
639
+ throw new Error(`${label} size or weight is invalid.`);
640
+ }
641
+ if (!["normal", "italic", "oblique"].includes(typography.style)
642
+ || !["none", "weight", "style", "weight-style"].includes(typography.synthesis)
643
+ || !["auto", "normal", "none"].includes(typography.kerning)
644
+ || !["auto", "ltr", "rtl"].includes(typography.direction)
645
+ || !["horizontal-tb", "vertical-rl", "vertical-lr"].includes(typography.writingMode)
646
+ || !["none", "uppercase", "lowercase", "capitalize"].includes(typography.transform)
647
+ || !["normal", "small-caps", "all-small-caps"].includes(typography.variantCaps)
648
+ || !["baseline", "super", "sub"].includes(typography.verticalAlign)) {
649
+ throw new Error(`${label} contains an unsupported typography enum.`);
650
+ }
651
+ for (const [name, value] of Object.entries({
652
+ trackingPx: typography.trackingPx,
653
+ wordSpacingPx: typography.wordSpacingPx,
654
+ lineHeight: typography.lineHeight,
655
+ baselineShiftPx: typography.baselineShiftPx,
656
+ indentationPx: typography.indentationPx,
657
+ paragraphBeforePx: typography.paragraphBeforePx,
658
+ paragraphAfterPx: typography.paragraphAfterPx,
659
+ })) finite(value, `${label}.${name}`);
660
+ if (typography.lineHeight <= 0 || !Number.isSafeInteger(typography.tabSize) || typography.tabSize <= 0) {
661
+ throw new Error(`${label} lineHeight or tabSize is invalid.`);
662
+ }
663
+ const axes = new Set<string>();
664
+ for (const [index, axis] of typography.axes.entries()) {
665
+ if (!/^[\x20-\x7e]{4}$/u.test(axis.tag) || axes.has(axis.tag)) throw new Error(`${label}.axes.${index} is invalid.`);
666
+ finite(axis.value, `${label}.axes.${index}.value`);
667
+ axes.add(axis.tag);
668
+ }
669
+ const features = new Set<string>();
670
+ for (const [index, feature] of typography.features.entries()) {
671
+ if (!/^[\x20-\x7e]{4}$/u.test(feature.tag) || features.has(feature.tag)) throw new Error(`${label}.features.${index} is invalid.`);
672
+ features.add(feature.tag);
673
+ }
674
+ const decorations = new Set<string>();
675
+ for (const [index, decoration] of typography.decorations.entries()) {
676
+ const item = `${label}.decorations.${index}`;
677
+ if (!["underline", "overline", "line-through"].includes(decoration.line)
678
+ || !["solid", "double", "dotted", "dashed", "wavy"].includes(decoration.style)
679
+ || decorations.has(decoration.line)) {
680
+ throw new Error(`${item} is invalid or repeated.`);
681
+ }
682
+ decorations.add(decoration.line);
683
+ assertColorPaint(decoration.paint, `${item}.paint`);
684
+ if (decoration.thicknessPx !== undefined) nonNegative(decoration.thicknessPx, `${item}.thicknessPx`);
685
+ if (decoration.offsetPx !== undefined) finite(decoration.offsetPx, `${item}.offsetPx`);
686
+ }
687
+ }
688
+
689
+ function assertRunStyle(style: VisualTextRunStyle | undefined, label: string): void {
690
+ if (style === undefined) return;
691
+ if (style.typography !== undefined) {
692
+ const merged = style.typography;
693
+ if (merged.fonts !== undefined) assertExactFonts(merged.fonts, `${label}.fonts`);
694
+ for (const [name, value] of Object.entries(merged)) {
695
+ if (typeof value === "number") finite(value, `${label}.${name}`);
696
+ }
697
+ }
698
+ for (const [index, paint] of (style.paints ?? []).entries()) assertTextPaint(paint, `${label}.paints.${index}`);
699
+ }
700
+
701
+ function inheritedTypography(
702
+ base: VisualTextTypography,
703
+ style: VisualTextRunStyle | undefined,
704
+ ): VisualTextTypography {
705
+ const override = style?.typography;
706
+ if (override === undefined) return base;
707
+ const {
708
+ fonts: _fonts,
709
+ axes: _axes,
710
+ features: _features,
711
+ decorations: _decorations,
712
+ cjk: _cjk,
713
+ ...scalarOverrides
714
+ } = override;
715
+ return {
716
+ ...base,
717
+ ...scalarOverrides,
718
+ fonts: override.fonts ?? base.fonts,
719
+ axes: override.axes ?? base.axes,
720
+ features: override.features ?? base.features,
721
+ decorations: override.decorations ?? base.decorations,
722
+ cjk: override.cjk === undefined ? base.cjk : { ...base.cjk, ...override.cjk },
723
+ };
724
+ }
725
+
726
+ function assertTextDocument(
727
+ document: VisualTextDocument,
728
+ typography: VisualTextTypography,
729
+ label: string,
730
+ ): void {
731
+ if (document.paragraphs.length === 0) throw new Error(`${label} has no paragraphs.`);
732
+ const ids = new Set<string>();
733
+ let hasText = false;
734
+ for (const [paragraphIndex, paragraph] of document.paragraphs.entries()) {
735
+ assertNonEmpty(paragraph.id, `${label}.paragraphs.${paragraphIndex}.id`);
736
+ if (ids.has(paragraph.id) || paragraph.inlines.length === 0) throw new Error(`${label} has an invalid paragraph.`);
737
+ ids.add(paragraph.id);
738
+ assertRunStyle(paragraph.style, `${label}.paragraphs.${paragraphIndex}.style`);
739
+ const paragraphTypography = inheritedTypography(typography, paragraph.style);
740
+ assertTypography(paragraphTypography, `${label}.paragraphs.${paragraphIndex}.typography`);
741
+ for (const [inlineIndex, inline] of paragraph.inlines.entries()) {
742
+ assertNonEmpty(inline.id, `${label}.paragraphs.${paragraphIndex}.inlines.${inlineIndex}.id`);
743
+ if (ids.has(inline.id)) throw new Error(`${label} repeats inline id ${inline.id}.`);
744
+ ids.add(inline.id);
745
+ if (inline.kind === "text") {
746
+ if (inline.text.length === 0) throw new Error(`${label} contains an empty text run.`);
747
+ hasText ||= inline.text.trim().length > 0;
748
+ assertRunStyle(inline.style, `${label}.paragraphs.${paragraphIndex}.inlines.${inlineIndex}.style`);
749
+ const inlineTypography = inheritedTypography(paragraphTypography, inline.style);
750
+ assertTypography(inlineTypography, `${label}.paragraphs.${paragraphIndex}.inlines.${inlineIndex}.typography`);
751
+ if (inline.direction !== undefined && !["auto", "ltr", "rtl"].includes(inline.direction)) {
752
+ throw new Error(`${label}.paragraphs.${paragraphIndex}.inlines.${inlineIndex}.direction is invalid.`);
753
+ }
754
+ } else if (inline.kind !== "break") throw new Error(`${label} contains an unsupported inline.`);
755
+ }
756
+ }
757
+ if (!hasText) throw new Error(`${label} contains no visible text.`);
758
+ }
759
+
760
+ function assertBoxDecoration(decoration: VisualTextBoxDecoration, label: string): void {
761
+ if (decoration.fill !== undefined) assertColorPaint(decoration.fill, `${label}.fill`);
762
+ for (const [name, value] of Object.entries(decoration.paddingPx)) nonNegative(value, `${label}.paddingPx.${name}`);
763
+ for (const [name, value] of Object.entries(decoration.radiiPx)) nonNegative(value, `${label}.radiiPx.${name}`);
764
+ if (decoration.border !== undefined) {
765
+ assertColorPaint(decoration.border.paint, `${label}.border.paint`);
766
+ if (!["solid", "dashed", "dotted"].includes(decoration.border.style)) {
767
+ throw new Error(`${label}.border.style is invalid.`);
768
+ }
769
+ for (const [name, value] of Object.entries(decoration.border.widthsPx)) nonNegative(value, `${label}.border.widthsPx.${name}`);
770
+ }
771
+ for (const [index, shadow] of decoration.shadows.entries()) {
772
+ assertColorPaint(shadow.paint, `${label}.shadows.${index}.paint`);
773
+ finite(shadow.offsetX, `${label}.shadows.${index}.offsetX`);
774
+ finite(shadow.offsetY, `${label}.shadows.${index}.offsetY`);
775
+ nonNegative(shadow.blurPx, `${label}.shadows.${index}.blurPx`);
776
+ finite(shadow.spreadPx, `${label}.shadows.${index}.spreadPx`);
777
+ }
778
+ if (decoration.tail !== undefined) {
779
+ if (!["top", "right", "bottom", "left"].includes(decoration.tail.side)) {
780
+ throw new Error(`${label}.tail.side is invalid.`);
781
+ }
782
+ finite(decoration.tail.offset, `${label}.tail.offset`);
783
+ nonNegative(decoration.tail.widthPx, `${label}.tail.widthPx`);
784
+ nonNegative(decoration.tail.heightPx, `${label}.tail.heightPx`);
785
+ assertColorPaint(decoration.tail.paint, `${label}.tail.paint`);
786
+ }
787
+ }
788
+
789
+ function assertTextPaint(paint: VisualTextPaintLayer, label: string): void {
790
+ if (paint.kind === "fill") return assertColorPaint(paint.paint, `${label}.paint`);
791
+ if (paint.kind === "stroke") {
792
+ assertColorPaint(paint.paint, `${label}.paint`);
793
+ if (!["inside", "center", "outside"].includes(paint.placement)) {
794
+ throw new Error(`${label}.placement is invalid.`);
795
+ }
796
+ return nonNegative(paint.widthPx, `${label}.widthPx`);
797
+ }
798
+ if (paint.kind === "shadow") {
799
+ assertColorPaint(paint.paint, `${label}.paint`);
800
+ finite(paint.offsetX, `${label}.offsetX`);
801
+ finite(paint.offsetY, `${label}.offsetY`);
802
+ nonNegative(paint.blurPx, `${label}.blurPx`);
803
+ finite(paint.spreadPx, `${label}.spreadPx`);
804
+ return;
805
+ }
806
+ if (paint.kind === "glow") {
807
+ assertColorPaint(paint.paint, `${label}.paint`);
808
+ nonNegative(paint.blurPx, `${label}.blurPx`);
809
+ finite(paint.spreadPx, `${label}.spreadPx`);
810
+ return;
811
+ }
812
+ if (paint.kind !== "box") throw new Error(`${label} has an unsupported Paint kind.`);
813
+ if (paint.continuity === "joined" && !["line", "word", "grapheme"].includes(paint.target)) {
814
+ throw new Error(`${label} joined continuity is invalid for ${paint.target}.`);
815
+ }
816
+ assertBoxDecoration(paint.decoration, `${label}.decoration`);
817
+ }
818
+
819
+ function assertTextFlow(flow: VisualTextFlow, label: string): void {
820
+ if (!(["hug", "fixed"] as const).includes(flow.inlineSize)
821
+ || !(["hug", "fixed"] as const).includes(flow.blockSize)
822
+ || !(["start", "center", "end", "justify"] as const).includes(flow.inlineAlign)
823
+ || !(["start", "center", "end"] as const).includes(flow.blockAlign)
824
+ || !(["none", "word", "grapheme"] as const).includes(flow.wrap)
825
+ || !(["visible", "clip", "ellipsis", "shrink"] as const).includes(flow.overflow)
826
+ || !(["line-box", "cap-height", "ink"] as const).includes(flow.metricEdge)) {
827
+ throw new Error(`${label} contains an unsupported flow enum.`);
828
+ }
829
+ if (flow.form.kind === "point" && (flow.inlineSize !== "hug" || flow.blockSize !== "hug" || flow.wrap !== "none")) {
830
+ throw new Error(`${label} Point Text must hug both axes and cannot soft-wrap.`);
831
+ }
832
+ for (const [name, value] of Object.entries(flow.paddingPx)) nonNegative(value, `${label}.paddingPx.${name}`);
833
+ if (!Number.isSafeInteger(flow.columns) || flow.columns <= 0) throw new Error(`${label}.columns must be positive.`);
834
+ nonNegative(flow.columnGapPx, `${label}.columnGapPx`);
835
+ if (flow.maxLines !== undefined && (!Number.isSafeInteger(flow.maxLines) || flow.maxLines <= 0)) {
836
+ throw new Error(`${label}.maxLines must be positive.`);
837
+ }
838
+ if (flow.maxLines !== undefined && flow.overflow !== "ellipsis" && flow.overflow !== "shrink") {
839
+ throw new Error(`${label}.maxLines is valid only for ellipsis or shrink.`);
840
+ }
841
+ if (flow.overflow === "shrink") {
842
+ if (flow.minimumScale === undefined || !Number.isFinite(flow.minimumScale) || flow.minimumScale <= 0 || flow.minimumScale > 1) {
843
+ throw new Error(`${label}.minimumScale is required in (0, 1] for shrink.`);
844
+ }
845
+ } else if (flow.minimumScale !== undefined) throw new Error(`${label}.minimumScale is valid only for shrink.`);
846
+ }
847
+
848
+ function assertTextSequences(
849
+ sequences: readonly VisualTextSequenceAnimation[],
850
+ _durationFrames: number,
851
+ label: string,
852
+ ): void {
853
+ const ids = new Set<string>();
854
+ for (const [index, sequence] of sequences.entries()) {
855
+ const item = `${label}.${index}`;
856
+ assertNonEmpty(sequence.id, `${item}.id`);
857
+ if (ids.has(sequence.id)) throw new Error(`${label} repeats ${sequence.id}.`);
858
+ ids.add(sequence.id);
859
+ if (!(["paragraph", "line", "run", "word", "grapheme"] as const).includes(sequence.unit)
860
+ || !(["forward", "reverse", "random"] as const).includes(sequence.order)) {
861
+ throw new Error(`${item} unit or order is invalid.`);
862
+ }
863
+ if (!Number.isSafeInteger(sequence.range.start) || !Number.isSafeInteger(sequence.range.endExclusive)
864
+ || sequence.range.start < 0 || sequence.range.endExclusive <= sequence.range.start
865
+ || !Number.isSafeInteger(sequence.startFrame) || sequence.startFrame < 0
866
+ || !Number.isSafeInteger(sequence.unitDurationFrames) || sequence.unitDurationFrames <= 0
867
+ || !Number.isSafeInteger(sequence.staggerFrames) || sequence.staggerFrames < 0
868
+ || !Number.isSafeInteger(sequence.cycles) || sequence.cycles <= 0
869
+ || (sequence.seed !== undefined && !Number.isSafeInteger(sequence.seed))) {
870
+ throw new Error(`${item} frame domain or range is invalid.`);
871
+ }
872
+ if ((sequence.order === "random") !== (sequence.seed !== undefined)) {
873
+ throw new Error(`${item} random order requires one explicit seed, and other orders forbid it.`);
874
+ }
875
+ if (sequence.keyframes.length < 2 || sequence.keyframes[0]?.atProgress !== 0 || sequence.keyframes.at(-1)?.atProgress !== 1) {
876
+ throw new Error(`${item} keyframes must cover progress [0, 1].`);
877
+ }
878
+ let previous = -1;
879
+ for (const [frameIndex, keyframe] of sequence.keyframes.entries()) {
880
+ if (!Number.isFinite(keyframe.atProgress) || keyframe.atProgress <= previous || keyframe.atProgress < 0 || keyframe.atProgress > 1) {
881
+ throw new Error(`${item}.keyframes.${frameIndex} progress is invalid.`);
882
+ }
883
+ assertStyle(keyframe.style, `${item}.keyframes.${frameIndex}.style`);
884
+ if (keyframe.style.some((declaration) => !ANIMATABLE_TEXT_UNIT_STYLES.has(declaration.name))) {
885
+ throw new Error(`${item}.keyframes.${frameIndex} animates an unsupported text-unit property.`);
886
+ }
887
+ previous = keyframe.atProgress;
888
+ }
889
+ }
890
+ }
891
+
892
+ function assertPathCommands(path: readonly VisualVectorPathCommand[], label: string): void {
893
+ if (path.length < 2 || path[0]?.kind !== "move") throw new Error(`${label} must begin with move and contain drawable geometry.`);
894
+ if (!path.some((command) => command.kind === "line" || command.kind === "quadratic" || command.kind === "cubic")) {
895
+ throw new Error(`${label} contains no drawable geometry.`);
896
+ }
897
+ for (const [index, command] of path.entries()) {
898
+ for (const [name, value] of Object.entries(command)) {
899
+ if (name !== "kind") finite(value as number, `${label}.${index}.${name}`);
900
+ }
901
+ }
902
+ }
903
+
904
+ function assertAnimation(animation: VisualAnimation | undefined, _durationFrames: number, label: string): void {
905
+ if (animation === undefined) return;
906
+ if (animation.keyframes.length < 2) throw new Error(`${label} animation must contain at least two keyframes.`);
907
+ let previous = -1;
908
+ for (const [index, keyframe] of animation.keyframes.entries()) {
909
+ if (
910
+ !Number.isSafeInteger(keyframe.atFrame)
911
+ || keyframe.atFrame < 0
912
+ || keyframe.atFrame <= previous
913
+ ) {
914
+ throw new Error(`${label} animation keyframe ${index + 1} has an invalid frame offset.`);
915
+ }
916
+ if (
917
+ keyframe.easing !== undefined
918
+ && !["linear", "ease-in", "ease-out", "ease-in-out"].includes(keyframe.easing)
919
+ ) {
920
+ throw new Error(`${label} animation keyframe ${index + 1} has an invalid easing.`);
921
+ }
922
+ if (keyframe.style.length === 0) throw new Error(`${label} animation keyframe ${index + 1} has no style.`);
923
+ assertStyle(keyframe.style, `${label}.animation.${index + 1}`);
924
+ for (const declaration of keyframe.style) {
925
+ if (!ANIMATABLE_LOCAL_STYLES.has(declaration.name)) {
926
+ throw new Error(`${label} animation cannot change ${declaration.name}.`);
927
+ }
928
+ }
929
+ previous = keyframe.atFrame;
930
+ }
931
+ }
932
+
933
+ function assertPresent(present: VisualPresent, programSpace: ProgramSpace | undefined, trackId: string): void {
934
+ const totalFrames = programSpace === undefined ? Number.MAX_SAFE_INTEGER : programSpaceFrameCount(programSpace);
935
+ assertNonEmpty(present.id, `${trackId} Present id`);
936
+ if (present.subjectId !== undefined) assertNonEmpty(present.subjectId, `${trackId}.${present.id} subjectId`);
937
+ assertFrameSpan(present.span, totalFrames, `${trackId}.${present.id}.span`);
938
+ assertNonEmpty(present.stacking.tieBreak, `${trackId}.${present.id} stacking tieBreak`);
939
+ if (!Number.isSafeInteger(present.stacking.order)) {
940
+ throw new Error(`${trackId}.${present.id} has invalid stacking order.`);
941
+ }
942
+ if (present.elements.length === 0) throw new Error(`${trackId}.${present.id} must contain an element.`);
943
+ const elements = new Map<string, VisualElement>();
944
+ const roots: VisualElement[] = [];
945
+ const orders = new Set<number>();
946
+ for (const element of present.elements) {
947
+ assertNonEmpty(element.id, `${trackId}.${present.id} element id`);
948
+ if (elements.has(element.id)) throw new Error(`${trackId}.${present.id} has duplicate element ${element.id}.`);
949
+ if (!Number.isSafeInteger(element.order) || element.order < 0 || orders.has(element.order)) {
950
+ throw new Error(`${trackId}.${present.id}.${element.id} has invalid or duplicate order.`);
951
+ }
952
+ orders.add(element.order);
953
+ elements.set(element.id, element);
954
+ if (element.parent === undefined) roots.push(element);
955
+ assertStyle(element.style, `${trackId}.${present.id}.${element.id}`);
956
+ assertAttributes(element.attributes, `${trackId}.${present.id}.${element.id}`);
957
+ assertAnimation(
958
+ element.animation,
959
+ present.span.endFrameExclusive - present.span.startFrame,
960
+ `${trackId}.${present.id}.${element.id}`,
961
+ );
962
+ if (element.kind === "program") {
963
+ assertNonEmpty(element.program.format, `${element.id}.program.format`);
964
+ if (element.program.payload === null || typeof element.program.payload !== "object" || Array.isArray(element.program.payload)) throw new Error("Visual program payload must be an object.");
965
+ canonicalStringify(element.program.payload);
966
+ for (const artifact of element.program.artifacts) assertMediaArtifact(artifact, `${element.id}.program.artifacts`);
967
+ }
968
+ if (element.kind === "image" || element.kind === "video") {
969
+ assertMediaArtifact(element.artifact, `${trackId}.${present.id}.${element.id}.artifact`);
970
+ if (!element.artifact.mediaType.startsWith(`${element.kind}/`)) {
971
+ throw new Error(`${trackId}.${present.id}.${element.id} media kind does not match its Artifact.`);
972
+ }
973
+ if (element.kind === "image" && element.sampling !== undefined) {
974
+ throw new Error(`${trackId}.${present.id}.${element.id} cannot sample a durationless image.`);
975
+ }
976
+ if (element.sampling !== undefined) {
977
+ if (element.animation !== undefined) {
978
+ throw new Error(`${trackId}.${present.id}.${element.id} sampling motion must live on an owned wrapper.`);
979
+ }
980
+ assertSampling(element.sampling, present.span.endFrameExclusive - present.span.startFrame,
981
+ `${trackId}.${present.id}.${element.id}.sampling`);
982
+ }
983
+ }
984
+ if (element.kind === "text") {
985
+ const label = `${trackId}.${present.id}.${element.id}`;
986
+ assertExactFonts(element.fonts, `${label}.fonts`);
987
+ const ownedFontStyles = new Set(["font", "font-family", "font-style", "font-synthesis", "font-weight"]);
988
+ if (element.style.some((declaration) => ownedFontStyles.has(declaration.name))) {
989
+ throw new Error(`${label} exact fonts conflict with a raw font style.`);
990
+ }
991
+ for (const [index, paint] of (element.paints ?? []).entries()) {
992
+ assertTextPaint(paint, `${label}.paints.${index}`);
993
+ // Box Paint decorates a laid-out run, and this element has no layout to decorate.
994
+ if (paint.kind === "box") throw new Error(`${label}.paints.${index} is Box Paint on a plain text element.`);
995
+ }
996
+ // Two ways to say the same thing render twice: the declared Paint draws the glyph, and the
997
+ // style would draw it again underneath.
998
+ const paintedStyles = new Set(["-webkit-text-stroke", "-webkit-text-stroke-color", "-webkit-text-stroke-width", "paint-order"]);
999
+ if (element.paints !== undefined && element.style.some((declaration) => paintedStyles.has(declaration.name))) {
1000
+ throw new Error(`${label} declares glyph Paint beside a raw stroke style.`);
1001
+ }
1002
+ }
1003
+ if (element.kind === "text-flow" || element.kind === "path-text") {
1004
+ const label = `${trackId}.${present.id}.${element.id}`;
1005
+ assertTextDocument(element.document, element.typography, `${label}.document`);
1006
+ assertTypography(element.typography, `${label}.typography`);
1007
+ const boxKeys = new Set<string>();
1008
+ for (const [index, paint] of element.paints.entries()) {
1009
+ assertTextPaint(paint, `${label}.paints.${index}`);
1010
+ if (paint.kind === "box") {
1011
+ const key = `${paint.target}:${paint.continuity}`;
1012
+ if (boxKeys.has(key)) throw new Error(`${label} repeats Box Paint ${key}.`);
1013
+ boxKeys.add(key);
1014
+ }
1015
+ }
1016
+ assertTextSequences(element.sequences, present.span.endFrameExclusive - present.span.startFrame, `${label}.sequences`);
1017
+ if (element.kind === "text-flow") assertTextFlow(element.flow, `${label}.flow`);
1018
+ else {
1019
+ assertPathCommands(element.path, `${label}.path`);
1020
+ if (!(["left", "right"] as const).includes(element.side)
1021
+ || !(["follow", "upright"] as const).includes(element.orientation)
1022
+ || !(["start", "center", "end"] as const).includes(element.align)
1023
+ || !(["visible", "clip"] as const).includes(element.overflow)) {
1024
+ throw new Error(`${label} contains an unsupported Path Text enum.`);
1025
+ }
1026
+ nonNegative(element.startMarginPx, `${label}.startMarginPx`);
1027
+ nonNegative(element.endMarginPx, `${label}.endMarginPx`);
1028
+ if (element.marginAnimation !== undefined) {
1029
+ const frames = element.marginAnimation.keyframes;
1030
+ if (frames.length < 2) throw new Error(`${label}.marginAnimation requires two keyframes.`);
1031
+ let previous = -1;
1032
+ for (const [index, keyframe] of frames.entries()) {
1033
+ if (!Number.isSafeInteger(keyframe.atFrame) || keyframe.atFrame <= previous) {
1034
+ throw new Error(`${label}.marginAnimation.${index} has an invalid frame.`);
1035
+ }
1036
+ nonNegative(keyframe.startMarginPx, `${label}.marginAnimation.${index}.startMarginPx`);
1037
+ previous = keyframe.atFrame;
1038
+ }
1039
+ }
1040
+ }
1041
+ }
1042
+ if (element.kind === "surface") {
1043
+ assertCompositableSurfaceRef(element.surface, `${trackId}.${present.id}.${element.id}.surface`);
1044
+ if (element.surface.timing.kind === "still" && element.sampling !== undefined) {
1045
+ throw new Error(`${trackId}.${present.id}.${element.id} cannot sample a still Surface.`);
1046
+ }
1047
+ if (element.sampling !== undefined) {
1048
+ if (element.animation !== undefined) {
1049
+ throw new Error(`${trackId}.${present.id}.${element.id} sampling motion must live on an owned wrapper.`);
1050
+ }
1051
+ if (element.surface.timing.kind !== "frames"
1052
+ || element.sampling.sourceFrameCount !== element.surface.timing.frameCount
1053
+ || element.sampling.sourceFrameRate.numerator !== element.surface.timing.frameRate.numerator
1054
+ || element.sampling.sourceFrameRate.denominator !== element.surface.timing.frameRate.denominator) {
1055
+ throw new Error(`${trackId}.${present.id}.${element.id} Surface sampling differs from its typed timing.`);
1056
+ }
1057
+ assertSampling(element.sampling, present.span.endFrameExclusive - present.span.startFrame,
1058
+ `${trackId}.${present.id}.${element.id}.sampling`);
1059
+ }
1060
+ if (element.surface.timing.kind === "frames") {
1061
+ const durationFrames = present.span.endFrameExclusive - present.span.startFrame;
1062
+ if (element.sampling === undefined && element.surface.timing.frameCount !== durationFrames) {
1063
+ throw new Error(`${trackId}.${present.id}.${element.id} Surface must exactly match its Present frame domain.`);
1064
+ }
1065
+ if (element.sampling === undefined && programSpace !== undefined && (
1066
+ element.surface.timing.frameRate.numerator !== programSpace.frameRate.numerator
1067
+ || element.surface.timing.frameRate.denominator !== programSpace.frameRate.denominator
1068
+ )) throw new Error(`${trackId}.${present.id}.${element.id} Surface must exactly match its Present frame domain.`);
1069
+ }
1070
+ }
1071
+ if (element.kind === "mask") {
1072
+ if (!["alpha", "luminance"].includes(element.mode)
1073
+ || element.maskElement === element.contentElement) {
1074
+ throw new Error(`${trackId}.${present.id}.${element.id} has an invalid local mask.`);
1075
+ }
1076
+ }
1077
+ }
1078
+ if (roots.length !== 1) throw new Error(`${trackId}.${present.id} must contain exactly one root element.`);
1079
+ for (const element of present.elements) {
1080
+ if (element.parent !== undefined && !elements.has(element.parent)) {
1081
+ throw new Error(`${trackId}.${present.id}.${element.id} references a foreign parent.`);
1082
+ }
1083
+ if (element.parent !== undefined && !["box", "mask", "program"].includes(elements.get(element.parent)?.kind ?? "")) {
1084
+ throw new Error(`${trackId}.${present.id}.${element.id} must have a box, mask or program parent.`);
1085
+ }
1086
+ const visited = new Set<string>();
1087
+ let cursor: VisualElement | undefined = element;
1088
+ while (cursor?.parent !== undefined) {
1089
+ if (visited.has(cursor.id)) throw new Error(`${trackId}.${present.id} contains an element cycle.`);
1090
+ visited.add(cursor.id);
1091
+ cursor = elements.get(cursor.parent);
1092
+ }
1093
+ }
1094
+ for (const element of present.elements) {
1095
+ if (element.kind !== "mask") continue;
1096
+ const direct = present.elements.filter((candidate) => candidate.parent === element.id);
1097
+ if (direct.length !== 2
1098
+ || !direct.some((candidate) => candidate.id === element.maskElement)
1099
+ || !direct.some((candidate) => candidate.id === element.contentElement)) {
1100
+ throw new Error(`${trackId}.${present.id}.${element.id} must own exactly its declared mask and content roots.`);
1101
+ }
1102
+ const maskRoot = direct.find((candidate) => candidate.id === element.maskElement)!;
1103
+ if (!["text", "text-flow", "path-text", "image", "surface"].includes(maskRoot.kind)
1104
+ || (maskRoot.kind === "surface" && maskRoot.surface.timing.kind !== "still")
1105
+ || present.elements.some((candidate) => candidate.parent === maskRoot.id)) {
1106
+ throw new Error(`${trackId}.${present.id}.${element.id} mask source must be one terminal owned text, image or still Surface.`);
1107
+ }
1108
+ }
1109
+ }
1110
+
1111
+ function normalizeStyle(style: readonly VisualStyleDeclaration[]): VisualStyleDeclaration[] {
1112
+ return [...style]
1113
+ .map((item) => ({ name: item.name, value: item.value }))
1114
+ .sort((left, right) => left.name.localeCompare(right.name));
1115
+ }
1116
+
1117
+ function normalizeAttributes(attributes: readonly VisualAttribute[]): readonly VisualAttribute[] {
1118
+ return [...attributes]
1119
+ .map((item) => ({ name: item.name, value: item.value }))
1120
+ .sort((left, right) => left.name.localeCompare(right.name));
1121
+ }
1122
+
1123
+ function normalizeAnimation(animation: VisualAnimation): VisualAnimation {
1124
+ return {
1125
+ keyframes: [...animation.keyframes]
1126
+ .map((keyframe) => ({
1127
+ atFrame: keyframe.atFrame,
1128
+ ...(keyframe.easing === undefined ? {} : { easing: keyframe.easing }),
1129
+ style: normalizeStyle(keyframe.style),
1130
+ }))
1131
+ .sort((left, right) => left.atFrame - right.atFrame),
1132
+ };
1133
+ }
1134
+
1135
+ function normalizeElement(element: VisualElement): VisualElement {
1136
+ const common = {
1137
+ id: element.id,
1138
+ ...(element.parent === undefined ? {} : { parent: element.parent }),
1139
+ order: element.order,
1140
+ style: normalizeStyle(element.style),
1141
+ ...(element.attributes === undefined ? {} : { attributes: normalizeAttributes(element.attributes) }),
1142
+ ...(element.animation === undefined ? {} : { animation: normalizeAnimation(element.animation) }),
1143
+ };
1144
+ if (element.kind === "box") return { ...common, kind: "box" };
1145
+ if (element.kind === "program") return { ...common, kind: "program", program: structuredClone(element.program) };
1146
+ if (element.kind === "mask") return {
1147
+ ...common,
1148
+ kind: "mask",
1149
+ mode: element.mode,
1150
+ maskElement: element.maskElement,
1151
+ contentElement: element.contentElement,
1152
+ };
1153
+ if (element.kind === "text") {
1154
+ return {
1155
+ ...common,
1156
+ kind: "text",
1157
+ text: element.text,
1158
+ fonts: element.fonts.map((font) => ({
1159
+ sources: font.sources.map((source) => ({
1160
+ artifact: { ...source.artifact },
1161
+ ...(source.unicodeRange === undefined ? {} : { unicodeRange: source.unicodeRange }),
1162
+ })),
1163
+ weight: font.weight,
1164
+ style: font.style,
1165
+ })),
1166
+ ...(element.paints === undefined ? {} : { paints: structuredClone(element.paints) as VisualTextPaintLayer[] }),
1167
+ };
1168
+ }
1169
+ if (element.kind === "text-flow" || element.kind === "path-text") {
1170
+ const copy = structuredClone(element);
1171
+ return {
1172
+ ...copy,
1173
+ ...common,
1174
+ kind: element.kind,
1175
+ sequences: element.sequences.map((sequence) => ({
1176
+ ...sequence,
1177
+ range: { ...sequence.range },
1178
+ keyframes: sequence.keyframes.map((keyframe) => ({
1179
+ ...keyframe,
1180
+ style: normalizeStyle(keyframe.style),
1181
+ })),
1182
+ })),
1183
+ } as VisualTextFlowElement | VisualPathTextElement;
1184
+ }
1185
+ if (element.kind === "surface") {
1186
+ return {
1187
+ ...common,
1188
+ kind: "surface",
1189
+ surface: {
1190
+ ...element.surface,
1191
+ artifact: { ...element.surface.artifact },
1192
+ timing: element.surface.timing.kind === "still"
1193
+ ? { kind: "still" }
1194
+ : { ...element.surface.timing, frameRate: { ...element.surface.timing.frameRate } },
1195
+ },
1196
+ ...(element.sampling === undefined ? {} : { sampling: {
1197
+ sourceFrameRate: { ...element.sampling.sourceFrameRate },
1198
+ sourceFrameCount: element.sampling.sourceFrameCount,
1199
+ segments: element.sampling.segments.map((segment) => ({
1200
+ target: { ...segment.target }, sourceFrame: { ...segment.sourceFrame }, rate: { ...segment.rate },
1201
+ ...(segment.loop === undefined ? {} : { loop: { ...segment.loop } }),
1202
+ })),
1203
+ } }),
1204
+ };
1205
+ }
1206
+ // Spreading an absent artifact produced `{}`, which is not an artifact and is not nothing either:
1207
+ // the field the author actually wrote was dropped without a word, and the refusal came one call
1208
+ // later from the identity check, naming `.artifact` — a field they had not typed.
1209
+ if (element.artifact === undefined) {
1210
+ throw new Error(`${element.id} is a ${element.kind} element with no artifact.`);
1211
+ }
1212
+ return {
1213
+ ...common,
1214
+ kind: element.kind,
1215
+ artifact: { ...element.artifact },
1216
+ ...(element.sampling === undefined ? {} : { sampling: {
1217
+ sourceFrameRate: { ...element.sampling.sourceFrameRate },
1218
+ sourceFrameCount: element.sampling.sourceFrameCount,
1219
+ segments: element.sampling.segments.map((segment) => ({
1220
+ target: { ...segment.target }, sourceFrame: { ...segment.sourceFrame }, rate: { ...segment.rate },
1221
+ ...(segment.loop === undefined ? {} : { loop: { ...segment.loop } }),
1222
+ })),
1223
+ } }),
1224
+ ...(element.muted === undefined ? {} : { muted: element.muted }),
1225
+ };
1226
+ }
1227
+
1228
+ function visualTrackContent(value: Omit<VisualTrack, "kind">): VisualTrack {
1229
+ return {
1230
+ kind: "visual",
1231
+ programSpaceId: value.programSpaceId,
1232
+ visualIr: value.visualIr,
1233
+ id: value.id,
1234
+ presents: [...value.presents]
1235
+ .map((present) => ({
1236
+ id: present.id,
1237
+ ...(present.subjectId === undefined ? {} : { subjectId: present.subjectId }),
1238
+ span: { ...present.span },
1239
+ stacking: { ...present.stacking },
1240
+ elements: [...present.elements].map(normalizeElement).sort((a, b) => a.order - b.order || a.id.localeCompare(b.id)),
1241
+ }))
1242
+ .sort((a, b) => a.span.startFrame - b.span.startFrame
1243
+ || a.stacking.order - b.stacking.order
1244
+ || a.stacking.tieBreak.localeCompare(b.stacking.tieBreak)
1245
+ || a.id.localeCompare(b.id)),
1246
+ };
1247
+ }
1248
+
1249
+ function audioTrackContent(value: Omit<AudioTrack, "kind">): AudioTrack {
1250
+ return {
1251
+ kind: "audio",
1252
+ programSpaceId: value.programSpaceId,
1253
+ id: value.id,
1254
+ clips: [...value.clips]
1255
+ .map((clip) => ({
1256
+ id: clip.id,
1257
+ ...(clip.subjectId === undefined ? {} : { subjectId: clip.subjectId }),
1258
+ artifact: { ...clip.artifact },
1259
+ target: { ...clip.target },
1260
+ source: { ...clip.source },
1261
+ playbackRate: clip.playbackRate,
1262
+ pitch: clip.pitch,
1263
+ gain: clip.gain,
1264
+ fadeInSamples: clip.fadeInSamples,
1265
+ fadeOutSamples: clip.fadeOutSamples,
1266
+ }))
1267
+ .sort((a, b) => a.target.startSample - b.target.startSample || a.id.localeCompare(b.id)),
1268
+ };
1269
+ }
1270
+
1271
+ export function sealVisualTrack(value: Omit<VisualTrack, "kind">): VisualTrack {
1272
+ return visualTrackContent(value);
1273
+ }
1274
+
1275
+ export function sealAudioTrack(value: Omit<AudioTrack, "kind">): AudioTrack {
1276
+ return audioTrackContent(value);
1277
+ }
1278
+
1279
+ export function assertVisualTrackIdentity(track: VisualTrack, programSpace?: ProgramSpace): void {
1280
+ if (programSpace !== undefined) assertProgramSpaceIdentity(programSpace);
1281
+ if (track.kind !== "visual") throw new Error("VisualTrack kind is invalid.");
1282
+ if (track.visualIr !== VISUAL_IR_V1) throw new Error("Unsupported VisualTrack visual IR.");
1283
+ assertNonEmpty(track.programSpaceId, "VisualTrack programSpaceId");
1284
+ if (programSpace !== undefined && track.programSpaceId !== programSpace.id) {
1285
+ throw new Error(`VisualTrack ${track.id} belongs to ProgramSpace ${track.programSpaceId}, not ${programSpace.id}.`);
1286
+ }
1287
+ assertNonEmpty(track.id, "VisualTrack id");
1288
+ const presentIds = new Set<string>();
1289
+ for (const present of track.presents) {
1290
+ if (presentIds.has(present.id)) throw new Error(`${track.id} has duplicate Present ${present.id}.`);
1291
+ presentIds.add(present.id);
1292
+ assertPresent(present, programSpace, track.id);
1293
+ }
1294
+ }
1295
+
1296
+ export function assertAudioTrackIdentity(track: AudioTrack, programSpace?: ProgramSpace): void {
1297
+ if (programSpace !== undefined) assertProgramSpaceIdentity(programSpace);
1298
+ if (track.kind !== "audio") throw new Error("AudioTrack kind is invalid.");
1299
+ assertNonEmpty(track.programSpaceId, "AudioTrack programSpaceId");
1300
+ if (programSpace !== undefined && track.programSpaceId !== programSpace.id) {
1301
+ throw new Error(`AudioTrack ${track.id} belongs to ProgramSpace ${track.programSpaceId}, not ${programSpace.id}.`);
1302
+ }
1303
+ assertNonEmpty(track.id, "AudioTrack id");
1304
+ const totalSamples = programSpace === undefined
1305
+ ? Number.MAX_SAFE_INTEGER
1306
+ : programSpaceSampleFrames(programSpace, 48_000);
1307
+ const clipIds = new Set<string>();
1308
+ for (const clip of track.clips) {
1309
+ if (clipIds.has(clip.id)) throw new Error(`${track.id} has duplicate clip ${clip.id}.`);
1310
+ clipIds.add(clip.id);
1311
+ assertNonEmpty(clip.id, `${track.id} clip id`);
1312
+ if (clip.subjectId !== undefined) assertNonEmpty(clip.subjectId, `${track.id}.${clip.id} subjectId`);
1313
+ assertAudioArtifact(clip.artifact, `${track.id}.${clip.id}.artifact`);
1314
+ if (!Number.isSafeInteger(clip.target.startSample) || clip.target.startSample < 0
1315
+ || !Number.isSafeInteger(clip.target.endSampleExclusive)
1316
+ || clip.target.endSampleExclusive <= clip.target.startSample
1317
+ || clip.target.endSampleExclusive > totalSamples) {
1318
+ throw new Error(`${track.id}.${clip.id} target sample interval is outside ProgramSpace.`);
1319
+ }
1320
+ if (!Number.isSafeInteger(clip.source.sampleFrames) || clip.source.sampleFrames <= 0
1321
+ || !Number.isSafeInteger(clip.source.startSample) || clip.source.startSample < 0
1322
+ || !Number.isSafeInteger(clip.source.endSampleExclusive)
1323
+ || clip.source.endSampleExclusive <= clip.source.startSample
1324
+ || clip.source.endSampleExclusive > clip.source.sampleFrames) {
1325
+ throw new Error(`${track.id}.${clip.id} source sample interval is invalid.`);
1326
+ }
1327
+ const sourceLength = clip.source.endSampleExclusive - clip.source.startSample;
1328
+ if (!Number.isSafeInteger(clip.source.phaseSample) || clip.source.phaseSample < 0
1329
+ || clip.source.phaseSample >= sourceLength
1330
+ || (!clip.source.loop && clip.source.phaseSample !== 0)) {
1331
+ throw new Error(`${track.id}.${clip.id} source loop phase is invalid.`);
1332
+ }
1333
+ if (!Number.isFinite(clip.playbackRate) || clip.playbackRate <= 0 || clip.playbackRate > 100) {
1334
+ throw new Error(`${track.id}.${clip.id} has invalid playbackRate.`);
1335
+ }
1336
+ if (clip.pitch !== "preserve") throw new Error(`${track.id}.${clip.id} pitch policy is invalid.`);
1337
+ if (!Number.isFinite(clip.gain) || clip.gain < 0 || clip.gain > 64) {
1338
+ throw new Error(`${track.id}.${clip.id} gain is invalid.`);
1339
+ }
1340
+ const targetLength = clip.target.endSampleExclusive - clip.target.startSample;
1341
+ if (!Number.isSafeInteger(clip.fadeInSamples) || clip.fadeInSamples < 0 || clip.fadeInSamples > targetLength
1342
+ || !Number.isSafeInteger(clip.fadeOutSamples) || clip.fadeOutSamples < 0
1343
+ || clip.fadeOutSamples > targetLength) {
1344
+ throw new Error(`${track.id}.${clip.id} fades are invalid.`);
1345
+ }
1346
+ }
1347
+ }
1348
+
1349
+ function trackKey(track: Track): string {
1350
+ return `${track.kind}\u0000${track.id}`;
1351
+ }
1352
+
1353
+ function compositionContent(value: Composition): Composition {
1354
+ return {
1355
+ id: value.id,
1356
+ canvas: { ...value.canvas },
1357
+ tracks: [...value.tracks].map((track) => structuredClone(track)).sort((a, b) => trackKey(a).localeCompare(trackKey(b))),
1358
+ };
1359
+ }
1360
+
1361
+ export function sealComposition(value: Composition): Composition {
1362
+ return compositionContent(value);
1363
+ }
1364
+
1365
+ export function assertCompositionIdentity(composition: Composition, programSpace?: ProgramSpace): void {
1366
+ assertNonEmpty(composition.id, "Composition id");
1367
+ if (programSpace !== undefined) assertProgramSpaceIdentity(programSpace);
1368
+ if (
1369
+ !Number.isSafeInteger(composition.canvas.width)
1370
+ || composition.canvas.width <= 0
1371
+ || !Number.isSafeInteger(composition.canvas.height)
1372
+ || composition.canvas.height <= 0
1373
+ || !/^#[0-9a-f]{6}(?:[0-9a-f]{2})?$/iu.test(composition.canvas.clearColor)
1374
+ ) {
1375
+ throw new Error("Composition canvas is invalid.");
1376
+ }
1377
+ const ids = new Set<string>();
1378
+ const stacking = new Map<string, Array<{ readonly trackId: string; readonly present: VisualPresent }>>();
1379
+ for (const track of composition.tracks) {
1380
+ if (ids.has(track.id)) throw new Error(`Composition contains duplicate Track id ${track.id}.`);
1381
+ ids.add(track.id);
1382
+ if (track.kind === "visual") {
1383
+ assertVisualTrackIdentity(track, programSpace);
1384
+ for (const present of track.presents) {
1385
+ const key = `${present.stacking.order}\u0000${present.stacking.tieBreak}`;
1386
+ const peers = stacking.get(key) ?? [];
1387
+ for (const peer of peers) {
1388
+ const overlaps = present.span.startFrame < peer.present.span.endFrameExclusive
1389
+ && peer.present.span.startFrame < present.span.endFrameExclusive;
1390
+ if (overlaps) {
1391
+ throw new Error(
1392
+ `Composition contains overlapping visual stacking key ${key} in ${peer.trackId}.${peer.present.id} and ${track.id}.${present.id}.`,
1393
+ );
1394
+ }
1395
+ }
1396
+ peers.push({ trackId: track.id, present });
1397
+ stacking.set(key, peers);
1398
+ }
1399
+ } else {
1400
+ assertAudioTrackIdentity(track, programSpace);
1401
+ }
1402
+ }
1403
+ }