cozyclay 3.0.3 → 3.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (246) hide show
  1. package/CHANGELOG.md +93 -0
  2. package/INSTALL_FOR_AGENTS.md +146 -0
  3. package/README.md +74 -192
  4. package/THIRD_PARTY_NOTICES.md +0 -21
  5. package/bin/agent/agent-routes.mjs +29 -62
  6. package/bin/agent/agent-runner.mjs +5 -3
  7. package/bin/agent/main-agent.mjs +70 -0
  8. package/bin/agent/main-prompt.mjs +17 -0
  9. package/bin/agent/plan-tool.mjs +114 -0
  10. package/bin/agent/script-tool.mjs +2 -0
  11. package/bin/agent/sculpt-sketch.mjs +190 -0
  12. package/bin/agent/session-store.mjs +4 -3
  13. package/bin/agent/sketch-code.mjs +151 -0
  14. package/bin/agent/sketch-sandbox.mjs +102 -0
  15. package/bin/agent/studio-prompt.mjs +1 -1
  16. package/bin/agent/studio-task-routes.mjs +185 -0
  17. package/bin/agent/studio-tasks.mjs +156 -0
  18. package/bin/agent/studio-tools.mjs +3 -2
  19. package/bin/agent/studio-turn-transaction.mjs +76 -0
  20. package/bin/agent/turn-frames.mjs +4 -0
  21. package/bin/cozyclay.mjs +5 -7
  22. package/dist/app/index.html +7 -6
  23. package/dist/assets/TaskBoard-ngdqiu7u.js +1 -0
  24. package/dist/assets/app-BlwOpest.css +1 -0
  25. package/dist/assets/app-DmR7jBkz.js +5144 -0
  26. package/dist/assets/compile-worker-D0pKioa0.js +5 -0
  27. package/dist/assets/landing-y3EqDgSZ.js +1 -0
  28. package/dist/assets/modulepreload-polyfill-P2Xu9kJm.js +1 -0
  29. package/dist/assets/motion3-compile-BB3_1-EB.js +1 -0
  30. package/dist/assets/scene-asset-sync-CBx7XRti.css +1 -0
  31. package/dist/assets/scene-asset-sync-Cgdtr1Yw.js +13 -0
  32. package/dist/assets/task-board-ErQvfoaz.js +14 -0
  33. package/dist/assets/workflow-zQM-EKW1.js +179 -0
  34. package/dist/assets/x-bot-tpose-body-BusyR3eg.json +1 -0
  35. package/dist/assets/y-bot-tpose-body-Dy1VKChZ.json +1 -0
  36. package/dist/cozyclay-package.json +1 -1
  37. package/dist/greybox-to-video/index.html +2 -3
  38. package/dist/index.html +7 -57
  39. package/dist/llms.txt +2 -1
  40. package/dist/previs-software/index.html +2 -2
  41. package/dist/privacy/index.html +3 -7
  42. package/dist/seedance-camera-control/index.html +2 -2
  43. package/dist/sitemap.xml +5 -5
  44. package/dist/sw.js +5 -1
  45. package/dist/thumbs/blank-stage-dark.webp +0 -0
  46. package/dist/thumbs/blank-stage-light.webp +0 -0
  47. package/dist/workflow/index.html +5 -4
  48. package/mcp/mesh-file.mjs +3 -1
  49. package/mcp/server.mjs +3 -0
  50. package/mcp/tool-handlers.mjs +2 -2
  51. package/package.json +5 -3
  52. package/src/App.jsx +51 -282
  53. package/src/analytics.js +3 -148
  54. package/src/app-stage.jsx +1 -1
  55. package/src/asset-pane.jsx +5 -10
  56. package/src/auto-flat.js +10 -0
  57. package/src/bus-tasks.js +11 -5
  58. package/src/command-bus.js +1 -1
  59. package/src/commands/elements.js +4 -3
  60. package/src/commands/motion3-compile.js +51 -27
  61. package/src/commands/motion3.js +3 -3
  62. package/src/commands/objects.js +1 -1
  63. package/src/commands/project.js +1 -1
  64. package/src/commands/shot.js +16 -4
  65. package/src/controls.jsx +0 -11
  66. package/src/cuts.js +11 -0
  67. package/src/domains/cast.js +3 -2
  68. package/src/domains/motion.js +3 -10
  69. package/src/domains/playback.js +32 -0
  70. package/src/domains/scenes.js +3 -22
  71. package/src/domains/shots.js +5 -5
  72. package/src/dualview.jsx +11 -15
  73. package/src/hierarchy-panel.css +18 -4
  74. package/src/hierarchy-panel.jsx +12 -11
  75. package/src/kits/held.js +3 -2
  76. package/src/light-blockers.js +2 -2
  77. package/src/main.jsx +5 -0
  78. package/src/material-look.js +189 -0
  79. package/src/material-presets.js +78 -0
  80. package/src/material-textures.js +157 -0
  81. package/src/motion/ground.js +5 -14
  82. package/src/motion/playback-frame-store.js +79 -0
  83. package/src/motion/playback-probe.js +16 -0
  84. package/src/motion/playback-subject.js +7 -0
  85. package/src/motion/timeline.css +43 -5
  86. package/src/motion/timeline.jsx +4 -3
  87. package/src/motion3/body.js +37 -5
  88. package/src/motion3/carried.js +11 -3
  89. package/src/motion3/compile-job.js +1 -1
  90. package/src/motion3/compiler/compile.js +7 -1
  91. package/src/motion3/compiler/finger-close.js +137 -0
  92. package/src/motion3/compiler/limbs.js +18 -3
  93. package/src/motion3/compiler/pose.js +6 -0
  94. package/src/motion3/compiler/validate-objects.js +17 -2
  95. package/src/motion3/compiler/validate-parts.js +2 -1
  96. package/src/motion3/compiler/vocab.js +4 -4
  97. package/src/motion3/describe.js +2 -2
  98. package/src/motion3/fix/index.js +5 -3
  99. package/src/motion3/flight.js +38 -0
  100. package/src/motion3/free-motion.js +10 -7
  101. package/src/motion3/load.js +125 -0
  102. package/src/motion3/mass.js +23 -0
  103. package/src/motion3/object-keys.js +11 -6
  104. package/src/motion3/object-pose.js +11 -3
  105. package/src/motion3/pipeline.js +3 -0
  106. package/src/motion3/qa/explain.js +3 -1
  107. package/src/motion3/qa/grasp-checks.js +123 -0
  108. package/src/motion3/qa/hints-grasp.js +71 -0
  109. package/src/motion3/qa/index.js +3 -1
  110. package/src/motion3/qa/object-checks.js +7 -2
  111. package/src/motion3/qa/patch.js +2 -1
  112. package/src/motion3/qa/spec-checks.js +10 -1
  113. package/src/motion3/schema/fields.js +3 -3
  114. package/src/motion3/schema/topics.js +9 -8
  115. package/src/motion3/schema/types.js +4 -1
  116. package/src/motion3/seat.js +84 -0
  117. package/src/motion3/settle.js +11 -6
  118. package/src/motion3/shapes.js +70 -0
  119. package/src/motion3/skills/catch.js +71 -0
  120. package/src/motion3/skills/index.js +10 -3
  121. package/src/motion3/skills/info.js +13 -0
  122. package/src/motion3/skills/throw.js +72 -0
  123. package/src/object-catalog.jsx +0 -4
  124. package/src/object-gizmo.jsx +2 -1
  125. package/src/object-look.js +9 -5
  126. package/src/object-path.js +1 -1
  127. package/src/panels/ProjectPanel.jsx +42 -21
  128. package/src/panels/details.css +15 -4
  129. package/src/popover.js +37 -0
  130. package/src/posestudio.jsx +15 -10
  131. package/src/primitive-look.js +38 -0
  132. package/src/project-browser-art.jsx +19 -0
  133. package/src/project-browser.css +74 -121
  134. package/src/project-browser.jsx +36 -60
  135. package/src/props.jsx +24 -35
  136. package/src/render-passes.js +7 -1
  137. package/src/retired-kinds.js +37 -0
  138. package/src/scene-objects.js +5 -9
  139. package/src/scenes.js +4 -5
  140. package/src/sculpt-colours.js +65 -0
  141. package/src/sculpt-compare.js +13 -50
  142. package/src/sculpt-csg.js +112 -0
  143. package/src/sculpt-curve.js +123 -0
  144. package/src/sculpt-cutters.js +43 -0
  145. package/src/sculpt-detail.js +207 -0
  146. package/src/sculpt-geometry-loft-convex.js +100 -0
  147. package/src/sculpt-geometry-shapes.js +250 -0
  148. package/src/sculpt-geometry.js +33 -15
  149. package/src/sculpt-loft-rings.js +225 -0
  150. package/src/sculpt-noise.js +65 -0
  151. package/src/sculpt-part-fields.js +27 -0
  152. package/src/sculpt-recipe-read.js +65 -0
  153. package/src/sculpt-recipe.js +33 -75
  154. package/src/sculpt-run.js +1 -1
  155. package/src/sculpt-scatter-items.js +183 -0
  156. package/src/sculpt-scatter-shape.js +57 -0
  157. package/src/sculpt-scatter.js +124 -0
  158. package/src/sculpt-shapes-curved.js +211 -0
  159. package/src/sculpt-shapes-loft-convex.js +218 -0
  160. package/src/sculpt-shapes.js +138 -0
  161. package/src/sculpt-sketch-state.js +76 -0
  162. package/src/sculpt-sketch.jsx +124 -0
  163. package/src/sculpt-surface-fields.js +65 -0
  164. package/src/settings-menu.jsx +1 -20
  165. package/src/shell/BottomDock.jsx +9 -9
  166. package/src/shell/MenuBar.jsx +1 -9
  167. package/src/shell/PreferencesDialog.jsx +3 -4
  168. package/src/shell/ViewportToolbar.jsx +3 -3
  169. package/src/shell/add-camera-shot.js +11 -0
  170. package/src/shell/glass-regions.css +3 -2
  171. package/src/shell/glass.css +0 -5
  172. package/src/shell/lens-scrub-math.js +51 -0
  173. package/src/shell/lens-scrub.css +73 -0
  174. package/src/shell/lens-scrub.jsx +98 -0
  175. package/src/shell/mode.css +6 -5
  176. package/src/shell/preferences.css +1 -32
  177. package/src/shell/shell.css +18 -1
  178. package/src/shell/studio-shell-context.js +5 -0
  179. package/src/shot-frame.js +26 -0
  180. package/src/stage-canvas-rigs.jsx +7 -8
  181. package/src/stage-characters.jsx +26 -0
  182. package/src/stage-gizmo.js +43 -0
  183. package/src/stage-labels-ko.js +0 -6
  184. package/src/stage-startup-defaults.js +3 -9
  185. package/src/starter-scenes.js +5 -11
  186. package/src/studio-agent-commands.js +2 -2
  187. package/src/studio-agent-protocol.js +2 -7
  188. package/src/studio-app-binding.js +1 -1
  189. package/src/studio-elements.js +6 -2
  190. package/src/styles/themes.css +13 -0
  191. package/src/styles.css +6 -674
  192. package/src/text/text-object.jsx +1 -1
  193. package/src/ui.jsx +8 -16
  194. package/src/use-embed-bridge.js +3 -6
  195. package/src/use-render-activity.js +3 -1
  196. package/src/view-ghosts.jsx +5 -3
  197. package/src/viewport-visible-rect.js +37 -0
  198. package/src/workflow/AgentPanel.jsx +79 -46
  199. package/src/workflow/AgentPlanCard.jsx +41 -0
  200. package/src/workflow/AgentProgressCard.jsx +1 -1
  201. package/src/workflow/TaskBoard.jsx +102 -0
  202. package/src/workflow/TaskInline.jsx +114 -0
  203. package/src/workflow/agent-client.js +25 -36
  204. package/src/workflow/agent-panel.css +14 -1
  205. package/src/workflow/agent-plan.css +93 -0
  206. package/src/workflow/agent-plan.js +59 -0
  207. package/src/workflow/attachment-image.js +10 -3
  208. package/src/workflow/attachment-video.js +91 -0
  209. package/src/workflow/task-board.css +98 -0
  210. package/src/workflow/task-board.js +169 -0
  211. package/tools/check-eslint.mjs +2 -1
  212. package/tools/check-knip.mjs +2 -1
  213. package/tools/dev/pages/greybox-to-video.html +2 -3
  214. package/tools/dev/pages/previs-software.html +2 -2
  215. package/tools/dev/pages/privacy.html +3 -7
  216. package/tools/dev/pages/seedance-camera-control.html +2 -2
  217. package/tools/dev-full.mjs +11 -2
  218. package/tools/eslint-baseline.json +6 -6
  219. package/tools/knip-baseline.json +0 -11
  220. package/tools/loc-baseline.json +30 -31
  221. package/tools/metrics-snapshot.mjs +43 -5
  222. package/tools/render-start-thumbs.mjs +175 -0
  223. package/tools/run-tests.mjs +10 -17
  224. package/tools/sitemap.mjs +1 -1
  225. package/dist/assets/analytics-BibyE5ar.js +0 -6
  226. package/dist/assets/app-DhRJ-PBz.js +0 -5088
  227. package/dist/assets/app-f-fkV5uP.css +0 -1
  228. package/dist/assets/compile-worker-DqiA4AaN.js +0 -5
  229. package/dist/assets/first-shot-handoff-Qx7SKl38.js +0 -1
  230. package/dist/assets/landing-DYg87MDY.js +0 -1
  231. package/dist/assets/scene-asset-sync-DBYQBR0T.js +0 -20
  232. package/dist/assets/scene-asset-sync-_S8NQl5B.css +0 -1
  233. package/dist/assets/workflow-BSA22Ofr.js +0 -179
  234. package/dist/scenes/city-block.cclayproject +0 -1
  235. package/src/burn-in.js +0 -91
  236. package/src/camera-tutorial.jsx +0 -520
  237. package/src/facing-marks.js +0 -88
  238. package/src/first-shot-handoff.js +0 -44
  239. package/src/panels/motion.css +0 -197
  240. package/src/set-pieces.jsx +0 -183
  241. package/src/tutorial-analytics.js +0 -86
  242. package/src/tutorial-walk.js +0 -17
  243. package/src/use-camera-tutorial.js +0 -50
  244. package/src/use-semantic-state.js +0 -12
  245. package/tools/metrics/archive-traffic.mjs +0 -138
  246. package/tools/perf/ik-camera-drag.mjs +0 -138
