cozyclay 2.1.1 → 3.0.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 (585) hide show
  1. package/CHANGELOG.md +88 -0
  2. package/README.md +12 -30
  3. package/bin/agent/agent-routes.mjs +43 -116
  4. package/bin/agent/agent-runner.mjs +14 -15
  5. package/bin/agent/cliproxy-provider.mjs +135 -0
  6. package/bin/agent/credential-store.mjs +30 -7
  7. package/bin/agent/pi-tools.mjs +4 -1
  8. package/bin/agent/provider-keys.mjs +32 -0
  9. package/bin/agent/provider-login.mjs +110 -0
  10. package/bin/agent/provider-routes.mjs +99 -0
  11. package/bin/agent/providers.mjs +19 -97
  12. package/bin/agent/script-tool.mjs +17 -4
  13. package/bin/agent/session-store.mjs +2 -2
  14. package/bin/agent/studio-context-budget.mjs +93 -0
  15. package/bin/agent/studio-motion-reference.mjs +23 -0
  16. package/bin/agent/studio-prompt.mjs +1 -1
  17. package/bin/agent/studio-rebase-text.mjs +32 -0
  18. package/bin/agent/studio-rebase.mjs +26 -39
  19. package/bin/agent/studio-tools.mjs +9 -28
  20. package/bin/agent/tool-arguments.mjs +49 -0
  21. package/bin/agent/turn-frames.mjs +66 -0
  22. package/bin/codex-auth.mjs +9 -2
  23. package/bin/cozyclay.mjs +10 -116
  24. package/bin/live/cli.mjs +3 -3
  25. package/bin/mcp-runtime.mjs +2 -12
  26. package/bin/package-signature.mjs +0 -4
  27. package/dist/app/index.html +7 -6
  28. package/dist/assets/EXRLoader-CvVIvGVE.js +1 -0
  29. package/dist/assets/analytics-BWCqdgWA.js +1 -0
  30. package/dist/assets/app-DfTCxaKk.js +5087 -0
  31. package/dist/assets/app-f-fkV5uP.css +1 -0
  32. package/dist/assets/compile-worker-BxKXh07s.js +5 -0
  33. package/dist/assets/fflate.module-KbGj5-H6.js +5 -0
  34. package/dist/assets/{first-shot-handoff-msLI71g1.js → first-shot-handoff-DNO8kv_N.js} +1 -1
  35. package/dist/assets/{landing-ChUvB_zL.js → landing-yfZaJkWc.js} +1 -1
  36. package/dist/assets/scene-asset-sync-U3kS2rvK.js +20 -0
  37. package/dist/assets/scene-asset-sync-_S8NQl5B.css +1 -0
  38. package/dist/assets/workflow-D78eiKTa.js +179 -0
  39. package/dist/cozyclay-package.json +1 -1
  40. package/dist/index.html +3 -3
  41. package/dist/sw.js +3 -6
  42. package/dist/workflow/index.html +5 -4
  43. package/mcp/LIVE-PROTOCOL.md +7 -47
  44. package/mcp/README.md +16 -26
  45. package/mcp/live-hub.mjs +6 -10
  46. package/mcp/package.json +1 -3
  47. package/mcp/tool-handlers.mjs +4 -168
  48. package/package.json +3 -22
  49. package/src/App.jsx +151 -2625
  50. package/src/agent-progress.js +80 -0
  51. package/src/agent-turn-mark.js +30 -0
  52. package/src/analytics.js +1 -19
  53. package/src/app-context.js +12 -2
  54. package/src/app-stage.jsx +2 -34
  55. package/src/asset-pane.jsx +6 -5
  56. package/src/camera-block.js +21 -0
  57. package/src/camera-direction.js +120 -0
  58. package/src/character-kind.js +3 -9
  59. package/src/command-bus.js +10 -8
  60. package/src/commands/cast.js +5 -34
  61. package/src/commands/elements/character.js +1 -1
  62. package/src/commands/elements/motion.js +1 -6
  63. package/src/commands/elements/object.js +6 -2
  64. package/src/commands/elements/shot.js +4 -1
  65. package/src/commands/elements.js +38 -14
  66. package/src/commands/index.js +3 -1
  67. package/src/commands/kits.js +37 -0
  68. package/src/commands/motion-timing.js +57 -0
  69. package/src/commands/motion.js +9 -152
  70. package/src/commands/motion3-compile.js +65 -0
  71. package/src/commands/motion3.js +214 -0
  72. package/src/commands/objects.js +6 -4
  73. package/src/commands/shot.js +55 -13
  74. package/src/commands/stage.js +14 -1
  75. package/src/commands/view.js +4 -1
  76. package/src/document-mirrors.js +42 -0
  77. package/src/document-store.js +4 -0
  78. package/src/domains/cast.js +19 -194
  79. package/src/domains/motion/motion-range-pin-rules.js +1 -1
  80. package/src/domains/motion/take-source.js +53 -0
  81. package/src/domains/motion.js +60 -1838
  82. package/src/domains/scenes.js +12 -55
  83. package/src/domains/shots.js +2 -2
  84. package/src/domains/stage.js +4 -2
  85. package/src/draft-ghost.js +47 -0
  86. package/src/draft-ghost.jsx +129 -0
  87. package/src/dualview.jsx +4 -3
  88. package/src/effects/EffectsLayer.jsx +112 -0
  89. package/src/effects/effect-meshes.js +232 -0
  90. package/src/effects/effect-record.js +103 -0
  91. package/src/effects/emitter.js +59 -0
  92. package/src/effects/simulate.js +261 -0
  93. package/src/effects/state.js +59 -0
  94. package/src/execution-telemetry.js +2 -3
  95. package/src/first-success-guide.jsx +5 -5
  96. package/src/ghost-set.js +257 -0
  97. package/src/held-object-edit.jsx +113 -0
  98. package/src/held-object-pose.js +175 -0
  99. package/src/hierarchy-model.js +1 -1
  100. package/src/hierarchy-panel.jsx +1 -1
  101. package/src/imported-mesh.jsx +103 -0
  102. package/src/kits/held.js +84 -0
  103. package/src/kits/index.js +70 -0
  104. package/src/kits/smoking.js +57 -0
  105. package/src/light-blockers.js +93 -0
  106. package/src/motion/beat-board-model.js +84 -0
  107. package/src/motion/beat-board.css +124 -0
  108. package/src/motion/beat-board.jsx +60 -0
  109. package/src/motion/center-of-mass.js +66 -0
  110. package/src/motion/fix-collisions.js +850 -0
  111. package/src/motion/physics-review.js +118 -0
  112. package/src/{ardy → motion}/physics-support.js +1 -76
  113. package/src/motion/rig-snapshot.js +22 -0
  114. package/src/motion/take-segments.jsx +140 -0
  115. package/src/{ardy → motion}/timeline-coordinates.js +0 -21
  116. package/src/{ardy → motion}/timeline.css +1 -2
  117. package/src/{ardy → motion}/timeline.jsx +42 -413
  118. package/src/motion/waypoints.js +76 -0
  119. package/src/motion3/beats.js +83 -0
  120. package/src/motion3/body.js +158 -0
  121. package/src/motion3/bones.js +47 -0
  122. package/src/motion3/carried.js +47 -0
  123. package/src/motion3/compile-job.js +79 -0
  124. package/src/motion3/compile-worker.js +10 -0
  125. package/src/motion3/compiler/anchors.js +113 -0
  126. package/src/motion3/compiler/arm-orient.js +128 -0
  127. package/src/motion3/compiler/channels.js +125 -0
  128. package/src/motion3/compiler/compile.js +205 -0
  129. package/src/motion3/compiler/gait-rhythm.js +97 -0
  130. package/src/motion3/compiler/grip.js +171 -0
  131. package/src/motion3/compiler/head-steady.js +48 -0
  132. package/src/motion3/compiler/hold.js +134 -0
  133. package/src/motion3/compiler/idle.js +113 -0
  134. package/src/motion3/compiler/limbs.js +197 -0
  135. package/src/motion3/compiler/math.js +72 -0
  136. package/src/motion3/compiler/pose.js +177 -0
  137. package/src/motion3/compiler/quat.js +49 -0
  138. package/src/motion3/compiler/skeleton.js +74 -0
  139. package/src/motion3/compiler/validate-common.js +32 -0
  140. package/src/motion3/compiler/validate-goals.js +118 -0
  141. package/src/motion3/compiler/validate-objects.js +144 -0
  142. package/src/motion3/compiler/validate-parts.js +118 -0
  143. package/src/motion3/compiler/validate.js +122 -0
  144. package/src/motion3/compiler/vocab.js +74 -0
  145. package/src/motion3/compiler/walk-pelvis.js +275 -0
  146. package/src/motion3/compiler/walk.js +207 -0
  147. package/src/motion3/compiler/wrist-clamp.js +32 -0
  148. package/src/motion3/delta.js +47 -0
  149. package/src/motion3/describe.js +177 -0
  150. package/src/motion3/docs.js +27 -0
  151. package/src/motion3/edit-carry.js +21 -0
  152. package/src/motion3/fix/ease.js +16 -0
  153. package/src/motion3/fix/ground.js +37 -0
  154. package/src/motion3/fix/index.js +52 -0
  155. package/src/motion3/fix/push.js +71 -0
  156. package/src/motion3/fix/reach.js +46 -0
  157. package/src/motion3/fix/retime.js +79 -0
  158. package/src/motion3/fix/self.js +211 -0
  159. package/src/motion3/fix/slide.js +70 -0
  160. package/src/motion3/fix/turn.js +51 -0
  161. package/src/motion3/follow.js +39 -0
  162. package/src/motion3/free-motion.js +204 -0
  163. package/src/motion3/grip-choice.js +130 -0
  164. package/src/motion3/hold-plan.js +157 -0
  165. package/src/motion3/json-patch.js +77 -0
  166. package/src/motion3/key-aim.js +105 -0
  167. package/src/motion3/key-edit.js +82 -0
  168. package/src/motion3/lenient.js +127 -0
  169. package/src/motion3/object-keys.js +236 -0
  170. package/src/motion3/object-pose.js +182 -0
  171. package/src/motion3/object-tracks.js +12 -0
  172. package/src/motion3/people.js +82 -0
  173. package/src/motion3/pipeline.js +102 -0
  174. package/src/motion3/playback.js +51 -0
  175. package/src/motion3/probes.js +91 -0
  176. package/src/motion3/qa/body-checks.js +34 -0
  177. package/src/motion3/qa/check-names.js +14 -0
  178. package/src/motion3/qa/checks.js +125 -0
  179. package/src/motion3/qa/contact-checks.js +51 -0
  180. package/src/motion3/qa/explain.js +80 -0
  181. package/src/motion3/qa/fmt.js +5 -0
  182. package/src/motion3/qa/foot-checks.js +72 -0
  183. package/src/motion3/qa/geometry.js +77 -0
  184. package/src/motion3/qa/goals.js +191 -0
  185. package/src/motion3/qa/ground.js +60 -0
  186. package/src/motion3/qa/hints-contact.js +195 -0
  187. package/src/motion3/qa/hints-goal.js +160 -0
  188. package/src/motion3/qa/hints-knee.js +24 -0
  189. package/src/motion3/qa/hints-motion.js +209 -0
  190. package/src/motion3/qa/hints-object.js +91 -0
  191. package/src/motion3/qa/index.js +44 -0
  192. package/src/motion3/qa/key-checks.js +82 -0
  193. package/src/motion3/qa/near.js +96 -0
  194. package/src/motion3/qa/object-checks.js +135 -0
  195. package/src/motion3/qa/patch.js +161 -0
  196. package/src/motion3/qa/people-checks.js +37 -0
  197. package/src/motion3/qa/severity.js +38 -0
  198. package/src/motion3/qa/spec-checks.js +65 -0
  199. package/src/motion3/qa/style.js +228 -0
  200. package/src/motion3/qa/wrist-checks.js +69 -0
  201. package/src/motion3/qa/wrist-obs.js +60 -0
  202. package/src/motion3/refs.js +129 -0
  203. package/src/motion3/repair-tune.js +121 -0
  204. package/src/motion3/repair.js +83 -0
  205. package/src/motion3/report.js +67 -0
  206. package/src/motion3/rigs/index.js +14 -0
  207. package/src/motion3/rigs/x-bot-tpose-body.json +1 -0
  208. package/src/motion3/rigs/x-bot-tpose.json +1 -0
  209. package/src/motion3/rigs/y-bot-tpose-body.json +1 -0
  210. package/src/motion3/rigs/y-bot-tpose.json +1 -0
  211. package/src/motion3/scene.js +60 -0
  212. package/src/motion3/schema/brief.js +89 -0
  213. package/src/motion3/schema/fields.js +44 -0
  214. package/src/motion3/schema/spec-examples.js +46 -0
  215. package/src/motion3/schema/topics.js +113 -0
  216. package/src/motion3/schema/types.js +149 -0
  217. package/src/motion3/search.js +117 -0
  218. package/src/motion3/second-hand.js +112 -0
  219. package/src/motion3/settle.js +136 -0
  220. package/src/motion3/skills/basic.js +83 -0
  221. package/src/motion3/skills/book.js +76 -0
  222. package/src/motion3/skills/car.js +145 -0
  223. package/src/motion3/skills/flip.js +200 -0
  224. package/src/motion3/skills/frames-auto.js +29 -0
  225. package/src/motion3/skills/impact.js +109 -0
  226. package/src/motion3/skills/index.js +85 -0
  227. package/src/motion3/skills/info.js +80 -0
  228. package/src/motion3/skills/smoke-kit.js +109 -0
  229. package/src/motion3/skills/smoke.js +160 -0
  230. package/src/motion3/spec-store.js +59 -0
  231. package/src/motion3/take-edit.js +155 -0
  232. package/src/motion3/take.js +63 -0
  233. package/src/motion3/timeline.js +127 -0
  234. package/src/motion3/views.js +121 -0
  235. package/src/motion3/walk-plan.js +119 -0
  236. package/src/object-catalog.jsx +7 -1
  237. package/src/object-colors.js +98 -0
  238. package/src/object-gizmo-parts.js +115 -0
  239. package/src/object-gizmo.jsx +37 -122
  240. package/src/object-glow.js +139 -0
  241. package/src/object-hidden.js +33 -0
  242. package/src/object-look.js +196 -0
  243. package/src/object-size.js +10 -0
  244. package/src/object-travel.js +71 -6
  245. package/src/panels/CameraPanel.jsx +7 -7
  246. package/src/panels/HdrEnvironmentControls.jsx +59 -0
  247. package/src/panels/LightPanel.jsx +25 -4
  248. package/src/panels/ObjectLookPanel.jsx +88 -0
  249. package/src/panels/PosePanel.jsx +2 -17
  250. package/src/panels/RigControlPanel.jsx +5 -53
  251. package/src/panels/SubjectBox.jsx +4 -1
  252. package/src/panels/details.css +14 -0
  253. package/src/posestudio.jsx +4 -27
  254. package/src/project-browser.jsx +3 -4
  255. package/src/project-resources.js +18 -31
  256. package/src/project.js +13 -104
  257. package/src/props.jsx +25 -280
  258. package/src/qa-label.js +25 -0
  259. package/src/rail-dot-drag.js +23 -0
  260. package/src/render-passes.js +10 -0
  261. package/src/resource-status.jsx +1 -0
  262. package/src/result-modal.jsx +4 -19
  263. package/src/room.jsx +20 -12
  264. package/src/scene-assets.js +8 -6
  265. package/src/scene-light-place.js +72 -0
  266. package/src/scene-lights.jsx +148 -0
  267. package/src/scene-objects.js +31 -139
  268. package/src/scenes.js +15 -105
  269. package/src/semantic-edit.js +2 -5
  270. package/src/set-pieces.jsx +183 -0
  271. package/src/settings-menu.jsx +3 -11
  272. package/src/shell/BottomDock.jsx +9 -51
  273. package/src/shell/DetailsSlot.jsx +16 -200
  274. package/src/shell/GhostsMenuGroup.jsx +74 -0
  275. package/src/shell/LibrarySlot.jsx +1 -3
  276. package/src/shell/MenuBar.jsx +3 -3
  277. package/src/shell/PreferencesDialog.jsx +15 -264
  278. package/src/shell/PreferencesSlot.jsx +2 -8
  279. package/src/shell/TopBar.jsx +5 -84
  280. package/src/shell/ViewportToolbar.jsx +10 -70
  281. package/src/shell/agent-glass.css +19 -6
  282. package/src/shell/details-selection.js +42 -0
  283. package/src/shell/ghosts-menu.css +22 -0
  284. package/src/shell/glass-regions.css +29 -3
  285. package/src/shell/preferences.css +6 -1
  286. package/src/shot-authoring.js +4 -7
  287. package/src/soft-shadows.js +37 -0
  288. package/src/stage-attach-frames.js +12 -12
  289. package/src/stage-canvas-rigs.jsx +3 -3
  290. package/src/stage-capture.jsx +42 -8
  291. package/src/stage-characters.jsx +22 -216
  292. package/src/stage-editor-gizmos.jsx +6 -6
  293. package/src/stage-environment.js +93 -0
  294. package/src/stage-hdr-builtins.js +107 -0
  295. package/src/stage-hdr-image.js +116 -0
  296. package/src/stage-hdr-library.js +70 -0
  297. package/src/stage-hdr-map.js +94 -0
  298. package/src/stage-hdr.js +130 -0
  299. package/src/stage-lighting.js +149 -0
  300. package/src/stage-occlusion.js +210 -0
  301. package/src/stage-sky.jsx +159 -0
  302. package/src/stage-startup-defaults.js +5 -9
  303. package/src/studio-actions.js +16 -14
  304. package/src/studio-agent-commands.js +19 -16
  305. package/src/studio-agent-motion.js +9 -9
  306. package/src/studio-agent-protocol.js +47 -77
  307. package/src/studio-app-binding.js +27 -47
  308. package/src/studio-asset-list.js +17 -0
  309. package/src/studio-contact-sheet.js +37 -5
  310. package/src/studio-elements.js +27 -7
  311. package/src/studio-entity-bounds.js +18 -0
  312. package/src/studio-error-codes.js +15 -0
  313. package/src/studio-export-framing.js +152 -0
  314. package/src/studio-lighting-check.js +103 -0
  315. package/src/studio-motion-visual.js +150 -0
  316. package/src/studio-schema-errors.js +80 -0
  317. package/src/studio-support-gap.js +74 -0
  318. package/src/styles.css +1 -19
  319. package/src/timeline-defaults.js +5 -0
  320. package/src/timeline-extent.js +8 -20
  321. package/src/tutorial-walk.js +17 -0
  322. package/src/ui-scrub.js +1 -1
  323. package/src/use-shot-camera-tracks.js +12 -0
  324. package/src/view-ghosts.js +97 -0
  325. package/src/view-ghosts.jsx +49 -0
  326. package/src/workflow/AgentPanel.jsx +47 -166
  327. package/src/workflow/AgentProgressCard.jsx +109 -0
  328. package/src/workflow/AgentReplyText.jsx +37 -0
  329. package/src/workflow/AgentTurnSteps.jsx +84 -0
  330. package/src/workflow/LoginPanel.jsx +140 -0
  331. package/src/workflow/WorkflowBuilder.jsx +7 -23
  332. package/src/workflow/agent-client.js +54 -51
  333. package/src/workflow/agent-panel.css +71 -1
  334. package/src/workflow/agent-progress-card.css +167 -0
  335. package/src/workflow/agent-progress-view.js +47 -0
  336. package/src/workflow/agent-turn-steps.css +113 -0
  337. package/src/workflow/agent-turn.js +191 -0
  338. package/src/workflow/login-client.js +34 -0
  339. package/src/workflow/motion-input.js +18 -31
  340. package/src/workflow/node-schema.js +1 -1
  341. package/src/workflow/reply-markdown.js +69 -0
  342. package/src/workflow/scene-asset-sync.js +8 -8
  343. package/tools/agent-session-stats.mjs +61 -0
  344. package/tools/dev-full.mjs +5 -56
  345. package/tools/eslint-baseline.json +12 -13
  346. package/tools/knip-baseline.json +0 -179
  347. package/tools/loc-baseline.json +31 -81
  348. package/tools/motion3/extract-body.mjs +103 -0
  349. package/tools/motion3/extract-rig.mjs +85 -0
  350. package/tools/process-supervisor.mjs +0 -88
  351. package/tools/run-tests.mjs +9 -125
  352. package/bin/agent/motion-runtime.mjs +0 -76
  353. package/dist/ardy/cskel27-rest.json +0 -557
  354. package/dist/assets/analytics-C9pMpW7s.js +0 -1
  355. package/dist/assets/app-B_2XB9rw.css +0 -1
  356. package/dist/assets/app-DAuvKPP8.js +0 -4920
  357. package/dist/assets/config-Bx7pYsD9.js +0 -1
  358. package/dist/assets/config-DeoFTYzb.css +0 -1
  359. package/dist/assets/demo-CvKuBgy5.js +0 -1
  360. package/dist/assets/scene-asset-sync-DKkpjKBV.js +0 -19
  361. package/dist/assets/scene-asset-sync-DjJ_cJ2R.css +0 -1
  362. package/dist/assets/ticket-BPk2Ni95.js +0 -1
  363. package/dist/assets/workflow-jJRBR94Z.js +0 -179
  364. package/dist/demo/walk-then-stop.npz +0 -0
  365. package/mcp/ardy-prompts.mjs +0 -218
  366. package/src/ardy/auto-fix-panel.css +0 -108
  367. package/src/ardy/auto-physics.js +0 -1194
  368. package/src/ardy/client.js +0 -153
  369. package/src/ardy/convert.js +0 -313
  370. package/src/ardy/cskel27-neutral.js +0 -39
  371. package/src/ardy/cskel27.js +0 -77
  372. package/src/ardy/export.js +0 -165
  373. package/src/ardy/fix-collisions.js +0 -2257
  374. package/src/ardy/foot-lock.js +0 -230
  375. package/src/ardy/motion-calibration.js +0 -118
  376. package/src/ardy/motion-edit.js +0 -213
  377. package/src/ardy/motion-url.js +0 -55
  378. package/src/ardy/mp4-duration.js +0 -102
  379. package/src/ardy/npz.js +0 -595
  380. package/src/ardy/physics-panel.css +0 -21
  381. package/src/ardy/physics-panel.jsx +0 -89
  382. package/src/ardy/physics-refine.js +0 -111
  383. package/src/ardy/physics-review.js +0 -567
  384. package/src/ardy/physics-temporal.js +0 -54
  385. package/src/ardy/platform-fit-panel.css +0 -64
  386. package/src/ardy/platform-fit-panel.jsx +0 -41
  387. package/src/ardy/platform-fit.js +0 -326
  388. package/src/ardy/playback.js +0 -711
  389. package/src/ardy/pose-pin.js +0 -97
  390. package/src/ardy/prompt-clips.js +0 -30
  391. package/src/ardy/retime.js +0 -211
  392. package/src/ardy/root-drop.js +0 -369
  393. package/src/ardy/timeline-resize.js +0 -13
  394. package/src/ardy/to-cskel27.js +0 -225
  395. package/src/ardy/trim.js +0 -33
  396. package/src/ardy/waypoints.js +0 -369
  397. package/src/ardy-bridge-contract.js +0 -281
  398. package/src/domains/motion/motion-video-capture.js +0 -664
  399. package/src/i2v-motion-client.js +0 -77
  400. package/src/i2v-motion-studio.jsx +0 -180
  401. package/src/line-edit.js +0 -1348
  402. package/src/motion/generation.js +0 -105
  403. package/src/motion-readiness-ui.jsx +0 -67
  404. package/src/motion-readiness.js +0 -40
  405. package/src/motion-resources.js +0 -177
  406. package/src/motion-store.js +0 -65
  407. package/src/motion-trail.js +0 -601
  408. package/src/multimodel-ingest.js +0 -394
  409. package/src/panels/PromptBlocksPanel.jsx +0 -444
  410. package/src/panels/VideoCapturePanel.jsx +0 -181
  411. package/src/pose-extract/browser.js +0 -42
  412. package/src/pose-extract/detector.js +0 -100
  413. package/src/pose-extract/fit.js +0 -227
  414. package/src/pose-extract/image-frame.js +0 -51
  415. package/src/pose-extract/index.js +0 -58
  416. package/src/pose-extract/keyframes.js +0 -74
  417. package/src/pose-extract/landmarks.js +0 -162
  418. package/src/pose-extract/mirror.js +0 -153
  419. package/src/pose-extract/take.js +0 -131
  420. package/src/pose-extract/video-frames.js +0 -91
  421. package/src/take-recipe.js +0 -165
  422. package/src/trail-key-conflicts.js +0 -39
  423. package/src/trail-pick.js +0 -59
  424. package/src/use-i2v-capture-modal.js +0 -15
  425. package/tools/ardy/BRIDGE.md +0 -37
  426. package/tools/ardy/GVHMR-NPZ.md +0 -68
  427. package/tools/ardy/README.md +0 -124
  428. package/tools/ardy/__pycache__/cclay_gvhmr_worker.cpython-313.pyc +0 -0
  429. package/tools/ardy/artifacts.mjs +0 -34
  430. package/tools/ardy/bridge.mjs +0 -1732
  431. package/tools/ardy/bvh-cskel27.mjs +0 -1265
  432. package/tools/ardy/cclay_constrained_generate.py +0 -561
  433. package/tools/ardy/cclay_gvhmr_worker.py +0 -264
  434. package/tools/ardy/cclay_motion_edit.py +0 -510
  435. package/tools/ardy/cclay_sequence_generate.py +0 -705
  436. package/tools/ardy/cclay_worker.py +0 -304
  437. package/tools/ardy/dump-npz.py +0 -205
  438. package/tools/ardy/extract-rest.mjs +0 -299
  439. package/tools/ardy/extract.mjs +0 -507
  440. package/tools/ardy/footage.mjs +0 -467
  441. package/tools/ardy/gvhmr-floor.mjs +0 -102
  442. package/tools/ardy/gvhmr-to-cskel27.mjs +0 -21
  443. package/tools/ardy/gvhmr_fastpath.py +0 -168
  444. package/tools/ardy/gvhmr_trajectory.py +0 -240
  445. package/tools/ardy/merge-text-encoder.py +0 -160
  446. package/tools/ardy/mocap-metrics.mjs +0 -200
  447. package/tools/ardy/mocap-quality-gate.mjs +0 -110
  448. package/tools/ardy/motion-stabilize.mjs +0 -348
  449. package/tools/ardy/npz.mjs +0 -414
  450. package/tools/ardy/pose-to-npz.mjs +0 -106
  451. package/tools/ardy/prompt-limits.mjs +0 -5
  452. package/tools/ardy/run-edit-on-box.sh +0 -73
  453. package/tools/ardy/run-local.mjs +0 -233
  454. package/tools/ardy/run-on-box.sh +0 -593
  455. package/tools/ardy/run-sequence-on-box.sh +0 -177
  456. package/tools/ardy/runners/gvhmr-worker.mjs +0 -206
  457. package/tools/ardy/runners/index.mjs +0 -18
  458. package/tools/ardy/runners/local.mjs +0 -455
  459. package/tools/ardy/runners/proc.mjs +0 -125
  460. package/tools/ardy/runners/remote.mjs +0 -252
  461. package/tools/ardy/setup-local.mjs +0 -189
  462. package/tools/ardy/setup-text-encoder-on-box.sh +0 -93
  463. package/tools/ardy/setup-text-encoder.py +0 -306
  464. package/tools/ardy/smpl-cskel27.mjs +0 -178
  465. package/tools/ardy/visual-qa.mjs +0 -196
  466. package/tools/ardy/vq-car.mjs +0 -52
  467. package/tools/bench/EXP3.md +0 -61
  468. package/tools/bench/cclay_bench_extract_incam.py +0 -125
  469. package/tools/bench/cclay_bench_extract_obs.py +0 -204
  470. package/tools/bench/cclay_bench_runner.py +0 -42
  471. package/tools/bench/cube-contact.mjs +0 -162
  472. package/tools/bench/exp3.mjs +0 -152
  473. package/tools/bench/extract-bench-lib.mjs +0 -216
  474. package/tools/bench/extract-bench.mjs +0 -302
  475. package/tools/bench/fal-generate.mjs +0 -88
  476. package/tools/bench/fit/README.md +0 -189
  477. package/tools/bench/fit/camera.mjs +0 -59
  478. package/tools/bench/fit/contact.mjs +0 -419
  479. package/tools/bench/fit/footlock.mjs +0 -234
  480. package/tools/bench/fit/motion.mjs +0 -85
  481. package/tools/bench/fit/pin.mjs +0 -27
  482. package/tools/bench/fit/remote.mjs +0 -105
  483. package/tools/bench/fit-bench.mjs +0 -126
  484. package/tools/bench/fit-sanity.mjs +0 -45
  485. package/tools/bench/metrics.mjs +0 -313
  486. package/tools/bench/obs/depth.mjs +0 -258
  487. package/tools/bench/obs/extrinsics.mjs +0 -175
  488. package/tools/bench/obs/fit_mannequin_betas.py +0 -340
  489. package/tools/bench/obs/ground.mjs +0 -294
  490. package/tools/bench/obs/heading.mjs +0 -151
  491. package/tools/bench/obs/ladder.mjs +0 -555
  492. package/tools/bench/obs/mannequin-betas.json +0 -124
  493. package/tools/bench/obs/remote.mjs +0 -83
  494. package/tools/bench/obs/rest_joints.py +0 -52
  495. package/tools/bench/obs/ybot-targets.mjs +0 -49
  496. package/tools/bench/obs-bench.mjs +0 -520
  497. package/tools/bench/score.mjs +0 -343
  498. package/tools/bench/summarize.mjs +0 -86
  499. package/tools/demo-worker/README.md +0 -137
  500. package/tools/demo-worker/api-client.mjs +0 -233
  501. package/tools/demo-worker/generate.mjs +0 -301
  502. package/tools/demo-worker/index.mjs +0 -466
  503. package/tools/demo-worker/sign-core.mjs +0 -112
  504. package/tools/demo-worker/sign.mjs +0 -161
  505. package/tools/gt-render/browser.mjs +0 -182
  506. package/tools/gt-render/camera-math.mjs +0 -276
  507. package/tools/gt-render/page.mjs +0 -267
  508. package/tools/gt-render/render.mjs +0 -514
  509. package/tools/gt-render/scene-box.mjs +0 -31
  510. package/tools/gt-render/take-transform.mjs +0 -87
  511. package/tools/kimodo/compare-seam.mjs +0 -108
  512. package/tools/kimodo/constraints.mjs +0 -244
  513. package/tools/kimodo/edit.mjs +0 -259
  514. package/tools/kimodo/effector-constraints.mjs +0 -200
  515. package/tools/kimodo/generate.mjs +0 -646
  516. package/tools/kimodo/local-output.mjs +0 -265
  517. package/tools/kimodo/measure-pose.mjs +0 -65
  518. package/tools/kimodo/measure-preserve.mjs +0 -899
  519. package/tools/kimodo/measure-waypoints.mjs +0 -55
  520. package/tools/kimodo/mlx-generate.py +0 -111
  521. package/tools/kimodo/pose-constraints.mjs +0 -248
  522. package/tools/kimodo/preserve-mask.mjs +0 -543
  523. package/tools/kimodo/read-npz.mjs +0 -189
  524. package/tools/kimodo/run-edit-on-box.mjs +0 -155
  525. package/tools/kimodo/run-sequence-on-box.mjs +0 -178
  526. package/tools/kimodo/runner.mjs +0 -284
  527. package/tools/kimodo/seam-batch.mjs +0 -77
  528. package/tools/kimodo/setup-local.mjs +0 -30
  529. package/tools/kimodo/setup-on-box.sh +0 -339
  530. package/tools/kimodo/soma77-to-cskel27.mjs +0 -305
  531. package/tools/morphgs/assets/gen_truth.py +0 -39
  532. package/tools/morphgs/assets/mesh_ori_rig.txt +0 -27
  533. package/tools/morphgs/assets/playback-check.mjs +0 -30
  534. package/tools/morphgs/demo-gate.sh +0 -26
  535. package/tools/morphgs/fbx2morphgs.mjs +0 -68
  536. package/tools/morphgs/morphgs-to-cskel27.mjs +0 -105
  537. package/tools/morphgs/patches/preprocess_src-none-mode.patch +0 -76
  538. package/tools/morphgs/setup-on-cluster.sh +0 -126
  539. package/tools/projflow/driver.py +0 -1069
  540. package/tools/projflow/generate.mjs +0 -805
  541. package/tools/projflow/hml22-to-cskel27.mjs +0 -735
  542. package/tools/projflow/line-edit-job.mjs +0 -547
  543. package/tools/projflow/replay.mjs +0 -452
  544. package/tools/projflow/runner.mjs +0 -269
  545. package/tools/projflow/service.mjs +0 -742
  546. package/tools/track/DESIGN.md +0 -513
  547. package/tools/track/backfill-provenance.mjs +0 -116
  548. package/tools/track/budget.mjs +0 -8
  549. package/tools/track/check-rig.mjs +0 -209
  550. package/tools/track/diagnostics.schema.json +0 -60
  551. package/tools/track/export-rig.mjs +0 -256
  552. package/tools/track/fallback.mjs +0 -7
  553. package/tools/track/fk-parity-fixture.mjs +0 -161
  554. package/tools/track/gate.mjs +0 -349
  555. package/tools/track/masks.mjs +0 -318
  556. package/tools/track/metrics.mjs +0 -201
  557. package/tools/track/publish-obs.mjs +0 -108
  558. package/tools/track/py/check_env.py +0 -61
  559. package/tools/track/py/eval_lr.py +0 -229
  560. package/tools/track/py/lr_viterbi.py +0 -294
  561. package/tools/track/py/masks.py +0 -405
  562. package/tools/track/py/objective.py +0 -382
  563. package/tools/track/py/rig.py +0 -508
  564. package/tools/track/py/scene.py +0 -326
  565. package/tools/track/py/test_joint_indices.py +0 -123
  566. package/tools/track/py/test_lr_viterbi.py +0 -195
  567. package/tools/track/py/test_masks.py +0 -229
  568. package/tools/track/py/test_rig.py +0 -288
  569. package/tools/track/py/test_scene.py +0 -354
  570. package/tools/track/py/test_track.py +0 -328
  571. package/tools/track/py/track.py +0 -411
  572. package/tools/track/remote.mjs +0 -140
  573. package/tools/track/rig-dump.mjs +0 -227
  574. package/tools/track/run-box-tests.mjs +0 -14
  575. package/tools/track/run-box.mjs +0 -168
  576. package/tools/track/setup-box.sh +0 -59
  577. package/tools/track/study-2d.mjs +0 -728
  578. /package/src/{ardy → motion}/collision-blockers.js +0 -0
  579. /package/src/{ardy → motion}/ground.js +0 -0
  580. /package/src/{ardy → motion}/ik-drag.js +0 -0
  581. /package/src/{ardy → motion}/ik-key-json.js +0 -0
  582. /package/src/{ardy → motion}/ik.js +0 -0
  583. /package/src/{ardy → motion}/physics-surface.js +0 -0
  584. /package/src/{ardy → motion}/playback-clock.js +0 -0
  585. /package/src/{ardy → motion}/range-pin.js +0 -0
