@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,689 @@
1
+ import { z } from "zod";
2
+ import {
3
+ CaptureInterruptionSchema as RecordingCaptureInterruptionSchema,
4
+ MAX_CAPTURE_INTERRUPTION_SOURCE_ID_BYTES,
5
+ type CaptureInterruption as RecordingCaptureInterruption,
6
+ } from "../contracts/recording";
7
+
8
+ export const CAPTURE_PROTOCOL_VERSION = 4 as const;
9
+ export const CAPTURE_HELPER_VERSION = "0.4.0" as const;
10
+ export const MAX_PROTOCOL_LINE_BYTES = 64 * 1024;
11
+ export const MAX_CAPTURE_DISPLAYS = 16;
12
+ export const MAX_CAPTURE_CAMERAS = 32;
13
+ export const MAX_CAPTURE_AUDIO_SOURCES = 64;
14
+ export const MAX_CAPTURE_SEGMENTS = 128;
15
+ export const MAX_CAPTURE_SOURCE_ID_BYTES =
16
+ MAX_CAPTURE_INTERRUPTION_SOURCE_ID_BYTES;
17
+
18
+ export {
19
+ CaptureInterruptionSchema,
20
+ type CaptureInterruption,
21
+ } from "../contracts/recording";
22
+
23
+ const BoundedIdentifierSchema = z.string().min(1).max(128).regex(/^[A-Za-z0-9._:-]+$/u);
24
+ const utf8ByteLength = (value: string): number =>
25
+ new TextEncoder().encode(value).byteLength;
26
+ const utf8BoundedString = (maximumBytes: number) => z.string().min(1)
27
+ .refine(
28
+ value => utf8ByteLength(value) <= maximumBytes && !value.includes("\0"),
29
+ `Expected a non-NUL string of at most ${String(maximumBytes)} UTF-8 bytes.`,
30
+ );
31
+ const BoundedFieldIdentifierSchema = utf8BoundedString(512);
32
+ const BoundedWindowIdentifierSchema = z.string().min(1)
33
+ .regex(/^[1-9][0-9]*$/u)
34
+ .refine(
35
+ value => utf8ByteLength(value) <= 32 && !value.includes("\0"),
36
+ "Expected a positive decimal window ID of at most 32 UTF-8 bytes.",
37
+ );
38
+ const BoundedWindowTitleSchema = utf8BoundedString(256);
39
+ const BoundedMessageSchema = z.string().min(1).max(4_096);
40
+ const SafeIntegerSchema = z.number().int().safe().nonnegative();
41
+ const PositiveSafeIntegerSchema = SafeIntegerSchema.positive();
42
+ const SignedSafeIntegerSchema = z.number().int().safe();
43
+ const PositiveProcessIdentifierSchema = z.number().int().positive()
44
+ .max(2_147_483_647);
45
+
46
+ const AbsoluteSessionDirectorySchema = z.string().min(1).max(4_096).superRefine((value, context) => {
47
+ if (!value.startsWith("/") || value.includes("\0")) {
48
+ context.addIssue({ code: "custom", message: "Expected an absolute macOS path." });
49
+ return;
50
+ }
51
+ if (value.split("/").some((part) => part === "." || part === "..")) {
52
+ context.addIssue({ code: "custom", message: "Absolute paths may not contain dot segments." });
53
+ }
54
+ });
55
+
56
+ const RelativeOutputPathSchema = z.string().min(1).max(1_024).superRefine((value, context) => {
57
+ if (
58
+ value.startsWith("/")
59
+ || value.startsWith("\\")
60
+ || value.includes("\\")
61
+ || value.includes("\0")
62
+ || value.split("/").some((part) => part.length === 0 || part === "." || part === "..")
63
+ ) {
64
+ context.addIssue({ code: "custom", message: "Expected a normalized session-relative output path." });
65
+ }
66
+ });
67
+
68
+ const RequestBase = {
69
+ protocolVersion: z.literal(CAPTURE_PROTOCOL_VERSION),
70
+ requestId: BoundedIdentifierSchema,
71
+ } as const;
72
+
73
+ export const TypedTextFocusIdentitySchema = z.strictObject({
74
+ fieldId: BoundedFieldIdentifierSchema,
75
+ processId: PositiveProcessIdentifierSchema,
76
+ windowId: BoundedWindowIdentifierSchema,
77
+ windowTitle: BoundedWindowTitleSchema,
78
+ });
79
+
80
+ export const TypedTextFocusIdentitiesSchema = z.array(TypedTextFocusIdentitySchema)
81
+ .max(16)
82
+ .superRefine((identities, context) => {
83
+ const keys = identities.map(identity =>
84
+ `${identity.processId}\0${identity.windowId}\0${identity.fieldId}\0${identity.windowTitle}`
85
+ );
86
+ if (new Set(keys).size !== keys.length) {
87
+ context.addIssue({
88
+ code: "custom",
89
+ message: "Typed-text focus identities must be unique.",
90
+ });
91
+ }
92
+ });
93
+
94
+ export const CaptureDisplaySelectionSchema = z.discriminatedUnion("kind", [
95
+ z.strictObject({ kind: z.literal("all") }),
96
+ z.strictObject({
97
+ displayIds: z.array(utf8BoundedString(64)).min(1).max(MAX_CAPTURE_DISPLAYS)
98
+ .superRefine((displayIds, context) => {
99
+ if (new Set(displayIds).size !== displayIds.length) {
100
+ context.addIssue({
101
+ code: "custom",
102
+ message: "Selected display IDs must be unique.",
103
+ });
104
+ }
105
+ }),
106
+ kind: z.literal("selected"),
107
+ }),
108
+ ]);
109
+
110
+ export const CaptureDeviceSelectionSchema = z.discriminatedUnion("kind", [
111
+ z.strictObject({ kind: z.literal("disabled") }),
112
+ z.strictObject({ kind: z.literal("default") }),
113
+ z.strictObject({
114
+ deviceId: utf8BoundedString(256),
115
+ kind: z.literal("device"),
116
+ }),
117
+ ]);
118
+
119
+ export const CaptureOptionsSchema = z.strictObject({
120
+ camera: CaptureDeviceSelectionSchema.default({ kind: "default" }),
121
+ displays: CaptureDisplaySelectionSchema.default({ kind: "all" }),
122
+ metadata: z.boolean().default(true),
123
+ microphone: CaptureDeviceSelectionSchema.default({ kind: "default" }),
124
+ interactionEventProcessIdentifier: PositiveProcessIdentifierSchema
125
+ .nullable()
126
+ .default(null),
127
+ strictSources: z.boolean().default(false),
128
+ systemAudio: z.boolean().default(true),
129
+ typedText: z.boolean().default(false),
130
+ typedTextFocusIdentities: TypedTextFocusIdentitiesSchema.nullable()
131
+ .default(null),
132
+ excludedBundleIdentifiers: z.array(z.string().min(1).max(256)).max(16).default(["com.hraness.slopcamera"]),
133
+ });
134
+
135
+ const ConfigureRequestSchema = z.strictObject({
136
+ ...RequestBase,
137
+ command: z.literal("configure"),
138
+ options: CaptureOptionsSchema.optional(),
139
+ sessionDirectory: AbsoluteSessionDirectorySchema,
140
+ });
141
+
142
+ const SimpleCommandSchema = <Command extends "pause" | "resume" | "shutdown" | "snapshot" | "start" | "status" | "stop">(
143
+ command: Command,
144
+ ) => z.strictObject({ ...RequestBase, command: z.literal(command) });
145
+
146
+ export const CaptureRequestSchema = z.discriminatedUnion("command", [
147
+ ConfigureRequestSchema,
148
+ SimpleCommandSchema("start"),
149
+ SimpleCommandSchema("pause"),
150
+ SimpleCommandSchema("resume"),
151
+ SimpleCommandSchema("snapshot"),
152
+ SimpleCommandSchema("status"),
153
+ SimpleCommandSchema("stop"),
154
+ SimpleCommandSchema("shutdown"),
155
+ ]);
156
+
157
+ export type CaptureOptions = Readonly<z.infer<typeof CaptureOptionsSchema>>;
158
+ export type CaptureRequest = Readonly<z.infer<typeof CaptureRequestSchema>>;
159
+ export type TypedTextFocusIdentity = Readonly<
160
+ z.infer<typeof TypedTextFocusIdentitySchema>
161
+ >;
162
+
163
+ export const PermissionStateSchema = z.enum([
164
+ "not-determined",
165
+ "authorized",
166
+ "denied",
167
+ "restricted",
168
+ "unavailable",
169
+ ]);
170
+
171
+ export const CapturePermissionsSchema = z.strictObject({
172
+ accessibility: PermissionStateSchema,
173
+ camera: PermissionStateSchema,
174
+ inputMonitoring: PermissionStateSchema,
175
+ microphone: PermissionStateSchema,
176
+ screenCapture: PermissionStateSchema,
177
+ systemAudio: PermissionStateSchema,
178
+ windowMetadata: PermissionStateSchema,
179
+ });
180
+
181
+ const RectSchema = z.strictObject({
182
+ height: z.number().finite().positive(),
183
+ width: z.number().finite().positive(),
184
+ x: z.number().finite(),
185
+ y: z.number().finite(),
186
+ });
187
+
188
+ export const DisplayGeometrySchema = z.strictObject({
189
+ bounds: RectSchema,
190
+ displayId: z.string().min(1).max(64),
191
+ isPrimary: z.boolean(),
192
+ pixelHeight: PositiveSafeIntegerSchema,
193
+ pixelWidth: PositiveSafeIntegerSchema,
194
+ scaleFactor: z.number().finite().positive().max(8),
195
+ });
196
+
197
+ export const CaptureSourceInventorySchema = z.strictObject({
198
+ audio: z.array(z.discriminatedUnion("kind", [
199
+ z.strictObject({
200
+ audioSourceId: z.string().min(1).max(256),
201
+ channels: z.number().int().positive().max(64),
202
+ kind: z.literal("system"),
203
+ label: z.string().min(1).max(512),
204
+ sampleRateHz: z.number().int().positive().max(768_000),
205
+ }),
206
+ z.strictObject({
207
+ audioSourceId: z.string().min(1).max(256),
208
+ channels: z.number().int().positive().max(64),
209
+ kind: z.literal("microphone"),
210
+ label: z.string().min(1).max(512),
211
+ sampleRateHz: z.number().int().positive().max(768_000),
212
+ }),
213
+ ])).max(MAX_CAPTURE_AUDIO_SOURCES),
214
+ cameras: z.array(z.strictObject({
215
+ cameraId: z.string().min(1).max(256),
216
+ frameRate: z.number().finite().positive().max(1_000),
217
+ label: z.string().min(1).max(512),
218
+ pixelSize: z.strictObject({
219
+ height: PositiveSafeIntegerSchema,
220
+ width: PositiveSafeIntegerSchema,
221
+ }),
222
+ position: z.enum(["front", "back", "external", "unspecified"]),
223
+ })).max(MAX_CAPTURE_CAMERAS),
224
+ displays: z.array(z.strictObject({
225
+ bounds: RectSchema,
226
+ displayId: z.string().min(1).max(64),
227
+ isPrimary: z.boolean(),
228
+ label: z.string().min(1).max(512),
229
+ pixelSize: z.strictObject({
230
+ height: PositiveSafeIntegerSchema,
231
+ width: PositiveSafeIntegerSchema,
232
+ }),
233
+ refreshRateHz: z.number().finite().positive().max(1_000),
234
+ scaleFactor: z.number().finite().positive().max(8),
235
+ })).max(MAX_CAPTURE_DISPLAYS),
236
+ }).superRefine((sources, context) => {
237
+ const duplicate = <Item>(items: readonly Item[], key: (item: Item) => string): boolean => {
238
+ const values = items.map(key);
239
+ return new Set(values).size !== values.length;
240
+ };
241
+ if (duplicate(sources.audio, ({ audioSourceId }) => audioSourceId)) {
242
+ context.addIssue({ code: "custom", message: "Capture audio source IDs must be unique." });
243
+ }
244
+ if (duplicate(sources.cameras, ({ cameraId }) => cameraId)) {
245
+ context.addIssue({ code: "custom", message: "Capture camera IDs must be unique." });
246
+ }
247
+ if (duplicate(sources.displays, ({ displayId }) => displayId)) {
248
+ context.addIssue({ code: "custom", message: "Capture display IDs must be unique." });
249
+ }
250
+ if (
251
+ sources.displays.length > 0
252
+ && sources.displays.filter(({ isPrimary }) => isPrimary).length !== 1
253
+ ) {
254
+ context.addIssue({ code: "custom", message: "Capture displays must identify exactly one primary display." });
255
+ }
256
+ });
257
+
258
+ const DiagnosticSchema = z.strictObject({
259
+ code: z.string().min(1).max(128),
260
+ message: BoundedMessageSchema,
261
+ recoverable: z.boolean(),
262
+ source: z.enum(["camera", "helper", "metadata", "microphone", "screen", "system-audio"]),
263
+ });
264
+
265
+ const CaptureClockAnchorSchema = z.strictObject({
266
+ nativeTimeUs: SafeIntegerSchema,
267
+ ptsUs: SignedSafeIntegerSchema,
268
+ uncertaintyUs: SafeIntegerSchema.max(1_000_000),
269
+ });
270
+
271
+ export const CaptureStreamTimingSchema = z.strictObject({
272
+ bufferCount: PositiveSafeIntegerSchema,
273
+ clockAnchors: z.strictObject({
274
+ end: CaptureClockAnchorSchema,
275
+ first: CaptureClockAnchorSchema,
276
+ }),
277
+ presentation: z.strictObject({
278
+ endPtsUs: SignedSafeIntegerSchema,
279
+ firstPtsUs: SignedSafeIntegerSchema,
280
+ lastPtsUs: SignedSafeIntegerSchema,
281
+ maximumSampleDurationUs: PositiveSafeIntegerSchema,
282
+ }),
283
+ sampleCount: PositiveSafeIntegerSchema,
284
+ }).superRefine((timing, context) => {
285
+ const { endPtsUs, firstPtsUs, lastPtsUs, maximumSampleDurationUs } = timing.presentation;
286
+ if (lastPtsUs < firstPtsUs) {
287
+ context.addIssue({ code: "custom", message: "Stream lastPtsUs cannot precede firstPtsUs." });
288
+ }
289
+ if (endPtsUs <= lastPtsUs) {
290
+ context.addIssue({ code: "custom", message: "Stream endPtsUs must be after lastPtsUs." });
291
+ }
292
+ if (endPtsUs - lastPtsUs > maximumSampleDurationUs) {
293
+ context.addIssue({ code: "custom", message: "Stream final sample exceeds maximumSampleDurationUs." });
294
+ }
295
+ if (
296
+ timing.clockAnchors.first.ptsUs !== firstPtsUs
297
+ || timing.clockAnchors.end.ptsUs !== endPtsUs
298
+ ) {
299
+ context.addIssue({ code: "custom", message: "Stream clock anchors must bind the first and exclusive-end PTS." });
300
+ }
301
+ if (timing.clockAnchors.end.nativeTimeUs <= timing.clockAnchors.first.nativeTimeUs) {
302
+ context.addIssue({ code: "custom", message: "Stream native clock anchors must increase." });
303
+ }
304
+ const presentationSpanUs = endPtsUs - firstPtsUs;
305
+ const nativeSpanUs = timing.clockAnchors.end.nativeTimeUs
306
+ - timing.clockAnchors.first.nativeTimeUs;
307
+ const clockMappingToleranceUs = timing.clockAnchors.first.uncertaintyUs
308
+ + timing.clockAnchors.end.uncertaintyUs
309
+ + 2;
310
+ if (Math.abs(nativeSpanUs - presentationSpanUs) > clockMappingToleranceUs) {
311
+ context.addIssue({ code: "custom", message: "Stream native clock anchors exceed their recorded mapping uncertainty." });
312
+ }
313
+ if (timing.sampleCount < timing.bufferCount) {
314
+ context.addIssue({ code: "custom", message: "Stream sampleCount cannot be smaller than bufferCount." });
315
+ }
316
+ });
317
+
318
+ const ClassifiedMediaStreamBase = {
319
+ channels: z.number().int().positive().max(64).optional(),
320
+ codec: z.string().min(1).max(64),
321
+ mapping: z.enum(["exact", "provisional"]),
322
+ sampleRateHz: z.number().int().positive().max(768_000).optional(),
323
+ streamIndex: SafeIntegerSchema,
324
+ timing: CaptureStreamTimingSchema,
325
+ trackId: SafeIntegerSchema.optional(),
326
+ } as const;
327
+
328
+ const MediaStreamSchema = z.discriminatedUnion("role", [
329
+ z.strictObject({ ...ClassifiedMediaStreamBase, role: z.literal("camera-video") }),
330
+ z.strictObject({ ...ClassifiedMediaStreamBase, role: z.literal("display-video") }),
331
+ z.strictObject({ ...ClassifiedMediaStreamBase, role: z.literal("microphone-audio") }),
332
+ z.strictObject({ ...ClassifiedMediaStreamBase, role: z.literal("system-audio") }),
333
+ z.strictObject({
334
+ channels: z.number().int().positive().max(64).optional(),
335
+ codec: z.string().min(1).max(64),
336
+ mapping: z.literal("provisional"),
337
+ role: z.literal("unclassified-audio"),
338
+ sampleRateHz: z.number().int().positive().max(768_000).optional(),
339
+ streamIndex: SafeIntegerSchema,
340
+ timing: z.never().optional(),
341
+ trackId: SafeIntegerSchema.optional(),
342
+ }),
343
+ ]);
344
+
345
+ const DisplayRecordingSchema = z.strictObject({
346
+ containerDurationUs: PositiveSafeIntegerSchema,
347
+ container: z.literal("mp4"),
348
+ display: DisplayGeometrySchema,
349
+ path: RelativeOutputPathSchema,
350
+ streams: z.array(MediaStreamSchema).min(1).max(3),
351
+ });
352
+
353
+ const CameraRecordingSchema = z.discriminatedUnion("availability", [
354
+ z.strictObject({
355
+ availability: z.literal("recorded"),
356
+ containerDurationUs: PositiveSafeIntegerSchema,
357
+ container: z.enum(["mov", "mp4"]),
358
+ deviceId: z.string().min(1).max(256),
359
+ label: z.string().min(1).max(512),
360
+ path: RelativeOutputPathSchema,
361
+ streams: z.array(MediaStreamSchema).length(1),
362
+ }),
363
+ z.strictObject({
364
+ availability: z.literal("unavailable"),
365
+ reason: z.enum([
366
+ "disabled", "denied", "missing", "restricted", "start-failed",
367
+ "finalization-failed", "inspection-failed",
368
+ ]),
369
+ }),
370
+ ]);
371
+
372
+ const MicrophoneRecordingSchema = z.discriminatedUnion("availability", [
373
+ z.strictObject({
374
+ availability: z.literal("recorded"),
375
+ containerDurationUs: PositiveSafeIntegerSchema,
376
+ container: z.literal("m4a"),
377
+ deviceId: z.string().min(1).max(256),
378
+ label: z.string().min(1).max(512),
379
+ path: RelativeOutputPathSchema,
380
+ streams: z.array(MediaStreamSchema).length(1),
381
+ }),
382
+ z.strictObject({
383
+ availability: z.literal("unavailable"),
384
+ reason: z.enum([
385
+ "disabled", "denied", "missing", "restricted", "start-failed",
386
+ "finalization-failed", "inspection-failed",
387
+ ]),
388
+ }),
389
+ ]);
390
+
391
+ const MetadataFileSchema = z.strictObject({
392
+ droppedEvents: SafeIntegerSchema,
393
+ eventKinds: z.array(z.enum([
394
+ "cursor.sample",
395
+ "display.topology",
396
+ "focus.changed",
397
+ "key.activity",
398
+ "lifecycle.marker",
399
+ "mouse.click",
400
+ "typing.input",
401
+ "window.changed",
402
+ "window.snapshot",
403
+ "diagnostic.dropped-events",
404
+ ])).min(1).max(10),
405
+ path: RelativeOutputPathSchema,
406
+ recordCount: SafeIntegerSchema,
407
+ });
408
+
409
+ export const SegmentCompletionSchema = z.strictObject({
410
+ camera: CameraRecordingSchema,
411
+ clock: z.strictObject({
412
+ end: z.strictObject({
413
+ nativeTimeUs: SafeIntegerSchema,
414
+ sourceTimeUs: SafeIntegerSchema,
415
+ }),
416
+ kind: z.literal("mach-continuous-microseconds"),
417
+ start: z.strictObject({
418
+ nativeTimeUs: SafeIntegerSchema,
419
+ sourceTimeUs: SafeIntegerSchema,
420
+ }),
421
+ }),
422
+ diagnostics: z.array(DiagnosticSchema).max(128),
423
+ displays: z.array(DisplayRecordingSchema).min(1).max(MAX_CAPTURE_DISPLAYS),
424
+ index: SafeIntegerSchema.max(MAX_CAPTURE_SEGMENTS - 1),
425
+ metadata: z.array(MetadataFileSchema).max(8),
426
+ microphone: MicrophoneRecordingSchema,
427
+ sources: CaptureSourceInventorySchema,
428
+ }).superRefine((segment, context) => {
429
+ const sourceDurationUs = segment.clock.end.sourceTimeUs - segment.clock.start.sourceTimeUs;
430
+ const nativeDurationUs = segment.clock.end.nativeTimeUs - segment.clock.start.nativeTimeUs;
431
+ if (sourceDurationUs <= 0 || nativeDurationUs <= 0) {
432
+ context.addIssue({ code: "custom", message: "Segment clock anchors must increase." });
433
+ } else if (sourceDurationUs !== nativeDurationUs) {
434
+ context.addIssue({ code: "custom", message: "Segment source and native clock durations must agree." });
435
+ }
436
+ const paths = [
437
+ ...segment.displays.map(({ path }) => path),
438
+ ...(segment.camera.availability === "recorded" ? [segment.camera.path] : []),
439
+ ...(segment.microphone.availability === "recorded" ? [segment.microphone.path] : []),
440
+ ...segment.metadata.map(({ path }) => path),
441
+ ];
442
+ if (new Set(paths).size !== paths.length) {
443
+ context.addIssue({ code: "custom", message: "Segment output paths must be unique." });
444
+ }
445
+ const outputDisplayIds = segment.displays.map(({ display }) => display.displayId);
446
+ if (new Set(outputDisplayIds).size !== outputDisplayIds.length) {
447
+ context.addIssue({ code: "custom", message: "Segment display output IDs must be unique." });
448
+ }
449
+ if (segment.displays.filter(({ display }) => display.isPrimary).length !== 1) {
450
+ context.addIssue({ code: "custom", message: "Segment outputs must identify exactly one primary display." });
451
+ }
452
+ const sourceDisplayIds = new Set(segment.sources.displays.map(({ displayId }) => displayId));
453
+ if (outputDisplayIds.some(displayId => !sourceDisplayIds.has(displayId))) {
454
+ context.addIssue({ code: "custom", message: "Segment display outputs must exist in the source inventory." });
455
+ }
456
+ let systemAudioTracks = 0;
457
+ for (const display of segment.displays) {
458
+ const displayVideo = display.streams.filter(({ role }) => role === "display-video");
459
+ if (displayVideo.length !== 1 || displayVideo[0]?.mapping !== "exact") {
460
+ context.addIssue({ code: "custom", message: "Each display file must identify one exact display-video stream." });
461
+ }
462
+ if (display.streams.some(({ role }) => role === "camera-video" || role === "microphone-audio")) {
463
+ context.addIssue({ code: "custom", message: "Display files may not claim camera or microphone streams." });
464
+ }
465
+ for (const stream of display.streams) {
466
+ if (stream.role === "system-audio") {
467
+ systemAudioTracks += 1;
468
+ if (stream.mapping !== "exact") {
469
+ context.addIssue({ code: "custom", message: "The isolated ScreenCaptureKit audio stream must have exact system-audio identity." });
470
+ }
471
+ }
472
+ }
473
+ }
474
+ if (systemAudioTracks > 1) {
475
+ context.addIssue({ code: "custom", message: "A segment may contain only one system-audio stream." });
476
+ }
477
+ if (
478
+ segment.camera.availability === "recorded"
479
+ && (segment.camera.streams[0]?.role !== "camera-video" || segment.camera.streams[0].mapping !== "exact")
480
+ ) {
481
+ context.addIssue({ code: "custom", message: "Recorded camera media must identify one exact camera-video stream." });
482
+ }
483
+ if (
484
+ segment.microphone.availability === "recorded"
485
+ && (segment.microphone.streams[0]?.role !== "microphone-audio" || segment.microphone.streams[0].mapping !== "exact")
486
+ ) {
487
+ context.addIssue({ code: "custom", message: "Recorded microphone media must identify one exact microphone-audio stream." });
488
+ }
489
+ });
490
+
491
+ const EventBase = {
492
+ protocolVersion: z.literal(CAPTURE_PROTOCOL_VERSION),
493
+ } as const;
494
+
495
+ const RequestEventBase = {
496
+ ...EventBase,
497
+ requestId: BoundedIdentifierSchema,
498
+ } as const;
499
+
500
+ const StateSchema = z.enum(["unconfigured", "ready", "recording", "paused", "stopped", "shutting-down"]);
501
+
502
+ export const CaptureHelperCapabilitiesSchema = z.strictObject({
503
+ availableSources: z.boolean(),
504
+ camera: z.boolean(),
505
+ displayRecording: z.boolean(),
506
+ interruptionDiagnostics: z.boolean(),
507
+ metadata: z.boolean(),
508
+ microphone: z.boolean(),
509
+ minimumMacOSMajorVersion: z.literal(15),
510
+ systemAudio: z.boolean(),
511
+ typedTextOptIn: z.boolean(),
512
+ });
513
+
514
+ export const CaptureHelperProbeSchema = z.strictObject({
515
+ availableSources: CaptureSourceInventorySchema,
516
+ capabilities: CaptureHelperCapabilitiesSchema,
517
+ helperVersion: z.literal(CAPTURE_HELPER_VERSION),
518
+ permissions: CapturePermissionsSchema,
519
+ protocolVersion: z.literal(CAPTURE_PROTOCOL_VERSION),
520
+ });
521
+
522
+ export type CaptureHelperProbe = Readonly<z.infer<typeof CaptureHelperProbeSchema>>;
523
+
524
+ const CaptureEventValueSchema = z.discriminatedUnion("event", [
525
+ z.strictObject({
526
+ ...EventBase,
527
+ capabilities: CaptureHelperCapabilitiesSchema,
528
+ event: z.literal("ready"),
529
+ helperVersion: z.literal(CAPTURE_HELPER_VERSION),
530
+ }),
531
+ z.strictObject({
532
+ ...RequestEventBase,
533
+ availableSources: CaptureSourceInventorySchema,
534
+ event: z.literal("configured"),
535
+ lastInterruption: RecordingCaptureInterruptionSchema.nullable(),
536
+ options: CaptureOptionsSchema,
537
+ permissions: CapturePermissionsSchema,
538
+ sources: CaptureSourceInventorySchema,
539
+ state: z.literal("ready"),
540
+ }),
541
+ z.strictObject({
542
+ ...RequestEventBase,
543
+ event: z.literal("status"),
544
+ activeSegmentIndex: SafeIntegerSchema.nullable(),
545
+ availableSources: CaptureSourceInventorySchema,
546
+ completedSegmentCount: SafeIntegerSchema.max(MAX_CAPTURE_SEGMENTS),
547
+ lastInterruption: RecordingCaptureInterruptionSchema.nullable(),
548
+ logicalTimeUs: SafeIntegerSchema,
549
+ permissions: CapturePermissionsSchema,
550
+ sources: CaptureSourceInventorySchema,
551
+ state: StateSchema,
552
+ }),
553
+ z.strictObject({
554
+ ...RequestEventBase,
555
+ event: z.literal("segment-started"),
556
+ index: SafeIntegerSchema.max(MAX_CAPTURE_SEGMENTS - 1),
557
+ nativeStartUs: SafeIntegerSchema,
558
+ permissions: CapturePermissionsSchema,
559
+ sources: CaptureSourceInventorySchema,
560
+ startUs: SafeIntegerSchema,
561
+ }),
562
+ z.strictObject({
563
+ ...RequestEventBase,
564
+ event: z.literal("segment-completed"),
565
+ interruption: RecordingCaptureInterruptionSchema.nullable(),
566
+ segment: SegmentCompletionSchema,
567
+ }),
568
+ z.strictObject({
569
+ ...RequestEventBase,
570
+ durationUs: SafeIntegerSchema,
571
+ event: z.literal("session-completed"),
572
+ segmentCount: SafeIntegerSchema.max(MAX_CAPTURE_SEGMENTS),
573
+ state: z.literal("stopped"),
574
+ }),
575
+ z.strictObject({
576
+ ...RequestEventBase,
577
+ code: z.string().min(1).max(128),
578
+ event: z.literal("error"),
579
+ interruption: RecordingCaptureInterruptionSchema.nullable(),
580
+ message: BoundedMessageSchema,
581
+ recoverable: z.boolean(),
582
+ state: StateSchema,
583
+ }),
584
+ z.strictObject({
585
+ ...RequestEventBase,
586
+ event: z.literal("shutdown"),
587
+ }),
588
+ ]);
589
+
590
+ export const CaptureEventSchema = CaptureEventValueSchema.superRefine(
591
+ (event, context) => {
592
+ if (event.event === "configured" && event.lastInterruption !== null) {
593
+ context.addIssue({
594
+ code: "custom",
595
+ message: "A newly configured capture session cannot have a prior interruption.",
596
+ });
597
+ }
598
+ if (event.event === "segment-completed" && event.interruption !== null) {
599
+ if (
600
+ event.interruption.segmentIndex !== event.segment.index
601
+ || event.interruption.nativeTimeUs
602
+ !== event.segment.clock.end.nativeTimeUs
603
+ || event.interruption.sourceTimeUs
604
+ !== event.segment.clock.end.sourceTimeUs
605
+ ) {
606
+ context.addIssue({
607
+ code: "custom",
608
+ message: "A segment-completed interruption must match the segment index and clock-end anchors.",
609
+ });
610
+ }
611
+ if (!event.interruption.recoverable) {
612
+ context.addIssue({
613
+ code: "custom",
614
+ message: "A completed interruption must be recoverable.",
615
+ });
616
+ }
617
+ }
618
+ if (
619
+ event.event === "error"
620
+ && event.interruption !== null
621
+ && event.interruption.recoverable !== event.recoverable
622
+ ) {
623
+ context.addIssue({
624
+ code: "custom",
625
+ message: "An error interruption must agree with the error recovery state.",
626
+ });
627
+ }
628
+ },
629
+ );
630
+
631
+ export type CaptureEvent = Readonly<z.infer<typeof CaptureEventSchema>>;
632
+ export type SegmentCompletion = Readonly<z.infer<typeof SegmentCompletionSchema>>;
633
+ export type CapturePermissions = Readonly<z.infer<typeof CapturePermissionsSchema>>;
634
+ export type CaptureSourceInventory = Readonly<
635
+ z.infer<typeof CaptureSourceInventorySchema>
636
+ >;
637
+
638
+ function parseBoundedJsonLine(line: string): unknown {
639
+ if (new TextEncoder().encode(line).byteLength > MAX_PROTOCOL_LINE_BYTES) {
640
+ throw new Error(`Capture protocol line exceeds ${MAX_PROTOCOL_LINE_BYTES} bytes.`);
641
+ }
642
+ if (line.trim().length === 0) {
643
+ throw new Error("Capture protocol line is empty.");
644
+ }
645
+ try {
646
+ return JSON.parse(line) as unknown;
647
+ } catch (error) {
648
+ const detail = error instanceof Error ? error.message : "unknown JSON error";
649
+ throw new Error(`Capture protocol line is not valid JSON: ${detail}`);
650
+ }
651
+ }
652
+
653
+ export function parseCaptureRequest(value: unknown): CaptureRequest {
654
+ return CaptureRequestSchema.parse(value);
655
+ }
656
+
657
+ export function parseCaptureRequestLine(line: string): CaptureRequest {
658
+ return parseCaptureRequest(parseBoundedJsonLine(line));
659
+ }
660
+
661
+ export function parseCaptureEvent(value: unknown): CaptureEvent {
662
+ return CaptureEventSchema.parse(value);
663
+ }
664
+
665
+ export function parseCaptureHelperProbe(value: unknown): CaptureHelperProbe {
666
+ return CaptureHelperProbeSchema.parse(value);
667
+ }
668
+
669
+ export function parseCaptureInterruption(
670
+ value: unknown,
671
+ ): RecordingCaptureInterruption {
672
+ return RecordingCaptureInterruptionSchema.parse(value);
673
+ }
674
+
675
+ export function parseCaptureEventLine(line: string): CaptureEvent {
676
+ return parseCaptureEvent(parseBoundedJsonLine(line));
677
+ }
678
+
679
+ export function encodeCaptureRequest(request: CaptureRequest): string {
680
+ return `${JSON.stringify(parseCaptureRequest(request))}\n`;
681
+ }
682
+
683
+ export function encodeCaptureEvent(event: CaptureEvent): string {
684
+ const line = JSON.stringify(parseCaptureEvent(event));
685
+ if (new TextEncoder().encode(line).byteLength > MAX_PROTOCOL_LINE_BYTES) {
686
+ throw new Error(`Encoded capture event exceeds ${MAX_PROTOCOL_LINE_BYTES} bytes.`);
687
+ }
688
+ return `${line}\n`;
689
+ }