@@ -1 +1 @@
1
- {"payload":"{\"distribution\":\"npm\",\"package\":\"cozyclay\",\"version\":\"3.0.3\",\"repository\":\"NomaDamas/CozyClay\",\"content_sha256\":\"b8a07fdd5d546c0314c6099680d3569a89a01e59bd3a442fb2360f1acec56330\"}","signature":"uZinWHO8tjMSZNdv8SjUSnLeHER+UvdGPW6ay++FCJiXOt8eIKjw0bYpN4HJpoNQG6/i9RBBeKMdrPBepn76Ag=="}
1
+ {"payload":"{\"distribution\":\"npm\",\"package\":\"cozyclay\",\"version\":\"3.1.1\",\"repository\":\"NomaDamas/CozyClay\",\"content_sha256\":\"65554e5162b89f817b066016390471333bfcabcee80e0ae0ee46939bdc759599\"}","signature":"M4R6haq7YzLWxDPcdy5h4zI/w7nVEBubTszIj4UzgWEKB4XZgZYtrjsQJmjt2rF3IooyCKnvMlzNiYB/arAGDg=="}
@@ -185,9 +185,8 @@
185
185
  <h2>Do it in the browser</h2>
186
186
  <p>
187
187
  CozyClay is open source previs that runs in a Chromium tab. It exists for exactly this loop: block,
