cozyclay 2.1.0 → 3.0.0
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.
- package/CHANGELOG.md +65 -0
- package/README.md +12 -30
- package/bin/agent/agent-routes.mjs +40 -113
- package/bin/agent/agent-runner.mjs +9 -10
- package/bin/agent/cliproxy-provider.mjs +135 -0
- package/bin/agent/credential-store.mjs +30 -7
- package/bin/agent/pi-tools.mjs +4 -1
- package/bin/agent/provider-keys.mjs +32 -0
- package/bin/agent/provider-login.mjs +110 -0
- package/bin/agent/provider-routes.mjs +99 -0
- package/bin/agent/providers.mjs +19 -97
- package/bin/agent/script-tool.mjs +17 -4
- package/bin/agent/studio-motion-reference.mjs +23 -0
- package/bin/agent/studio-prompt.mjs +1 -1
- package/bin/agent/studio-rebase-text.mjs +32 -0
- package/bin/agent/studio-rebase.mjs +26 -39
- package/bin/agent/studio-tools.mjs +9 -28
- package/bin/agent/tool-arguments.mjs +49 -0
- package/bin/agent/turn-frames.mjs +66 -0
- package/bin/codex-auth.mjs +9 -2
- package/bin/cozyclay.mjs +10 -116
- package/bin/live/cli.mjs +22 -6
- package/bin/mcp-runtime.mjs +2 -12
- package/bin/package-signature.mjs +0 -4
- package/dist/app/index.html +7 -6
- package/dist/assets/EXRLoader-CvVIvGVE.js +1 -0
- package/dist/assets/analytics-C9sUnndd.js +1 -0
- package/dist/assets/app-CCh--1Hc.js +5087 -0
- package/dist/assets/app-f-fkV5uP.css +1 -0
- package/dist/assets/compile-worker-CkxiD6lH.js +5 -0
- package/dist/assets/fflate.module-KbGj5-H6.js +5 -0
- package/dist/assets/{first-shot-handoff-BlT33CGf.js → first-shot-handoff-CC4xe4HM.js} +1 -1
- package/dist/assets/{landing-BSesrCpL.js → landing-DjHD8u7k.js} +1 -1
- package/dist/assets/scene-asset-sync-Hx_FzdOH.js +20 -0
- package/dist/assets/scene-asset-sync-_S8NQl5B.css +1 -0
- package/dist/assets/workflow-C4yKH1p4.js +179 -0
- package/dist/cozyclay-package.json +1 -1
- package/dist/index.html +3 -3
- package/dist/llms.txt +14 -0
- package/dist/sw.js +3 -6
- package/dist/workflow/index.html +5 -4
- package/mcp/LIVE-PROTOCOL.md +7 -47
- package/mcp/README.md +16 -26
- package/mcp/live-hub.mjs +6 -10
- package/mcp/package.json +1 -3
- package/mcp/tool-handlers.mjs +4 -168
- package/package.json +3 -22
- package/src/App.jsx +174 -2639
- package/src/agent-progress.js +79 -0
- package/src/agent-turn-mark.js +30 -0
- package/src/analytics.js +1 -19
- package/src/app-context.js +5 -0
- package/src/app-stage.jsx +2 -34
- package/src/asset-pane.jsx +6 -5
- package/src/camera-block.js +21 -0
- package/src/camera-direction.js +120 -0
- package/src/character-kind.js +3 -9
- package/src/command-bus.js +8 -6
- package/src/commands/cast.js +5 -34
- package/src/commands/elements/character.js +1 -1
- package/src/commands/elements/motion.js +1 -6
- package/src/commands/elements/object.js +6 -2
- package/src/commands/elements/shot.js +4 -1
- package/src/commands/elements.js +38 -14
- package/src/commands/index.js +3 -1
- package/src/commands/kits.js +37 -0
- package/src/commands/motion-timing.js +57 -0
- package/src/commands/motion.js +9 -152
- package/src/commands/motion3-compile.js +65 -0
- package/src/commands/motion3.js +207 -0
- package/src/commands/objects.js +6 -4
- package/src/commands/shot.js +49 -11
- package/src/commands/stage.js +14 -1
- package/src/commands/view.js +4 -1
- package/src/document-mirrors.js +42 -0
- package/src/document-store.js +4 -0
- package/src/domains/cast.js +19 -194
- package/src/domains/motion/motion-range-pin-rules.js +1 -1
- package/src/domains/motion/take-source.js +51 -0
- package/src/domains/motion.js +60 -1838
- package/src/domains/scenes.js +12 -55
- package/src/domains/shots.js +2 -2
- package/src/domains/stage.js +4 -2
- package/src/draft-ghost.js +46 -0
- package/src/draft-ghost.jsx +129 -0
- package/src/dualview.jsx +4 -3
- package/src/effects/EffectsLayer.jsx +112 -0
- package/src/effects/effect-meshes.js +232 -0
- package/src/effects/effect-record.js +103 -0
- package/src/effects/emitter.js +59 -0
- package/src/effects/simulate.js +261 -0
- package/src/effects/state.js +59 -0
- package/src/execution-telemetry.js +2 -3
- package/src/first-success-guide.jsx +5 -5
- package/src/ghost-set.js +257 -0
- package/src/held-object-edit.jsx +113 -0
- package/src/held-object-pose.js +175 -0
- package/src/hierarchy-model.js +1 -1
- package/src/hierarchy-panel.jsx +1 -1
- package/src/imported-mesh.jsx +103 -0
- package/src/kits/held.js +84 -0
- package/src/kits/index.js +70 -0
- package/src/kits/smoking.js +57 -0
- package/src/light-blockers.js +93 -0
- package/src/motion/beat-board-model.js +84 -0
- package/src/motion/beat-board.css +124 -0
- package/src/motion/beat-board.jsx +59 -0
- package/src/motion/center-of-mass.js +66 -0
- package/src/motion/fix-collisions.js +850 -0
- package/src/motion/physics-review.js +118 -0
- package/src/{ardy → motion}/physics-support.js +1 -76
- package/src/motion/rig-snapshot.js +22 -0
- package/src/motion/take-segments.jsx +140 -0
- package/src/{ardy → motion}/timeline-coordinates.js +0 -21
- package/src/{ardy → motion}/timeline.css +1 -2
- package/src/{ardy → motion}/timeline.jsx +48 -419
- package/src/motion/waypoints.js +76 -0
- package/src/motion3/beats.js +83 -0
- package/src/motion3/body.js +158 -0
- package/src/motion3/bones.js +47 -0
- package/src/motion3/carried.js +47 -0
- package/src/motion3/compile-job.js +75 -0
- package/src/motion3/compile-worker.js +10 -0
- package/src/motion3/compiler/anchors.js +105 -0
- package/src/motion3/compiler/arm-orient.js +128 -0
- package/src/motion3/compiler/channels.js +125 -0
- package/src/motion3/compiler/compile.js +205 -0
- package/src/motion3/compiler/gait-rhythm.js +97 -0
- package/src/motion3/compiler/grip.js +171 -0
- package/src/motion3/compiler/head-steady.js +48 -0
- package/src/motion3/compiler/hold.js +134 -0
- package/src/motion3/compiler/idle.js +113 -0
- package/src/motion3/compiler/limbs.js +170 -0
- package/src/motion3/compiler/math.js +72 -0
- package/src/motion3/compiler/pose.js +162 -0
- package/src/motion3/compiler/quat.js +49 -0
- package/src/motion3/compiler/skeleton.js +74 -0
- package/src/motion3/compiler/validate-common.js +32 -0
- package/src/motion3/compiler/validate-goals.js +118 -0
- package/src/motion3/compiler/validate-objects.js +143 -0
- package/src/motion3/compiler/validate-parts.js +116 -0
- package/src/motion3/compiler/validate.js +122 -0
- package/src/motion3/compiler/vocab.js +73 -0
- package/src/motion3/compiler/walk-pelvis.js +275 -0
- package/src/motion3/compiler/walk.js +207 -0
- package/src/motion3/compiler/wrist-clamp.js +32 -0
- package/src/motion3/delta.js +47 -0
- package/src/motion3/describe.js +174 -0
- package/src/motion3/docs.js +27 -0
- package/src/motion3/edit-carry.js +21 -0
- package/src/motion3/fix/ease.js +16 -0
- package/src/motion3/fix/ground.js +37 -0
- package/src/motion3/fix/index.js +52 -0
- package/src/motion3/fix/push.js +71 -0
- package/src/motion3/fix/reach.js +46 -0
- package/src/motion3/fix/retime.js +79 -0
- package/src/motion3/fix/self.js +211 -0
- package/src/motion3/fix/slide.js +70 -0
- package/src/motion3/fix/turn.js +51 -0
- package/src/motion3/follow.js +39 -0
- package/src/motion3/free-motion.js +173 -0
- package/src/motion3/grip-choice.js +130 -0
- package/src/motion3/hold-plan.js +157 -0
- package/src/motion3/json-patch.js +77 -0
- package/src/motion3/key-aim.js +105 -0
- package/src/motion3/key-edit.js +82 -0
- package/src/motion3/lenient.js +127 -0
- package/src/motion3/object-keys.js +236 -0
- package/src/motion3/object-pose.js +182 -0
- package/src/motion3/object-tracks.js +12 -0
- package/src/motion3/pipeline.js +102 -0
- package/src/motion3/playback.js +51 -0
- package/src/motion3/probes.js +91 -0
- package/src/motion3/qa/body-checks.js +34 -0
- package/src/motion3/qa/check-names.js +14 -0
- package/src/motion3/qa/checks.js +121 -0
- package/src/motion3/qa/contact-checks.js +51 -0
- package/src/motion3/qa/explain.js +80 -0
- package/src/motion3/qa/fmt.js +5 -0
- package/src/motion3/qa/foot-checks.js +72 -0
- package/src/motion3/qa/geometry.js +77 -0
- package/src/motion3/qa/goals.js +191 -0
- package/src/motion3/qa/ground.js +60 -0
- package/src/motion3/qa/hints-contact.js +179 -0
- package/src/motion3/qa/hints-goal.js +160 -0
- package/src/motion3/qa/hints-knee.js +24 -0
- package/src/motion3/qa/hints-motion.js +209 -0
- package/src/motion3/qa/hints-object.js +91 -0
- package/src/motion3/qa/index.js +42 -0
- package/src/motion3/qa/key-checks.js +82 -0
- package/src/motion3/qa/near.js +96 -0
- package/src/motion3/qa/object-checks.js +135 -0
- package/src/motion3/qa/patch.js +161 -0
- package/src/motion3/qa/severity.js +38 -0
- package/src/motion3/qa/spec-checks.js +65 -0
- package/src/motion3/qa/style.js +218 -0
- package/src/motion3/qa/wrist-checks.js +69 -0
- package/src/motion3/qa/wrist-obs.js +60 -0
- package/src/motion3/refs.js +120 -0
- package/src/motion3/repair-tune.js +121 -0
- package/src/motion3/repair.js +83 -0
- package/src/motion3/report.js +67 -0
- package/src/motion3/rigs/index.js +14 -0
- package/src/motion3/rigs/x-bot-tpose-body.json +1 -0
- package/src/motion3/rigs/x-bot-tpose.json +1 -0
- package/src/motion3/rigs/y-bot-tpose-body.json +1 -0
- package/src/motion3/rigs/y-bot-tpose.json +1 -0
- package/src/motion3/scene.js +60 -0
- package/src/motion3/schema/brief.js +89 -0
- package/src/motion3/schema/fields.js +44 -0
- package/src/motion3/schema/spec-examples.js +46 -0
- package/src/motion3/schema/topics.js +111 -0
- package/src/motion3/schema/types.js +147 -0
- package/src/motion3/search.js +117 -0
- package/src/motion3/second-hand.js +112 -0
- package/src/motion3/skills/basic.js +82 -0
- package/src/motion3/skills/book.js +76 -0
- package/src/motion3/skills/car.js +145 -0
- package/src/motion3/skills/frames-auto.js +29 -0
- package/src/motion3/skills/index.js +83 -0
- package/src/motion3/skills/info.js +65 -0
- package/src/motion3/skills/smoke-kit.js +109 -0
- package/src/motion3/skills/smoke.js +160 -0
- package/src/motion3/spec-store.js +59 -0
- package/src/motion3/take-edit.js +155 -0
- package/src/motion3/take.js +63 -0
- package/src/motion3/timeline.js +127 -0
- package/src/motion3/views.js +121 -0
- package/src/motion3/walk-plan.js +119 -0
- package/src/object-catalog.jsx +7 -1
- package/src/object-colors.js +98 -0
- package/src/object-gizmo-parts.js +115 -0
- package/src/object-gizmo.jsx +37 -122
- package/src/object-glow.js +139 -0
- package/src/object-hidden.js +33 -0
- package/src/object-look.js +196 -0
- package/src/object-size.js +10 -0
- package/src/object-travel.js +71 -6
- package/src/panels/CameraPanel.jsx +7 -7
- package/src/panels/HdrEnvironmentControls.jsx +59 -0
- package/src/panels/LightPanel.jsx +25 -4
- package/src/panels/ObjectLookPanel.jsx +88 -0
- package/src/panels/PoseImagePanel.jsx +1 -1
- package/src/panels/PosePanel.jsx +2 -17
- package/src/panels/RigControlPanel.jsx +5 -53
- package/src/panels/SubjectBox.jsx +4 -1
- package/src/panels/details.css +14 -0
- package/src/posestudio.jsx +4 -27
- package/src/project-browser.jsx +3 -4
- package/src/project-resources.js +18 -31
- package/src/project.js +13 -104
- package/src/props.jsx +25 -280
- package/src/rail-dot-drag.js +23 -0
- package/src/render-passes.js +10 -0
- package/src/resource-status.jsx +1 -0
- package/src/result-modal.jsx +4 -19
- package/src/room.jsx +20 -12
- package/src/scene-assets.js +8 -6
- package/src/scene-light-place.js +72 -0
- package/src/scene-lights.jsx +148 -0
- package/src/scene-objects.js +31 -139
- package/src/scenes.js +15 -105
- package/src/semantic-edit.js +2 -5
- package/src/set-pieces.jsx +183 -0
- package/src/settings-menu.jsx +3 -11
- package/src/shell/BottomDock.jsx +11 -53
- package/src/shell/CompositionGuideButton.jsx +20 -0
- package/src/shell/DetailsSlot.jsx +16 -200
- package/src/shell/GhostsMenuGroup.jsx +74 -0
- package/src/shell/LibrarySlot.jsx +1 -3
- package/src/shell/MenuBar.jsx +3 -3
- package/src/shell/PreferencesDialog.jsx +15 -264
- package/src/shell/PreferencesSlot.jsx +2 -8
- package/src/shell/ShotPreviewHeader.jsx +17 -0
- package/src/shell/TopBar.jsx +5 -83
- package/src/shell/ViewportToolbar.jsx +23 -93
- package/src/shell/agent-glass.css +19 -6
- package/src/shell/details-selection.js +42 -0
- package/src/shell/ghosts-menu.css +22 -0
- package/src/shell/glass-regions.css +29 -3
- package/src/shell/preferences.css +6 -1
- package/src/shell/viewport.css +12 -0
- package/src/shot-authoring.js +4 -7
- package/src/soft-shadows.js +37 -0
- package/src/stage-attach-frames.js +12 -12
- package/src/stage-canvas-rigs.jsx +3 -3
- package/src/stage-capture.jsx +42 -8
- package/src/stage-characters.jsx +22 -216
- package/src/stage-editor-gizmos.jsx +6 -6
- package/src/stage-environment.js +93 -0
- package/src/stage-hdr-builtins.js +107 -0
- package/src/stage-hdr-image.js +116 -0
- package/src/stage-hdr-library.js +70 -0
- package/src/stage-hdr-map.js +94 -0
- package/src/stage-hdr.js +130 -0
- package/src/stage-lighting.js +149 -0
- package/src/stage-occlusion.js +210 -0
- package/src/stage-sky.jsx +159 -0
- package/src/stage-startup-defaults.js +5 -9
- package/src/studio-actions.js +12 -14
- package/src/studio-agent-commands.js +46 -16
- package/src/studio-agent-motion.js +9 -9
- package/src/studio-agent-protocol.js +46 -73
- package/src/studio-app-binding.js +29 -45
- package/src/studio-asset-list.js +17 -0
- package/src/studio-contact-sheet.js +37 -5
- package/src/studio-elements.js +27 -7
- package/src/studio-entity-bounds.js +18 -0
- package/src/studio-error-codes.js +8 -0
- package/src/studio-export-framing.js +152 -0
- package/src/studio-lighting-check.js +103 -0
- package/src/studio-motion-visual.js +150 -0
- package/src/studio-schema-errors.js +80 -0
- package/src/studio-support-gap.js +74 -0
- package/src/styles.css +1 -19
- package/src/timeline-defaults.js +5 -0
- package/src/timeline-extent.js +8 -20
- package/src/tutorial-walk.js +17 -0
- package/src/ui-scrub.js +1 -1
- package/src/use-shot-camera-tracks.js +12 -0
- package/src/view-ghosts.js +97 -0
- package/src/view-ghosts.jsx +49 -0
- package/src/workflow/AgentPanel.jsx +47 -166
- package/src/workflow/AgentProgressCard.jsx +107 -0
- package/src/workflow/AgentReplyText.jsx +37 -0
- package/src/workflow/AgentTurnSteps.jsx +84 -0
- package/src/workflow/LoginPanel.jsx +140 -0
- package/src/workflow/WorkflowBuilder.jsx +7 -23
- package/src/workflow/agent-client.js +54 -51
- package/src/workflow/agent-panel.css +71 -1
- package/src/workflow/agent-progress-card.css +167 -0
- package/src/workflow/agent-progress-view.js +47 -0
- package/src/workflow/agent-turn-steps.css +113 -0
- package/src/workflow/agent-turn.js +191 -0
- package/src/workflow/login-client.js +34 -0
- package/src/workflow/motion-input.js +18 -31
- package/src/workflow/node-schema.js +1 -1
- package/src/workflow/reply-markdown.js +69 -0
- package/src/workflow/scene-asset-sync.js +8 -8
- package/tools/agent-session-stats.mjs +61 -0
- package/tools/dev-full.mjs +5 -56
- package/tools/eslint-baseline.json +12 -13
- package/tools/headless-studio.mjs +85 -0
- package/tools/knip-baseline.json +0 -179
- package/tools/loc-baseline.json +33 -83
- package/tools/motion3/extract-body.mjs +103 -0
- package/tools/motion3/extract-rig.mjs +85 -0
- package/tools/process-supervisor.mjs +0 -88
- package/tools/run-tests.mjs +9 -124
- package/bin/agent/motion-runtime.mjs +0 -76
- package/dist/ardy/cskel27-rest.json +0 -557
- package/dist/assets/analytics-B41FmPYI.js +0 -1
- package/dist/assets/app-Do-Og5Pu.css +0 -1
- package/dist/assets/app-DwP-tl2x.js +0 -4920
- package/dist/assets/config-Bx7pYsD9.js +0 -1
- package/dist/assets/config-DeoFTYzb.css +0 -1
- package/dist/assets/demo-Dt0qZfS7.js +0 -1
- package/dist/assets/scene-asset-sync-BCWDJB1d.js +0 -19
- package/dist/assets/scene-asset-sync-DjJ_cJ2R.css +0 -1
- package/dist/assets/ticket-jqMhqL88.js +0 -1
- package/dist/assets/workflow-Br-K7Srs.js +0 -179
- package/dist/demo/walk-then-stop.npz +0 -0
- package/mcp/ardy-prompts.mjs +0 -218
- package/src/ardy/auto-fix-panel.css +0 -108
- package/src/ardy/auto-physics.js +0 -1194
- package/src/ardy/client.js +0 -153
- package/src/ardy/convert.js +0 -313
- package/src/ardy/cskel27-neutral.js +0 -39
- package/src/ardy/cskel27.js +0 -77
- package/src/ardy/export.js +0 -165
- package/src/ardy/fix-collisions.js +0 -2257
- package/src/ardy/foot-lock.js +0 -230
- package/src/ardy/motion-calibration.js +0 -118
- package/src/ardy/motion-edit.js +0 -213
- package/src/ardy/motion-url.js +0 -55
- package/src/ardy/mp4-duration.js +0 -102
- package/src/ardy/npz.js +0 -595
- package/src/ardy/physics-panel.css +0 -21
- package/src/ardy/physics-panel.jsx +0 -89
- package/src/ardy/physics-refine.js +0 -111
- package/src/ardy/physics-review.js +0 -567
- package/src/ardy/physics-temporal.js +0 -54
- package/src/ardy/platform-fit-panel.css +0 -64
- package/src/ardy/platform-fit-panel.jsx +0 -41
- package/src/ardy/platform-fit.js +0 -326
- package/src/ardy/playback.js +0 -711
- package/src/ardy/pose-pin.js +0 -97
- package/src/ardy/prompt-clips.js +0 -30
- package/src/ardy/retime.js +0 -211
- package/src/ardy/root-drop.js +0 -369
- package/src/ardy/timeline-resize.js +0 -13
- package/src/ardy/to-cskel27.js +0 -225
- package/src/ardy/trim.js +0 -33
- package/src/ardy/waypoints.js +0 -369
- package/src/ardy-bridge-contract.js +0 -281
- package/src/domains/motion/motion-video-capture.js +0 -664
- package/src/i2v-motion-client.js +0 -77
- package/src/i2v-motion-studio.jsx +0 -180
- package/src/line-edit.js +0 -1348
- package/src/motion/generation.js +0 -105
- package/src/motion-readiness-ui.jsx +0 -67
- package/src/motion-readiness.js +0 -40
- package/src/motion-resources.js +0 -177
- package/src/motion-store.js +0 -65
- package/src/motion-trail.js +0 -601
- package/src/multimodel-ingest.js +0 -394
- package/src/panels/PromptBlocksPanel.jsx +0 -444
- package/src/panels/VideoCapturePanel.jsx +0 -181
- package/src/pose-extract/browser.js +0 -42
- package/src/pose-extract/detector.js +0 -100
- package/src/pose-extract/fit.js +0 -227
- package/src/pose-extract/image-frame.js +0 -51
- package/src/pose-extract/index.js +0 -58
- package/src/pose-extract/keyframes.js +0 -74
- package/src/pose-extract/landmarks.js +0 -162
- package/src/pose-extract/mirror.js +0 -153
- package/src/pose-extract/take.js +0 -131
- package/src/pose-extract/video-frames.js +0 -91
- package/src/take-recipe.js +0 -165
- package/src/trail-key-conflicts.js +0 -39
- package/src/trail-pick.js +0 -59
- package/src/use-i2v-capture-modal.js +0 -15
- package/tools/ardy/BRIDGE.md +0 -37
- package/tools/ardy/GVHMR-NPZ.md +0 -68
- package/tools/ardy/README.md +0 -124
- package/tools/ardy/__pycache__/cclay_gvhmr_worker.cpython-313.pyc +0 -0
- package/tools/ardy/artifacts.mjs +0 -34
- package/tools/ardy/bridge.mjs +0 -1732
- package/tools/ardy/bvh-cskel27.mjs +0 -1265
- package/tools/ardy/cclay_constrained_generate.py +0 -561
- package/tools/ardy/cclay_gvhmr_worker.py +0 -264
- package/tools/ardy/cclay_motion_edit.py +0 -510
- package/tools/ardy/cclay_sequence_generate.py +0 -705
- package/tools/ardy/cclay_worker.py +0 -304
- package/tools/ardy/dump-npz.py +0 -205
- package/tools/ardy/extract-rest.mjs +0 -299
- package/tools/ardy/extract.mjs +0 -507
- package/tools/ardy/footage.mjs +0 -467
- package/tools/ardy/gvhmr-floor.mjs +0 -102
- package/tools/ardy/gvhmr-to-cskel27.mjs +0 -21
- package/tools/ardy/gvhmr_fastpath.py +0 -168
- package/tools/ardy/gvhmr_trajectory.py +0 -240
- package/tools/ardy/merge-text-encoder.py +0 -160
- package/tools/ardy/mocap-metrics.mjs +0 -200
- package/tools/ardy/mocap-quality-gate.mjs +0 -110
- package/tools/ardy/motion-stabilize.mjs +0 -348
- package/tools/ardy/npz.mjs +0 -414
- package/tools/ardy/pose-to-npz.mjs +0 -106
- package/tools/ardy/prompt-limits.mjs +0 -5
- package/tools/ardy/run-edit-on-box.sh +0 -73
- package/tools/ardy/run-local.mjs +0 -233
- package/tools/ardy/run-on-box.sh +0 -593
- package/tools/ardy/run-sequence-on-box.sh +0 -177
- package/tools/ardy/runners/gvhmr-worker.mjs +0 -206
- package/tools/ardy/runners/index.mjs +0 -18
- package/tools/ardy/runners/local.mjs +0 -455
- package/tools/ardy/runners/proc.mjs +0 -125
- package/tools/ardy/runners/remote.mjs +0 -252
- package/tools/ardy/setup-local.mjs +0 -189
- package/tools/ardy/setup-text-encoder-on-box.sh +0 -93
- package/tools/ardy/setup-text-encoder.py +0 -306
- package/tools/ardy/smpl-cskel27.mjs +0 -178
- package/tools/ardy/visual-qa.mjs +0 -196
- package/tools/ardy/vq-car.mjs +0 -52
- package/tools/bench/EXP3.md +0 -61
- package/tools/bench/cclay_bench_extract_incam.py +0 -125
- package/tools/bench/cclay_bench_extract_obs.py +0 -204
- package/tools/bench/cclay_bench_runner.py +0 -42
- package/tools/bench/cube-contact.mjs +0 -162
- package/tools/bench/exp3.mjs +0 -152
- package/tools/bench/extract-bench-lib.mjs +0 -216
- package/tools/bench/extract-bench.mjs +0 -302
- package/tools/bench/fal-generate.mjs +0 -88
- package/tools/bench/fit/README.md +0 -189
- package/tools/bench/fit/camera.mjs +0 -59
- package/tools/bench/fit/contact.mjs +0 -419
- package/tools/bench/fit/footlock.mjs +0 -234
- package/tools/bench/fit/motion.mjs +0 -85
- package/tools/bench/fit/pin.mjs +0 -27
- package/tools/bench/fit/remote.mjs +0 -105
- package/tools/bench/fit-bench.mjs +0 -126
- package/tools/bench/fit-sanity.mjs +0 -45
- package/tools/bench/metrics.mjs +0 -313
- package/tools/bench/obs/depth.mjs +0 -258
- package/tools/bench/obs/extrinsics.mjs +0 -175
- package/tools/bench/obs/fit_mannequin_betas.py +0 -340
- package/tools/bench/obs/ground.mjs +0 -294
- package/tools/bench/obs/heading.mjs +0 -151
- package/tools/bench/obs/ladder.mjs +0 -555
- package/tools/bench/obs/mannequin-betas.json +0 -124
- package/tools/bench/obs/remote.mjs +0 -83
- package/tools/bench/obs/rest_joints.py +0 -52
- package/tools/bench/obs/ybot-targets.mjs +0 -49
- package/tools/bench/obs-bench.mjs +0 -520
- package/tools/bench/score.mjs +0 -343
- package/tools/bench/summarize.mjs +0 -86
- package/tools/demo-worker/README.md +0 -137
- package/tools/demo-worker/api-client.mjs +0 -233
- package/tools/demo-worker/generate.mjs +0 -301
- package/tools/demo-worker/index.mjs +0 -466
- package/tools/demo-worker/sign-core.mjs +0 -112
- package/tools/demo-worker/sign.mjs +0 -161
- package/tools/gt-render/browser.mjs +0 -159
- package/tools/gt-render/camera-math.mjs +0 -276
- package/tools/gt-render/page.mjs +0 -267
- package/tools/gt-render/render.mjs +0 -514
- package/tools/gt-render/scene-box.mjs +0 -31
- package/tools/gt-render/take-transform.mjs +0 -87
- package/tools/kimodo/compare-seam.mjs +0 -108
- package/tools/kimodo/constraints.mjs +0 -244
- package/tools/kimodo/edit.mjs +0 -259
- package/tools/kimodo/effector-constraints.mjs +0 -200
- package/tools/kimodo/generate.mjs +0 -646
- package/tools/kimodo/local-output.mjs +0 -265
- package/tools/kimodo/measure-pose.mjs +0 -65
- package/tools/kimodo/measure-preserve.mjs +0 -899
- package/tools/kimodo/measure-waypoints.mjs +0 -55
- package/tools/kimodo/mlx-generate.py +0 -111
- package/tools/kimodo/pose-constraints.mjs +0 -248
- package/tools/kimodo/preserve-mask.mjs +0 -543
- package/tools/kimodo/read-npz.mjs +0 -189
- package/tools/kimodo/run-edit-on-box.mjs +0 -155
- package/tools/kimodo/run-sequence-on-box.mjs +0 -178
- package/tools/kimodo/runner.mjs +0 -284
- package/tools/kimodo/seam-batch.mjs +0 -77
- package/tools/kimodo/setup-local.mjs +0 -30
- package/tools/kimodo/setup-on-box.sh +0 -339
- package/tools/kimodo/soma77-to-cskel27.mjs +0 -305
- package/tools/morphgs/assets/gen_truth.py +0 -39
- package/tools/morphgs/assets/mesh_ori_rig.txt +0 -27
- package/tools/morphgs/assets/playback-check.mjs +0 -30
- package/tools/morphgs/demo-gate.sh +0 -26
- package/tools/morphgs/fbx2morphgs.mjs +0 -68
- package/tools/morphgs/morphgs-to-cskel27.mjs +0 -105
- package/tools/morphgs/patches/preprocess_src-none-mode.patch +0 -76
- package/tools/morphgs/setup-on-cluster.sh +0 -126
- package/tools/projflow/driver.py +0 -1069
- package/tools/projflow/generate.mjs +0 -805
- package/tools/projflow/hml22-to-cskel27.mjs +0 -735
- package/tools/projflow/line-edit-job.mjs +0 -547
- package/tools/projflow/replay.mjs +0 -452
- package/tools/projflow/runner.mjs +0 -269
- package/tools/projflow/service.mjs +0 -742
- package/tools/track/DESIGN.md +0 -513
- package/tools/track/backfill-provenance.mjs +0 -116
- package/tools/track/budget.mjs +0 -8
- package/tools/track/check-rig.mjs +0 -209
- package/tools/track/diagnostics.schema.json +0 -60
- package/tools/track/export-rig.mjs +0 -256
- package/tools/track/fallback.mjs +0 -7
- package/tools/track/fk-parity-fixture.mjs +0 -161
- package/tools/track/gate.mjs +0 -349
- package/tools/track/masks.mjs +0 -318
- package/tools/track/metrics.mjs +0 -201
- package/tools/track/publish-obs.mjs +0 -108
- package/tools/track/py/check_env.py +0 -61
- package/tools/track/py/eval_lr.py +0 -229
- package/tools/track/py/lr_viterbi.py +0 -294
- package/tools/track/py/masks.py +0 -405
- package/tools/track/py/objective.py +0 -382
- package/tools/track/py/rig.py +0 -508
- package/tools/track/py/scene.py +0 -326
- package/tools/track/py/test_joint_indices.py +0 -123
- package/tools/track/py/test_lr_viterbi.py +0 -195
- package/tools/track/py/test_masks.py +0 -229
- package/tools/track/py/test_rig.py +0 -288
- package/tools/track/py/test_scene.py +0 -354
- package/tools/track/py/test_track.py +0 -328
- package/tools/track/py/track.py +0 -411
- package/tools/track/remote.mjs +0 -140
- package/tools/track/rig-dump.mjs +0 -227
- package/tools/track/run-box-tests.mjs +0 -14
- package/tools/track/run-box.mjs +0 -168
- package/tools/track/setup-box.sh +0 -59
- package/tools/track/study-2d.mjs +0 -728
- /package/src/{ardy → motion}/collision-blockers.js +0 -0
- /package/src/{ardy → motion}/ground.js +0 -0
- /package/src/{ardy → motion}/ik-drag.js +0 -0
- /package/src/{ardy → motion}/ik-key-json.js +0 -0
- /package/src/{ardy → motion}/ik.js +0 -0
- /package/src/{ardy → motion}/physics-surface.js +0 -0
- /package/src/{ardy → motion}/playback-clock.js +0 -0
- /package/src/{ardy → motion}/range-pin.js +0 -0
package/src/take-recipe.js
DELETED
|
@@ -1,165 +0,0 @@
|
|
|
1
|
-
/* ======================== take recipes (contract C9) ========================
|
|
2
|
-
* A take is a RECIPE, not a result: seed + prompt blocks + the line edits that
|
|
3
|
-
* were pulled on top of it. Determinism on the box (re-chain diff = 0 bitwise)
|
|
4
|
-
* is what makes that true — given the recipe the same take can be rebuilt at
|
|
5
|
-
* any time, which is the whole reason regenerate/extend no longer destroys the
|
|
6
|
-
* refinements the artist spent their afternoon on.
|
|
7
|
-
*
|
|
8
|
-
* recipe = {
|
|
9
|
-
* seed: 1234, // ALWAYS a concrete integer, never null
|
|
10
|
-
* blocks: [{ prompt, duration }],// ordered; a single-prompt take = length 1
|
|
11
|
-
* lineEdits: [ <C6 payload WITHOUT sourceMotion> ], // application order
|
|
12
|
-
* }
|
|
13
|
-
*
|
|
14
|
-
* THE SEED RULE, and why it lives here. A recipe with no seed cannot replay,
|
|
15
|
-
* so no request that CREATES a take may omit one. When the artist leaves the
|
|
16
|
-
* seed field empty the app rolls one, SENDS it, and records it — rolling it
|
|
17
|
-
* here rather than letting the box pick silently is the difference between a
|
|
18
|
-
* take you can rebuild and a take you can only remember.
|
|
19
|
-
*
|
|
20
|
-
* This file is deliberately React-free and side-effect-free: every function is
|
|
21
|
-
* a pure value transform, so test/verify-take-recipe.mjs can pin the whole
|
|
22
|
-
* contract in plain node without a DOM. Recipes come out DEEP FROZEN — the
|
|
23
|
-
* one invariant that keeps "the recipe travels with the motionUrl" honest is
|
|
24
|
-
* that no later edit can reach back and rewrite a version that is already on
|
|
25
|
-
* the strip. */
|
|
26
|
-
|
|
27
|
-
/** C10's cap on a replay array. The bridge refuses more, and the app must not
|
|
28
|
-
* discover that by being refused. */
|
|
29
|
-
export const RECIPE_MAX_LINE_EDITS = 16;
|
|
30
|
-
|
|
31
|
-
/** C12's cap on the version strip. The bridge's motion allowlist holds 64, so
|
|
32
|
-
* 20 checkpoints are all still loadable when the oldest is dropped. */
|
|
33
|
-
export const TAKE_VERSIONS_MAX = 20;
|
|
34
|
-
|
|
35
|
-
/** Every key a C6 lineEdit payload may carry into a C10 replay entry, minus
|
|
36
|
-
* sourceMotion (replay rebinds that to the freshly generated take). `seed` is
|
|
37
|
-
* C10's optional per-entry seed and is the only field the app ADDS: it is the
|
|
38
|
-
* seed that was actually sent with the edit, so a replay reproduces the edit
|
|
39
|
-
* bit for bit instead of re-rolling it.
|
|
40
|
-
*
|
|
41
|
-
* `pins3d` is the second gesture's payload and rides the SAME list: a replayed
|
|
42
|
-
* pin needs no camera and no polyline, and because the whitelist is a
|
|
43
|
-
* whitelist, omitting it would have made a pinned edit vanish from its own
|
|
44
|
-
* take's recipe silently — the take would regenerate without the refinement and
|
|
45
|
-
* nothing would say why. */
|
|
46
|
-
const REPLAY_KEYS = ["track", "frameRange", "points2d", "pins3d", "camera", "prompt", "seed"];
|
|
47
|
-
|
|
48
|
-
function deepFreeze(value) {
|
|
49
|
-
if (value === null || typeof value !== "object" || Object.isFrozen(value)) return value;
|
|
50
|
-
Object.freeze(value);
|
|
51
|
-
for (const entry of Array.isArray(value) ? value : Object.values(value)) deepFreeze(entry);
|
|
52
|
-
return value;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/** Roll a seed the way the seed rule demands. `random` is injectable so tests
|
|
56
|
-
* can pin the arithmetic instead of sampling it. */
|
|
57
|
-
export function rollSeed(max, random = Math.random) {
|
|
58
|
-
if (!Number.isInteger(max) || max <= 0) throw new Error(`rollSeed needs a positive integer max, got ${max}`);
|
|
59
|
-
return Math.floor(random() * max);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/** The seed a request will actually carry. `typed` is the artist's raw field
|
|
63
|
-
* value (empty string = "you pick"); a typed seed is NEVER overwritten, and an
|
|
64
|
-
* empty one is rolled here so the same integer can be both sent and recorded.
|
|
65
|
-
* Returns an integer, always — this is the function every take-creating call
|
|
66
|
-
* site goes through. */
|
|
67
|
-
export function resolveSeed(typed, max, random = Math.random) {
|
|
68
|
-
const text = typeof typed === "string" ? typed.trim() : typed;
|
|
69
|
-
if (text === "" || text === null || text === undefined) return rollSeed(max, random);
|
|
70
|
-
const value = Number(text);
|
|
71
|
-
if (!Number.isInteger(value) || value < 0 || value > max) {
|
|
72
|
-
throw new Error(`seed must be an integer in 0..${max}, got ${typed}`);
|
|
73
|
-
}
|
|
74
|
-
return value;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
/** The prompt blocks a request actually asked for. A segments body (chained
|
|
78
|
-
* blocks) contributes one block per segment on the WIRE clock it was built
|
|
79
|
-
* against; anything else is the single prompt+duration pair the bridge was
|
|
80
|
-
* handed. Durations come out in seconds either way, because that is the one
|
|
81
|
-
* frame-rate-free number in the request. */
|
|
82
|
-
export function blocksFromRequest(body, fps) {
|
|
83
|
-
if (!body || typeof body !== "object") throw new Error("blocksFromRequest needs a request body");
|
|
84
|
-
if (!(fps > 0)) throw new Error(`blocksFromRequest needs a positive fps, got ${fps}`);
|
|
85
|
-
const basePrompt = typeof body.prompt === "string" ? body.prompt : "";
|
|
86
|
-
if (Array.isArray(body.segments) && body.segments.length > 0) {
|
|
87
|
-
return body.segments.map((segment) => ({
|
|
88
|
-
prompt: (typeof segment.prompt === "string" && segment.prompt) || basePrompt,
|
|
89
|
-
duration: Math.max(0, (segment.endFrame - segment.startFrame) / fps),
|
|
90
|
-
}));
|
|
91
|
-
}
|
|
92
|
-
return [{ prompt: basePrompt, duration: Number(body.duration) || 0 }];
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/** A recipe for a take that was just generated. `lineEdits` defaults to empty —
|
|
96
|
-
* a plain generate has none — but a regeneration that CARRIED `replay` starts
|
|
97
|
-
* life with exactly the edits the box re-applied, because those edits are in
|
|
98
|
-
* the resulting npz and dropping them here would make the NEXT regeneration
|
|
99
|
-
* lose them. */
|
|
100
|
-
export function freshRecipe({ seed, blocks, lineEdits = [] }) {
|
|
101
|
-
if (!Number.isInteger(seed)) throw new Error(`a recipe needs a concrete integer seed, got ${seed}`);
|
|
102
|
-
if (!Array.isArray(blocks) || blocks.length === 0) throw new Error("a recipe needs at least one block");
|
|
103
|
-
return deepFreeze({
|
|
104
|
-
seed,
|
|
105
|
-
blocks: blocks.map((block) => ({ prompt: String(block.prompt ?? ""), duration: Number(block.duration) || 0 })),
|
|
106
|
-
lineEdits: lineEdits.map(stripSourceMotion),
|
|
107
|
-
});
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
/** A C6 payload reduced to what a C10 replay entry may carry: sourceMotion is
|
|
111
|
-
* dropped (replay rebinds it), unknown keys are dropped with it, and absent
|
|
112
|
-
* optional keys stay absent rather than becoming undefined on the wire. */
|
|
113
|
-
export function stripSourceMotion(payload) {
|
|
114
|
-
if (!payload || typeof payload !== "object") throw new Error("a line edit payload is required");
|
|
115
|
-
const entry = {};
|
|
116
|
-
for (const key of REPLAY_KEYS) {
|
|
117
|
-
if (payload[key] !== undefined) entry[key] = payload[key];
|
|
118
|
-
}
|
|
119
|
-
if (!entry.track) throw new Error("a line edit payload must name a track");
|
|
120
|
-
return deepFreeze(entry);
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
/** Push a successful line edit onto the take's recipe. Returns a NEW recipe;
|
|
124
|
-
* the input is never touched, which is what lets an old version keep the
|
|
125
|
-
* recipe it was saved with after the artist edits from it. */
|
|
126
|
-
export function withLineEdit(recipe, payload) {
|
|
127
|
-
if (!recipe) throw new Error("withLineEdit needs a recipe to extend");
|
|
128
|
-
return deepFreeze({
|
|
129
|
-
seed: recipe.seed,
|
|
130
|
-
blocks: recipe.blocks.map((block) => ({ ...block })),
|
|
131
|
-
lineEdits: [...recipe.lineEdits, stripSourceMotion(payload)],
|
|
132
|
-
});
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
/** The C10 `replay` array for this recipe, or [] when there is nothing to
|
|
136
|
-
* replay. TRUNCATION KEEPS THE PREFIX, not the tail: entry i was authored on
|
|
137
|
-
* top of entries 0..i-1, so the first N edits are the only slice that is
|
|
138
|
-
* self-consistent. Dropping the newest work is the honest failure here, and
|
|
139
|
-
* the caller surfaces it (replayTruncated) rather than silently shipping 16. */
|
|
140
|
-
export function replayPayload(recipe) {
|
|
141
|
-
if (!recipe || !Array.isArray(recipe.lineEdits) || recipe.lineEdits.length === 0) return [];
|
|
142
|
-
return recipe.lineEdits.slice(0, RECIPE_MAX_LINE_EDITS).map(stripSourceMotion);
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
/** True when this recipe carries more edits than one replay request can hold. */
|
|
146
|
-
export function replayTruncated(recipe) {
|
|
147
|
-
return (recipe?.lineEdits?.length ?? 0) > RECIPE_MAX_LINE_EDITS;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
/** Append a checkpoint to the version strip, oldest dropped past the cap.
|
|
151
|
-
* Re-pushing a motionUrl that is already on the strip is a no-op: loading an
|
|
152
|
-
* old version must not clone it onto the top, and a retried delivery must not
|
|
153
|
-
* either. */
|
|
154
|
-
export function pushTakeVersion(versions, entry, cap = TAKE_VERSIONS_MAX) {
|
|
155
|
-
const list = Array.isArray(versions) ? versions : [];
|
|
156
|
-
if (!entry?.motionUrl) throw new Error("a take version needs a motionUrl");
|
|
157
|
-
if (list.some((item) => item.motionUrl === entry.motionUrl)) return list;
|
|
158
|
-
const next = [...list, Object.freeze({
|
|
159
|
-
motionUrl: entry.motionUrl,
|
|
160
|
-
recipe: entry.recipe ?? null,
|
|
161
|
-
savedAt: Number.isFinite(entry.savedAt) ? entry.savedAt : Date.now(),
|
|
162
|
-
label: typeof entry.label === "string" ? entry.label : "",
|
|
163
|
-
})];
|
|
164
|
-
return next.length > cap ? next.slice(next.length - cap) : next;
|
|
165
|
-
}
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
const CHAIN_BY_EFFECTOR = Object.freeze({
|
|
2
|
-
LeftHand: "leftHand",
|
|
3
|
-
RightHand: "rightHand",
|
|
4
|
-
LeftFoot: "leftFoot",
|
|
5
|
-
RightFoot: "rightFoot",
|
|
6
|
-
});
|
|
7
|
-
const EFFECTOR_BY_CHAIN = Object.freeze({
|
|
8
|
-
leftHand: "LeftHand",
|
|
9
|
-
rightHand: "RightHand",
|
|
10
|
-
leftFoot: "LeftFoot",
|
|
11
|
-
rightFoot: "RightFoot",
|
|
12
|
-
});
|
|
13
|
-
|
|
14
|
-
function trackIds(track) {
|
|
15
|
-
const id = typeof track === "string" ? track : track?.id ?? track?.joint ?? track?.effector;
|
|
16
|
-
const chain = typeof track === "object" ? track?.chain : null;
|
|
17
|
-
return new Set([id, chain, CHAIN_BY_EFFECTOR[id], EFFECTOR_BY_CHAIN[id]].filter(Boolean));
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
function entryFor(entries, id) {
|
|
21
|
-
return typeof entries?.get === "function" ? entries.get(id) : entries?.[id];
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/** Return absolute IK-key frames that can override a trail edit. */
|
|
25
|
-
export function findAbsoluteIkKeyConflicts({ keys, track, startFrame, endFrame }) {
|
|
26
|
-
const ids = trackIds(track);
|
|
27
|
-
const frames = [];
|
|
28
|
-
for (const [frame, entries] of keys ?? []) {
|
|
29
|
-
if (frame < startFrame || frame >= endFrame) continue;
|
|
30
|
-
for (const id of ids) {
|
|
31
|
-
const key = entryFor(entries, id);
|
|
32
|
-
if (key && key.baseQ == null) {
|
|
33
|
-
frames.push(frame);
|
|
34
|
-
break;
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
return [...new Set(frames)].sort((a, b) => a - b);
|
|
39
|
-
}
|
package/src/trail-pick.js
DELETED
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
/** Pure picking for motion-trail pointer rays. */
|
|
2
|
-
|
|
3
|
-
const FRAME_PENALTY = 0.001;
|
|
4
|
-
const TIE_DISTANCE = 0.01;
|
|
5
|
-
const MIN_FRAME_WINDOW = 12;
|
|
6
|
-
|
|
7
|
-
/** Pick the trail track/frame intended by a ray near the current playhead. */
|
|
8
|
-
export function pickTrailPoint({
|
|
9
|
-
tracks,
|
|
10
|
-
playheadFrame,
|
|
11
|
-
falloffFrames,
|
|
12
|
-
rayOrigin,
|
|
13
|
-
rayDirection,
|
|
14
|
-
maxDistance,
|
|
15
|
-
}) {
|
|
16
|
-
if (!Array.isArray(tracks) || !rayOrigin || !rayDirection) return null;
|
|
17
|
-
const directionLength = Math.hypot(rayDirection.x, rayDirection.y, rayDirection.z);
|
|
18
|
-
if (!Number.isFinite(directionLength) || directionLength === 0) return null;
|
|
19
|
-
const dx = rayDirection.x / directionLength;
|
|
20
|
-
const dy = rayDirection.y / directionLength;
|
|
21
|
-
const dz = rayDirection.z / directionLength;
|
|
22
|
-
const center = Number.isFinite(playheadFrame) ? playheadFrame : 0;
|
|
23
|
-
const radius = Math.max(2 * (Number.isFinite(falloffFrames) ? falloffFrames : 0), MIN_FRAME_WINDOW);
|
|
24
|
-
const limit = Number.isFinite(maxDistance) ? maxDistance : 0;
|
|
25
|
-
let best = null;
|
|
26
|
-
|
|
27
|
-
for (const track of tracks) {
|
|
28
|
-
const points = track?.flat;
|
|
29
|
-
if (!track?.id || !points || points.length < 3) continue;
|
|
30
|
-
const firstFrame = Math.max(0, Math.ceil(center - radius));
|
|
31
|
-
const lastFrame = Math.min(Math.floor(points.length / 3) - 1, Math.floor(center + radius));
|
|
32
|
-
for (let frame = firstFrame; frame <= lastFrame; frame += 1) {
|
|
33
|
-
const offset = frame * 3;
|
|
34
|
-
const px = points[offset] - rayOrigin.x;
|
|
35
|
-
const py = points[offset + 1] - rayOrigin.y;
|
|
36
|
-
const pz = points[offset + 2] - rayOrigin.z;
|
|
37
|
-
const depth = px * dx + py * dy + pz * dz;
|
|
38
|
-
if (depth < 0) continue;
|
|
39
|
-
const ox = px - depth * dx;
|
|
40
|
-
const oy = py - depth * dy;
|
|
41
|
-
const oz = pz - depth * dz;
|
|
42
|
-
const distance = Math.hypot(ox, oy, oz);
|
|
43
|
-
if (distance > limit) continue;
|
|
44
|
-
const score = distance + Math.abs(frame - center) * FRAME_PENALTY;
|
|
45
|
-
const scoreDelta = score - (best?.score ?? Infinity);
|
|
46
|
-
if (
|
|
47
|
-
!best
|
|
48
|
-
|| scoreDelta < -TIE_DISTANCE
|
|
49
|
-
|| (Math.abs(scoreDelta) <= TIE_DISTANCE && (
|
|
50
|
-
depth < best.depth
|
|
51
|
-
|| (depth === best.depth && score < best.score)
|
|
52
|
-
))
|
|
53
|
-
) {
|
|
54
|
-
best = { track: track.id, grabFrame: frame, score, depth };
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
return best ? { track: best.track, grabFrame: best.grabFrame } : null;
|
|
59
|
-
}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { useState } from "react";
|
|
2
|
-
|
|
3
|
-
export function useI2vCaptureModal() {
|
|
4
|
-
const [i2vMotionEnabled, setI2vMotionEnabled] = useState(false);
|
|
5
|
-
const [i2vMotionMode, setI2vMotionMode] = useState("interpolate");
|
|
6
|
-
const [i2vMotionCameraUnlocked, setI2vMotionCameraUnlocked] = useState(false);
|
|
7
|
-
return {
|
|
8
|
-
i2vMotionEnabled,
|
|
9
|
-
setI2vMotionEnabled,
|
|
10
|
-
i2vMotionMode,
|
|
11
|
-
setI2vMotionMode,
|
|
12
|
-
i2vMotionCameraUnlocked,
|
|
13
|
-
setI2vMotionCameraUnlocked,
|
|
14
|
-
};
|
|
15
|
-
}
|
package/tools/ardy/BRIDGE.md
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
# Motion bridge (`tools/ardy/bridge.mjs`)
|
|
2
|
-
|
|
3
|
-
This is the loopback HTTP sidecar used by the Studio. It keeps the historical
|
|
4
|
-
`/ardy/*` route names so saved projects and motion URLs remain readable, but
|
|
5
|
-
the local Studio uses Kimodo for authored generation and GVHMR for video mocap
|
|
6
|
-
extraction. Legacy ARDY local/remote selection and its setup scripts are no
|
|
7
|
-
longer part of the bridge launch path.
|
|
8
|
-
|
|
9
|
-
Run it directly when debugging:
|
|
10
|
-
|
|
11
|
-
```bash
|
|
12
|
-
CCLAY_KIMODO_HOST=user@gpu-box node tools/ardy/bridge.mjs --port 5181
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
The sidecar owns health, base-listing, generation, footage download,
|
|
16
|
-
video-to-motion extraction, and allowlisted motion delivery. It binds to
|
|
17
|
-
`127.0.0.1`; the Vite dev server proxies only those API routes while serving
|
|
18
|
-
`public/ardy/` assets itself.
|
|
19
|
-
|
|
20
|
-
Kimodo settings:
|
|
21
|
-
|
|
22
|
-
| Variable | Default | Purpose |
|
|
23
|
-
| --- | --- | --- |
|
|
24
|
-
| `CCLAY_KIMODO_HOST` | required | SSH destination for the generation host |
|
|
25
|
-
| `CCLAY_KIMODO_REPO` | `$HOME/kimodo` | Kimodo checkout on that host |
|
|
26
|
-
| `CCLAY_KIMODO_MODEL` | `Kimodo-SOMA-RP-v1.1` | model identifier |
|
|
27
|
-
| `COZYCLAY_BRIDGE_PORT` | `5181` | loopback listen port |
|
|
28
|
-
|
|
29
|
-
Video mocap extraction requires `CCLAY_EXTRACT_BACKEND=gvhmr` (the default).
|
|
30
|
-
Any other backend or `CCLAY_EXTRACT_CMD` makes `/ardy/extract` return the named
|
|
31
|
-
`extract-backend-unsupported` error. Set `CCLAY_EXTRACT_HOST` (or
|
|
32
|
-
`CCLAY_ARDY_HOST`) to the GPU host that has the GVHMR checkout and virtualenv.
|
|
33
|
-
The GVHMR detector is fixed to palette segmentation for the coloured mannequin;
|
|
34
|
-
`CCLAY_EXTRACT_DETECTOR` cannot switch it to YOLO or auto.
|
|
35
|
-
|
|
36
|
-
The wire path stays `/ardy` for backward compatibility; this does not
|
|
37
|
-
re-enable the removed ARDY backend.
|
package/tools/ardy/GVHMR-NPZ.md
DELETED
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
# GVHMR extraction npz contract (box runner → CozyClay)
|
|
2
|
-
|
|
3
|
-
Written by `cclay_gvhmr_extract.py` (lives in the GVHMR checkout on the GPU
|
|
4
|
-
box, `~/cclay-ingest/GVHMR`), read by `tools/ardy/extract.mjs` when
|
|
5
|
-
`CCLAY_EXTRACT_BACKEND=gvhmr`.
|
|
6
|
-
|
|
7
|
-
All arrays float32 unless noted. World frame: metres, Y-up, gravity-aligned;
|
|
8
|
-
pelvis XZ of frame 0 at the origin, the clip's lowest body vertex at Y=0,
|
|
9
|
-
the body facing +Z at frame 0 (GVHMR's own "ayfz" normalisation).
|
|
10
|
-
|
|
11
|
-
| member | shape | meaning |
|
|
12
|
-
|---------------------|--------------|---------|
|
|
13
|
-
| `fps` | int32 scalar | source video rate |
|
|
14
|
-
| `positions` | [T, 22, 3] | SMPL body joints 0..21 in the world frame (legacy; the positions lift reads this) |
|
|
15
|
-
| `contact` | [T, 6] | GVHMR static-contact logits (order as the model emits) |
|
|
16
|
-
| `smpl_joints` | [T, 24, 3] | SMPL joints 0..23 (22 body + L/R hand) in the world frame, from the neutral SMPL J-regressor |
|
|
17
|
-
| `smpl_global_orient`| [T, 3] | axis-angle (rad) of the pelvis in the world frame |
|
|
18
|
-
| `smpl_body_pose` | [T, 23, 3] | axis-angle (rad) LOCAL rotation of SMPL joints 1..23 relative to their SMPL parent, standard SMPL kinematic tree |
|
|
19
|
-
| `smpl_transl` | [T, 3] | pelvis position in the world frame, i.e. equal to `smpl_joints[:, 0]` |
|
|
20
|
-
| `smpl_betas` | [10] | mean shape over the clip |
|
|
21
|
-
| `smpl_rest_joints` | [24, 3] | SMPL joints of the ZERO pose for `smpl_betas` (pelvis at origin): the source rest skeleton the rotations are relative to |
|
|
22
|
-
|
|
23
|
-
SMPL joint order (parents in brackets):
|
|
24
|
-
```
|
|
25
|
-
0 pelvis(-) 1 L_hip(0) 2 R_hip(0) 3 spine1(0)
|
|
26
|
-
4 L_knee(1) 5 R_knee(2) 6 spine2(3) 7 L_ankle(4)
|
|
27
|
-
8 R_ankle(5) 9 spine3(6) 10 L_foot(7) 11 R_foot(8)
|
|
28
|
-
12 neck(9) 13 L_collar(9) 14 R_collar(9) 15 head(12)
|
|
29
|
-
16 L_shoulder(13) 17 R_shoulder(14) 18 L_elbow(16) 19 R_elbow(17)
|
|
30
|
-
20 L_wrist(18) 21 R_wrist(19) 22 L_hand(20) 23 R_hand(21)
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
Rotation convention: SMPL global rotation of joint j is
|
|
34
|
-
`G_j = G_parent(j) · R(body_pose[j-1])`, with `G_0 = R(global_orient)`, and
|
|
35
|
-
joint positions are `P_j = P_parent + G_parent · (rest_j - rest_parent)`.
|
|
36
|
-
The world frame's normalisation (heading, floor) has ALREADY been folded into
|
|
37
|
-
`global_orient`/`transl`, so FK from these arrays reproduces `smpl_joints`
|
|
38
|
-
exactly (up to float32). The SMPL zero pose is NOT a T-pose: the upper arm
|
|
39
|
-
rests ~11° below horizontal and the collar points ~58° up. Retarget visible
|
|
40
|
-
limb rest-pose differences, but keep the target rig's pelvis/spine/neck/head
|
|
41
|
-
bind shape. SMPL's J-regressor joints form an internal torso S-curve and put
|
|
42
|
-
the head joint forward inside the skull; aiming the target bones at those
|
|
43
|
-
positions visibly hunches an otherwise upright character.
|
|
44
|
-
|
|
45
|
-
## Repeatable QA loop
|
|
46
|
-
|
|
47
|
-
Convert the raw runner archive, gate the retarget math, then capture the same
|
|
48
|
-
sampled frames from the front and side on both shipped bodies:
|
|
49
|
-
|
|
50
|
-
```bash
|
|
51
|
-
node tools/ardy/gvhmr-to-cskel27.mjs /path/to/gvhmr.npz public/demo/qa-gvhmr.npz
|
|
52
|
-
# For takes extracted from CozyClay-rendered clips, use --bone-scale 1.
|
|
53
|
-
node --test test/smpl-cskel27.test.mjs
|
|
54
|
-
|
|
55
|
-
# Keep `npm run dev:ui -- --host 127.0.0.1 --port 5180` running separately.
|
|
56
|
-
for model in x-bot-tpose y-bot-tpose; do
|
|
57
|
-
for view in front side; do
|
|
58
|
-
QA_URL='http://127.0.0.1:5180/app/?motion=/demo/qa-gvhmr.npz' \
|
|
59
|
-
MODEL="$model" VIEW="$view" FRAMES=0,60,120,180,240,300 \
|
|
60
|
-
OUT="/tmp/gvhmr-qa/$model" npm run qa:browser -- node test/qa-screenshot-browser.mjs
|
|
61
|
-
done
|
|
62
|
-
done
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
Review the captures against video frames at the same timestamps. Do not accept
|
|
66
|
-
a take unless the test passes, upright samples retain the character's bind
|
|
67
|
-
torso/neck silhouette, performed bends remain present, and neither body shows
|
|
68
|
-
detached joints. Remove the temporary `public/demo/qa-gvhmr.npz` afterwards.
|
package/tools/ardy/README.md
DELETED
|
@@ -1,124 +0,0 @@
|
|
|
1
|
-
# Motion bridge support files
|
|
2
|
-
|
|
3
|
-
The local Studio uses Kimodo for authored motion generation. Video mocap
|
|
4
|
-
extraction is a separate path and uses GVHMR as its only backend. The bridge
|
|
5
|
-
entry point remains at `tools/ardy/bridge.mjs` for compatibility with the
|
|
6
|
-
existing `/ardy/*` browser protocol and stored motion URLs; the name is a
|
|
7
|
-
wire-format path, not a selectable backend.
|
|
8
|
-
|
|
9
|
-
## Local development
|
|
10
|
-
|
|
11
|
-
```bash
|
|
12
|
-
CCLAY_KIMODO_HOST=user@gpu-box npm run dev
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
Install the Kimodo host once with `npm run kimodo:setup`. To run the UI without
|
|
16
|
-
any sidecar, use `npm run dev:ui`; the seeded motion and all staging, camera,
|
|
17
|
-
IK, and playback features still work.
|
|
18
|
-
|
|
19
|
-
The bridge accepts `COZYCLAY_BRIDGE_PORT` (or `--port`) and binds loopback
|
|
20
|
-
only. Kimodo connection settings are `CCLAY_KIMODO_HOST`,
|
|
21
|
-
`CCLAY_KIMODO_REPO`, and `CCLAY_KIMODO_MODEL`.
|
|
22
|
-
|
|
23
|
-
## Shared utilities
|
|
24
|
-
|
|
25
|
-
`npz.mjs`, `artifacts.mjs`, `footage.mjs`, `extract.mjs`, and the files under
|
|
26
|
-
`src/ardy/` provide the common motion archive, ingest, conversion, IK, and
|
|
27
|
-
playback contracts used by both generated and imported takes. They are not an
|
|
28
|
-
ARDY runtime installation.
|
|
29
|
-
|
|
30
|
-
The hosted demo worker still has a separately managed local runner for its
|
|
31
|
-
queue jobs; that deployment path is intentionally independent of the local
|
|
32
|
-
Studio selector.
|
|
33
|
-
|
|
34
|
-
## GVHMR extraction (required backend)
|
|
35
|
-
|
|
36
|
-
`CCLAY_EXTRACT_BACKEND` defaults to `gvhmr`, and GVHMR is the only supported
|
|
37
|
-
video mocap backend. The bridge rejects another backend value or a custom
|
|
38
|
-
`CCLAY_EXTRACT_CMD` with `extract-backend-unsupported`; the Studio also refuses
|
|
39
|
-
to extract until the local GPU bridge reports GVHMR. There is no browser
|
|
40
|
-
MediaPipe fallback for video or photo mocap.
|
|
41
|
-
|
|
42
|
-
GVHMR's subject detector is fixed to the `palette` segmentation path for
|
|
43
|
-
CozyClay's coloured mannequin. `CCLAY_EXTRACT_DETECTOR` is retained for
|
|
44
|
-
deployment compatibility but cannot switch the detector to YOLO or auto.
|
|
45
|
-
|
|
46
|
-
`CCLAY_EXTRACT_KEYPOINTS` picks the 2D joint source: `vitpose`, `palette`,
|
|
47
|
-
`hybrid`, or `auto` (default, which is `hybrid` on a palette clip). Hybrid is
|
|
48
|
-
palette joints for the body and ViTPose for the five face points, measured on
|
|
49
|
-
the v15 bat-swagger clip (#380): ViTPose body joints jitter 29 px/f² frame to
|
|
50
|
-
frame on the flat-shaded mannequin (ankle confidence 0.30) where the palette's
|
|
51
|
-
overlap/axis joints jitter 8; but the palette pins every face point to the
|
|
52
|
-
head centroid and GVHMR then reads a head that never turns (root travel 6.3 →
|
|
53
|
-
2.9 m), so the face stays ViTPose (travel 6.1 m, arm swing 0.84 m). Shoulders
|
|
54
|
-
from ViTPose wreck the arms (wrist-above-shoulder 93 % → 12 %). Where the
|
|
55
|
-
render lost a limb part (a prop repainting the hand) the joint comes from the
|
|
56
|
-
surviving part's axis end. The runner side lives in
|
|
57
|
-
`~/cclay-ingest/GVHMR/cclay_gvhmr_extract.py` on the box (`hybrid_kp2d`).
|
|
58
|
-
|
|
59
|
-
With GVHMR enabled, extraction uses one serial SSH worker.
|
|
60
|
-
It deploys the repo-owned worker, preparation and trajectory Python modules into a content-addressed
|
|
61
|
-
remote `/tmp/cozyclay-gvhmr-worker-*` directory and imports the existing
|
|
62
|
-
`~/cclay-ingest/GVHMR/cclay_gvhmr_extract.py`. The original runner and model
|
|
63
|
-
checkpoints are not overwritten. The host needs its existing GVHMR venv
|
|
64
|
-
(validated with PyTorch 2.3.0+cu121 on an RTX 3070 8 GB).
|
|
65
|
-
|
|
66
|
-
ViTPose/HMR2 share identical decoded crops. Complete checkpoint coverage is
|
|
67
|
-
checked before accepting skipped random initialization; memory mapping falls
|
|
68
|
-
back for legacy checkpoint formats. Their models stay on **CPU** between jobs,
|
|
69
|
-
moving to CUDA one at a time. The tracker is new for every clip. Precision,
|
|
70
|
-
flip testing, batch sizes, camera settings and neural motion prediction
|
|
71
|
-
are unchanged by acceleration. The optional trajectory stage below intentionally
|
|
72
|
-
changes accepted vertical trajectories. There is no cached motion-result shortcut.
|
|
73
|
-
|
|
74
|
-
Concurrent extraction returns `extract-worker-busy`. Disconnect, timeout or
|
|
75
|
-
bridge shutdown terminates the owned worker; it also exits after ten idle
|
|
76
|
-
minutes. Restart the bridge after upgrading upstream code. Checkpoint
|
|
77
|
-
size/mtime changes invalidate cached preprocessing models. The final `done`
|
|
78
|
-
event includes stage timing, cache hits and PyTorch GPU-memory metrics.
|
|
79
|
-
Palette takes also include `performance.segmentation`: detected and missing
|
|
80
|
-
frames, dropout gaps, mask coverage quantiles, per-frame coverage, and HSV hue
|
|
81
|
-
error (median/P95/max). These values come from the detector's own mask; older
|
|
82
|
-
bridges without the instrumentation omit this optional report rather than
|
|
83
|
-
reporting a clean zero-valued take.
|
|
84
|
-
|
|
85
|
-
Rollback: launch the bridge with `CCLAY_GVHMR_WORKER=0` to use the original
|
|
86
|
-
GVHMR one-shot command. Other extraction backends and `CCLAY_EXTRACT_CMD` stay
|
|
87
|
-
unsupported so a misconfigured bridge fails explicitly.
|
|
88
|
-
CPU lifecycle tests run in `npm test`; `test/qa-gvhmr-speed.py` performs real
|
|
89
|
-
GPU raw-output/preprocessing equality checks, and `test/qa-gvhmr-bridge.mjs`
|
|
90
|
-
compares original/cold/warm HTTP extraction including retargeted NPZ arrays.
|
|
91
|
-
|
|
92
|
-
## GVHMR delayed-descent recovery
|
|
93
|
-
|
|
94
|
-
The worker now defaults to observation-anchored vertical recovery for static
|
|
95
|
-
camera footage. It requires a confident, large image-space descent, a stable
|
|
96
|
-
observed landing, and delayed world-space descent. If the world endpoint never
|
|
97
|
-
settles before the clip ends, a persistent observed landing plateau and camera
|
|
98
|
-
scale recover its height instead; short or moving landings remain unchanged.
|
|
99
|
-
It keeps frame count, timestamps, joint
|
|
100
|
-
rotations and XZ travel; it does not classify a particular action such as bowing.
|
|
101
|
-
An actual-time, segment-mass COM gravity curve is used only when it agrees with
|
|
102
|
-
the observed motion. Disagreement keeps observation-based timing and is reported
|
|
103
|
-
as `mode: observed-timing`, not as a physically verified flight.
|
|
104
|
-
|
|
105
|
-
After retargeting, a root-only safety pass measures both shipped character skins
|
|
106
|
-
with Studio's playback transforms and prevents floor penetration throughout a
|
|
107
|
-
take with an accepted descent, including initial standing frames. Observation-derived endpoints are calibrated upward
|
|
108
|
-
to measured skin clearance before residual floor safety, with the datum change
|
|
109
|
-
distributed over the descent; after landing each pose uses its own clearance
|
|
110
|
-
instead of retaining an unnecessary constant lift. Elevated landings are not forced down to the floor.
|
|
111
|
-
It does not run AutoPhysics or create IK edits.
|
|
112
|
-
This is not full human-scene reconstruction: moving cameras and ambiguous
|
|
113
|
-
landings are skipped, and existing articulation errors can still cause small
|
|
114
|
-
post-landing height variation. Metadata is in `done.performance.trajectory`,
|
|
115
|
-
including rejected spans, gravity fit, timing and per-model floor clearance.
|
|
116
|
-
|
|
117
|
-
Set `CCLAY_GVHMR_TRAJECTORY=0` and restart the bridge for legacy motion with
|
|
118
|
-
acceleration retained. `CCLAY_GVHMR_WORKER=0` disables both stages. Previously
|
|
119
|
-
extracted takes are not rewritten; re-extract the source to use the improvement.
|
|
120
|
-
See `test/GVHMR-TRAJECTORY-QA.md` for actual source/Studio comparisons and limits.
|
|
121
|
-
The follow-up failure, fix checklist and actual user-clip QA are recorded in
|
|
122
|
-
`test/GVHMR-FOLLOWUP-QA.md`. The Studio extraction receipt now distinguishes
|
|
123
|
-
applied recovery from rejected/disabled recovery and reports authored scene Y
|
|
124
|
-
offsets. Playback uses elapsed time rather than one frame per delayed timer.
|
|
Binary file
|
package/tools/ardy/artifacts.mjs
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import { chmodSync, lstatSync, mkdirSync, mkdtempSync, rmSync } from "node:fs";
|
|
2
|
-
import { dirname, join } from "node:path";
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Creates a mode-0700 request directory beneath a mode-0700 artifact root.
|
|
6
|
-
* The atomic mkdtemp allocation makes artifact names unguessable; exclusive
|
|
7
|
-
* ownership prevents a local peer from planting a symlink for a later write.
|
|
8
|
-
*/
|
|
9
|
-
export function createPrivateArtifactDir(parentDir, label) {
|
|
10
|
-
mkdirSync(parentDir, { recursive: true, mode: 0o700 });
|
|
11
|
-
if (lstatSync(parentDir).isSymbolicLink()) {
|
|
12
|
-
throw new Error(`artifact root must not be a symlink: ${parentDir}`);
|
|
13
|
-
}
|
|
14
|
-
chmodSync(parentDir, 0o700);
|
|
15
|
-
const requestDir = mkdtempSync(join(parentDir, `${label}-`));
|
|
16
|
-
chmodSync(requestDir, 0o700);
|
|
17
|
-
return requestDir;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/** Removes a failed request's private artifacts without following contents. */
|
|
21
|
-
export function removePrivateArtifactDir(path) {
|
|
22
|
-
rmSync(path, { recursive: true, force: true, maxRetries: 3 });
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/** Drop one allowlist id and remove its request directory only after every
|
|
26
|
-
* sibling artifact from that same request has also expired. */
|
|
27
|
-
export function evictPrivateArtifact(allowlist, id) {
|
|
28
|
-
const evictedPath = allowlist.get(id);
|
|
29
|
-
allowlist.delete(id);
|
|
30
|
-
if (!evictedPath) return;
|
|
31
|
-
const artifactDir = dirname(evictedPath);
|
|
32
|
-
const siblingRemains = [...allowlist.values()].some((path) => dirname(path) === artifactDir);
|
|
33
|
-
if (!siblingRemains) removePrivateArtifactDir(artifactDir);
|
|
34
|
-
}
|