@hraness/slopcamera 3.2.4

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 (441) hide show
  1. package/LICENSE +21 -0
  2. package/NOTICE.md +60 -0
  3. package/PRIVACY.md +46 -0
  4. package/README.md +311 -0
  5. package/SECURITY.md +21 -0
  6. package/apps/desktop/README.md +966 -0
  7. package/apps/desktop/analysis/protocol.ts +223 -0
  8. package/apps/desktop/application/capability-binding.ts +594 -0
  9. package/apps/desktop/application/context.ts +97 -0
  10. package/apps/desktop/application/creative-iteration.ts +1385 -0
  11. package/apps/desktop/application/default-registry.ts +146 -0
  12. package/apps/desktop/application/directing-contract.ts +218 -0
  13. package/apps/desktop/application/directing-plan.ts +178 -0
  14. package/apps/desktop/application/errors.ts +18 -0
  15. package/apps/desktop/application/gateway-port.ts +867 -0
  16. package/apps/desktop/application/html-overlay-browser-runtime.ts +687 -0
  17. package/apps/desktop/application/html-overlay-integrity.ts +337 -0
  18. package/apps/desktop/application/html-overlay-renderer.ts +45 -0
  19. package/apps/desktop/application/index.ts +13 -0
  20. package/apps/desktop/application/operation-completion-checkpoint.ts +333 -0
  21. package/apps/desktop/application/operation-effects.ts +94 -0
  22. package/apps/desktop/application/operation.ts +224 -0
  23. package/apps/desktop/application/operations/analysis/faces.ts +244 -0
  24. package/apps/desktop/application/operations/analysis/music.ts +248 -0
  25. package/apps/desktop/application/operations/analysis/project-auto-zooms.ts +302 -0
  26. package/apps/desktop/application/operations/analysis/project-inactivity.ts +381 -0
  27. package/apps/desktop/application/operations/analysis/scenes.ts +272 -0
  28. package/apps/desktop/application/operations/analysis/shared.ts +202 -0
  29. package/apps/desktop/application/operations/derive/edit-batch.ts +967 -0
  30. package/apps/desktop/application/operations/derive/follow-faces.ts +454 -0
  31. package/apps/desktop/application/operations/edit/bind-candidate-revision.ts +91 -0
  32. package/apps/desktop/application/operations/edit/create-candidate-revision.ts +377 -0
  33. package/apps/desktop/application/operations/edit/create-revision.ts +255 -0
  34. package/apps/desktop/application/operations/edit/freeze-revision.ts +182 -0
  35. package/apps/desktop/application/operations/gateway/image.ts +41 -0
  36. package/apps/desktop/application/operations/gateway/index.ts +17 -0
  37. package/apps/desktop/application/operations/gateway/shared.ts +122 -0
  38. package/apps/desktop/application/operations/gateway/speech.ts +41 -0
  39. package/apps/desktop/application/operations/gateway/transcription.ts +42 -0
  40. package/apps/desktop/application/operations/gateway/video.ts +41 -0
  41. package/apps/desktop/application/operations/index.ts +31 -0
  42. package/apps/desktop/application/operations/iteration/create-candidate.ts +240 -0
  43. package/apps/desktop/application/operations/iteration/create-matrix.ts +117 -0
  44. package/apps/desktop/application/operations/iteration/select.ts +155 -0
  45. package/apps/desktop/application/operations/iteration/shared.ts +250 -0
  46. package/apps/desktop/application/operations/media/audio-effects.ts +376 -0
  47. package/apps/desktop/application/operations/media/binding.ts +79 -0
  48. package/apps/desktop/application/operations/media/capabilities.ts +112 -0
  49. package/apps/desktop/application/operations/media/color-grade.ts +343 -0
  50. package/apps/desktop/application/operations/media/html-overlay.ts +802 -0
  51. package/apps/desktop/application/operations/media/index.ts +8 -0
  52. package/apps/desktop/application/operations/media/ingest.ts +303 -0
  53. package/apps/desktop/application/operations/media/overlay.ts +729 -0
  54. package/apps/desktop/application/operations/media/shared.ts +845 -0
  55. package/apps/desktop/application/operations/media/transform-platform.ts +120 -0
  56. package/apps/desktop/application/operations/project/commit-edits.ts +2054 -0
  57. package/apps/desktop/application/operations/project/promote-selection.ts +495 -0
  58. package/apps/desktop/application/operations/project/snapshot.ts +95 -0
  59. package/apps/desktop/application/operations/recording/index.ts +5 -0
  60. package/apps/desktop/application/operations/recording/pause.ts +34 -0
  61. package/apps/desktop/application/operations/recording/resume.ts +34 -0
  62. package/apps/desktop/application/operations/recording/shared.ts +199 -0
  63. package/apps/desktop/application/operations/recording/start.ts +169 -0
  64. package/apps/desktop/application/operations/recording/stop.ts +34 -0
  65. package/apps/desktop/application/operations/render/bind-candidate-output.ts +324 -0
  66. package/apps/desktop/application/operations/render/materialize-selection.ts +322 -0
  67. package/apps/desktop/application/operations/render/project-caption-plan.ts +287 -0
  68. package/apps/desktop/application/operations/render/project-plan.ts +939 -0
  69. package/apps/desktop/application/operations/render/project-spatial-receipt.ts +70 -0
  70. package/apps/desktop/application/operations/render/project.ts +1922 -0
  71. package/apps/desktop/application/operations/shared.ts +67 -0
  72. package/apps/desktop/application/operations/slopcamera-portable.ts +1188 -0
  73. package/apps/desktop/application/operations/slopcamera-visuals.ts +784 -0
  74. package/apps/desktop/application/operations/spatial-project.ts +209 -0
  75. package/apps/desktop/application/operations/spatial-render.ts +415 -0
  76. package/apps/desktop/application/operations/spatial-scene.ts +97 -0
  77. package/apps/desktop/application/operations/studio.ts +143 -0
  78. package/apps/desktop/application/output-publication-lease.ts +163 -0
  79. package/apps/desktop/application/project-publication-lease.ts +233 -0
  80. package/apps/desktop/application/project-store.ts +196 -0
  81. package/apps/desktop/application/receipts.ts +533 -0
  82. package/apps/desktop/application/registry.ts +182 -0
  83. package/apps/desktop/application/spatial-assets.ts +675 -0
  84. package/apps/desktop/application/spatial-compositor-cadence.ts +23 -0
  85. package/apps/desktop/application/spatial-project-authority.ts +35 -0
  86. package/apps/desktop/application/spatial-project-lease.ts +126 -0
  87. package/apps/desktop/application/spatial-project-render-preparation.ts +225 -0
  88. package/apps/desktop/application/spatial-project-store.ts +286 -0
  89. package/apps/desktop/application/spatial-render-projection.ts +201 -0
  90. package/apps/desktop/application/spatial-render.ts +677 -0
  91. package/apps/desktop/application/spatial-spz.ts +44 -0
  92. package/apps/desktop/application/spatial-world-import.ts +135 -0
  93. package/apps/desktop/application/spatial-world-provenance.ts +46 -0
  94. package/apps/desktop/application/studio-port.ts +58 -0
  95. package/apps/desktop/application/verified-receipt-reconciliation.ts +1574 -0
  96. package/apps/desktop/capture/protocol.ts +689 -0
  97. package/apps/desktop/cli/analyzer.ts +406 -0
  98. package/apps/desktop/cli/args.ts +3181 -0
  99. package/apps/desktop/cli/asset-ingest.ts +747 -0
  100. package/apps/desktop/cli/atomic-render-effects.ts +210 -0
  101. package/apps/desktop/cli/atomic-render-platform.ts +205 -0
  102. package/apps/desktop/cli/atomic-render.ts +50 -0
  103. package/apps/desktop/cli/audio-analysis.ts +252 -0
  104. package/apps/desktop/cli/bounded-map.ts +39 -0
  105. package/apps/desktop/cli/bundle-service.ts +256 -0
  106. package/apps/desktop/cli/capabilities.ts +212 -0
  107. package/apps/desktop/cli/capture-bundle.ts +1117 -0
  108. package/apps/desktop/cli/command-host-resources.ts +251 -0
  109. package/apps/desktop/cli/commands.ts +6836 -0
  110. package/apps/desktop/cli/directing-blob.ts +291 -0
  111. package/apps/desktop/cli/directing-media.ts +517 -0
  112. package/apps/desktop/cli/directing-quote.ts +89 -0
  113. package/apps/desktop/cli/directing-service.ts +288 -0
  114. package/apps/desktop/cli/emoji-assets.ts +538 -0
  115. package/apps/desktop/cli/errors.ts +29 -0
  116. package/apps/desktop/cli/face-analysis-service.ts +940 -0
  117. package/apps/desktop/cli/filter-script.ts +76 -0
  118. package/apps/desktop/cli/gateway-application-port.ts +1142 -0
  119. package/apps/desktop/cli/gateway-credential.ts +81 -0
  120. package/apps/desktop/cli/gateway-media-artifacts.ts +723 -0
  121. package/apps/desktop/cli/gateway-media-catalog.ts +922 -0
  122. package/apps/desktop/cli/gateway-media-service.ts +3106 -0
  123. package/apps/desktop/cli/gateway-media-signature.ts +122 -0
  124. package/apps/desktop/cli/gateway-provider-options.ts +562 -0
  125. package/apps/desktop/cli/gateway-scene-provider.ts +391 -0
  126. package/apps/desktop/cli/help.ts +501 -0
  127. package/apps/desktop/cli/html-overlay-gpu.ts +97 -0
  128. package/apps/desktop/cli/html-overlay-renderer.ts +2478 -0
  129. package/apps/desktop/cli/io.ts +290 -0
  130. package/apps/desktop/cli/main.ts +123 -0
  131. package/apps/desktop/cli/media-effects-service.ts +885 -0
  132. package/apps/desktop/cli/media-ingest-model.ts +364 -0
  133. package/apps/desktop/cli/media-ingest-platform.ts +227 -0
  134. package/apps/desktop/cli/media-ingest-program.ts +200 -0
  135. package/apps/desktop/cli/media-ingest.ts +30 -0
  136. package/apps/desktop/cli/music-analysis-service.ts +434 -0
  137. package/apps/desktop/cli/mutation-lock.ts +530 -0
  138. package/apps/desktop/cli/native-assets.d.ts +12 -0
  139. package/apps/desktop/cli/native-media-runtime.macos.ts +7 -0
  140. package/apps/desktop/cli/overlay-playback.ts +177 -0
  141. package/apps/desktop/cli/paths.ts +265 -0
  142. package/apps/desktop/cli/portable-surface.ts +242 -0
  143. package/apps/desktop/cli/project-camera-receipt.ts +112 -0
  144. package/apps/desktop/cli/project-face-camera.ts +394 -0
  145. package/apps/desktop/cli/project-inactivity-service.ts +552 -0
  146. package/apps/desktop/cli/project-media-integrity.ts +121 -0
  147. package/apps/desktop/cli/project-renderer.ts +1526 -0
  148. package/apps/desktop/cli/project-service.ts +519 -0
  149. package/apps/desktop/cli/project-state-transaction.ts +520 -0
  150. package/apps/desktop/cli/query-limits.ts +1 -0
  151. package/apps/desktop/cli/recording-controller.ts +1567 -0
  152. package/apps/desktop/cli/recording-daemon.ts +931 -0
  153. package/apps/desktop/cli/recording-ref.ts +56 -0
  154. package/apps/desktop/cli/renamed-environment.ts +6 -0
  155. package/apps/desktop/cli/renderer.ts +1439 -0
  156. package/apps/desktop/cli/run-cli-test-helper.ts +60 -0
  157. package/apps/desktop/cli/scene-analysis-service.ts +879 -0
  158. package/apps/desktop/cli/spatial-compositor-verifier.ts +213 -0
  159. package/apps/desktop/cli/spatial-project-service.ts +90 -0
  160. package/apps/desktop/cli/spatial-scene-service.ts +105 -0
  161. package/apps/desktop/cli/spatial-world-service.ts +39 -0
  162. package/apps/desktop/cli/speech-analysis-service.ts +682 -0
  163. package/apps/desktop/cli/studio-assemble.ts +58 -0
  164. package/apps/desktop/cli/studio-command.ts +60 -0
  165. package/apps/desktop/cli/studio-custody.ts +60 -0
  166. package/apps/desktop/cli/studio-encode.ts +216 -0
  167. package/apps/desktop/cli/studio-exr.ts +52 -0
  168. package/apps/desktop/cli/studio-files.ts +179 -0
  169. package/apps/desktop/cli/studio-output-validation.ts +162 -0
  170. package/apps/desktop/cli/studio-process.ts +145 -0
  171. package/apps/desktop/cli/studio-runtime.ts +77 -0
  172. package/apps/desktop/cli/studio-scaffold.ts +70 -0
  173. package/apps/desktop/cli/studio-service.ts +301 -0
  174. package/apps/desktop/cli/studio-spatial-asset.ts +248 -0
  175. package/apps/desktop/cli/studio-template-names.ts +3 -0
  176. package/apps/desktop/cli/studio-workflow.ts +19 -0
  177. package/apps/desktop/cli/time.ts +25 -0
  178. package/apps/desktop/cli/workflow-code.ts +584 -0
  179. package/apps/desktop/cli/workflow-runs.ts +576 -0
  180. package/apps/desktop/code/advanced.ts +139 -0
  181. package/apps/desktop/code/application-node-planner.ts +1288 -0
  182. package/apps/desktop/code/compiler.ts +329 -0
  183. package/apps/desktop/code/contracts.ts +13 -0
  184. package/apps/desktop/code/creative-recipes.ts +94 -0
  185. package/apps/desktop/code/define-workflow.ts +115 -0
  186. package/apps/desktop/code/editing.ts +284 -0
  187. package/apps/desktop/code/file-candidate-provenance.ts +420 -0
  188. package/apps/desktop/code/file-candidate.ts +69 -0
  189. package/apps/desktop/code/graph-builder.ts +10 -0
  190. package/apps/desktop/code/host-resource-policy.ts +55 -0
  191. package/apps/desktop/code/plan-contracts.ts +159 -0
  192. package/apps/desktop/code/planning.ts +361 -0
  193. package/apps/desktop/code/public.ts +134 -0
  194. package/apps/desktop/code/reference-projection.ts +62 -0
  195. package/apps/desktop/code/run-contracts.ts +466 -0
  196. package/apps/desktop/code/run-store.ts +2478 -0
  197. package/apps/desktop/code/runtime-identity.ts +328 -0
  198. package/apps/desktop/code/scheduler.ts +3067 -0
  199. package/apps/desktop/code/semantic-builder.ts +1436 -0
  200. package/apps/desktop/code/source-bundle.ts +1641 -0
  201. package/apps/desktop/code/source-typecheck.ts +211 -0
  202. package/apps/desktop/code/testing.ts +79 -0
  203. package/apps/desktop/code/worker-client.ts +1675 -0
  204. package/apps/desktop/code/worker-effects.ts +141 -0
  205. package/apps/desktop/code/worker-entry.ts +435 -0
  206. package/apps/desktop/code/worker-lease-guardian.ts +179 -0
  207. package/apps/desktop/code/worker-process-identity.ts +484 -0
  208. package/apps/desktop/code/worker-protocol.ts +211 -0
  209. package/apps/desktop/code/workflow-effects.ts +132 -0
  210. package/apps/desktop/contracts/analysis.ts +949 -0
  211. package/apps/desktop/contracts/edit.ts +576 -0
  212. package/apps/desktop/contracts/index.ts +9 -0
  213. package/apps/desktop/contracts/media-effects.ts +139 -0
  214. package/apps/desktop/contracts/project-render.ts +644 -0
  215. package/apps/desktop/contracts/project.ts +740 -0
  216. package/apps/desktop/contracts/recording.ts +1434 -0
  217. package/apps/desktop/contracts/render.ts +334 -0
  218. package/apps/desktop/contracts/runtime.ts +155 -0
  219. package/apps/desktop/contracts/spatial-compositor.ts +58 -0
  220. package/apps/desktop/contracts/spatial-project.ts +159 -0
  221. package/apps/desktop/contracts/spatial-world.ts +48 -0
  222. package/apps/desktop/contracts/video-effects.ts +120 -0
  223. package/apps/desktop/core/alignment-apply.ts +400 -0
  224. package/apps/desktop/core/audio-alignment.ts +466 -0
  225. package/apps/desktop/core/auto-zoom.ts +209 -0
  226. package/apps/desktop/core/canonical-json.ts +14 -0
  227. package/apps/desktop/core/emoji.ts +210 -0
  228. package/apps/desktop/core/events.ts +409 -0
  229. package/apps/desktop/core/face-framing.ts +533 -0
  230. package/apps/desktop/core/face-tracks.ts +326 -0
  231. package/apps/desktop/core/inactivity.ts +137 -0
  232. package/apps/desktop/core/index.ts +30 -0
  233. package/apps/desktop/core/intervals.ts +123 -0
  234. package/apps/desktop/core/montage.ts +236 -0
  235. package/apps/desktop/core/music-analysis.ts +518 -0
  236. package/apps/desktop/core/plan.ts +244 -0
  237. package/apps/desktop/core/project-auto-zoom.ts +75 -0
  238. package/apps/desktop/core/project-camera-spatial.ts +676 -0
  239. package/apps/desktop/core/project-camera.ts +403 -0
  240. package/apps/desktop/core/project-captions.ts +888 -0
  241. package/apps/desktop/core/project-inactivity.ts +125 -0
  242. package/apps/desktop/core/project-metadata.ts +927 -0
  243. package/apps/desktop/core/project-plan.ts +375 -0
  244. package/apps/desktop/core/project-render-plan.ts +303 -0
  245. package/apps/desktop/core/project-time.ts +469 -0
  246. package/apps/desktop/core/render-plan.ts +442 -0
  247. package/apps/desktop/core/scene-cache.ts +174 -0
  248. package/apps/desktop/core/scene-sampling.ts +448 -0
  249. package/apps/desktop/core/spatial-compositor.ts +22 -0
  250. package/apps/desktop/core/spatial-durability.ts +99 -0
  251. package/apps/desktop/core/spatial-project.ts +169 -0
  252. package/apps/desktop/core/spatial-shot-clock.ts +32 -0
  253. package/apps/desktop/core/speech-analysis.ts +333 -0
  254. package/apps/desktop/core/storage.ts +970 -0
  255. package/apps/desktop/core/time-map.ts +91 -0
  256. package/apps/desktop/core/time.ts +61 -0
  257. package/apps/desktop/core/video-effects.ts +660 -0
  258. package/apps/desktop/dist/cli/NebulaSans-Bold-26se8aek.otf +0 -0
  259. package/apps/desktop/dist/cli/NebulaSans-Bold-bcz7y08t.woff2 +0 -0
  260. package/apps/desktop/dist/cli/NebulaSans-Book-5ax05zvn.woff2 +0 -0
  261. package/apps/desktop/dist/cli/NebulaSans-Book-8cenzchw.otf +0 -0
  262. package/apps/desktop/dist/cli/main.js +5086 -0
  263. package/apps/desktop/html-overlay/catalog.ts +171 -0
  264. package/apps/desktop/html-overlay/contracts.ts +372 -0
  265. package/apps/desktop/html-overlay/execution-profile.ts +77 -0
  266. package/apps/desktop/html-overlay/index.ts +98 -0
  267. package/apps/desktop/html-overlay/libraries.ts +263 -0
  268. package/apps/desktop/html-overlay/random.ts +49 -0
  269. package/apps/desktop/html-overlay/runtime.ts +813 -0
  270. package/apps/desktop/html-overlay/scaffolds.ts +792 -0
  271. package/apps/desktop/html-overlay/spark-runtime.ts +88 -0
  272. package/apps/desktop/html-overlay/spatial-splat-runtime.ts +60 -0
  273. package/apps/desktop/html-overlay/spatial.ts +720 -0
  274. package/apps/desktop/studio/assets/README.md +39 -0
  275. package/apps/desktop/studio/assets/contracts.ts +129 -0
  276. package/apps/desktop/studio/assets/network.ts +64 -0
  277. package/apps/desktop/studio/assets/poly-haven.ts +148 -0
  278. package/apps/desktop/studio/drivers/blender_driver.py +466 -0
  279. package/apps/desktop/studio/drivers/cadquery_driver.py +176 -0
  280. package/apps/desktop/studio/education/driver.py +308 -0
  281. package/apps/desktop/studio/education/lesson.py +180 -0
  282. package/apps/desktop/studio/education/toolkit.py +249 -0
  283. package/apps/desktop/workflows/chaptered-demo.ts +48 -0
  284. package/apps/desktop/workflows/creative-iteration.ts +107 -0
  285. package/apps/desktop/workflows/creative-selection.ts +92 -0
  286. package/apps/desktop/workflows/fragments.ts +486 -0
  287. package/apps/desktop/workflows/index.ts +93 -0
  288. package/apps/desktop/workflows/polished-screen-demo.ts +128 -0
  289. package/apps/desktop/workflows/scene-direction.ts +12 -0
  290. package/apps/desktop/workflows/social-variants.ts +75 -0
  291. package/apps/desktop/workflows/talking-head-cleanup.ts +53 -0
  292. package/dist/NebulaSans-Bold-26se8aek.otf +0 -0
  293. package/dist/NebulaSans-Bold-bcz7y08t.woff2 +0 -0
  294. package/dist/NebulaSans-Book-5ax05zvn.woff2 +0 -0
  295. package/dist/NebulaSans-Book-8cenzchw.otf +0 -0
  296. package/dist/cli.js +479 -0
  297. package/dist/code/advanced.js +270 -0
  298. package/dist/code/index.js +2240 -0
  299. package/dist/generate.js +24 -0
  300. package/dist/host-resources.js +26 -0
  301. package/dist/index-42zsesc1.js +2257 -0
  302. package/dist/index-7308egqr.js +48 -0
  303. package/dist/index-8txs6fkn.js +712 -0
  304. package/dist/index-mcy8z0br.js +192 -0
  305. package/dist/index-p63wavx0.js +2029 -0
  306. package/dist/index-r7gdhmsp.js +424 -0
  307. package/dist/index-sh6xbav6.js +1219 -0
  308. package/dist/index-z1w83f81.js +4 -0
  309. package/dist/index-z7239b4h.js +2363 -0
  310. package/dist/index-zfeg9hmw.js +2013 -0
  311. package/dist/index.js +241 -0
  312. package/dist/operations.js +29 -0
  313. package/dist/skill-install-dh0ntqba.js +10 -0
  314. package/dist/vectorize/worker.js +142 -0
  315. package/dist/workflow.js +16 -0
  316. package/docs/README.md +38 -0
  317. package/docs/studio.md +215 -0
  318. package/examples/studio/blender/README.md +26 -0
  319. package/examples/studio/blender/character.py +152 -0
  320. package/examples/studio/blender/cloth.py +101 -0
  321. package/examples/studio/blender/color_chart.py +29 -0
  322. package/examples/studio/blender/fluid.py +78 -0
  323. package/examples/studio/blender/import_model.py +74 -0
  324. package/examples/studio/blender/product.py +53 -0
  325. package/examples/studio/blender/shaded_street.py +481 -0
  326. package/examples/studio/blender/studio_scene.py +147 -0
  327. package/examples/studio/cadquery/README.md +13 -0
  328. package/examples/studio/cadquery/bracket.py +36 -0
  329. package/examples/studio/cadquery/import_step.py +12 -0
  330. package/examples/studio/education/README.md +46 -0
  331. package/examples/studio/education/lesson.json +99 -0
  332. package/examples/studio/education/scene.py +7 -0
  333. package/examples/studio/hybrid-scene.ts +96 -0
  334. package/examples/studio/native-workflow.ts +14 -0
  335. package/examples/studio/vgpu/README.md +64 -0
  336. package/examples/studio/vgpu/heat-field.mjs +290 -0
  337. package/package.json +304 -0
  338. package/packages/scene/src/index.ts +1 -0
  339. package/packages/scene/src/scene.ts +215 -0
  340. package/schema/diagram.schema.json +334 -0
  341. package/skills/slopcamera/SKILL.md +45 -0
  342. package/skills/slopcamera/agents/openai.yaml +4 -0
  343. package/skills/slopcamera/references/customization.md +77 -0
  344. package/skills/slopcamera/references/diagrams.md +153 -0
  345. package/skills/slopcamera/references/directed-scenes.md +42 -0
  346. package/skills/slopcamera/references/directing-video.md +18 -0
  347. package/skills/slopcamera/references/educational-video.md +26 -0
  348. package/skills/slopcamera/references/gateway-media.md +134 -0
  349. package/skills/slopcamera/references/install.md +62 -0
  350. package/skills/slopcamera/references/native-studio.md +31 -0
  351. package/skills/slopcamera/references/reference-led-3d.md +140 -0
  352. package/skills/slopcamera/references/rubber-stamp-examples/poster-example-1.jpg +0 -0
  353. package/skills/slopcamera/references/rubber-stamp-examples/poster-example-2.jpg +0 -0
  354. package/skills/slopcamera/references/rubber-stamp-examples/stamp-style-1.png +0 -0
  355. package/skills/slopcamera/references/rubber-stamp-examples/stamp-style-2.png +0 -0
  356. package/skills/slopcamera/references/rubber-stamp-field-notes.md +144 -0
  357. package/skills/slopcamera/references/vectorization.md +29 -0
  358. package/skills/slopcamera/references/video-projects.md +187 -0
  359. package/skills/slopcamera/references/visual-communication.md +120 -0
  360. package/skills/slopcamera/references/workflows-sdk.md +45 -0
  361. package/skills/slopcamera/scripts/compose-rubber-stamp-field-note.ts +229 -0
  362. package/src/artifacts.ts +106 -0
  363. package/src/assets/fonts/nebula-sans/LICENSE.txt +96 -0
  364. package/src/assets/fonts/nebula-sans/NebulaSans-Bold.otf +0 -0
  365. package/src/assets/fonts/nebula-sans/NebulaSans-Bold.woff2 +0 -0
  366. package/src/assets/fonts/nebula-sans/NebulaSans-Book.otf +0 -0
  367. package/src/assets/fonts/nebula-sans/NebulaSans-Book.woff2 +0 -0
  368. package/src/assets/fonts/nebula-sans/PROVENANCE.md +21 -0
  369. package/src/assets.d.ts +9 -0
  370. package/src/cli.ts +601 -0
  371. package/src/cloud-errors.ts +26 -0
  372. package/src/code/advanced.ts +10 -0
  373. package/src/code/boundary.ts +21 -0
  374. package/src/code/canonical-json.ts +129 -0
  375. package/src/code/compiler.ts +953 -0
  376. package/src/code/contracts.ts +576 -0
  377. package/src/code/define-workflow.ts +334 -0
  378. package/src/code/errors.ts +41 -0
  379. package/src/code/graph-builder.ts +945 -0
  380. package/src/code/index.ts +121 -0
  381. package/src/code/json-snapshot.ts +899 -0
  382. package/src/code/json-utf8.ts +88 -0
  383. package/src/code/portable-builder.ts +136 -0
  384. package/src/code/projection.ts +378 -0
  385. package/src/code/public-operations.ts +450 -0
  386. package/src/code/runtime.ts +580 -0
  387. package/src/code/sha256.ts +36 -0
  388. package/src/config.ts +180 -0
  389. package/src/desktop.ts +253 -0
  390. package/src/fs.ts +10 -0
  391. package/src/generate.ts +704 -0
  392. package/src/host-resource-posix.ts +161 -0
  393. package/src/host-resources.ts +1749 -0
  394. package/src/icons.ts +58 -0
  395. package/src/index.ts +200 -0
  396. package/src/label-layout.ts +130 -0
  397. package/src/layout.ts +413 -0
  398. package/src/lint.ts +127 -0
  399. package/src/mcp/boundary.ts +354 -0
  400. package/src/mcp/index.ts +33 -0
  401. package/src/mcp/server.ts +272 -0
  402. package/src/mcp/tools.ts +963 -0
  403. package/src/mcp/types.ts +71 -0
  404. package/src/operations.ts +775 -0
  405. package/src/parse.ts +861 -0
  406. package/src/process-environment.ts +17 -0
  407. package/src/render.ts +437 -0
  408. package/src/skill-install.ts +49 -0
  409. package/src/spatial-scene/authoring.ts +27 -0
  410. package/src/spatial-scene/camera-track.ts +83 -0
  411. package/src/spatial-scene/contracts.ts +277 -0
  412. package/src/spatial-scene/evaluate.ts +145 -0
  413. package/src/spatial-scene/gltf.ts +558 -0
  414. package/src/spatial-scene/identity.ts +260 -0
  415. package/src/spatial-scene/index.ts +10 -0
  416. package/src/spatial-scene/inspect.ts +68 -0
  417. package/src/spatial-scene/math.ts +280 -0
  418. package/src/spatial-scene/patch.ts +131 -0
  419. package/src/spatial-scene/time.ts +53 -0
  420. package/src/studio/contracts.ts +129 -0
  421. package/src/studio/index.ts +2 -0
  422. package/src/studio/plan.ts +156 -0
  423. package/src/studio/shared.ts +41 -0
  424. package/src/theme.ts +68 -0
  425. package/src/tldr.ts +474 -0
  426. package/src/types.ts +212 -0
  427. package/src/vectorize/archive.ts +101 -0
  428. package/src/vectorize/command.ts +797 -0
  429. package/src/vectorize/index.ts +27 -0
  430. package/src/vectorize/limits.ts +61 -0
  431. package/src/vectorize/metrics.ts +351 -0
  432. package/src/vectorize/pixels.ts +323 -0
  433. package/src/vectorize/supervisor.ts +339 -0
  434. package/src/vectorize/svg.ts +188 -0
  435. package/src/vectorize/tool.ts +542 -0
  436. package/src/vectorize/types.ts +113 -0
  437. package/src/vectorize/vectorize.ts +634 -0
  438. package/src/vectorize/worker-protocol.ts +40 -0
  439. package/src/vectorize/worker.ts +209 -0
  440. package/src/version.ts +1 -0
  441. package/src/workflow.ts +409 -0