188
- camera, export, generate. The <a href="/#try">playground on the home page</a> walks through the camera
189
- part in seven moves on the same city block you see in the reels, and <code>npx cozyclay --scene city-block</code>
190
- opens that set on your machine.
188
+ camera, export, generate. The <a href="/#try">playground on the home page</a> runs the studio in the page, and
189
+ <code>npx cozyclay</code> runs it on your machine.
191
190
  </p>
192
191
  <div class="cta">
193
192
  <a class="btn primary" href="/#try">Try it in your browser</a>
package/dist/index.html CHANGED
@@ -159,23 +159,9 @@
159
159
  a.card { color: var(--ink); text-decoration: none; font-size: 19px; font-weight: 600; min-height: 96px; transition: transform .2s; }
160
160
  a.card:hover { transform: translateY(-2px); }
161
161
 
162
- /* Playground. The ids and data-state values belong to the tutorial script below. */
163
- /* The steps sit in the window's title bar so the studio gets the full
164
- content width and height; started, the demo scrolls up to fill the screen. */
162
+ /* Playground. The ids and data-state values belong to the script below. */
165
163
  .demo { scroll-margin-top: 76px; }
166
164
  .demo .window { min-width: 0; box-shadow: 0 2px 6px rgba(0, 0, 0, .06), 0 24px 48px rgba(0, 0, 0, .14); }
