@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
package/src/cli.ts ADDED
@@ -0,0 +1,601 @@
1
+ #!/usr/bin/env bun
2
+
3
+ import { writeFile } from "node:fs/promises"
4
+ import { resolve } from "node:path"
5
+ import { createInterface } from "node:readline/promises"
6
+ import {
7
+ artifactSummary,
8
+ checkDiagramFile,
9
+ desktopStatus,
10
+ getLatestDesktopRelease,
11
+ installDesktop,
12
+ openInDesktop,
13
+ renderDiagramFile,
14
+ runMcpServer,
15
+ selectDesktopAsset,
16
+ vectorizeImage,
17
+ } from "./index.js"
18
+ import {
19
+ generateSlopcameraImageFile,
20
+ slopcameraGatewayCredentialStatus,
21
+ slopcameraImageModels,
22
+ type SlopcameraImageModel,
23
+ } from "./generate.js"
24
+ import {
25
+ executeSlopcameraOperation,
26
+ slopcameraOperationCodes,
27
+ isSlopcameraOperationCode,
28
+ searchSlopcameraOperations,
29
+ withSlopcameraOperationHostAdmission,
30
+ } from "./operations.js"
31
+ import type { HostResourceCoordinator } from "./host-resources.js"
32
+ import { installSkill, type SkillScope, type SkillTarget } from "./skill-install.js"
33
+ import { pathExists } from "./fs.js"
34
+ import { SLOPCAMERA_VERSION } from "./version.js"
35
+
36
+ export const slopcameraCliVersion = SLOPCAMERA_VERSION
37
+
38
+ const help = `slopcamera ${slopcameraCliVersion}
39
+
40
+ Turn source material into deterministic diagrams, images, and canvas assets.
41
+
42
+ Usage:
43
+ slopcamera diagram init [file]
44
+ slopcamera diagram check <file> [--config <file>] [--strict]
45
+ slopcamera diagram render <file> [--out-dir <directory>] [--config <file>] [--scale <number>]
46
+ slopcamera image vectorize <image> --output <file.svg> [--json] [--duotone <#rgb,#rgb>]
47
+ slopcamera image generate <prompt> --output <file.png|jpg|webp> [--model <provider/model>] [--json]
48
+ slopcamera code search [query] [--limit <number>]
49
+ slopcamera code execute <operation> --input <JSON>
50
+ slopcamera mcp --root <workspace>
51
+ slopcamera canvas open <file.tldr|file.tldraw>
52
+ slopcamera canvas status
53
+ slopcamera canvas url
54
+ slopcamera canvas install [--yes] [--download-only]
55
+ slopcamera doctor
56
+ slopcamera skill path
57
+ slopcamera skill install [--target codex|claude|agents] [--scope user|project] [--force]
58
+
59
+ Render writes the same five replaceable artifacts on every run:
60
+ <name>.tldr
61
+ <name>.light.svg
62
+ <name>.dark.svg
63
+ <name>.light.png
64
+ <name>.dark.png
65
+
66
+ The .tldr file is editable tldraw interchange. It imports into tldraw Offline,
67
+ which can save the newer app-owned .tldraw bundle. Rendering does not require
68
+ tldraw Offline or the tldraw SDK.
69
+
70
+ Vectorize adaptively traces a raster with a checksum-pinned VTracer binary.
71
+ It enforces bounded input, decode, time, path, and output budgets and emits a
72
+ safe path-only SVG (plus an internal vector alpha mask when fidelity requires).
73
+ It is fully local. No source path or bytes are sent to a network endpoint.
74
+
75
+ Generate sends one bounded, non-retried request directly to Vercel AI Gateway.
76
+ Set AI_GATEWAY_API_KEY, or run through \`vercel env run -- …\` so
77
+ VERCEL_OIDC_TOKEN is available. Slopcamera never stores or prints the token.
78
+ PNG, JPEG, and WebP responses are signature-checked and published atomically.
79
+
80
+ Code mode searches and executes a fixed semantic registry. Execute accepts
81
+ typed JSON for one exact owned operation code; it never evaluates source text.
82
+
83
+ MCP preserves root-relative check_diagram/render_diagram and adds closed
84
+ search_slopcamera/execute_slopcamera registry tools. It uses built-in assets, never
85
+ executes workspace config or caller code, and writes protocol messages only to
86
+ stdout.
87
+ `
88
+
89
+ interface ParsedArguments {
90
+ readonly positionals: readonly string[]
91
+ readonly options: Readonly<Record<string, string>>
92
+ readonly flags: ReadonlySet<string>
93
+ }
94
+
95
+ function parseArguments(args: readonly string[], valueOptions: ReadonlySet<string>): ParsedArguments {
96
+ const positionals: string[] = []
97
+ const options: Record<string, string> = {}
98
+ const flags = new Set<string>()
99
+ for (let index = 0; index < args.length; index += 1) {
100
+ const argument = args[index]
101
+ if (argument === undefined) continue
102
+ if (!argument.startsWith("--")) {
103
+ positionals.push(argument)
104
+ continue
105
+ }
106
+ const name = argument.slice(2)
107
+ if (!valueOptions.has(name)) {
108
+ flags.add(name)
109
+ continue
110
+ }
111
+ const value = args[index + 1]
112
+ if (value === undefined || value.startsWith("--")) {
113
+ throw new Error(`--${name} requires a value`)
114
+ }
115
+ options[name] = value
116
+ index += 1
117
+ }
118
+ return { positionals, options, flags }
119
+ }
120
+
121
+ function requiredPositional(parsed: ParsedArguments, index: number, label: string): string {
122
+ const value = parsed.positionals[index]
123
+ if (value === undefined) throw new Error(`Missing ${label}`)
124
+ return value
125
+ }
126
+
127
+ function requiredOption(parsed: ParsedArguments, name: string): string {
128
+ const value = parsed.options[name]
129
+ if (value === undefined) throw new Error(`--${name} is required`)
130
+ return value
131
+ }
132
+
133
+ function parsePositiveInteger(value: string | undefined, name: string): number | undefined {
134
+ if (value === undefined) return undefined
135
+ const parsed = Number(value)
136
+ if (!Number.isInteger(parsed) || parsed < 1) {
137
+ throw new Error(`--${name} must be a positive integer`)
138
+ }
139
+ return parsed
140
+ }
141
+
142
+ function parseDuotone(value: string | undefined): readonly [string, string] | undefined {
143
+ if (value === undefined) return undefined
144
+ const colors = value.split(",").map((color) => color.trim())
145
+ if (
146
+ colors.length !== 2 ||
147
+ colors.some((color) => !/^#[a-f0-9]{3}(?:[a-f0-9]{3})?$/iu.test(color))
148
+ ) {
149
+ throw new Error("--duotone must contain two #rgb or #rrggbb colors separated by a comma")
150
+ }
151
+ return [colors[0]!, colors[1]!]
152
+ }
153
+
154
+ function printFindings(findings: Awaited<ReturnType<typeof checkDiagramFile>>["findings"]): void {
155
+ if (findings.length === 0) {
156
+ console.log("No diagram lint findings.")
157
+ return
158
+ }
159
+ console.warn(`${findings.length} diagram lint finding${findings.length === 1 ? "" : "s"}:`)
160
+ for (const finding of findings) {
161
+ console.warn(` [${finding.code}] ${finding.message}`)
162
+ }
163
+ }
164
+
165
+ const starter = {
166
+ $schema: "https://raw.githubusercontent.com/hraness/slopcamera/main/schema/diagram.schema.json",
167
+ version: 1,
168
+ name: "example-flow",
169
+ canvas: { width: 960, height: 540, padding: 64 },
170
+ layout: { type: "stack", direction: "horizontal", gap: 160, align: "center" },
171
+ shapes: [
172
+ {
173
+ id: "source",
174
+ type: "rect",
175
+ width: 240,
176
+ height: 160,
177
+ label: "Source",
178
+ icon: "document",
179
+ tone: "blue",
180
+ },
181
+ {
182
+ id: "result",
183
+ type: "rect",
184
+ width: 240,
185
+ height: 160,
186
+ label: "Result",
187
+ icon: "check",
188
+ tone: "green",
189
+ },
190
+ ],
191
+ edges: [{ id: "source-result", from: "source", to: "result" }],
192
+ }
193
+
194
+ async function confirmInstall(): Promise<boolean> {
195
+ if (!process.stdin.isTTY) {
196
+ throw new Error("Pass --yes to download the 100–230 MB official tldraw Offline installer")
197
+ }
198
+ const prompt = createInterface({ input: process.stdin, output: process.stdout })
199
+ try {
200
+ const answer = await prompt.question(
201
+ "Download, verify, and launch the official tldraw Offline installer? [y/N] ",
202
+ )
203
+ return answer.trim().toLowerCase() === "y" || answer.trim().toLowerCase() === "yes"
204
+ } finally {
205
+ prompt.close()
206
+ }
207
+ }
208
+
209
+ export interface SlopcameraCliDependencies {
210
+ readonly generate?: typeof generateSlopcameraImageFile
211
+ readonly hostResourceCoordinator?: HostResourceCoordinator
212
+ readonly log?: (value: string) => void
213
+ readonly vectorize?: typeof vectorizeImage
214
+ }
215
+
216
+ function hostAdmissionOptions(
217
+ dependencies: SlopcameraCliDependencies,
218
+ ): { readonly hostResourceCoordinator?: HostResourceCoordinator } {
219
+ return dependencies.hostResourceCoordinator === undefined
220
+ ? {}
221
+ : { hostResourceCoordinator: dependencies.hostResourceCoordinator }
222
+ }
223
+
224
+ function canonicalArguments(args: readonly string[]): readonly string[] {
225
+ const [surface, subcommand, ...rest] = args
226
+ if (surface === "diagram") {
227
+ if (subcommand === "init" || subcommand === "check" || subcommand === "render") {
228
+ return [subcommand, ...rest]
229
+ }
230
+ throw new Error("Use slopcamera diagram init, check, or render")
231
+ }
232
+ if (surface === "image") {
233
+ if (subcommand === "vectorize" || subcommand === "generate") {
234
+ return [subcommand, ...rest]
235
+ }
236
+ throw new Error("Use slopcamera image vectorize or generate")
237
+ }
238
+ if (surface === "canvas") {
239
+ if (subcommand === "open") return ["open", ...rest]
240
+ if (subcommand === "status" || subcommand === "url" || subcommand === "install") {
241
+ return ["desktop", subcommand, ...rest]
242
+ }
243
+ throw new Error("Use slopcamera canvas open, status, url, or install")
244
+ }
245
+ if (
246
+ surface === "init" ||
247
+ surface === "check" ||
248
+ surface === "render" ||
249
+ surface === "vectorize" ||
250
+ surface === "generate" ||
251
+ surface === "open" ||
252
+ surface === "desktop"
253
+ ) {
254
+ throw new Error(`The flat \`${surface}\` command moved to a namespaced Slopcamera surface.\n\n${help}`)
255
+ }
256
+ return args
257
+ }
258
+
259
+ export async function main(
260
+ args: readonly string[],
261
+ dependencies: SlopcameraCliDependencies = {},
262
+ ): Promise<void> {
263
+ const [command, ...rest] = canonicalArguments(args)
264
+ if (command === undefined || command === "help" || command === "--help" || command === "-h") {
265
+ console.log(help)
266
+ return
267
+ }
268
+ if (command === "version" || command === "--version" || command === "-v") {
269
+ console.log(slopcameraCliVersion)
270
+ return
271
+ }
272
+
273
+ if (command === "init") {
274
+ const parsed = parseArguments(rest, new Set())
275
+ const filePath = resolve(parsed.positionals[0] ?? "diagram.diagram.json")
276
+ if (await pathExists(filePath)) throw new Error(`Refusing to overwrite existing file: ${filePath}`)
277
+ await writeFile(filePath, `${JSON.stringify(starter, null, 2)}\n`)
278
+ console.log(`Created ${filePath}`)
279
+ return
280
+ }
281
+
282
+ if (command === "check") {
283
+ const parsed = parseArguments(rest, new Set(["config"]))
284
+ const result = await withSlopcameraOperationHostAdmission(
285
+ "slopcamera.diagram.check",
286
+ async () => await checkDiagramFile({
287
+ filePath: requiredPositional(parsed, 0, "diagram file"),
288
+ ...(parsed.options.config === undefined
289
+ ? {}
290
+ : { configPath: parsed.options.config }),
291
+ }),
292
+ hostAdmissionOptions(dependencies),
293
+ )
294
+ console.log(`Valid diagram${result.configPath === null ? "" : ` with ${result.configPath}`}.`)
295
+ printFindings(result.findings)
296
+ if (parsed.flags.has("strict") && result.findings.length > 0) process.exitCode = 2
297
+ return
298
+ }
299
+
300
+ if (command === "render") {
301
+ const parsed = parseArguments(rest, new Set(["out-dir", "config", "scale"]))
302
+ const scale =
303
+ parsed.options.scale === undefined ? undefined : Number.parseFloat(parsed.options.scale)
304
+ const result = await withSlopcameraOperationHostAdmission(
305
+ "slopcamera.diagram.render",
306
+ async () => await renderDiagramFile({
307
+ filePath: requiredPositional(parsed, 0, "diagram file"),
308
+ ...(parsed.options["out-dir"] === undefined
309
+ ? {}
310
+ : { outDirectory: parsed.options["out-dir"] }),
311
+ ...(parsed.options.config === undefined
312
+ ? {}
313
+ : { configPath: parsed.options.config }),
314
+ ...(scale === undefined ? {} : { scale }),
315
+ }),
316
+ hostAdmissionOptions(dependencies),
317
+ )
318
+ console.log(artifactSummary(result.artifacts))
319
+ printFindings(result.findings)
320
+ return
321
+ }
322
+
323
+ if (command === "vectorize") {
324
+ const parsed = parseArguments(
325
+ rest,
326
+ new Set(["output", "duotone", "alpha-cutoff", "timeout-ms"]),
327
+ )
328
+ const unknownFlags = [...parsed.flags].filter((flag) => flag !== "json")
329
+ if (unknownFlags.length > 0) {
330
+ throw new Error(`Unknown vectorize option: --${unknownFlags[0]}`)
331
+ }
332
+ if (parsed.positionals.length > 1) {
333
+ throw new Error("slopcamera image vectorize accepts exactly one raster input")
334
+ }
335
+ const output = requiredOption(parsed, "output")
336
+ if (!output.toLowerCase().endsWith(".svg")) {
337
+ throw new Error("--output must end in .svg")
338
+ }
339
+ const alphaCutoff = parsePositiveInteger(parsed.options["alpha-cutoff"], "alpha-cutoff")
340
+ const timeoutMs = parsePositiveInteger(parsed.options["timeout-ms"], "timeout-ms")
341
+ const duotone = parseDuotone(parsed.options.duotone)
342
+ const result = await withSlopcameraOperationHostAdmission(
343
+ "slopcamera.image.vectorize",
344
+ async (lease) => await (dependencies.vectorize ?? vectorizeImage)(
345
+ requiredPositional(parsed, 0, "raster image"),
346
+ {
347
+ ...(alphaCutoff === undefined ? {} : { alphaCutoff }),
348
+ ...(duotone === undefined ? {} : { duotone }),
349
+ ...(timeoutMs === undefined
350
+ ? {}
351
+ : { limits: { maxDurationMs: timeoutMs } }),
352
+ inheritedFileDescriptors: [lease.inheritedFileDescriptor],
353
+ outputPath: output,
354
+ },
355
+ ),
356
+ hostAdmissionOptions(dependencies),
357
+ )
358
+ if (parsed.flags.has("json")) {
359
+ ;(dependencies.log ?? console.log)(
360
+ JSON.stringify({ ...result.receipt, outputPath: result.outputPath }, null, 2),
361
+ )
362
+ } else {
363
+ ;(dependencies.log ?? console.log)(
364
+ `Vectorized ${result.receipt.width}×${result.receipt.height} with `
365
+ + `${result.receipt.profile}/${result.receipt.representation}: ${result.outputPath}`,
366
+ )
367
+ }
368
+ return
369
+ }
370
+
371
+ if (command === "generate") {
372
+ const parsed = parseArguments(
373
+ rest,
374
+ new Set(["model", "output"]),
375
+ )
376
+ const unknownFlags = [...parsed.flags].filter((flag) => flag !== "json")
377
+ if (unknownFlags.length > 0) {
378
+ throw new Error(`Unknown generate option: --${unknownFlags[0]}`)
379
+ }
380
+ if (parsed.positionals.length !== 1) {
381
+ throw new Error("slopcamera image generate accepts exactly one prompt")
382
+ }
383
+ const model = parsed.options.model ?? slopcameraImageModels[1]
384
+ if (
385
+ model.length > 256 ||
386
+ !/^[a-z0-9][a-z0-9._-]*\/[a-z0-9][a-z0-9._:-]*$/iu.test(model)
387
+ ) {
388
+ throw new Error(
389
+ "--model must be a bounded Vercel AI Gateway provider/model id",
390
+ )
391
+ }
392
+ const result = await withSlopcameraOperationHostAdmission(
393
+ "slopcamera.image.generate",
394
+ async () => await (dependencies.generate ?? generateSlopcameraImageFile)({
395
+ model: model as SlopcameraImageModel,
396
+ prompt: requiredPositional(parsed, 0, "prompt"),
397
+ outputPath: requiredOption(parsed, "output"),
398
+ }),
399
+ hostAdmissionOptions(dependencies),
400
+ )
401
+ if (parsed.flags.has("json")) {
402
+ ;(dependencies.log ?? console.log)(JSON.stringify(result, null, 2))
403
+ } else {
404
+ ;(dependencies.log ?? console.log)(
405
+ `Generated ${result.mediaType} with ${result.model}: ${result.outputPath} (${result.bytes} bytes, request ${result.requestId})`,
406
+ )
407
+ }
408
+ return
409
+ }
410
+
411
+ if (command === "code") {
412
+ const [subcommand, ...subcommandArgs] = rest
413
+ if (subcommand === "search") {
414
+ const parsed = parseArguments(subcommandArgs, new Set(["limit"]))
415
+ if (parsed.flags.size > 0 || parsed.positionals.length > 1) {
416
+ throw new Error(
417
+ "Use slopcamera code search [query] [--limit <number>]",
418
+ )
419
+ }
420
+ const limit =
421
+ parsePositiveInteger(parsed.options.limit, "limit") ??
422
+ slopcameraOperationCodes.length
423
+ const operations = searchSlopcameraOperations(
424
+ parsed.positionals[0] ?? "",
425
+ limit,
426
+ )
427
+ console.log(JSON.stringify({ operations }, null, 2))
428
+ return
429
+ }
430
+ if (subcommand === "execute") {
431
+ const parsed = parseArguments(subcommandArgs, new Set(["input"]))
432
+ if (
433
+ parsed.flags.size > 0 ||
434
+ parsed.positionals.length !== 1
435
+ ) {
436
+ throw new Error(
437
+ "Use slopcamera code execute <operation> --input <JSON>",
438
+ )
439
+ }
440
+ const requestedOperation = parsed.positionals[0]!
441
+ const operation = isSlopcameraOperationCode(requestedOperation)
442
+ ? requestedOperation
443
+ : undefined
444
+ if (operation === undefined) {
445
+ throw new Error(`Unknown Slopcamera operation code: ${requestedOperation}`)
446
+ }
447
+ const inputText = requiredOption(parsed, "input")
448
+ if (Buffer.byteLength(inputText, "utf8") > 64 * 1024) {
449
+ throw new Error("--input JSON must be no more than 65536 UTF-8 bytes")
450
+ }
451
+ let input: unknown
452
+ try {
453
+ input = JSON.parse(inputText)
454
+ } catch {
455
+ throw new Error("--input must be valid JSON")
456
+ }
457
+ const result = await executeSlopcameraOperation(operation, input, {
458
+ ...hostAdmissionOptions(dependencies),
459
+ })
460
+ ;(dependencies.log ?? console.log)(
461
+ JSON.stringify({ operation, result }, null, 2),
462
+ )
463
+ return
464
+ }
465
+ throw new Error(
466
+ "Use slopcamera code search [query] or slopcamera code execute <operation> --input <JSON>",
467
+ )
468
+ }
469
+
470
+ if (command === "mcp") {
471
+ const parsed = parseArguments(rest, new Set(["root"]))
472
+ if (parsed.positionals.length > 0 || parsed.flags.size > 0) {
473
+ throw new Error("slopcamera mcp accepts only --root <workspace>")
474
+ }
475
+ await runMcpServer({
476
+ rootDirectory: requiredOption(parsed, "root"),
477
+ serverVersion: slopcameraCliVersion,
478
+ })
479
+ return
480
+ }
481
+
482
+ if (command === "open") {
483
+ const parsed = parseArguments(rest, new Set())
484
+ await openInDesktop(requiredPositional(parsed, 0, "tldraw file"))
485
+ console.log("Opened in tldraw Offline.")
486
+ return
487
+ }
488
+
489
+ if (command === "doctor") {
490
+ const status = await desktopStatus()
491
+ console.log(`slopcamera ${slopcameraCliVersion}`)
492
+ console.log(`Bun ${process.versions.bun ?? "not detected"}`)
493
+ console.log("Headless diagram SVG/PNG/tldraw renderer ready")
494
+ console.log(
495
+ process.platform === "win32"
496
+ ? "Local raster-to-SVG vectorizer unavailable on Windows (fails closed with tool_platform)"
497
+ : "Local raster-to-SVG vectorizer ready without authentication (VTracer downloads on first use)",
498
+ )
499
+ console.log("Root-relative MCP check/render server ready (trusted local workspace)")
500
+ const gateway = slopcameraGatewayCredentialStatus()
501
+ console.log(
502
+ gateway.available
503
+ ? `Vercel AI Gateway ready via ${gateway.source}`
504
+ : "Vercel AI Gateway requires AI_GATEWAY_API_KEY or VERCEL_OIDC_TOKEN",
505
+ )
506
+ console.log(
507
+ status.installedPath === null
508
+ ? "tldraw Offline not installed (optional)"
509
+ : `tldraw Offline: ${status.installedPath}`,
510
+ )
511
+ console.log(
512
+ status.server === null
513
+ ? "tldraw Offline agent server not running (optional)"
514
+ : `tldraw Offline agent server: localhost:${status.server.port}`,
515
+ )
516
+ return
517
+ }
518
+
519
+ if (command === "desktop") {
520
+ const [subcommand, ...subcommandArgs] = rest
521
+ if (subcommand === "status") {
522
+ const status = await desktopStatus()
523
+ console.log(JSON.stringify(status, null, 2))
524
+ return
525
+ }
526
+ if (subcommand === "url") {
527
+ const release = await getLatestDesktopRelease()
528
+ const asset = selectDesktopAsset(release)
529
+ console.log(
530
+ JSON.stringify(
531
+ {
532
+ release: release.tag_name,
533
+ releaseUrl: release.html_url,
534
+ asset: asset.name,
535
+ url: asset.browser_download_url,
536
+ bytes: asset.size,
537
+ sha256: asset.digest,
538
+ },
539
+ null,
540
+ 2,
541
+ ),
542
+ )
543
+ return
544
+ }
545
+ if (subcommand === "install") {
546
+ const parsed = parseArguments(subcommandArgs, new Set())
547
+ if (!parsed.flags.has("yes") && !(await confirmInstall())) {
548
+ console.log("Cancelled.")
549
+ return
550
+ }
551
+ const result = await installDesktop({ downloadOnly: parsed.flags.has("download-only") })
552
+ console.log(
553
+ `${parsed.flags.has("download-only") ? "Downloaded" : "Prepared"} tldraw Offline ${result.release}: ${result.filePath}`,
554
+ )
555
+ return
556
+ }
557
+ throw new Error("Use slopcamera canvas status, url, or install")
558
+ }
559
+
560
+ if (command === "skill") {
561
+ const [subcommand, ...subcommandArgs] = rest
562
+ if (subcommand === "path") {
563
+ const { bundledSkillPath } = await import("./skill-install.js")
564
+ console.log(bundledSkillPath())
565
+ return
566
+ }
567
+ if (subcommand === "install") {
568
+ const parsed = parseArguments(subcommandArgs, new Set(["target", "scope", "project"]))
569
+ const target = (parsed.options.target ?? "codex") as SkillTarget
570
+ const scope = (parsed.options.scope ?? "user") as SkillScope
571
+ if (!["codex", "claude", "agents"].includes(target)) {
572
+ throw new Error("--target must be codex, claude, or agents")
573
+ }
574
+ if (!["user", "project"].includes(scope)) {
575
+ throw new Error("--scope must be user or project")
576
+ }
577
+ const destination = await installSkill({
578
+ target,
579
+ scope,
580
+ ...(parsed.options.project === undefined
581
+ ? {}
582
+ : { projectDirectory: parsed.options.project }),
583
+ force: parsed.flags.has("force"),
584
+ })
585
+ console.log(`Installed slopcamera skill at ${destination}`)
586
+ return
587
+ }
588
+ throw new Error("Use slopcamera skill path or install")
589
+ }
590
+
591
+ throw new Error(`Unknown command: ${command}\n\n${help}`)
592
+ }
593
+
594
+ if (import.meta.main) {
595
+ try {
596
+ await main(process.argv.slice(2))
597
+ } catch (error) {
598
+ console.error(error instanceof Error ? error.message : String(error))
599
+ process.exitCode = 1
600
+ }
601
+ }
@@ -0,0 +1,26 @@
1
+ export type SlopcameraCloudErrorCode =
2
+ | "AUTHENTICATION_REQUIRED"
3
+ | "GENERATION_FAILED"
4
+ | "GENERATION_INVALID_RESPONSE"
5
+ | "INVALID_ARGUMENT"
6
+ | "OUTPUT_WRITE_FAILED"
7
+
8
+ /**
9
+ * A stable, redacted failure from the direct Gateway boundary.
10
+ *
11
+ * `cause` is retained for local diagnostics but is deliberately not included
12
+ * in the public message or CLI output.
13
+ */
14
+ export class SlopcameraCloudError extends Error {
15
+ readonly code: SlopcameraCloudErrorCode
16
+
17
+ constructor(
18
+ code: SlopcameraCloudErrorCode,
19
+ message: string,
20
+ options?: ErrorOptions,
21
+ ) {
22
+ super(`[${code}] ${message}`, options)
23
+ this.name = "SlopcameraCloudError"
24
+ this.code = code
25
+ }
26
+ }
@@ -0,0 +1,10 @@
1
+ export * from "./canonical-json.js"
2
+ export * from "./compiler.js"
3
+ export * from "./contracts.js"
4
+ export * from "./define-workflow.js"
5
+ export * from "./errors.js"
6
+ export * from "./graph-builder.js"
7
+ export * from "./portable-builder.js"
8
+ export * from "./projection.js"
9
+ export * from "./public-operations.js"
10
+ export * from "./runtime.js"
@@ -0,0 +1,21 @@
1
+ import type { z } from "zod"
2
+
3
+ import { SlopcameraCodeError } from "./errors.js"
4
+
5
+ export function parseCodeBoundary<Output>(
6
+ schema: z.ZodType<Output>,
7
+ input: unknown,
8
+ name: string,
9
+ ): Output {
10
+ const result = schema.safeParse(input)
11
+ if (!result.success) {
12
+ throw new SlopcameraCodeError("invalid-data", `Invalid ${name}.`, {
13
+ issues: result.error.issues.map(issue => ({
14
+ code: issue.code,
15
+ message: issue.message,
16
+ path: issue.path.map(String),
17
+ })),
18
+ })
19
+ }
20
+ return result.data
21
+ }