@@ -0,0 +1,945 @@
1
+ import {
2
+ AuthoredComputeIdentitySchema,
3
+ AuthoredGraphNodeV1Schema,
4
+ AuthoredWorkflowGraphV1Schema,
5
+ MAX_SERIALIZED_GRAPH_NODES,
6
+ MAX_SERIALIZED_NODE_DEPENDENCIES,
7
+ MAX_SERIALIZED_REF_PATH_SEGMENTS,
8
+ NodeKeySegmentSchema,
9
+ OperationDiscoverySchema,
10
+ SerializedRefV1Schema,
11
+ LEGACY_TRUSTED_COMPUTE_BRAND,
12
+ TRUSTED_COMPUTE_BRAND,
13
+ TRUSTED_COMPUTE_VERSION,
14
+ WORKFLOW_GRAPH_VERSION,
15
+ WORKFLOW_REF_BRAND,
16
+ WORKFLOW_REF_VERSION,
17
+ WorkflowIdentitySchema,
18
+ type AuthoredGraphNodeV1,
19
+ type AuthoredWorkflowGraphV1,
20
+ type AnyTrustedComputeDefinition,
21
+ type GraphInputValue,
22
+ type OperationContract,
23
+ type OperationDiscovery,
24
+ type OperationDiscoverySource,
25
+ type OperationInputValue,
26
+ type OperationKind,
27
+ type Ref,
28
+ type SerializedRefV1,
29
+ type TrustedComputeDefinition,
30
+ type WorkflowIdentity,
31
+ type WorkflowOutputBinding,
32
+ type WorkflowOutputValue,
33
+ type WorkflowRegistryProjection,
34
+ } from "./contracts.js"
35
+ import { parseCodeBoundary } from "./boundary.js"
36
+ import { SlopcameraCodeError } from "./errors.js"
37
+ import { deepFreezeJson } from "./json-snapshot.js"
38
+ import { boundedOperationDiscoveryList } from "./projection.js"
39
+
40
+ export type OperationDiscoveryProvider =
41
+ | OperationDiscoverySource
42
+ | Pick<WorkflowRegistryProjection, "discovery">
43
+
44
+ export interface OperationNodeOptions {
45
+ /** Adds causal dependencies without threading a producer value into input. */
46
+ readonly after?: Ref<unknown> | readonly Ref<unknown>[]
47
+ readonly label?: string
48
+ }
49
+
50
+ export interface UntypedOperationRequest {
51
+ readonly input: unknown
52
+ readonly kind: OperationKind
53
+ readonly version: number
54
+ }
55
+
56
+ export interface WorkflowFragment<Input, Output> {
57
+ build(builder: WorkflowGraphBuilder, input: Input): Output
58
+ }
59
+
60
+ interface BuilderState {
61
+ authoredValues: number
62
+ readonly computes: Map<string, AnyTrustedComputeDefinition>
63
+ readonly discovery: ReadonlyMap<string, OperationDiscovery>
64
+ readonly nodes: Map<string, AuthoredGraphNodeV1>
65
+ readonly references: WeakSet<object>
66
+ }
67
+
68
+ interface EncodedInput {
69
+ readonly dependencies: readonly string[]
70
+ readonly value: GraphInputValue
71
+ readonly values: number
72
+ }
73
+
74
+ const MAX_AUTHORING_VALUE_DEPTH = 128
75
+ const MAX_AUTHORING_VALUES = 1_000_000
76
+ const NORMALIZED_LEGACY_COMPUTES = new WeakMap<
77
+ object,
78
+ AnyTrustedComputeDefinition
79
+ >()
80
+
81
+ interface EncodingBudget {
82
+ consumed: number
83
+ readonly maximum: number
84
+ }
85
+
86
+ function consumeAuthoringValue(budget: EncodingBudget): void {
87
+ if (budget.consumed >= budget.maximum) {
88
+ throw new SlopcameraCodeError(
89
+ "invalid-data",
90
+ `Workflow authoring values exceed the ${String(MAX_AUTHORING_VALUES)} value limit.`,
91
+ )
92
+ }
93
+ budget.consumed += 1
94
+ }
95
+
96
+ function consumeAuthoringValues(
97
+ budget: EncodingBudget,
98
+ additional: number,
99
+ ): void {
100
+ requireAuthoringCapacity(budget, additional)
101
+ budget.consumed += additional
102
+ }
103
+
104
+ function requireAuthoringCapacity(
105
+ budget: EncodingBudget,
106
+ additional: number,
107
+ ): void {
108
+ if (additional > budget.maximum - budget.consumed) {
109
+ throw new SlopcameraCodeError(
110
+ "invalid-data",
111
+ `Workflow authoring values exceed the ${String(MAX_AUTHORING_VALUES)} value limit.`,
112
+ )
113
+ }
114
+ }
115
+
116
+ function encodingBudget(state: BuilderState): EncodingBudget {
117
+ return {
118
+ consumed: 0,
119
+ maximum: MAX_AUTHORING_VALUES - state.authoredValues,
120
+ }
121
+ }
122
+
123
+ function requireStateCapacity(state: BuilderState, additional: number): void {
124
+ if (additional > MAX_AUTHORING_VALUES - state.authoredValues) {
125
+ throw new SlopcameraCodeError(
126
+ "invalid-data",
127
+ `Workflow authoring values exceed the ${String(MAX_AUTHORING_VALUES)} value limit.`,
128
+ )
129
+ }
130
+ }
131
+
132
+ function normalizeTrustedComputeDefinition<Input, Output>(
133
+ definition: TrustedComputeDefinition<Input, Output>,
134
+ ): TrustedComputeDefinition<Input, Output> | undefined {
135
+ if (definition[TRUSTED_COMPUTE_BRAND] === true) return definition
136
+ if (Reflect.get(definition, LEGACY_TRUSTED_COMPUTE_BRAND) !== true) {
137
+ return undefined
138
+ }
139
+ const existing = NORMALIZED_LEGACY_COMPUTES.get(definition)
140
+ if (existing !== undefined) {
141
+ return existing as TrustedComputeDefinition<Input, Output>
142
+ }
143
+ const normalized = Object.freeze({
144
+ [TRUSTED_COMPUTE_BRAND]: true as const,
145
+ bounds: definition.bounds,
146
+ inputSchema: definition.inputSchema,
147
+ inputSchemaId: definition.inputSchemaId,
148
+ key: definition.key,
149
+ outputSchema: definition.outputSchema,
150
+ outputSchemaId: definition.outputSchemaId,
151
+ run: definition.run,
152
+ }) satisfies TrustedComputeDefinition<Input, Output>
153
+ NORMALIZED_LEGACY_COMPUTES.set(definition, normalized)
154
+ return normalized
155
+ }
156
+
157
+ function discoveryKey(kind: OperationKind, version: number): string {
158
+ return `${kind}@${String(version)}`
159
+ }
160
+
161
+ function providerDiscovery(
162
+ provider: OperationDiscoveryProvider,
163
+ ): readonly unknown[] {
164
+ const source = provider as Partial<OperationDiscoverySource>
165
+ const discovery = typeof source.list === "function"
166
+ ? source.list()
167
+ : (provider as Pick<WorkflowRegistryProjection, "discovery">).discovery
168
+ return boundedOperationDiscoveryList(discovery)
169
+ }
170
+
171
+ function operationContractValue<Input, Output>(
172
+ discovery: Pick<OperationDiscovery, "inputSchemaId" | "kind" | "outputSchemaId" | "version">,
173
+ ): OperationContract<Input, Output> {
174
+ return Object.freeze({
175
+ inputSchemaId: discovery.inputSchemaId,
176
+ kind: discovery.kind,
177
+ outputSchemaId: discovery.outputSchemaId,
178
+ version: discovery.version,
179
+ })
180
+ }
181
+
182
+ function isPlainRecord(value: object): value is Record<string, unknown> {
183
+ const prototype: unknown = Object.getPrototypeOf(value)
184
+ return prototype === Object.prototype || prototype === null
185
+ }
186
+
187
+ function rejectEnumerableSymbols(
188
+ descriptors: object,
189
+ name: string,
190
+ ): void {
191
+ if (Object.getOwnPropertySymbols(descriptors).some(
192
+ symbol => (Reflect.get(descriptors, symbol) as PropertyDescriptor | undefined)
193
+ ?.enumerable === true,
194
+ )) {
195
+ throw new SlopcameraCodeError(
196
+ "invalid-data",
197
+ `${name} cannot contain enumerable symbol properties.`,
198
+ )
199
+ }
200
+ }
201
+
202
+ function cloneSerializedRef(reference: Ref<unknown>): SerializedRefV1 {
203
+ return deepFreezeJson(parseCodeBoundary(
204
+ SerializedRefV1Schema,
205
+ reference.serialized,
206
+ "workflow reference",
207
+ ))
208
+ }
209
+
210
+ function serializedReferenceValueCount(reference: SerializedRefV1): number {
211
+ const path = reference.$ref.path
212
+ // Root object + its two fields + nested $ref fields + optional path values.
213
+ return path === undefined ? 5 : 6 + path.length
214
+ }
215
+
216
+ function isOwnedRef(value: unknown, state: BuilderState): value is Ref<unknown> {
217
+ return typeof value === "object"
218
+ && value !== null
219
+ && WORKFLOW_REF_BRAND in value
220
+ && state.references.has(value)
221
+ }
222
+
223
+ function encodeInputValue(
224
+ input: unknown,
225
+ state: BuilderState,
226
+ dependencies: Set<string>,
227
+ ancestors: Set<object>,
228
+ depth: number,
229
+ budget: EncodingBudget,
230
+ ): GraphInputValue {
231
+ if (depth > MAX_AUTHORING_VALUE_DEPTH) {
232
+ throw new SlopcameraCodeError(
233
+ "invalid-data",
234
+ `Workflow input nesting exceeds ${String(MAX_AUTHORING_VALUE_DEPTH)} levels.`,
235
+ )
236
+ }
237
+ if (isOwnedRef(input, state)) {
238
+ const serialized = cloneSerializedRef(input)
239
+ consumeAuthoringValues(budget, serializedReferenceValueCount(serialized))
240
+ dependencies.add(serialized.$ref.nodeKey)
241
+ return serialized
242
+ }
243
+ consumeAuthoringValue(budget)
244
+ if (typeof input === "object" && input !== null && WORKFLOW_REF_BRAND in input) {
245
+ throw new SlopcameraCodeError(
246
+ "invalid-data",
247
+ "Use a typed Ref value created by this workflow graph builder.",
248
+ )
249
+ }
250
+ if (input === null || typeof input === "boolean" || typeof input === "string") {
251
+ return input
252
+ }
253
+ if (typeof input === "number") {
254
+ if (!Number.isFinite(input)) {
255
+ throw new SlopcameraCodeError(
256
+ "invalid-data",
257
+ "Workflow node input numbers must be finite.",
258
+ )
259
+ }
260
+ return Object.is(input, -0) ? 0 : input
261
+ }
262
+ if (typeof input !== "object") {
263
+ throw new SlopcameraCodeError(
264
+ "invalid-data",
265
+ `Workflow node input cannot contain ${typeof input} values.`,
266
+ )
267
+ }
268
+ if (ancestors.has(input)) {
269
+ throw new SlopcameraCodeError(
270
+ "invalid-data",
271
+ "Workflow node input cannot contain cycles.",
272
+ )
273
+ }
274
+ ancestors.add(input)
275
+ try {
276
+ if (Array.isArray(input)) {
277
+ const length = input.length
278
+ requireAuthoringCapacity(budget, length)
279
+ const descriptors = Object.getOwnPropertyDescriptors(input)
280
+ rejectEnumerableSymbols(descriptors, "Workflow node input arrays")
281
+ const keys = Object.keys(descriptors)
282
+ .filter(key => descriptors[key]?.enumerable === true)
283
+ if (
284
+ keys.length !== length
285
+ || keys.some((key, index) => key !== String(index))
286
+ ) {
287
+ throw new SlopcameraCodeError(
288
+ "invalid-data",
289
+ "Workflow node input arrays must be dense and cannot have named properties.",
290
+ )
291
+ }
292
+ const encoded: GraphInputValue[] = []
293
+ for (let index = 0; index < length; index += 1) {
294
+ const descriptor = descriptors[String(index)]
295
+ if (
296
+ descriptor === undefined
297
+ || descriptor.get !== undefined
298
+ || descriptor.set !== undefined
299
+ ) {
300
+ throw new SlopcameraCodeError(
301
+ "invalid-data",
302
+ "Workflow node input arrays must contain plain data elements.",
303
+ )
304
+ }
305
+ encoded.push(encodeInputValue(
306
+ descriptor.value,
307
+ state,
308
+ dependencies,
309
+ ancestors,
310
+ depth + 1,
311
+ budget,
312
+ ))
313
+ }
314
+ return encoded
315
+ }
316
+ if (!isPlainRecord(input)) {
317
+ throw new SlopcameraCodeError(
318
+ "invalid-data",
319
+ "Workflow node input accepts only JSON values and typed workflow references.",
320
+ )
321
+ }
322
+ if (Object.hasOwn(input, "$ref")) {
323
+ throw new SlopcameraCodeError(
324
+ "invalid-data",
325
+ "Use a typed Ref value instead of constructing the reserved $ref field.",
326
+ )
327
+ }
328
+ const descriptors = Object.getOwnPropertyDescriptors(input)
329
+ rejectEnumerableSymbols(descriptors, "Workflow node inputs")
330
+ const keys = Object.keys(descriptors)
331
+ .filter(key => descriptors[key]?.enumerable === true)
332
+ .sort()
333
+ requireAuthoringCapacity(budget, keys.length)
334
+ const encoded: Record<string, GraphInputValue> = {}
335
+ for (const key of keys) {
336
+ if (key === "__proto__") {
337
+ throw new SlopcameraCodeError(
338
+ "invalid-data",
339
+ "Workflow inputs cannot contain the reserved __proto__ object key.",
340
+ )
341
+ }
342
+ const descriptor = descriptors[key]
343
+ if (
344
+ descriptor === undefined
345
+ || descriptor.get !== undefined
346
+ || descriptor.set !== undefined
347
+ ) {
348
+ throw new SlopcameraCodeError(
349
+ "invalid-data",
350
+ "Workflow node input properties must be plain data properties.",
351
+ )
352
+ }
353
+ encoded[key] = encodeInputValue(
354
+ descriptor.value,
355
+ state,
356
+ dependencies,
357
+ ancestors,
358
+ depth + 1,
359
+ budget,
360
+ )
361
+ }
362
+ return encoded
363
+ } finally {
364
+ ancestors.delete(input)
365
+ }
366
+ }
367
+
368
+ function encodeOperationInput(input: unknown, state: BuilderState): EncodedInput {
369
+ const dependencies = new Set<string>()
370
+ const budget = encodingBudget(state)
371
+ const value = encodeInputValue(input, state, dependencies, new Set(), 0, budget)
372
+ return {
373
+ dependencies: [...dependencies].sort((left, right) => left.localeCompare(right)),
374
+ value,
375
+ values: budget.consumed,
376
+ }
377
+ }
378
+
379
+ function encodeControlDependencies(
380
+ after: OperationNodeOptions["after"],
381
+ state: BuilderState,
382
+ ): readonly string[] {
383
+ if (after === undefined) return []
384
+ const dependencies = new Set<string>()
385
+ const appendReference = (reference: unknown): void => {
386
+ if (!isOwnedRef(reference, state)) {
387
+ throw new SlopcameraCodeError(
388
+ "invalid-data",
389
+ "Operation control dependencies must be typed Ref values created by this workflow graph builder.",
390
+ )
391
+ }
392
+ dependencies.add(cloneSerializedRef(reference).$ref.nodeKey)
393
+ }
394
+ if (!Array.isArray(after)) {
395
+ appendReference(after)
396
+ return [...dependencies]
397
+ }
398
+ const length = after.length
399
+ if (length > MAX_SERIALIZED_NODE_DEPENDENCIES) {
400
+ throw new SlopcameraCodeError(
401
+ "invalid-data",
402
+ `Operation control dependencies cannot exceed ${String(MAX_SERIALIZED_NODE_DEPENDENCIES)} entries.`,
403
+ )
404
+ }
405
+ const descriptors = Object.getOwnPropertyDescriptors(after)
406
+ rejectEnumerableSymbols(descriptors, "Operation control dependencies")
407
+ const keys = Object.keys(descriptors)
408
+ .filter(key => descriptors[key]?.enumerable === true)
409
+ if (
410
+ keys.length !== length
411
+ || keys.some((key, index) => key !== String(index))
412
+ ) {
413
+ throw new SlopcameraCodeError(
414
+ "invalid-data",
415
+ "Operation control dependencies must be a dense array without named properties.",
416
+ )
417
+ }
418
+ for (let index = 0; index < length; index += 1) {
419
+ const descriptor = descriptors[String(index)]
420
+ if (
421
+ descriptor === undefined
422
+ || descriptor.get !== undefined
423
+ || descriptor.set !== undefined
424
+ ) {
425
+ throw new SlopcameraCodeError(
426
+ "invalid-data",
427
+ "Operation control dependencies must contain plain data elements.",
428
+ )
429
+ }
430
+ appendReference(descriptor.value)
431
+ }
432
+ return [...dependencies].sort((left, right) => left.localeCompare(right))
433
+ }
434
+
435
+ function combineDependencies(
436
+ dataDependencies: readonly string[],
437
+ controlDependencies: readonly string[],
438
+ ): readonly string[] {
439
+ return [...new Set([...dataDependencies, ...controlDependencies])]
440
+ .sort((left, right) => left.localeCompare(right))
441
+ }
442
+
443
+ function encodeOutputValue(
444
+ output: unknown,
445
+ state: BuilderState,
446
+ ancestors: Set<object>,
447
+ depth: number,
448
+ budget: EncodingBudget,
449
+ ): WorkflowOutputBinding {
450
+ if (depth > MAX_AUTHORING_VALUE_DEPTH) {
451
+ throw new SlopcameraCodeError(
452
+ "invalid-data",
453
+ `Workflow output nesting exceeds ${String(MAX_AUTHORING_VALUE_DEPTH)} levels.`,
454
+ )
455
+ }
456
+ if (isOwnedRef(output, state)) {
457
+ const serialized = cloneSerializedRef(output)
458
+ consumeAuthoringValues(budget, serializedReferenceValueCount(serialized))
459
+ return serialized
460
+ }
461
+ consumeAuthoringValue(budget)
462
+ if (typeof output !== "object" || output === null) {
463
+ throw new SlopcameraCodeError(
464
+ "invalid-data",
465
+ "Workflow outputs must contain only typed references, arrays, and named objects.",
466
+ )
467
+ }
468
+ if (ancestors.has(output)) {
469
+ throw new SlopcameraCodeError("invalid-data", "Workflow outputs cannot contain cycles.")
470
+ }
471
+ ancestors.add(output)
472
+ try {
473
+ if (Array.isArray(output)) {
474
+ const length = output.length
475
+ requireAuthoringCapacity(budget, length)
476
+ const descriptors = Object.getOwnPropertyDescriptors(output)
477
+ rejectEnumerableSymbols(descriptors, "Workflow output arrays")
478
+ const keys = Object.keys(descriptors)
479
+ .filter(key => descriptors[key]?.enumerable === true)
480
+ if (
481
+ keys.length !== length
482
+ || keys.some((key, index) => key !== String(index))
483
+ ) {
484
+ throw new SlopcameraCodeError(
485
+ "invalid-data",
486
+ "Workflow output arrays must be dense and cannot have named properties.",
487
+ )
488
+ }
489
+ const encoded: WorkflowOutputBinding[] = []
490
+ for (let index = 0; index < length; index += 1) {
491
+ const descriptor = descriptors[String(index)]
492
+ if (
493
+ descriptor === undefined
494
+ || descriptor.get !== undefined
495
+ || descriptor.set !== undefined
496
+ ) {
497
+ throw new SlopcameraCodeError(
498
+ "invalid-data",
499
+ "Workflow output arrays must contain plain data elements.",
500
+ )
501
+ }
502
+ encoded.push(encodeOutputValue(
503
+ descriptor.value,
504
+ state,
505
+ ancestors,
506
+ depth + 1,
507
+ budget,
508
+ ))
509
+ }
510
+ return encoded
511
+ }
512
+ if (!isPlainRecord(output)) {
513
+ throw new SlopcameraCodeError(
514
+ "invalid-data",
515
+ "Workflow outputs accept only typed references, arrays, and plain objects.",
516
+ )
517
+ }
518
+ if (Object.hasOwn(output, "$ref")) {
519
+ throw new SlopcameraCodeError(
520
+ "invalid-data",
521
+ "Use a typed Ref value instead of constructing the reserved $ref field.",
522
+ )
523
+ }
524
+ const descriptors = Object.getOwnPropertyDescriptors(output)
525
+ rejectEnumerableSymbols(descriptors, "Workflow outputs")
526
+ const keys = Object.keys(descriptors)
527
+ .filter(key => descriptors[key]?.enumerable === true)
528
+ .sort()
529
+ requireAuthoringCapacity(budget, keys.length)
530
+ const encoded: Record<string, WorkflowOutputBinding> = {}
531
+ for (const key of keys) {
532
+ if (key === "__proto__") {
533
+ throw new SlopcameraCodeError(
534
+ "invalid-data",
535
+ "Workflow outputs cannot contain the reserved __proto__ object key.",
536
+ )
537
+ }
538
+ const descriptor = descriptors[key]
539
+ if (
540
+ descriptor === undefined
541
+ || descriptor.get !== undefined
542
+ || descriptor.set !== undefined
543
+ ) {
544
+ throw new SlopcameraCodeError(
545
+ "invalid-data",
546
+ "Workflow output properties must be plain data properties.",
547
+ )
548
+ }
549
+ encoded[key] = encodeOutputValue(
550
+ descriptor.value,
551
+ state,
552
+ ancestors,
553
+ depth + 1,
554
+ budget,
555
+ )
556
+ }
557
+ return encoded
558
+ } finally {
559
+ ancestors.delete(output)
560
+ }
561
+ }
562
+
563
+ function createReference<Output>(
564
+ nodeKey: string,
565
+ schemaId: string,
566
+ state: BuilderState,
567
+ path: readonly (number | string)[] = [],
568
+ ): Ref<Output> {
569
+ if (path.length > MAX_SERIALIZED_REF_PATH_SEGMENTS) {
570
+ throw new SlopcameraCodeError(
571
+ "invalid-data",
572
+ `Workflow reference paths cannot exceed ${String(MAX_SERIALIZED_REF_PATH_SEGMENTS)} segments.`,
573
+ )
574
+ }
575
+ const serialized = deepFreezeJson({
576
+ $ref: {
577
+ nodeKey,
578
+ ...(path.length === 0 ? {} : { path: [...path] }),
579
+ schemaId,
580
+ },
581
+ version: WORKFLOW_REF_VERSION,
582
+ } satisfies SerializedRefV1)
583
+ const reference = Object.freeze({
584
+ [WORKFLOW_REF_BRAND]: (): Output => {
585
+ throw new SlopcameraCodeError(
586
+ "internal",
587
+ "A workflow reference type marker is not executable.",
588
+ )
589
+ },
590
+ at: (index: number) => {
591
+ if (!Number.isSafeInteger(index) || index < 0) {
592
+ throw new SlopcameraCodeError(
593
+ "invalid-data",
594
+ "Workflow reference array indexes must be nonnegative safe integers.",
595
+ )
596
+ }
597
+ if (path.length >= MAX_SERIALIZED_REF_PATH_SEGMENTS) {
598
+ throw new SlopcameraCodeError(
599
+ "invalid-data",
600
+ `Workflow reference paths cannot exceed ${String(MAX_SERIALIZED_REF_PATH_SEGMENTS)} segments.`,
601
+ )
602
+ }
603
+ return createReference(nodeKey, schemaId, state, [...path, index]) as (
604
+ Output extends readonly (infer Item)[] ? Ref<Item> : never
605
+ )
606
+ },
607
+ select: <Key extends Extract<keyof Output, string>>(key: Key): Ref<Output[Key]> => {
608
+ if (typeof key !== "string" || key.length < 1 || key.length > 128) {
609
+ throw new SlopcameraCodeError(
610
+ "invalid-data",
611
+ "Workflow reference field names must contain 1–128 characters.",
612
+ )
613
+ }
614
+ if (path.length >= MAX_SERIALIZED_REF_PATH_SEGMENTS) {
615
+ throw new SlopcameraCodeError(
616
+ "invalid-data",
617
+ `Workflow reference paths cannot exceed ${String(MAX_SERIALIZED_REF_PATH_SEGMENTS)} segments.`,
618
+ )
619
+ }
620
+ return createReference<Output[Key]>(nodeKey, schemaId, state, [...path, key])
621
+ },
622
+ serialized,
623
+ }) as unknown as Ref<Output>
624
+ state.references.add(reference)
625
+ return reference
626
+ }
627
+
628
+ function createState(provider: OperationDiscoveryProvider): BuilderState {
629
+ const discovery = new Map<string, OperationDiscovery>()
630
+ for (const input of providerDiscovery(provider)) {
631
+ const item = parseCodeBoundary(
632
+ OperationDiscoverySchema,
633
+ input,
634
+ "operation discovery entry",
635
+ )
636
+ const key = discoveryKey(item.kind, item.version)
637
+ if (discovery.has(key)) {
638
+ throw new SlopcameraCodeError(
639
+ "conflict",
640
+ `Duplicate operation discovery entry: ${key}`,
641
+ { kind: item.kind, version: item.version },
642
+ )
643
+ }
644
+ discovery.set(key, item)
645
+ }
646
+ return {
647
+ // Root graph, nodes array, version, workflow object, and its three fields.
648
+ // The output subtree is charged temporarily by build().
649
+ authoredValues: 7,
650
+ computes: new Map(),
651
+ discovery,
652
+ nodes: new Map(),
653
+ references: new WeakSet(),
654
+ }
655
+ }
656
+
657
+ export function defineWorkflowFragment<Input, Output>(
658
+ build: (builder: WorkflowGraphBuilder, input: Input) => Output,
659
+ ): WorkflowFragment<Input, Output> {
660
+ if (typeof build !== "function") {
661
+ throw new SlopcameraCodeError(
662
+ "invalid-data",
663
+ "Workflow fragments require a build function.",
664
+ )
665
+ }
666
+ return Object.freeze({ build })
667
+ }
668
+
669
+ export function operationContract<Input, Output>(
670
+ provider: OperationDiscoveryProvider,
671
+ kind: OperationKind,
672
+ version: number,
673
+ ): OperationContract<Input, Output> {
674
+ const discovery = createState(provider).discovery.get(discoveryKey(kind, version))
675
+ if (discovery === undefined) {
676
+ throw new SlopcameraCodeError(
677
+ "unsupported-plan",
678
+ `Unsupported operation: ${kind}@${String(version)}`,
679
+ { kind, version },
680
+ )
681
+ }
682
+ return operationContractValue<Input, Output>(discovery)
683
+ }
684
+
685
+ export class WorkflowGraphBuilder {
686
+ readonly #namespace: readonly string[]
687
+ readonly #state: BuilderState
688
+
689
+ private constructor(state: BuilderState, namespace: readonly string[]) {
690
+ this.#namespace = namespace
691
+ this.#state = state
692
+ }
693
+
694
+ static create(provider: OperationDiscoveryProvider): WorkflowGraphBuilder {
695
+ return new WorkflowGraphBuilder(createState(provider), [])
696
+ }
697
+
698
+ namespace(segmentInput: string): WorkflowGraphBuilder {
699
+ const segment = parseCodeBoundary(
700
+ NodeKeySegmentSchema,
701
+ segmentInput,
702
+ "workflow namespace segment",
703
+ )
704
+ return new WorkflowGraphBuilder(this.#state, [...this.#namespace, segment])
705
+ }
706
+
707
+ fragment<Input, Output>(
708
+ namespace: string,
709
+ fragment: WorkflowFragment<Input, Output>,
710
+ input: Input,
711
+ ): Output {
712
+ return fragment.build(this.namespace(namespace), input)
713
+ }
714
+
715
+ operation<Input, Output>(
716
+ keyInput: string,
717
+ contract: OperationContract<Input, Output>,
718
+ input: OperationInputValue<Input>,
719
+ options: OperationNodeOptions = {},
720
+ ): Ref<Output> {
721
+ return this.#addOperation<Output>(keyInput, {
722
+ input,
723
+ inputSchemaId: contract.inputSchemaId,
724
+ kind: contract.kind,
725
+ outputSchemaId: contract.outputSchemaId,
726
+ version: contract.version,
727
+ }, options)
728
+ }
729
+
730
+ operationByKind<Output>(
731
+ keyInput: string,
732
+ request: UntypedOperationRequest,
733
+ options: OperationNodeOptions = {},
734
+ ): Ref<Output> {
735
+ const discovery = this.#state.discovery.get(
736
+ discoveryKey(request.kind, request.version),
737
+ )
738
+ if (discovery === undefined) {
739
+ throw new SlopcameraCodeError(
740
+ "unsupported-plan",
741
+ `Unsupported operation: ${request.kind}@${String(request.version)}`,
742
+ { kind: request.kind, version: request.version },
743
+ )
744
+ }
745
+ return this.#addOperation<Output>(keyInput, {
746
+ input: request.input,
747
+ inputSchemaId: discovery.inputSchemaId,
748
+ kind: request.kind,
749
+ outputSchemaId: discovery.outputSchemaId,
750
+ version: request.version,
751
+ }, options)
752
+ }
753
+
754
+ compute<Input, Output>(
755
+ keyInput: string,
756
+ definition: TrustedComputeDefinition<Input, Output>,
757
+ input: OperationInputValue<Input>,
758
+ options: OperationNodeOptions = {},
759
+ ): Ref<Output> {
760
+ if (typeof definition !== "object" || definition === null) {
761
+ throw new SlopcameraCodeError(
762
+ "invalid-data",
763
+ "Compute nodes require a definition created by defineCompute().",
764
+ )
765
+ }
766
+ const normalizedDefinition = normalizeTrustedComputeDefinition(definition)
767
+ if (normalizedDefinition === undefined) {
768
+ throw new SlopcameraCodeError(
769
+ "invalid-data",
770
+ "Compute nodes require a definition created by defineCompute().",
771
+ )
772
+ }
773
+ const compute = parseCodeBoundary(
774
+ AuthoredComputeIdentitySchema,
775
+ {
776
+ bounds: normalizedDefinition.bounds,
777
+ key: normalizedDefinition.key,
778
+ version: TRUSTED_COMPUTE_VERSION,
779
+ },
780
+ "trusted compute identity",
781
+ )
782
+ const existing = this.#state.computes.get(compute.key)
783
+ if (existing !== undefined && existing !== normalizedDefinition) {
784
+ throw new SlopcameraCodeError(
785
+ "conflict",
786
+ `Duplicate trusted compute key: ${compute.key}`,
787
+ { key: compute.key },
788
+ )
789
+ }
790
+ const key = this.#nodeKey(keyInput)
791
+ const encoded = encodeOperationInput(input, this.#state)
792
+ const controlDependencies = encodeControlDependencies(options.after, this.#state)
793
+ const dependencies = combineDependencies(
794
+ encoded.dependencies,
795
+ controlDependencies,
796
+ )
797
+ const nodeValues = encoded.values
798
+ + 15
799
+ + controlDependencies.length
800
+ + dependencies.length
801
+ + (options.label === undefined ? 0 : 1)
802
+ requireStateCapacity(this.#state, nodeValues)
803
+ const node = parseCodeBoundary(AuthoredGraphNodeV1Schema, {
804
+ controlDependencies,
805
+ dependencies,
806
+ executor: { compute, kind: "compute" },
807
+ input: encoded.value,
808
+ inputSchemaId: normalizedDefinition.inputSchemaId,
809
+ key,
810
+ ...(options.label === undefined ? {} : { label: options.label }),
811
+ outputSchemaId: normalizedDefinition.outputSchemaId,
812
+ }, "authored compute node")
813
+ this.#state.computes.set(compute.key, normalizedDefinition)
814
+ this.#state.nodes.set(key, node)
815
+ this.#state.authoredValues += nodeValues
816
+ return createReference<Output>(
817
+ key,
818
+ normalizedDefinition.outputSchemaId,
819
+ this.#state,
820
+ )
821
+ }
822
+
823
+ computeDefinitions(): readonly AnyTrustedComputeDefinition[] {
824
+ return Object.freeze(
825
+ [...this.#state.computes.values()]
826
+ .sort((left, right) => left.key.localeCompare(right.key)),
827
+ )
828
+ }
829
+
830
+ build(
831
+ workflowInput: WorkflowIdentity,
832
+ outputs: WorkflowOutputValue,
833
+ ): AuthoredWorkflowGraphV1 {
834
+ const workflow = parseCodeBoundary(
835
+ WorkflowIdentitySchema,
836
+ workflowInput,
837
+ "workflow identity",
838
+ )
839
+ const outputBudget = encodingBudget(this.#state)
840
+ const encodedOutputs = encodeOutputValue(
841
+ outputs,
842
+ this.#state,
843
+ new Set(),
844
+ 0,
845
+ outputBudget,
846
+ )
847
+ return deepFreezeJson(parseCodeBoundary(AuthoredWorkflowGraphV1Schema, {
848
+ nodes: [...this.#state.nodes.values()]
849
+ .sort((left, right) => left.key.localeCompare(right.key)),
850
+ outputs: encodedOutputs,
851
+ version: WORKFLOW_GRAPH_VERSION,
852
+ workflow,
853
+ }, "authored workflow graph"))
854
+ }
855
+
856
+ #nodeKey(keyInput: string): string {
857
+ const keySegment = parseCodeBoundary(
858
+ NodeKeySegmentSchema,
859
+ keyInput,
860
+ "workflow node key segment",
861
+ )
862
+ const key = [...this.#namespace, keySegment].join("/")
863
+ if (this.#state.nodes.has(key)) {
864
+ throw new SlopcameraCodeError(
865
+ "conflict",
866
+ `Duplicate workflow node key: ${key}`,
867
+ { nodeKey: key },
868
+ )
869
+ }
870
+ if (this.#state.nodes.size >= MAX_SERIALIZED_GRAPH_NODES) {
871
+ throw new SlopcameraCodeError(
872
+ "invalid-data",
873
+ `Workflow nodes cannot exceed ${String(MAX_SERIALIZED_GRAPH_NODES)} entries.`,
874
+ )
875
+ }
876
+ return key
877
+ }
878
+
879
+ #addOperation<Output>(
880
+ keyInput: string,
881
+ request: {
882
+ readonly input: unknown
883
+ readonly inputSchemaId: string
884
+ readonly kind: OperationKind
885
+ readonly outputSchemaId: string
886
+ readonly version: number
887
+ },
888
+ options: OperationNodeOptions,
889
+ ): Ref<Output> {
890
+ const key = this.#nodeKey(keyInput)
891
+ const discovery = this.#state.discovery.get(discoveryKey(request.kind, request.version))
892
+ if (discovery === undefined) {
893
+ throw new SlopcameraCodeError(
894
+ "unsupported-plan",
895
+ `Unsupported operation: ${request.kind}@${String(request.version)}`,
896
+ { kind: request.kind, version: request.version },
897
+ )
898
+ }
899
+ if (
900
+ request.inputSchemaId !== discovery.inputSchemaId
901
+ || request.outputSchemaId !== discovery.outputSchemaId
902
+ ) {
903
+ throw new SlopcameraCodeError(
904
+ "invalid-data",
905
+ `Operation contract schema mismatch for ${request.kind}@${String(request.version)}.`,
906
+ {
907
+ actualInputSchemaId: request.inputSchemaId,
908
+ actualOutputSchemaId: request.outputSchemaId,
909
+ expectedInputSchemaId: discovery.inputSchemaId,
910
+ expectedOutputSchemaId: discovery.outputSchemaId,
911
+ kind: request.kind,
912
+ version: request.version,
913
+ },
914
+ )
915
+ }
916
+ const encoded = encodeOperationInput(request.input, this.#state)
917
+ const controlDependencies = encodeControlDependencies(options.after, this.#state)
918
+ const dependencies = combineDependencies(
919
+ encoded.dependencies,
920
+ controlDependencies,
921
+ )
922
+ const nodeValues = encoded.values
923
+ + 11
924
+ + controlDependencies.length
925
+ + dependencies.length
926
+ + (options.label === undefined ? 0 : 1)
927
+ requireStateCapacity(this.#state, nodeValues)
928
+ const node = parseCodeBoundary(AuthoredGraphNodeV1Schema, {
929
+ controlDependencies,
930
+ dependencies,
931
+ executor: {
932
+ kind: "operation",
933
+ operation: { kind: discovery.kind, version: discovery.version },
934
+ },
935
+ input: encoded.value,
936
+ inputSchemaId: discovery.inputSchemaId,
937
+ key,
938
+ ...(options.label === undefined ? {} : { label: options.label }),
939
+ outputSchemaId: discovery.outputSchemaId,
940
+ }, "authored operation node")
941
+ this.#state.nodes.set(key, node)
942
+ this.#state.authoredValues += nodeValues
943
+ return createReference<Output>(key, discovery.outputSchemaId, this.#state)
944
+ }
945
+ }