167
- .tutorial-steps { flex: 1; min-width: 0; display: flex; justify-content: center; gap: 4px; margin: 0 52px 0 0; padding: 0; list-style: none; overflow: hidden; }
168
- .tutorial-steps[hidden] { display: none; }
169
- .tutorial-steps li {
170
- display: flex; align-items: center; gap: 6px; min-height: 28px; padding: 0 10px; border-radius: 999px; white-space: nowrap;
171
- background: var(--panel); border: 1px solid var(--line); color: var(--ink); font-size: 14px;
172
- opacity: .55; transition: opacity .2s, background .15s;
173
- }
174
- .playground-live .tutorial-steps li { opacity: 1; }
175
- .tutorial-steps li[data-done="1"] { color: var(--ok); border-color: var(--ok); }
176
- .tutorial-steps li[data-done="1"]::after { content: "✓"; font-weight: 700; }
177
- .tutorial-steps li[data-current="1"] { background: var(--accent); border-color: var(--accent); color: #fff; font-weight: 600; }
178
-
179
165
  .playground {
180
166
  position: relative;
181
167
  /* Header 64 + margin 12 + title bar 40 + bottom bar 52 + 12. */
@@ -216,26 +202,6 @@
216
202
  .playground-bar .spacer { flex: 1; }
217
203
  button.copy[data-state="copied"] { border-color: var(--ok); color: var(--ok); }
218
204
 
219
- .tutorial-card {
220
- position: absolute; left: 14px; top: 14px; z-index: 2; max-width: 46%;
221
- display: flex; gap: 10px; align-items: baseline;
222
- padding: 10px 14px; border-radius: 10px; pointer-events: none;
223
- background: rgba(255, 255, 255, .92); border: 1px solid var(--line); color: var(--ink);
224
- font-size: 17px; line-height: 1.45; backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px);
225
- box-shadow: var(--shadow-card);
226
- }
227
- .tutorial-card[hidden] { display: none; }
228
- .tutorial-card-step { color: var(--accent); font-size: 14px; font-weight: 600; white-space: nowrap; }
229
- .tutorial-card b { color: var(--accent); font-weight: 600; }
230
- .tutorial-card kbd, .tutorial-done kbd {
231
- padding: 2px 6px; border-radius: 5px;
232
- border: 1px solid var(--line-strong); background: var(--bg); color: var(--ink);
233
- }
234
- .tutorial-card kbd[data-done="1"] { border-color: var(--ok); color: var(--ok); background: #e6f2e7; }
235
- .tutorial-done { flex-basis: 100%; margin: 0 0 4px; color: var(--ink); display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
236
- .tutorial-done[hidden] { display: none; }
237
- .tutorial-done p { flex-basis: 100%; margin: 0; }
238
- #playground-download-status, #playground-download-error { flex-basis: 100%; margin: 0; }
239
205
  .demo-note { margin: 24px 0 0; }
240
206
 
241
207
  /* Quick start */
@@ -285,11 +251,8 @@
285
251
  .playground-cover .btn, .playground-cover small { display: none; }
286
252
  .playground-phone { display: block; font-size: 14px; padding: 0 24px; text-align: center; }
287
253
  .playground-cover { cursor: default; }
288
- /* No playground here, so no steps squeezed into the title bar. */
289
- .tutorial-steps { visibility: hidden; }
290
254
  }
291
255
  @media (max-width: 720px) {
292
- .tutorial-card { max-width: 90%; }
293
256
  section { padding: 64px 0; }
294
257
  .hero { padding: 56px 0 40px; }
295
258
  .proof { padding-bottom: 64px; }
@@ -298,12 +261,11 @@
298
261
  }
299
262
  @media (prefers-reduced-motion: reduce) {
300
263
  html { scroll-behavior: auto; }
301
- .btn, a.card, .seg button, .tutorial-steps li { transition: none; }
264
+ .btn, a.card, .seg button { transition: none; }
302
265
  }
303
266
  </style>
304
- <script type="module" crossorigin src="/assets/landing-DYg87MDY.js"></script>
305
- <link rel="modulepreload" crossorigin href="/assets/analytics-BibyE5ar.js">
306
- <link rel="modulepreload" crossorigin href="/assets/first-shot-handoff-Qx7SKl38.js">
267
+ <script type="module" crossorigin src="/assets/landing-y3EqDgSZ.js"></script>
268
+ <link rel="modulepreload" crossorigin href="/assets/modulepreload-polyfill-P2Xu9kJm.js">
307
269
  </head>
308
270
  <body>
309
271
  <header class="site">
@@ -383,28 +345,16 @@
383
345
  <h2>Try it</h2>
384
346
  <div class="demo">
385
347
  <div class="window">
386
- <div class="titlebar"><i aria-hidden="true"></i><i aria-hidden="true"></i><i aria-hidden="true"></i><ol class="tutorial-steps" id="tutorial-steps" aria-label="Tutorial steps"></ol></div>
348
+ <div class="titlebar" aria-hidden="true"><i></i><i></i><i></i><span>CozyClay</span></div>
387
349
  <div class="playground" id="playground" style="background-image: url('/media/playground-poster.jpg')">
388
350
  <button class="playground-cover" id="playground-start" type="button" aria-label="Start the playground">
389
- <span class="btn primary">Play with the scene</span>
351
+ <span class="btn primary">Open the studio here</span>
390
352
  <small>About 2 MB</small>
391
353
  <span class="playground-phone">Needs a mouse and keyboard. Come back on a computer, or run <code>npx cozyclay --via site</code>.</span>
392
354
  </button>
393
355
  <div class="playground-loading">Loading the studio…</div>
394
- <div class="tutorial-card" id="tutorial-card" aria-live="polite">
395
- <span class="tutorial-card-step" id="tutorial-card-step"></span>
396
- <span class="tutorial-card-text" id="tutorial-now"></span>
397
- </div>
398
356
  </div>
399
357
  <div class="playground-bar">
400
- <div class="tutorial-done" id="tutorial-done" hidden>
401
- <p>Take your shot with you. Video export is not offered in this embedded Playground.</p>
402
- <p>Download your edited project, run <code>npx cozyclay --via playground</code>, and open the downloaded <code>.cclayproject</code> in the local Studio. Use its existing Export menu for video.</p>
403
- <button type="button" id="playground-download" class="copy">Download my project</button>
404
- <button type="button" id="playground-handoff-dismiss">Continue editing</button>
405
- </div>
406
- <p id="playground-download-status" role="status" hidden></p>
407
- <p id="playground-download-error" role="alert" hidden></p>
408
358
  <span class="spacer"></span>
409
359
  <button type="button" id="playground-full">Fullscreen</button>
410
360
  <a href="/app/" target="_blank" rel="noopener">Open studio ↗</a>
@@ -422,7 +372,7 @@
422
372
  <div class="cards">
423
373
  <div class="card">
424
374
  <h3>Stage a scene</h3>
425
- <p>Primitives, set pieces, plan view.</p>
375
+ <p>Primitives, imported models, plan view.</p>
426
376
  </div>
427
377
  <div class="card">
428
378
  <h3>Move through the set</h3>
package/dist/llms.txt CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  ## Pages
6
6
 
7
- - [Home](https://cozyclay.org/): what it does, demo reels, an in-browser playground with a seven-step camera tutorial, quick start.
7
+ - [Home](https://cozyclay.org/): what it does, demo reels, an in-browser playground running the studio, quick start.
8
8
  - [Greybox to AI video](https://cozyclay.org/greybox-to-video/): why a grey blockout is the most reliable input to a video model, and the block-then-generate workflow.
9
9
  - [Previs software compared](https://cozyclay.org/previs-software/): free, open source and browser-based previs tools side by side.
10
10
  - [Seedance 2.5 camera control](https://cozyclay.org/seedance-camera-control/): getting the same camera every take with a reference clip instead of camera prompts.
@@ -28,4 +28,5 @@ For source-checkout CI, start the same Studio in owned headless Chrome with `nod
28
28
  ## Source
29
29
 
30
30
  - GitHub: https://github.com/NomaDamas/CozyClay
31
+ - Agent install guide: https://github.com/NomaDamas/CozyClay/blob/main/INSTALL_FOR_AGENTS.md
31
32
  - npm: https://www.npmjs.com/package/cozyclay
@@ -124,8 +124,8 @@
124
124
  <p>
125
125
  The honest split is time, not money. Blender can do everything on this page and will take an
126
126
  afternoon to learn just the camera. CozyClay does one thing (block, camera, cut, export) and expects
127
- you to be productive in the first ten minutes; there is a <a href="/#try">seven-step tutorial on the home page</a>
128
- that takes about that long.
127
+ you to be productive in the first ten minutes; the <a href="/#try">playground on the home page</a>
128
+ runs it in the page.
129
129
  </p>
130
130
  </section>
131
131
 
@@ -132,12 +132,11 @@ cclay telemetry on</code></pre>
132
132
  <thead><tr><th>Event</th><th>Purpose</th></tr></thead>
133
133
  <tbody>
134
134
  <tr><td>install:first_launch, app:session_started, app:session_ended</td><td>Counting installs and sessions; duration and action counts are bucketed. install:first_launch may carry heard_from (x, hn, reddit, github, friend, other, site or playground), from the first-launch prompt or a copied <code>npx cozyclay --via</code> command. app:session_ended also carries per-session edit gesture counts in five groups, pose_edit_bucket, camera_edit_bucket, object_edit_bucket, shot_edit_bucket and prompt_edit_bucket, each bucketed (0, 1-3, 4-10 or gte11); never what was edited</td></tr>
135
- <tr><td>feature:used</td><td>One signal per feature per session: a fixed feature name such as pose_edit (a real bone or pose change), pose_save (saving a pose to the library), fal_motion_open (opening the AI video A/B card), camera_fly or export_video</td></tr>
135
+ <tr><td>feature:used</td><td>One signal per feature per session: a fixed feature name such as pose_edit (a real bone or pose change), pose_save (saving a pose to the library), camera_fly or export_video</td></tr>
136
136
  <tr><td>$pageview, scene:created, scene:loaded, craft:first_action, activation:completed</td><td>Funnel and drop-off analysis</td></tr>
137
137
  <tr><td>craft:first_edit</td><td>First successful Studio authoring change per editor mount; only a fixed edit-kind label and definition version 1 (not camera navigation, playback, loading, restore, or undo/redo)</td></tr>
138
138
  <tr><td>playground:first_edit</td><td>The same versioned first-edit definition for Playground, counted separately from Studio; no prompts or scene contents</td></tr>
139
139
  <tr><td>project:saved, project:opened</td><td>Whether people keep their work (object counts and ages are bucketed; never names or paths)</td></tr>
140
- <tr><td>motion:backend_state</td><td>Session capability baseline: backend (none, local_kimodo or hosted) and boolean host_configured, never a host address</td></tr>
141
140
  <tr><td>motion:generate_requested</td><td>Explicit generation intent, not prompt-block editing: initiating surface (timeline, line_edit, trail, mcp, fal_card or agent), input_mode (prompt, pose, edit, a_to_b or still) and an ephemeral random request_id</td></tr>
142
141
  <tr><td>motion:preflight_blocked</td><td>Request readiness refusal: request_id, surface and normalized reason (unconfigured, unreachable, unsupported_route, locked or missing_input). locked means the AI video route is not enabled for the account yet; missing_input means the A/B captures were incomplete</td></tr>
143
142
  <tr><td>motion:preflight_passed</td><td>Request readiness accepted, before job start: request_id, surface and backend (none, local_kimodo, hosted or fal)</td></tr>
@@ -163,10 +162,6 @@ cclay telemetry on</code></pre>
163
162
  <tr><td>device:profile</td><td>Once per session, whether the studio can run smoothly: gpu_vendor (nvidia, amd, intel, apple, qualcomm, arm, software, other or unknown), gpu_class (discrete, integrated, software or unknown), webgl (webgl2, webgl1 or none), cpu_bucket (1-4, 5-8, 9-16, gte17 or unknown), memory_bucket (lt4, 4-7, gte8 or unknown) and frame_rate_bucket (lt20, 20-40, 40-55, gte55 or unknown) from one three-second sample. The GPU renderer string and exact hardware values never leave the browser.</td></tr>
164
163
  <tr><td>survey:use_case</td><td>An optional question shown at most once after a successful export, only while telemetry is on: use_case (animation, film, game, ad_mv, personal, other or skip) and team (team, solo or skip). Closed choices only; no free text.</td></tr>
165
164
  <tr><td>hosted:composer_viewed, hosted:login_started, hosted:ticket_created, hosted:result_opened, hosted:opened_in_studio</td><td>Hosted demo funnel</td></tr>
166
- <tr><td>tutorial:started</td><td>Camera tutorial attempts on surface (studio or playground), with numeric tutorial_version 1 and start_source (query, settings or landing). Restarting starts a new attempt; no tutorial attempt identifier or user text is sent.</td></tr>
167
- <tr><td>tutorial:step_entered, tutorial:dismissed</td><td>Entered steps and explicit dismissal of an unfinished tutorial; surface (studio or playground), numeric tutorial_version 1 and step_kind (fly, walk, dolly, orbit, shot, rail or play). Missing completion can indicate abandonment or missing telemetry; browser close does not promise a dismissal event.</td></tr>
168
- <tr><td>tutorial:step_completed</td><td>One completion per step per attempt; surface (studio or playground), numeric tutorial_version 1, step_kind (fly, walk, dolly, orbit, shot, rail or play) and elapsed_bucket (lt1s, 1-3s, 3-10s, 10-30s or gte30s) since entering that step. No raw timing, prompts, scene contents, names or paths.</td></tr>
169
- <tr><td>tutorial:completed</td><td>All seven steps completed; surface (studio or playground), numeric tutorial_version 1 and elapsed_bucket (lt1s, 1-3s, 3-10s, 10-30s or gte30s) since tutorial start. Sample loading and camera playback do not count as a user edit.</td></tr>
170
165
  </tbody>
171
166
  </table>
172
167
  </div>
@@ -178,7 +173,8 @@ cclay telemetry on</code></pre>
178
173
  <section>
179
174
  <h2>The hosted demo (Google sign-in)</h2>
180
175
  <p>
181
- The hosted motion demo asks you to sign in with Google so that the daily generation cap can be
176
+ The hosted demo is not open to the public right now. This section describes what it handled while it
177
+ was running. The hosted motion demo asks you to sign in with Google so that the daily generation cap can be
182
178
  enforced per account. It receives your Google account's email address and basic profile only, stores
183
179
  a session cookie signed by our server, and keeps your prompt and the generated result for up to 30
184
180
  days so the ticket link keeps working. Results are stored on Cloudflare R2 and deleted after that
@@ -146,8 +146,8 @@
146
146
  Any 3D tool that renders flat can make the reference. Blender works with a clay material and a
147
147
  workbench render. CozyClay, open source and in the browser, exports the flat clip directly with the
148
148
  delivery ratio and a camera timeline built in; the reel at the top of this page came out of it.
149
- The <a href="/#try">home-page playground</a> walks through blocking a shot and drawing a dolly rail in
150
- seven moves, and <code>npx cozyclay --scene city-block</code> opens that set locally.
149
+ The <a href="/#try">home-page playground</a> runs the studio in the page, and
150
+ <code>npx cozyclay</code> runs it locally.
151
151
  </p>
152
152
  <div class="cta">
153
153
  <a class="btn primary" href="/#try">Try it in your browser</a>
package/dist/sitemap.xml CHANGED
@@ -2,19 +2,19 @@
2
2
  <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
3
3
  <url>
4
4
  <loc>https://cozyclay.org/</loc>
5
- <lastmod>2026-10-08</lastmod>
5
+ <lastmod>2026-10-21</lastmod>
6
6
  </url>
7
7
  <url>
8
8
  <loc>https://cozyclay.org/greybox-to-video/</loc>
9
- <lastmod>2026-09-14</lastmod>
9
+ <lastmod>2026-10-21</lastmod>
10
10
  </url>
11
11
  <url>
12
12
  <loc>https://cozyclay.org/previs-software/</loc>
13
- <lastmod>2026-09-10</lastmod>
13
+ <lastmod>2026-10-21</lastmod>
14
14
  </url>
15
15
  <url>
16
16
  <loc>https://cozyclay.org/seedance-camera-control/</loc>
17
- <lastmod>2026-09-10</lastmod>
17
+ <lastmod>2026-10-21</lastmod>
18
18
  </url>
19
19
  <url>
20
20
  <loc>https://cozyclay.org/ai-camera-control/</loc>
@@ -22,6 +22,6 @@
22
22
  </url>
23
23
  <url>
24
24
  <loc>https://cozyclay.org/privacy/</loc>
25
- <lastmod>2026-10-01</lastmod>
25
+ <lastmod>2026-10-22</lastmod>
26
26
  </url>
27
27
  </urlset>
package/dist/sw.js CHANGED
@@ -10,7 +10,9 @@ const CACHE_PREFIX = "cozyclay-pwa-";
10
10
  // v7: force-refresh the asset cache — v6 clients were holding a stale app shell
11
11
  // (the html-flex crash-screen regression) and never re-fetching it.
12
12
  // v8: CozyClay 3 drops the shipped walk clip (motion is compiled in the studio).
13
- const CACHE_NAME = `${CACHE_PREFIX}v8`;
13
+ // v9: start-screen template thumbnails (public/thumbs, tools/render-start-thumbs.mjs).
14
+ // v10: the City Block starter and its thumbnails are removed.
15
+ const CACHE_NAME = `${CACHE_PREFIX}v10`;
14
16
  // The installable app is the studio, not the landing page.
15
17
  const APP_SHELL = "/app/";
16
18
  const CORE_ASSETS = [
@@ -26,6 +28,8 @@ const CORE_ASSETS = [
26
28
  "./fonts/inter-latin.woff2",
27
29
  "./models/x-bot-tpose.fbx",
28
30
  "./models/y-bot-tpose.fbx",
31
+ "./thumbs/blank-stage-light.webp",
32
+ "./thumbs/blank-stage-dark.webp",
29
33
  ];
30
34
 
31
35
  async function cacheResponse(cache, request, response) {
@@ -8,12 +8,13 @@
8
8
  <meta name="theme-color" content="#101116" />
9
9
  <meta name="description" content="CozyClay visual workflow builder" />
10
10
  <title>CozyClay Workflow</title>
11
- <script type="module" crossorigin src="/assets/workflow-BSA22Ofr.js"></script>
11
+ <script type="module" crossorigin src="/assets/workflow-zQM-EKW1.js"></script>
12
12
  <link rel="modulepreload" crossorigin href="/assets/rolldown-runtime-hePW80VL.js">
13
- <link rel="modulepreload" crossorigin href="/assets/analytics-BibyE5ar.js">
13
+ <link rel="modulepreload" crossorigin href="/assets/modulepreload-polyfill-P2Xu9kJm.js">
14
+ <link rel="modulepreload" crossorigin href="/assets/task-board-ErQvfoaz.js">
14
15
  <link rel="modulepreload" crossorigin href="/assets/fflate.module-KbGj5-H6.js">
15
- <link rel="modulepreload" crossorigin href="/assets/scene-asset-sync-DBYQBR0T.js">
16
- <link rel="stylesheet" crossorigin href="/assets/scene-asset-sync-_S8NQl5B.css">
16
+ <link rel="modulepreload" crossorigin href="/assets/scene-asset-sync-Cgdtr1Yw.js">
17
+ <link rel="stylesheet" crossorigin href="/assets/scene-asset-sync-CBx7XRti.css">
17
18
  <link rel="stylesheet" crossorigin href="/assets/workflow-DRdwoDBT.css">
18
19
  </head>
19
20
  <body>
package/mcp/mesh-file.mjs CHANGED
@@ -2,6 +2,7 @@ import { constants as fsConstants } from "node:fs";
2
2
  import { open as openFile } from "node:fs/promises";
3
3
  import { homedir } from "node:os";
4
4
  import { basename, join, resolve } from "node:path";
5
+ import { fileURLToPath } from "node:url";
5
6
 
6
7
  import { ASSET_MAX_SOURCE_BYTES } from "../src/scene-assets.js";
7
8
  import { classifyMeshBytes, meshMimeForKind } from "../src/mesh-sniff.js";
@@ -12,7 +13,8 @@ export function normalizeMeshPath(raw, { home = homedir() } = {}) {
12
13
  if (path.startsWith("file:")) {
13
14
  try {
14
15
  const url = new URL(path);
15
- if (url.protocol === "file:") path = decodeURIComponent(url.pathname);
16
+ // On Windows the pathname of file:///D:/x is /D:/x; fileURLToPath drops that leading slash.
17
+ if (url.protocol === "file:") path = process.platform === "win32" ? fileURLToPath(url) : decodeURIComponent(url.pathname);
16
18
  } catch {
17
19
  path = path.replace(/^file:\/\//, "");
18
20
  }
package/mcp/server.mjs CHANGED
@@ -175,6 +175,9 @@ if (httpFlag === -1) {
175
175
  setLiveHub(hub);
176
176
  configureLiveHub(hub, liveToken);
177
177
  await server.connect(new StdioServerTransport());
178
+ // A client ends a stdio session by closing stdin. Exit then, so the exit hooks
179
+ // remove the endpoint file even where SIGTERM cannot be caught (Windows).
180
+ process.stdin.once("end", () => process.exit(0));
178
181
  } else {
179
182
  // Tools execute in the stdio children, not this HTTP front. Each child tries
180
183
  // to own the one editor port; the winner is live and later sessions see the
@@ -1155,10 +1155,10 @@ export const createToolHandlers = ({ projectRootPromise } = {}) => {
1155
1155
  title: "Sculpt a clay prop from a recipe of soft parts",
1156
1156
  description:
1157
1157
  "Unlike place_object, import_mesh and compare_sculpt, sculpt_object builds or changes a clay prop from a recipe of parts you write, typically after reading a reference image. It needs no file and no catalogue entry. " +
1158
- "recipe = { version: 1, parts: [{ id, shape, size: [x, y, z], position?, rotation?, color?, parent?, mirror?, roundness?, taper?, border? }] }. " +
1158
+ "recipe = { version: 1, parts: [{ id, shape, size: [x, y, z], position?, rotation?, color?, parent?, mirror?, ...shape fields, material?, finish?, detail?, gradient?, op? }] }. " +
1159
1159
  "Units are metres and degrees. The floor is y = 0, front is +z, and the subject's own left is +x. size is the full extent; position is the part's centre, in its parent part's frame when parent is set. " +
1160
1160
  "shape: blob (soft superellipsoid: roundness 0 is an ellipsoid, 1 is a rounded box; taper narrows the top when positive and the bottom when negative), box (roundness bevels the edges), " +
1161
- "cylinder (taper 1 is a cone), torus (size [outer, outer, tube]), frame (a rectangular ring in x/y with a border width, for glasses rims, windows and picture frames). " +
1161
+ "cylinder (taper 1 is a cone), torus (size [outer, outer, tube]), frame (a rectangular ring in x/y with a border width, for glasses rims, windows and picture frames), " + "lathe { profile: [[r 0..1 of half-width, y 0..1 of height], ...] bottom to top, smooth? } for turned objects (pot, vase, bottle, bowl, lampshade, mushroom), " + "tube { path: [[x, y, z] each -0.5..0.5 of size], thickness (m, diameter), taper?, closed? } for ropes, vines, cables, handles, branches and bike frames, " + "extrude { outline: [[x, y] -0.5..0.5 of size], holes?, roundness? } for flat cut shapes pushed through size z (sign, leaf, gable, gear, star), " + "loft { sections: [{ y 0..1, points: [[x, z]...] } or { y, w, d, x?, z?, roundness? }] bottom to top (first y 0, last y 1), smooth? } for cross-sections that change (hull, car body, shoe, loaf; lay it down with rotation [-90,0,0]), " + "convex { points: [[x, y, z]...] or seed + facetCount?, facets? } for rocks, boulders, gems and crystals, " + "scatter { item: blade|tuft|flower|leaf|pebble|twig, count <= 4000, spread: ground|shell, seed? } for thousands of small items as ONE part (grass, flower beds, gravel; shell covers a crown or bush it is parented to; 12000 items per recipe). " + "Any part also takes material clay|wood|straw|stone|brick|concrete|metal|glass|ceramic|plastic|rubber|fabric|paper|foliage (real texture and shine; color tints it; never fake glass with opacity or thatch with stripes) and finish matte|satin|gloss; detail { amount 0..1, scale?, seed? } for a lumpy surface (clouds, bushes, rocks, hay, bread), gradient { color, axis? y|x|z, from?, to? } to blend into a second colour (sky-lit clouds, fruit, sunset walls), " + "and op: subtract|intersect, which makes the part an undrawn cutter of its parent (windows, doors, arches; hollow a lathe with a smaller lathe of the same profile; cut deeper than the wall; mirror cuts both sides). " +
1162
1162
  "mirror: true adds a copy reflected across x = 0 of the parent frame, with its children; author the subject's left (+x) side once. color is #rrggbb. At most 48 parts after mirrors. " +
1163
1163
  "To fix a sculpt, pass its id with edits instead of a whole recipe: [{ set: partId, ...fields }, { add: part }, { remove: partId }] (parent: null and mirror: false clear; remove takes the part's children). " +
1164
1164
  "capture: true also returns the editor's frame (connected editor only), so one call is one round. " +
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cozyclay",
3
- "version": "3.0.3",
3
+ "version": "3.1.1",
4
4
  "description": "Open source previs software in the browser: block a scene, pose characters, author camera moves and cuts, then take the same shots to an AI video model.",
5
5
  "scripts": {
6
6
  "dev": "node tools/dev-full.mjs --host 127.0.0.1 --port 5180",
@@ -32,7 +32,6 @@
32
32
  "test:appearance": "node test/verify-appearance.mjs",
33
33
  "test:auto-color": "node test/verify-auto-color.mjs",
34
34
  "test:shot-guides": "node test/verify-shot-guides.mjs",
35
- "test:burn-in": "node test/verify-burn-in.mjs",
36
35
  "test:layout": "node test/verify-layout.mjs",
37
36
  "test:timeline-camera": "node test/verify-timeline-camera.mjs",
38
37
  "test:timeline-shots": "node test/verify-timeline-shots.mjs",
@@ -57,7 +56,7 @@
57
56
  "prepack": "npm run build && node tools/prepare-package.mjs",
58
57
  "postpack": "node tools/prepare-package.mjs --clean",
59
58
  "prepublishOnly": "npm run build && node tools/prepare-package.mjs --check-key && node tools/prepare-package.mjs && node tools/verify-package-tarball.mjs",
60
- "metrics:traffic": "node tools/metrics/archive-traffic.mjs"
59
+ "metrics:snapshot": "node tools/metrics-snapshot.mjs"
61
60
  },
62
61
  "license": "AGPL-3.0-or-later",
63
62
  "type": "module",
@@ -83,6 +82,8 @@
83
82
  "react-icons": "^5.7.0",
84
83
  "reactflow": "^11.11.4",
85
84
  "three": "^0.185.1",
85
+ "three-bvh-csg": "^0.0.18",
86
+ "three-mesh-bvh": "^0.9.16",
86
87
  "vite": "^8.2.0"
87
88
  },
88
89
  "bin": {
@@ -106,6 +107,7 @@
106
107
  "mcp/README.md",
107
108
  "mcp/LIVE-PROTOCOL.md",
108
109
  "README.md",
110
+ "INSTALL_FOR_AGENTS.md",
109
111
  "CHANGELOG.md",
110
112
  "LICENSE",
111
113
  "LICENSES",