@@ -1,414 +0,0 @@
1
- /**
2
- * Pure-Node writer for numpy .npz archives: v1.0 .npy members inside a
3
- * STORED (uncompressed) zip. No numpy on the workstation and no new
4
- * dependencies -- .npy is a 10-byte prefix plus a little-endian float32
5
- * payload, and STORED zip keeps CRC-32 and sizes trivial to compute.
6
- *
7
- * The only consumer today is the ARDY constrained generator:
8
- *
9
- * --pose-from <npz> <src-frame> <dst-frame>
10
- *
11
- * cclay_constrained_generate.load_poses reads exactly two float32 members,
12
- * local_rot_mats (frames, 27, 3, 3) and posed_joints (frames, 27, 3), then
13
- * runs its own FK. poseArraysToNpzMembers turns one CozyClay frame into
14
- * that exact 1-frame member set, so a hand-blocked pose can be materialized
15
- * as a standalone npz without ever hardcoding a rest skeleton: proportions
16
- * come from the base clip (deriveBoneOffsets), the 8 joints CozyClay does not
17
- * author stay IDENTITY, and an optional int32 rotation mask prevents those
18
- * identity placeholders from becoming rotation constraints.
19
- */
20
- import { writeFileSync } from "node:fs";
21
-
22
- const ZIP_LOCAL_SIG = 0x04034b50; // PK\x03\x04
23
- const ZIP_CENTRAL_SIG = 0x02014b50; // PK\x01\x02
24
- const ZIP_EOCD_SIG = 0x06054b50; // PK\x05\x06
25
-
26
- // --- CRC-32 (IEEE 802.3, reflected, polynomial 0xEDB88320) ----------------
27
-
28
- const CRC_TABLE = (() => {
29
- const table = new Uint32Array(256);
30
- for (let n = 0; n < 256; n += 1) {
31
- let c = n;
32
- for (let k = 0; k < 8; k += 1) c = c & 1 ? 0xedb88320 ^ (c >>> 1) : c >>> 1;
33
- table[n] = c >>> 0;
34
- }
35
- return table;
36
- })();
37
-
38
- function crc32(buf) {
39
- let c = 0xffffffff;
40
- for (let i = 0; i < buf.length; i += 1) c = CRC_TABLE[(c ^ buf[i]) & 0xff] ^ (c >>> 8);
41
- return (c ^ 0xffffffff) >>> 0;
42
- }
43
-
44
- // --- .npy v1.0 -------------------------------------------------------------
45
-
46
- /**
47
- * The ASCII dict header, matching numpy's own text byte for byte:
48
- * {'descr': '<f4', 'fortran_order': False, 'shape': (1, 27, 3, 3), }
49
- * Shape tuples follow Python repr: `()` for 0-d, `(n,)` for a single
50
- * element, `(a, b, c)` otherwise.
51
- */
52
- function npyHeader(shape, descr = "<f4") {
53
- const tuple =
54
- shape.length === 0 ? "()" : `(${shape.join(", ")}${shape.length === 1 ? "," : ""})`;
55
- const dict = `{'descr': '${descr}', 'fortran_order': False, 'shape': ${tuple}, }`;
56
- // Pad so magic(6) + version(2) + len(2) + header is a multiple of 64,
57
- // i.e. the header-with-newline is 54 mod 64. numpy's loader only reads
58
- // the length field and ast.literal_eval's the dict, so it accepts either
59
- // alignment; this repo's convention is that the whole prefix aligns.
60
- const pad = (53 - (dict.length % 64) + 64) % 64;
61
- return dict + " ".repeat(pad) + "\n";
62
- }
63
-
64
- function buildNpy(data, shape) {
65
- const descr = data instanceof Float32Array ? "<f4" : data instanceof Int32Array ? "<i4" : null;
66
- if (!descr) throw new Error(`buildNpy: unsupported typed array ${data?.constructor?.name ?? typeof data}`);
67
- const header = npyHeader(shape, descr);
68
- const prefix = Buffer.alloc(10);
69
- prefix.writeUInt8(0x93, 0);
70
- prefix.write("NUMPY", 1, "ascii");
71
- prefix.writeUInt8(1, 6); // version 1.0
72
- prefix.writeUInt8(0, 7);
73
- prefix.writeUInt16LE(header.length, 8);
74
- // Float32Array is little-endian on every platform this repo runs on;
75
- // the view (not a copy) is safe: writeNpz builds the payload and the
76
- // archive in the same synchronous call.
77
- const payload = Buffer.from(data.buffer, data.byteOffset, data.byteLength);
78
- return Buffer.concat([prefix, Buffer.from(header, "ascii"), payload]);
79
- }
80
-
81
- // --- ZIP (STORED) -----------------------------------------------------------
82
-
83
- /**
84
- * Build the archive: local headers + payloads, central directory, EOCD.
85
- * Every size is known up front, so the whole file is one Buffer.
86
- */
87
- function buildZip(entries) {
88
- const chunks = [];
89
- const central = [];
90
- let offset = 0;
91
- for (const { name, payload } of entries) {
92
- const nameBuf = Buffer.from(name, "ascii");
93
- const crc = crc32(payload);
94
- const local = Buffer.alloc(30);
95
- local.writeUInt32LE(ZIP_LOCAL_SIG, 0);
96
- local.writeUInt16LE(20, 4); // version needed to extract
97
- local.writeUInt16LE(0, 6); // general purpose flags
98
- local.writeUInt16LE(0, 8); // method: STORED
99
- local.writeUInt16LE(0, 10); // last mod time
100
- local.writeUInt16LE(0x21, 12); // last mod date (1980-01-01)
101
- local.writeUInt32LE(crc, 14);
102
- local.writeUInt32LE(payload.length, 18); // compressed size
103
- local.writeUInt32LE(payload.length, 22); // uncompressed size
104
- local.writeUInt16LE(nameBuf.length, 26);
105
- local.writeUInt16LE(0, 28); // extra field length
106
- chunks.push(local, nameBuf, payload);
107
- central.push({ name: nameBuf, crc, size: payload.length, offset });
108
- offset += 30 + nameBuf.length + payload.length;
109
- }
110
- const centralDirStart = offset;
111
- const centralChunks = [];
112
- let centralDirSize = 0;
113
- for (const entry of central) {
114
- const c = Buffer.alloc(46);
115
- c.writeUInt32LE(ZIP_CENTRAL_SIG, 0);
116
- c.writeUInt16LE(20, 4); // version made by
117
- c.writeUInt16LE(20, 6); // version needed to extract
118
- c.writeUInt16LE(0, 8); // general purpose flags
119
- c.writeUInt16LE(0, 10); // method: STORED
120
- c.writeUInt16LE(0, 12); // last mod time
121
- c.writeUInt16LE(0x21, 14); // last mod date
122
- c.writeUInt32LE(entry.crc, 16);
123
- c.writeUInt32LE(entry.size, 20); // compressed size
124
- c.writeUInt32LE(entry.size, 24); // uncompressed size
125
- c.writeUInt16LE(entry.name.length, 28);
126
- c.writeUInt16LE(0, 30); // extra field length
127
- c.writeUInt16LE(0, 32); // file comment length
128
- c.writeUInt16LE(0, 34); // disk number start
129
- c.writeUInt16LE(0, 36); // internal attributes
130
- c.writeUInt32LE(0, 38); // external attributes
131
- c.writeUInt32LE(entry.offset, 42); // local header offset
132
- centralChunks.push(c, entry.name);
133
- centralDirSize += 46 + entry.name.length;
134
- }
135
- const eocd = Buffer.alloc(22);
136
- eocd.writeUInt32LE(ZIP_EOCD_SIG, 0);
137
- eocd.writeUInt16LE(0, 4); // disk number
138
- eocd.writeUInt16LE(0, 6); // disk with central directory
139
- eocd.writeUInt16LE(entries.length, 8); // entries on this disk
140
- eocd.writeUInt16LE(entries.length, 10); // total entries
141
- eocd.writeUInt32LE(centralDirSize, 12);
142
- eocd.writeUInt32LE(centralDirStart, 16);
143
- eocd.writeUInt16LE(0, 20); // comment length
144
- return Buffer.concat([...chunks, ...centralChunks, eocd]);
145
- }
146
-
147
- // --- public API -------------------------------------------------------------
148
-
149
- /**
150
- * Write a numpy .npz archive: one STORED zip entry `<key>.npy` per member.
151
- * Each member is { data: Float32Array, shape: number[] } in C order.
152
- * Throws on an empty member set, a member whose shape product does not
153
- * match its data length, a non-finite value, or a member name that would
154
- * not make a flat zip entry.
155
- */
156
- export function writeNpz(path, arrays) {
157
- const names = Object.keys(arrays);
158
- if (names.length === 0) {
159
- throw new Error("writeNpz: refusing to write an npz with no members");
160
- }
161
- const entries = names.map((name) => {
162
- if (!/^[A-Za-z0-9][A-Za-z0-9_.-]*$/.test(name)) {
163
- throw new Error(`writeNpz: invalid member name ${JSON.stringify(name)}`);
164
- }
165
- const member = arrays[name];
166
- if (
167
- !member ||
168
- (!(member.data instanceof Float32Array) && !(member.data instanceof Int32Array)) ||
169
- !Array.isArray(member.shape)
170
- ) {
171
- throw new Error(
172
- `writeNpz: member ${JSON.stringify(name)} must be { data: Float32Array|Int32Array, shape: number[] }`
173
- );
174
- }
175
- const { data, shape } = member;
176
- const size = shape.reduce((n, d) => n * d, 1);
177
- if (size !== data.length) {
178
- throw new Error(
179
- `writeNpz: member ${JSON.stringify(name)} shape ${JSON.stringify(shape)} ` +
180
- `has ${size} elements but data has ${data.length}`
181
- );
182
- }
183
- for (let i = 0; i < data.length; i += 1) {
184
- if (!Number.isFinite(data[i])) {
185
- throw new Error(
186
- `writeNpz: member ${JSON.stringify(name)}[${i}] is not finite: ${data[i]}`
187
- );
188
- }
189
- }
190
- return { name: `${name}.npy`, payload: buildNpy(data, shape) };
191
- });
192
- writeFileSync(path, buildZip(entries));
193
- }
194
-
195
- /**
196
- * Turn one CozyClay frame of plain nested arrays into the exact 1-frame
197
- * members load_poses expects: local_rot_mats [1, 27, 3, 3] and posed_joints
198
- * [1, 27, 3], both float32 C order. Inputs are the ardy.frame.v1 fixture
199
- * shapes: local_rot_mats [27][3][3] and posed_joints [27][3]. The leading 1
200
- * is the frames axis, so the generator's `[frame]` / `[frame, root_idx]`
201
- * indexing works unchanged.
202
- */
203
- export function poseArraysToNpzMembers({
204
- local_rot_mats,
205
- posed_joints,
206
- rotation_constraint_indices,
207
- }) {
208
- const members = {
209
- local_rot_mats: {
210
- data: flattenToF32(local_rot_mats, [27, 3, 3], "local_rot_mats"),
211
- shape: [1, 27, 3, 3],
212
- },
213
- posed_joints: {
214
- data: flattenToF32(posed_joints, [27, 3], "posed_joints"),
215
- shape: [1, 27, 3],
216
- },
217
- };
218
- if (rotation_constraint_indices !== undefined) {
219
- if (
220
- !Array.isArray(rotation_constraint_indices) ||
221
- rotation_constraint_indices.some(
222
- (index) => !Number.isInteger(index) || index < 0 || index >= 27
223
- )
224
- ) {
225
- throw new Error(
226
- "poseArraysToNpzMembers: rotation_constraint_indices must contain joint indices in 0..26"
227
- );
228
- }
229
- members.rotation_constraint_indices = {
230
- data: Int32Array.from(rotation_constraint_indices),
231
- shape: [rotation_constraint_indices.length],
232
- };
233
- }
234
- return members;
235
- }
236
-
237
- /**
238
- * Depth-first flatten of a nested number array against an expected shape.
239
- * Throws on a structural mismatch or a non-finite value so a bad pose can
240
- * never silently serialize.
241
- */
242
- function flattenToF32(value, dims, name) {
243
- const out = [];
244
- const walk = (node, depth, path) => {
245
- if (depth === dims.length) {
246
- if (typeof node !== "number") {
247
- throw new Error(
248
- `poseArraysToNpzMembers: ${name}${path} is not a number: ${node}`
249
- );
250
- }
251
- if (!Number.isFinite(node)) {
252
- throw new Error(
253
- `poseArraysToNpzMembers: ${name}${path} is not finite: ${node}`
254
- );
255
- }
256
- out.push(node);
257
- return;
258
- }
259
- if (!Array.isArray(node) || node.length !== dims[depth]) {
260
- throw new Error(
261
- `poseArraysToNpzMembers: ${name}${path} must be an array of length ` +
262
- `${dims[depth]} (expected shape ${JSON.stringify(dims)})`
263
- );
264
- }
265
- for (let i = 0; i < node.length; i += 1) walk(node[i], depth + 1, `${path}[${i}]`);
266
- };
267
- walk(value, 0, "");
268
- return Float32Array.from(out);
269
- }
270
-
271
-
272
- /**
273
- * Convert decoded ARDY motion arrays into writer members.
274
- *
275
- * `personScale` (the filmed performer's leg length as a fraction of the
276
- * canonical body, from bvhToCskel27Motion) is written as a `person_scale`
277
- * scalar when the source estimated one. It has to live IN the archive: the
278
- * conversion already divided the root translation by it, so the trajectory is
279
- * only metrically right once the character is scaled by the same number. A
280
- * take whose stature travelled separately from its frames replays a filmed
281
- * stride at canonical size and skates the feet.
282
- *
283
- * The member is APPENDED and only when present: an ARDY-generated take has no
284
- * filmed performer, so its archive stays byte-identical to before, and a
285
- * reader that ignores the extra member (numpy, dump-npz.py, the generators)
286
- * sees the original four unchanged and in the original order.
287
- */
288
- export function motionArraysToNpzMembers({ frames, fps, rotMats, rootPos, posedJoints, personScale, boneScale }) {
289
- if (!Number.isInteger(frames) || frames < 1) throw new Error("motionArraysToNpzMembers: frames must be positive");
290
- if (!Number.isInteger(fps) || fps < 1) throw new Error("motionArraysToNpzMembers: fps must be positive");
291
- const requireLength = (array, length, label) => {
292
- if (!(array instanceof Float32Array) || array.length !== length) {
293
- throw new Error(`motionArraysToNpzMembers: ${label} must be Float32Array(${length})`);
294
- }
295
- };
296
- requireLength(rotMats, frames * 27 * 9, "rotMats");
297
- requireLength(rootPos, frames * 3, "rootPos");
298
- requireLength(posedJoints, frames * 27 * 3, "posedJoints");
299
- const members = {
300
- local_rot_mats: { data: rotMats, shape: [frames, 27, 3, 3] },
301
- root_positions: { data: rootPos, shape: [frames, 3] },
302
- posed_joints: { data: posedJoints, shape: [frames, 27, 3] },
303
- fps: { data: Int32Array.of(fps), shape: [] },
304
- };
305
- if (personScale !== undefined && personScale !== null) {
306
- if (!Number.isFinite(personScale) || personScale <= 0) {
307
- throw new Error(
308
- `motionArraysToNpzMembers: personScale must be a positive finite number, got ${personScale}`
309
- );
310
- }
311
- // 1 is the canonical body — the reader's own default — so recording it
312
- // would add a member that says nothing. Keeping it out means a
313
- // generated take that passes through a decode/edit/rewrite round trip
314
- // (bridge.mjs's motion edit reads person_scale back as 1) still writes
315
- // the same four members it always did.
316
- // float32 scalar, same 0-d shape convention as fps.
317
- if (personScale !== 1) members.person_scale = { data: Float32Array.of(personScale), shape: [] };
318
- }
319
- // `boneScale` (mocap): the performer's bone lengths as a factor per cskel27
320
- // joint over the canonical body. posedJoints were grown with these, so the
321
- // take is only geometrically consistent when playback stretches the bones
322
- // it drives by rotation alone by the same factors — it has to ride in the
323
- // archive. All-ones is the canonical body, the reader's default, and is
324
- // left out for the same reason person_scale 1 is.
325
- if (boneScale !== undefined && boneScale !== null) {
326
- if (!(boneScale instanceof Float32Array) || boneScale.length !== 27 || !boneScale.every((v) => Number.isFinite(v) && v > 0)) {
327
- throw new Error("motionArraysToNpzMembers: boneScale must be a Float32Array(27) of positive finite factors");
328
- }
329
- if (boneScale.some((v) => v !== 1)) members.bone_scale = { data: boneScale, shape: [27] };
330
- }
331
- return members;
332
- }
333
-
334
- /** Concatenate contiguous, already world-aligned generated blocks. */
335
- export function stitchMotionSegments(segments) {
336
- if (!Array.isArray(segments) || segments.length === 0) {
337
- throw new Error("stitchMotionSegments: at least one segment is required");
338
- }
339
- const fps = segments[0].fps;
340
- if (!segments.every((segment) => segment.fps === fps)) {
341
- throw new Error("stitchMotionSegments: every segment must use the same fps");
342
- }
343
- // One performer per stitch: the segments are consecutive blocks of the same
344
- // body, so two different statures here means two different people were
345
- // concatenated into one trajectory and the travel of at least one is wrong.
346
- const scales = new Set(segments.map((segment) => segment.personScale).filter((value) => Number.isFinite(value)));
347
- if (scales.size > 1) {
348
- throw new Error("stitchMotionSegments: segments disagree on personScale");
349
- }
350
- const frames = segments.reduce((sum, segment) => sum + segment.frames, 0);
351
- const concat = (key, stride) => {
352
- const out = new Float32Array(frames * stride);
353
- let offset = 0;
354
- for (const segment of segments) {
355
- const values = segment[key];
356
- if (!(values instanceof Float32Array) || values.length !== segment.frames * stride) {
357
- throw new Error(`stitchMotionSegments: invalid ${key} length for ${segment.frames}-frame segment`);
358
- }
359
- out.set(values, offset);
360
- offset += values.length;
361
- }
362
- return out;
363
- };
364
- const stitched = {
365
- frames,
366
- fps,
367
- rotMats: concat("rotMats", 27 * 9),
368
- rootPos: concat("rootPos", 3),
369
- posedJoints: concat("posedJoints", 27 * 3),
370
- };
371
- if (scales.size === 1) stitched.personScale = [...scales][0];
372
- if (segments[0].boneScale) stitched.boneScale = segments[0].boneScale;
373
- return stitched;
374
- }
375
-
376
- /** Return a copy of a motion with one equal-fps replacement written at startFrame. */
377
- export function replaceMotionSegment(base, replacement, startFrame) {
378
- if (!Number.isInteger(startFrame) || startFrame < 0) {
379
- throw new Error("replaceMotionSegment: startFrame must be a non-negative integer");
380
- }
381
- if (!base || !replacement || base.fps !== replacement.fps) {
382
- throw new Error("replaceMotionSegment: motions must use the same fps");
383
- }
384
- if (startFrame + replacement.frames > base.frames) {
385
- throw new Error("replaceMotionSegment: replacement extends past the base motion");
386
- }
387
- const copyAndReplace = (key, stride) => {
388
- const source = base[key];
389
- const patch = replacement[key];
390
- if (
391
- !(source instanceof Float32Array) ||
392
- source.length !== base.frames * stride ||
393
- !(patch instanceof Float32Array) ||
394
- patch.length !== replacement.frames * stride
395
- ) {
396
- throw new Error(`replaceMotionSegment: invalid ${key} array`);
397
- }
398
- const out = new Float32Array(source);
399
- out.set(patch, startFrame * stride);
400
- return out;
401
- };
402
- const edited = {
403
- frames: base.frames,
404
- fps: base.fps,
405
- rotMats: copyAndReplace("rotMats", 27 * 9),
406
- rootPos: copyAndReplace("rootPos", 3),
407
- posedJoints: copyAndReplace("posedJoints", 27 * 3),
408
- };
409
- // The base clip is still the same body after an edited span is written into
410
- // it, and its root travel is still expressed against that stature.
411
- if (Number.isFinite(base.personScale)) edited.personScale = base.personScale;
412
- if (base.boneScale) edited.boneScale = base.boneScale;
413
- return edited;
414
- }
@@ -1,106 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * CozyClayPoseV1 -> a one-frame ARDY pose npz.
4
- *
5
- * `cclay_constrained_generate.load_poses` reads exactly two arrays out of a pose
6
- * source, `local_rot_mats` and `posed_joints`, and its docstring is blunt about
7
- * why the file has to exist at all: "A FullBodyConstraintSet needs all 27
8
- * joints, so the pose has to come from an existing npz -- 27 rotations are not
9
- * authorable by hand." CozyClay authors 19 of them. This fills the remaining 8
10
- * with identity (ARDY rest) and says so out loud rather than pretending the
11
- * whole skeleton was blocked.
12
- *
13
- * Proportions and root come from the base clip's own reference frame, never from
14
- * a hardcoded rest skeleton -- same reasoning as
15
- * `motion_constraints.derive_bone_offsets`, which derives offsets from the clip
16
- * so it stays correct if ARDY ever reproportions cskel27.
17
- */
18
- import { readFileSync, mkdirSync } from "node:fs";
19
- import { dirname, basename, resolve } from "node:path";
20
- import { poseToCskel27 } from "../../src/ardy/to-cskel27.js";
21
- import { poseArraysToNpzMembers, writeNpz } from "./npz.mjs";
22
-
23
- const HERE = new URL(".", import.meta.url).pathname;
24
- const REPO = resolve(HERE, "../..");
25
-
26
- function usage(message) {
27
- if (message) process.stderr.write(`pose-to-npz: ${message}\n\n`);
28
- process.stderr.write(
29
- `usage: pose-to-npz.mjs <pose.json> [--reference <frame.json>] [--rest <rest.json>] [--out <npz>]\n\n` +
30
- ` <pose.json> a CozyClayPoseV1 export from the app\n` +
31
- ` --reference optional ardy.frame.v1 skeleton-proportion reference; placement always\n` +
32
- ` comes from pose.root or the floor-aligned canonical neutral skeleton.\n` +
33
- ` --rest cskel27 rest rotations (default public/ardy/cskel27-rest.json)\n` +
34
- ` --out destination npz (default tools/ardy/out/<pose-basename>.npz)\n`,
35
- );
36
- process.exit(2);
37
- }
38
-
39
- const argv = process.argv.slice(2);
40
- if (argv.length === 0 || argv.includes("-h") || argv.includes("--help")) usage();
41
-
42
- let posePath = "";
43
- let referencePath = "";
44
- let restPath = resolve(REPO, "public/ardy/cskel27-rest.json");
45
- let outPath = "";
46
- for (let i = 0; i < argv.length; i += 1) {
47
- const a = argv[i];
48
- const next = () => {
49
- if (i + 1 >= argv.length) usage(`${a} needs a value`);
50
- i += 1;
51
- return argv[i];
52
- };
53
- if (a === "--reference") referencePath = next();
54
- else if (a === "--rest") restPath = next();
55
- else if (a === "--out") outPath = next();
56
- else if (a.startsWith("-")) usage(`unknown option ${a}`);
57
- else if (!posePath) posePath = a;
58
- else usage(`unexpected argument ${a}`);
59
- }
60
- if (!posePath) usage("missing <pose.json>");
61
-
62
- const readJson = (p, label) => {
63
- try {
64
- return JSON.parse(readFileSync(p, "utf8"));
65
- } catch (error) {
66
- process.stderr.write(`pose-to-npz: cannot read ${label} at ${p}: ${error.message}\n`);
67
- process.exit(1);
68
- }
69
- };
70
-
71
- const pose = readJson(posePath, "pose");
72
- const rest = readJson(restPath, "rest table");
73
- const reference = referencePath ? readJson(referencePath, "reference frame") : undefined;
74
-
75
- if (reference && reference.schema !== "ardy.frame.v1") {
76
- process.stderr.write(`pose-to-npz: --reference must be schema ardy.frame.v1, got ${reference.schema}\n`);
77
- process.exit(1);
78
- }
79
-
80
- if (!outPath) {
81
- outPath = resolve(REPO, "tools/ardy/out", `${basename(posePath).replace(/\.json$/i, "")}.npz`);
82
- }
83
-
84
- let result;
85
- try {
86
- result = poseToCskel27({ pose, rest, reference });
87
- } catch (error) {
88
- process.stderr.write(`pose-to-npz: ${error.message}\n`);
89
- process.exit(1);
90
- }
91
-
92
- mkdirSync(dirname(outPath), { recursive: true });
93
- writeNpz(outPath, poseArraysToNpzMembers(result));
94
-
95
- const root = result.posed_joints[0];
96
- process.stdout.write(
97
- `pose-to-npz: wrote ${outPath}\n` +
98
- `pose-to-npz: rig ${pose.source?.rig ?? "unknown"}, slate ${JSON.stringify(pose.slate ?? "")}\n` +
99
- (reference
100
- ? `pose-to-npz: skeleton proportions from ${reference.source_npz} frame ${reference.frame}\n`
101
- : `pose-to-npz: skeleton proportions from floor-aligned canonical neutral\n`) +
102
- `pose-to-npz: root [${root.map((v) => v.toFixed(4)).join(", ")}]\n` +
103
- `pose-to-npz: ${result.filled_identity.length} joint(s) left at ARDY rest: ` +
104
- `${result.filled_identity.map((f) => f.joint).join(", ")}\n` +
105
- `pose-to-npz: --pose-from pins full-body shape, root XYZ, and heading at its destination frame\n`,
106
- );
@@ -1,5 +0,0 @@
1
- // Shared ARDY prompt and duration limits. Keep this module dependency-free so
2
- // browser tooling, the bridge, and the Workers API can import the same values.
3
- export const PROMPT_MAX_CHARS = 500;
4
- export const DURATION_MIN = 0.15;
5
- export const DURATION_MAX = 1200;
@@ -1,73 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
-
4
- HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
5
- HOST="${CCLAY_ARDY_HOST:-}"
6
- REMOTE="${CCLAY_ARDY_REPO:-\$HOME/ardy}"
7
- VENV_PY="${CCLAY_ARDY_VENV:-~/ardy/.venv-cuda/bin/python}"
8
- SCRIPT="$HERE/cclay_motion_edit.py"
9
- SOURCE=""
10
- MANIFEST=""
11
- PROMPT=""
12
- OUTPUT=""
13
- SEED=""
14
- CONTEXT_BEFORE=40
15
- CONTEXT_AFTER=20
16
- POSES=()
17
-
18
- SSH_OPTS=(-o BatchMode=yes -o ConnectTimeout=10 -o ServerAliveInterval=30 -o ServerAliveCountMax=240)
19
- SCP_OPTS=(-o BatchMode=yes -o ConnectTimeout=10)
20
-
21
- usage() {
22
- echo "usage: run-edit-on-box.sh --source motion.npz --manifest edits.json --prompt TEXT --output out.npz [--seed N] [--context-before N] [--context-after N]" >&2
23
- exit 2
24
- }
25
-
26
- while [[ $# -gt 0 ]]; do
27
- case "$1" in
28
- --source) SOURCE="${2:-}"; shift 2 ;;
29
- --manifest) MANIFEST="${2:-}"; shift 2 ;;
30
- --prompt) PROMPT="${2:-}"; shift 2 ;;
31
- --output) OUTPUT="${2:-}"; shift 2 ;;
32
- --seed) SEED="${2:-}"; shift 2 ;;
33
- --context-before) CONTEXT_BEFORE="${2:-}"; shift 2 ;;
34
- --context-after) CONTEXT_AFTER="${2:-}"; shift 2 ;;
35
- --pose) POSES+=("${2:-}"); shift 2 ;;
36
- *) usage ;;
37
- esac
38
- done
39
-
40
- [[ -n "$HOST" ]] || {
41
- echo "run-edit-on-box: CCLAY_ARDY_HOST is required (for example: user@ardy-host)" >&2
42
- exit 2
43
- }
44
-
45
- [[ -f "$SOURCE" && -f "$MANIFEST" && -f "$SCRIPT" && -n "$PROMPT" && -n "$OUTPUT" ]] || usage
46
- [[ ${#POSES[@]} -gt 0 ]] || usage
47
- [[ "$CONTEXT_BEFORE" =~ ^[0-9]+$ && "$CONTEXT_AFTER" =~ ^[0-9]+$ ]] || usage
48
- [[ -z "$SEED" || "$SEED" =~ ^[0-9]+$ ]] || usage
49
-
50
- mkdir -p "$(dirname "$OUTPUT")"
51
- REMOTE_TMP="$(ssh "${SSH_OPTS[@]}" "$HOST" "mktemp -d" </dev/null)"
52
- [[ "$REMOTE_TMP" == /* ]] || { echo "run-edit-on-box: unsafe remote temp path" >&2; exit 1; }
53
- trap 'ssh "${SSH_OPTS[@]}" "$HOST" "rm -rf ${REMOTE_TMP}" </dev/null >/dev/null 2>&1 || true' EXIT
54
-
55
- scp -q "${SCP_OPTS[@]}" "$SOURCE" "$HOST:${REMOTE_TMP}/source.npz"
56
- scp -q "${SCP_OPTS[@]}" "$MANIFEST" "$HOST:${REMOTE_TMP}/manifest.json"
57
- scp -q "${SCP_OPTS[@]}" "$SCRIPT" "$HOST:${REMOTE_TMP}/edit.py"
58
- for ((i = 0; i < ${#POSES[@]}; i += 1)); do
59
- [[ -f "${POSES[$i]}" ]] || { echo "run-edit-on-box: missing pose ${POSES[$i]}" >&2; exit 1; }
60
- scp -q "${SCP_OPTS[@]}" "${POSES[$i]}" "$HOST:${REMOTE_TMP}/pose-${i}.npz"
61
- done
62
-
63
- CMD="cd ${REMOTE} && ${VENV_PY} ${REMOTE_TMP}/edit.py"
64
- CMD+=" --source ${REMOTE_TMP}/source.npz --manifest ${REMOTE_TMP}/manifest.json"
65
- CMD+=" --prompt $(printf '%q' "$PROMPT") --output ${REMOTE_TMP}/out.npz"
66
- CMD+=" --context-before ${CONTEXT_BEFORE} --context-after ${CONTEXT_AFTER}"
67
- [[ -z "$SEED" ]] || CMD+=" --seed ${SEED}"
68
-
69
- echo "run-edit-on-box: editing with ARDY history and sparse constraints ..."
70
- ssh "${SSH_OPTS[@]}" "$HOST" "$CMD" </dev/null
71
- scp -q "${SCP_OPTS[@]}" "$HOST:${REMOTE_TMP}/out.npz" "$OUTPUT"
72
- [[ -s "$OUTPUT" ]] || { echo "run-edit-on-box: empty output" >&2; exit 1; }
73
- echo "run-edit-on-box: done - ${OUTPUT} ($(wc -c < "$OUTPUT" | tr -d ' ') bytes)"