cozyclay 1.9.0 → 2.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 +171 -0
- package/bin/agent/agent-routes.mjs +74 -70
- package/bin/agent/agent-runner.mjs +10 -3
- package/bin/agent/motion-runtime.mjs +32 -260
- package/bin/agent/providers.mjs +46 -3
- package/bin/agent/session-store.mjs +41 -5
- package/bin/agent/studio-prompt.mjs +1 -1
- package/bin/agent/studio-tools.mjs +48 -11
- package/bin/cozyclay.mjs +26 -8
- package/bin/live/cli.mjs +22 -3
- package/bin/mcp-runtime.mjs +35 -20
- package/bin/telemetry-state.mjs +5 -2
- package/bin/update-check.mjs +15 -0
- package/dist/app/index.html +6 -6
- package/dist/assets/analytics-MVZOEW8O.js +1 -0
- package/dist/assets/app-C1sdVbg4.css +1 -0
- package/dist/assets/app-CA55tcI3.js +4876 -0
- package/dist/assets/{demo-B-eg1CT8.js → demo-ByeYp-dY.js} +1 -1
- package/dist/assets/{first-shot-handoff-CGgnvNu8.js → first-shot-handoff-DgT28ZiV.js} +1 -1
- package/dist/assets/{landing-IbRp3FnQ.js → landing-BaXkpFip.js} +1 -1
- package/dist/assets/shot-prompt-CbqWcWYi.css +1 -0
- package/dist/assets/shot-prompt-Yrt99wZx.js +17 -0
- package/dist/assets/{ticket-BgIzOBOf.js → ticket-BcmsnHn5.js} +1 -1
- package/dist/assets/workflow-DRdwoDBT.css +1 -0
- package/dist/assets/workflow-dNPGY9xz.js +179 -0
- package/dist/cozyclay-package.json +1 -1
- package/dist/fonts/IBM-Plex-Sans-OFL.txt +92 -0
- package/dist/fonts/JetBrains-Mono-OFL.txt +93 -0
- package/dist/fonts/README.md +13 -9
- package/dist/fonts/ibm-plex-sans-400-latin.woff2 +0 -0
- package/dist/fonts/ibm-plex-sans-500-latin.woff2 +0 -0
- package/dist/fonts/ibm-plex-sans-600-latin.woff2 +0 -0
- package/dist/fonts/jetbrains-mono-400-latin.woff2 +0 -0
- package/dist/fonts/jetbrains-mono-500-latin.woff2 +0 -0
- package/dist/index.html +7 -7
- package/dist/privacy/index.html +13 -8
- package/dist/sitemap.xml +6 -6
- package/dist/workflow/index.html +5 -5
- package/mcp/LIVE-PROTOCOL.md +1 -1
- package/mcp/live-hub.mjs +35 -93
- package/mcp/mesh-file.mjs +48 -0
- package/mcp/server.mjs +6 -77
- package/mcp/tool-handlers.mjs +224 -377
- package/package.json +2 -1
- package/src/App.jsx +1273 -9075
- package/src/analytics.js +393 -9
- package/src/app-context.js +211 -0
- package/src/app-stage.jsx +25 -24
- package/src/ardy/auto-fix-panel.css +108 -0
- package/src/ardy/collision-blockers.js +9 -3
- package/src/ardy/fix-collisions.js +10 -66
- package/src/ardy/ground.js +4 -4
- package/src/ardy/ik-drag.js +101 -0
- package/src/ardy/ik-key-json.js +43 -0
- package/src/ardy/ik.js +122 -76
- package/src/ardy/physics-panel.css +2 -0
- package/src/ardy/physics-panel.jsx +17 -5
- package/src/ardy/platform-fit-panel.css +64 -0
- package/src/ardy/platform-fit-panel.jsx +40 -0
- package/src/ardy/platform-fit.js +326 -0
- package/src/ardy/playback.js +166 -20
- package/src/ardy/range-pin.js +299 -0
- package/src/ardy/timeline-coordinates.js +26 -0
- package/src/ardy/timeline.css +1199 -0
- package/src/ardy/timeline.jsx +149 -41
- package/src/ardy/waypoints.js +2 -2
- package/src/asset-pane.css +462 -0
- package/src/asset-pane.jsx +461 -232
- package/src/command-bus.js +349 -0
- package/src/commands/ai.js +31 -0
- package/src/commands/cast.js +140 -0
- package/src/commands/elements/character.js +13 -0
- package/src/commands/elements/motion.js +14 -0
- package/src/commands/elements/object.js +22 -0
- package/src/commands/elements/scene.js +16 -0
- package/src/commands/elements/shot.js +9 -0
- package/src/commands/elements/stage.js +11 -0
- package/src/commands/elements.js +155 -0
- package/src/commands/export.js +20 -0
- package/src/commands/index.js +40 -0
- package/src/commands/motion.js +231 -0
- package/src/commands/objects.js +174 -0
- package/src/commands/project.js +53 -0
- package/src/commands/scene.js +81 -0
- package/src/commands/shared.js +19 -0
- package/src/commands/shot.js +103 -0
- package/src/commands/stage.js +17 -0
- package/src/commands/view.js +42 -0
- package/src/document-store.js +144 -0
- package/src/domains/cast.js +1007 -0
- package/src/domains/motion.js +3219 -0
- package/src/domains/objects.js +932 -0
- package/src/domains/scenes.js +817 -0
- package/src/domains/shots.js +404 -0
- package/src/domains/stage.js +93 -0
- package/src/dualview.jsx +113 -57
- package/src/facing-marks.js +3 -0
- package/src/first-success-guide.jsx +14 -14
- package/src/grid-view.js +18 -5
- package/src/hierarchy-model.js +24 -16
- package/src/hierarchy-panel.css +386 -0
- package/src/hierarchy-panel.jsx +150 -21
- package/src/{fal-motion-client.js → i2v-motion-client.js} +13 -13
- package/src/i2v-motion-studio.jsx +180 -0
- package/src/ik-camera.js +3 -0
- package/src/main.jsx +6 -0
- package/src/motion/generation.js +105 -0
- package/src/motion-readiness-ui.jsx +4 -4
- package/src/motion-readiness.js +11 -0
- package/src/motion-trail.js +366 -9
- package/src/object-gizmo.jsx +7 -1
- package/src/otio.js +2 -1
- package/src/panels/CameraPanel.jsx +60 -0
- package/src/panels/CharacterTransformPanel.jsx +48 -0
- package/src/panels/EnvironmentPanel.jsx +40 -0
- package/src/panels/Foldout.jsx +32 -0
- package/src/panels/LightPanel.jsx +24 -0
- package/src/panels/ObjectTransformPanel.jsx +554 -0
- package/src/panels/PosePanel.jsx +97 -0
- package/src/panels/ProjectPanel.jsx +33 -0
- package/src/panels/PromptBlocksPanel.jsx +442 -0
- package/src/panels/PropsPanel.jsx +70 -0
- package/src/panels/ReferenceImageField.jsx +91 -0
- package/src/panels/RigControlPanel.jsx +78 -0
- package/src/panels/RigPanel.jsx +37 -0
- package/src/panels/SubjectBox.jsx +47 -0
- package/src/panels/SubjectsPanel.jsx +39 -0
- package/src/panels/VideoCapturePanel.jsx +180 -0
- package/src/panels/details.css +1171 -0
- package/src/panels/motion.css +197 -0
- package/src/panels/pose.css +39 -0
- package/src/planview.jsx +60 -31
- package/src/posestudio.jsx +59 -4
- package/src/project-browser.css +1073 -0
- package/src/project-browser.jsx +284 -123
- package/src/range-pin-object-transform.js +19 -0
- package/src/range-pin-panel.css +518 -0
- package/src/range-pin-panel.jsx +344 -0
- package/src/result-modal.jsx +5 -5
- package/src/room.jsx +79 -51
- package/src/scene-objects.js +37 -1
- package/src/scenes.js +5 -0
- package/src/semantic-edit.js +2 -0
- package/src/settings-menu.jsx +39 -105
- package/src/shell/BottomDock.jsx +450 -0
- package/src/shell/DetailsSlot.jsx +513 -0
- package/src/shell/LibrarySlot.jsx +86 -0
- package/src/shell/MenuBar.jsx +601 -0
- package/src/shell/OutlinerSlot.jsx +50 -0
- package/src/shell/PreferencesDialog.jsx +538 -0
- package/src/shell/PreferencesSlot.jsx +40 -0
- package/src/shell/StatusBar.jsx +125 -0
- package/src/shell/StudioShell.jsx +92 -0
- package/src/shell/TopBar.jsx +129 -0
- package/src/shell/ViewportToolbar.jsx +656 -0
- package/src/shell/agent-glass.css +296 -0
- package/src/shell/dock.css +93 -0
- package/src/shell/glass-regions.css +985 -0
- package/src/shell/glass.css +687 -0
- package/src/shell/log-store.js +52 -0
- package/src/shell/mode.css +9 -0
- package/src/shell/preferences.css +651 -0
- package/src/shell/shell.css +282 -0
- package/src/shell/studio-shell-context.js +19 -0
- package/src/shell/topbar.css +435 -0
- package/src/shell/viewport.css +451 -0
- package/src/store/authored-intent.js +22 -0
- package/src/store/runtime-adapters.js +92 -0
- package/src/store/scene-stage.js +21 -0
- package/src/store/use-document-store.js +14 -0
- package/src/studio-actions.js +210 -0
- package/src/studio-agent-commands.js +41 -271
- package/src/studio-agent-context.js +39 -10
- package/src/studio-agent-motion.js +122 -373
- package/src/studio-agent-protocol.js +67 -31
- package/src/studio-app-binding.js +379 -0
- package/src/studio-contact-sheet.js +73 -0
- package/src/studio-elements.js +58 -51
- package/src/styles/themes.css +200 -0
- package/src/styles/tokens.css +69 -0
- package/src/styles.css +460 -1742
- package/src/theme.js +44 -0
- package/src/timeline-extent.js +16 -0
- package/src/trail-key-conflicts.js +39 -0
- package/src/trail-pick.js +59 -0
- package/src/ui.jsx +8 -8
- package/src/use-case-question.jsx +66 -0
- package/src/workflow/AgentPanel.jsx +82 -69
- package/src/workflow/agent-client.js +12 -2
- package/src/workflow/agent-panel.css +34 -32
- package/src/workflow/cozy-scene-node.css +2 -0
- package/src/workflow/workflow.css +2 -0
- package/tools/ardy/__pycache__/cclay_gvhmr_worker.cpython-313.pyc +0 -0
- package/tools/ardy/bridge.mjs +164 -146
- package/tools/ardy/visual-qa.mjs +5 -5
- package/tools/bench/EXP3.md +61 -0
- package/tools/bench/cclay_bench_extract_incam.py +125 -0
- package/tools/bench/cclay_bench_extract_obs.py +204 -0
- package/tools/bench/cclay_bench_runner.py +42 -0
- package/tools/bench/cube-contact.mjs +162 -0
- package/tools/bench/exp3.mjs +152 -0
- package/tools/bench/extract-bench-lib.mjs +216 -0
- package/tools/bench/extract-bench.mjs +302 -0
- package/tools/bench/fal-generate.mjs +88 -0
- package/tools/bench/fit/README.md +189 -0
- package/tools/bench/fit/camera.mjs +59 -0
- package/tools/bench/fit/contact.mjs +419 -0
- package/tools/bench/fit/footlock.mjs +234 -0
- package/tools/bench/fit/motion.mjs +85 -0
- package/tools/bench/fit/pin.mjs +27 -0
- package/tools/bench/fit/remote.mjs +105 -0
- package/tools/bench/fit-bench.mjs +126 -0
- package/tools/bench/fit-sanity.mjs +45 -0
- package/tools/bench/metrics.mjs +313 -0
- package/tools/bench/obs/depth.mjs +258 -0
- package/tools/bench/obs/extrinsics.mjs +175 -0
- package/tools/bench/obs/fit_mannequin_betas.py +340 -0
- package/tools/bench/obs/ground.mjs +294 -0
- package/tools/bench/obs/heading.mjs +151 -0
- package/tools/bench/obs/ladder.mjs +555 -0
- package/tools/bench/obs/mannequin-betas.json +124 -0
- package/tools/bench/obs/remote.mjs +83 -0
- package/tools/bench/obs/rest_joints.py +52 -0
- package/tools/bench/obs/ybot-targets.mjs +49 -0
- package/tools/bench/obs-bench.mjs +520 -0
- package/tools/bench/score.mjs +343 -0
- package/tools/bench/summarize.mjs +86 -0
- package/tools/dev/pages/privacy.html +13 -8
- package/tools/gt-render/browser.mjs +159 -0
- package/tools/gt-render/camera-math.mjs +276 -0
- package/tools/gt-render/page.mjs +267 -0
- package/tools/gt-render/render.mjs +514 -0
- package/tools/gt-render/scene-box.mjs +31 -0
- package/tools/gt-render/take-transform.mjs +87 -0
- package/tools/morphgs/assets/gen_truth.py +39 -0
- package/tools/morphgs/assets/mesh_ori_rig.txt +27 -0
- package/tools/morphgs/assets/playback-check.mjs +30 -0
- package/tools/morphgs/demo-gate.sh +26 -0
- package/tools/morphgs/fbx2morphgs.mjs +68 -0
- package/tools/morphgs/morphgs-to-cskel27.mjs +105 -0
- package/tools/morphgs/patches/preprocess_src-none-mode.patch +76 -0
- package/tools/morphgs/setup-on-cluster.sh +126 -0
- package/tools/qa/css-rule-usage.mjs +283 -0
- package/tools/qa/studio-control-count.mjs +70 -32
- package/tools/run-tests.mjs +134 -12
- package/tools/track/DESIGN.md +513 -0
- package/tools/track/backfill-provenance.mjs +116 -0
- package/tools/track/budget.mjs +8 -0
- package/tools/track/check-rig.mjs +209 -0
- package/tools/track/diagnostics.schema.json +60 -0
- package/tools/track/export-rig.mjs +256 -0
- package/tools/track/fallback.mjs +7 -0
- package/tools/track/fk-parity-fixture.mjs +161 -0
- package/tools/track/gate.mjs +349 -0
- package/tools/track/masks.mjs +318 -0
- package/tools/track/metrics.mjs +201 -0
- package/tools/track/publish-obs.mjs +108 -0
- package/tools/track/py/check_env.py +61 -0
- package/tools/track/py/eval_lr.py +229 -0
- package/tools/track/py/lr_viterbi.py +294 -0
- package/tools/track/py/masks.py +405 -0
- package/tools/track/py/objective.py +382 -0
- package/tools/track/py/rig.py +508 -0
- package/tools/track/py/scene.py +326 -0
- package/tools/track/py/test_joint_indices.py +123 -0
- package/tools/track/py/test_lr_viterbi.py +195 -0
- package/tools/track/py/test_masks.py +229 -0
- package/tools/track/py/test_rig.py +288 -0
- package/tools/track/py/test_scene.py +354 -0
- package/tools/track/py/test_track.py +328 -0
- package/tools/track/py/track.py +411 -0
- package/tools/track/remote.mjs +140 -0
- package/tools/track/rig-dump.mjs +227 -0
- package/tools/track/run-box-tests.mjs +14 -0
- package/tools/track/run-box.mjs +168 -0
- package/tools/track/setup-box.sh +59 -0
- package/tools/track/study-2d.mjs +728 -0
- package/dist/assets/analytics-B1hnH66c.js +0 -1
- package/dist/assets/app-BWusbqgO.js +0 -4861
- package/dist/assets/app-qKDo4PBX.css +0 -1
- package/dist/assets/shot-prompt-CHUtw6af.js +0 -17
- package/dist/assets/shot-prompt-C_g2BHVc.css +0 -1
- package/dist/assets/workflow-CVwzMhz2.js +0 -179
- package/dist/assets/workflow-DsudxKHF.css +0 -1
- package/src/fal-motion-studio.jsx +0 -180
- package/src/scene-history.js +0 -129
package/tools/run-tests.mjs
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { spawn } from "node:child_process";
|
|
3
3
|
import { mkdtempSync, readdirSync, rmSync } from "node:fs";
|
|
4
4
|
import { createRequire } from "node:module";
|
|
5
|
-
import { tmpdir } from "node:os";
|
|
5
|
+
import { availableParallelism, tmpdir } from "node:os";
|
|
6
6
|
import { join, relative } from "node:path";
|
|
7
7
|
|
|
8
8
|
// Whatever a suite drives through the agent sidecar lands in a scratch
|
|
@@ -14,7 +14,10 @@ if (!process.env.COZYCLAY_AGENT_SESSIONS_DIR) {
|
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
const NODE_FILES = [
|
|
17
|
+
"test/verify-morphgs-exporter.mjs",
|
|
17
18
|
"test/verify-studio-elements.mjs",
|
|
19
|
+
"test/bus/verify-view-mode-pose.mjs",
|
|
20
|
+
"test/verify-studio-actions.mjs",
|
|
18
21
|
"test/ardy/verify-base-free.mjs",
|
|
19
22
|
"test/ardy/verify-browser-motion.mjs",
|
|
20
23
|
"test/ardy/verify-collision-blockers.mjs",
|
|
@@ -26,11 +29,34 @@ const NODE_FILES = [
|
|
|
26
29
|
"test/ardy/verify-motion-calibration.mjs",
|
|
27
30
|
"test/ardy/verify-palette-segmentation.mjs",
|
|
28
31
|
"test/verify-motion-stabilize.mjs",
|
|
29
|
-
"test/verify-
|
|
32
|
+
"test/verify-i2v-motion-prompt.mjs",
|
|
30
33
|
"test/verify-facing-marks.mjs",
|
|
31
34
|
"test/ardy/verify-gvhmr-floor.mjs",
|
|
32
35
|
"test/verify-gvhmr-detector-flag.mjs",
|
|
33
36
|
"test/verify-gvhmr-only.mjs",
|
|
37
|
+
"test/verify-extract-bench.mjs",
|
|
38
|
+
"test/verify-fit-bench.mjs",
|
|
39
|
+
"test/verify-obs-extrinsics.mjs",
|
|
40
|
+
"test/verify-obs-depth.mjs",
|
|
41
|
+
"test/verify-obs-ground.mjs",
|
|
42
|
+
"test/verify-obs-betas.mjs",
|
|
43
|
+
"test/verify-obs-remote.mjs",
|
|
44
|
+
"test/verify-track-run-box.mjs",
|
|
45
|
+
"test/verify-track-gate.mjs",
|
|
46
|
+
"test/verify-track-backfill.mjs",
|
|
47
|
+
"test/verify-track-remote.mjs",
|
|
48
|
+
"test/verify-track-metrics.mjs",
|
|
49
|
+
"test/verify-track-study-2d.mjs",
|
|
50
|
+
"test/verify-track-masks.mjs",
|
|
51
|
+
"test/verify-obs-ladder.mjs",
|
|
52
|
+
"test/verify-obs-isolation.mjs",
|
|
53
|
+
"test/verify-obs-bench-t1.mjs",
|
|
54
|
+
"test/verify-track-rig-dump.mjs",
|
|
55
|
+
"test/verify-scene-continuity.mjs",
|
|
56
|
+
"test/verify-heading-unwrap.mjs",
|
|
57
|
+
"test/verify-scene-ray.mjs",
|
|
58
|
+
"test/verify-footlock.mjs",
|
|
59
|
+
"test/verify-cube-contact.mjs",
|
|
34
60
|
"test/ardy/verify-key-runs.mjs",
|
|
35
61
|
"test/ardy/verify-playback-skinning.mjs",
|
|
36
62
|
"test/ardy/verify-playback-clock.mjs",
|
|
@@ -42,8 +68,10 @@ const NODE_FILES = [
|
|
|
42
68
|
"test/ardy/verify-root-drop.mjs",
|
|
43
69
|
"test/ardy/verify-surface-rise.mjs",
|
|
44
70
|
"test/ardy/verify-secure-artifacts.mjs",
|
|
71
|
+
"test/ardy/verify-motion-cors.mjs",
|
|
45
72
|
"test/ardy/verify-timeline-coordinates.mjs",
|
|
46
73
|
"test/ardy/verify-timeline-resize.mjs",
|
|
74
|
+
"test/verify-tokens.mjs",
|
|
47
75
|
"test/demo/verify-demo-pages.mjs",
|
|
48
76
|
"test/demo/verify-motion-api.mjs",
|
|
49
77
|
"test/demo/verify-motion-url-allowlist.mjs",
|
|
@@ -57,10 +85,19 @@ const NODE_FILES = [
|
|
|
57
85
|
"test/ik/verify-ground.mjs",
|
|
58
86
|
"test/ik/verify-auto-physics.mjs",
|
|
59
87
|
"test/ik/verify-physics-review.mjs",
|
|
88
|
+
"test/ik/verify-platform-fit.mjs",
|
|
60
89
|
"test/ik/verify-physics-support.mjs",
|
|
61
90
|
"test/ik/verify-physics-surface.mjs",
|
|
62
91
|
"test/ik/verify-ik.mjs",
|
|
92
|
+
"test/ik/verify-knee-side.mjs",
|
|
93
|
+
"test/ik/translation-step.mjs",
|
|
94
|
+
"test/ik/verify-ik-drag-delta.mjs",
|
|
95
|
+
"test/ik/verify-ik-blend-range.mjs",
|
|
96
|
+
"test/ik/verify-range-pin.mjs",
|
|
97
|
+
"test/ik/verify-range-pin-ui.mjs",
|
|
98
|
+
"test/ik/verify-range-pin-object-transform.mjs",
|
|
63
99
|
"test/verify-ik-camera-performance.mjs",
|
|
100
|
+
"test/verify-ik-entry-camera.mjs",
|
|
64
101
|
"test/process/verify-bridge-launch.mjs",
|
|
65
102
|
"test/process/verify-lifecycle.mjs",
|
|
66
103
|
"test/process/verify-mcp-package-isolation.mjs",
|
|
@@ -70,6 +107,7 @@ const NODE_FILES = [
|
|
|
70
107
|
"test/verify-agent-panel.mjs",
|
|
71
108
|
"test/verify-agent-host.mjs",
|
|
72
109
|
"test/verify-agent-routes.mjs",
|
|
110
|
+
"test/verify-agent-live-runtime.mjs",
|
|
73
111
|
"test/verify-agent-runner-errors.mjs",
|
|
74
112
|
"test/verify-agent-steer.mjs",
|
|
75
113
|
"test/verify-pi-tools.mjs",
|
|
@@ -123,6 +161,13 @@ const NODE_FILES = [
|
|
|
123
161
|
"test/verify-kimodo-runner.mjs",
|
|
124
162
|
"test/verify-kimodo-setup.mjs",
|
|
125
163
|
"test/verify-motion-trail.mjs",
|
|
164
|
+
"test/verify-motion-trail-limb.mjs",
|
|
165
|
+
"test/verify-trail-key-conflicts.mjs",
|
|
166
|
+
"test/verify-motion-trail-orientation.mjs",
|
|
167
|
+
"test/verify-trail-pick.mjs",
|
|
168
|
+
"test/verify-trail-rendered-geometry.mjs",
|
|
169
|
+
"test/verify-motion-trail-overreach.mjs",
|
|
170
|
+
"test/verify-motion-trail-persistence.mjs",
|
|
126
171
|
"test/verify-kimodo-waypoints.mjs",
|
|
127
172
|
"test/verify-keyframe-pack.mjs",
|
|
128
173
|
"test/verify-keyframe-pack-request.mjs",
|
|
@@ -139,9 +184,12 @@ const NODE_FILES = [
|
|
|
139
184
|
"test/verify-matte.mjs",
|
|
140
185
|
"test/verify-model-presets.mjs",
|
|
141
186
|
"test/verify-mp4-duration.mjs",
|
|
187
|
+
"test/verify-gt-render-camera.mjs",
|
|
188
|
+
"test/verify-bench-metrics.mjs",
|
|
142
189
|
"test/verify-mcp-invariants.mjs",
|
|
143
190
|
"test/verify-motion-edit.mjs",
|
|
144
191
|
"test/verify-motion-readiness.mjs",
|
|
192
|
+
"test/verify-demo-seed.mjs",
|
|
145
193
|
"test/verify-motion-readiness-ui.mjs",
|
|
146
194
|
"test/verify-multimodel-ingest.mjs",
|
|
147
195
|
"test/verify-offscreen-export.mjs",
|
|
@@ -176,6 +224,7 @@ const NODE_FILES = [
|
|
|
176
224
|
"test/verify-studio-agent-motion.mjs",
|
|
177
225
|
"test/verify-studio-agent-binding.mjs",
|
|
178
226
|
"test/verify-studio-undo-hygiene.mjs",
|
|
227
|
+
"test/verify-studio-contact-sheet.mjs",
|
|
179
228
|
"test/verify-reference-slots.mjs",
|
|
180
229
|
"test/verify-scenes.mjs",
|
|
181
230
|
"test/verify-cozy-scene-node.mjs",
|
|
@@ -247,6 +296,7 @@ const BROWSER_FILES = [
|
|
|
247
296
|
"test/verify-static-shot-export-browser.mjs",
|
|
248
297
|
"test/qa-agent-view-toggle-browser.mjs",
|
|
249
298
|
"test/qa-studio-agent-browser.mjs",
|
|
299
|
+
"test/qa-agent-scenarios-browser.mjs",
|
|
250
300
|
"test/qa-camera-tutorial-browser.mjs",
|
|
251
301
|
"test/qa-first-shot-handoff-browser.mjs",
|
|
252
302
|
"test/qa-tutorial-analytics-browser.mjs",
|
|
@@ -263,12 +313,13 @@ const BROWSER_FILES = [
|
|
|
263
313
|
"test/qa-execution-outcomes-browser.mjs",
|
|
264
314
|
"test/qa-view-menu-browser.mjs",
|
|
265
315
|
"test/qa-agent-activity-browser.mjs",
|
|
316
|
+
"test/qa-platform-fit-browser.mjs",
|
|
266
317
|
];
|
|
267
318
|
|
|
268
319
|
// The inventory sweep only picks up `verify*.mjs`; a browser suite named for
|
|
269
320
|
// the QA runner it needs is listed here so it still shows up in the manifest
|
|
270
321
|
// (as an EXCLUDE with its reason) instead of going unmentioned.
|
|
271
|
-
const EXTRA_INVENTORY = ["test/qa-studio-agent-browser.mjs", "test/qa-execution-outcomes-browser.mjs", "test/qa-motion-readiness-browser.mjs", "test/qa-export-recovery-browser.mjs", "test/qa-agent-view-toggle-browser.mjs", "test/qa-camera-tutorial-browser.mjs", "test/qa-first-shot-handoff-browser.mjs", "test/qa-tutorial-analytics-browser.mjs", "test/qa-camera-pointer-lock-browser.mjs", "test/qa-first-edit-browser.mjs", "test/qa-ia-tail-browser.mjs", "test/qa-keyframe-pack-browser.mjs", "test/qa-preview-browser.mjs", "test/qa-project-resources-browser.mjs", "test/qa-reference-slots-browser.mjs", "test/qa-scene-playback-browser.mjs", "test/qa-scene-switcher-browser.mjs", "test/qa-send-to-ai-browser.mjs", "test/qa-view-menu-browser.mjs", "test/qa-agent-activity-browser.mjs", "test/qa-live-reconnect-browser.mjs"];
|
|
322
|
+
const EXTRA_INVENTORY = ["test/ik/translation-step.mjs", "test/qa-studio-agent-browser.mjs", "test/qa-agent-scenarios-browser.mjs", "test/qa-execution-outcomes-browser.mjs", "test/qa-motion-readiness-browser.mjs", "test/qa-export-recovery-browser.mjs", "test/qa-agent-view-toggle-browser.mjs", "test/qa-camera-tutorial-browser.mjs", "test/qa-first-shot-handoff-browser.mjs", "test/qa-tutorial-analytics-browser.mjs", "test/qa-camera-pointer-lock-browser.mjs", "test/qa-first-edit-browser.mjs", "test/qa-ia-tail-browser.mjs", "test/qa-keyframe-pack-browser.mjs", "test/qa-preview-browser.mjs", "test/qa-project-resources-browser.mjs", "test/qa-reference-slots-browser.mjs", "test/qa-scene-playback-browser.mjs", "test/qa-scene-switcher-browser.mjs", "test/qa-send-to-ai-browser.mjs", "test/qa-view-menu-browser.mjs", "test/qa-agent-activity-browser.mjs", "test/qa-live-reconnect-browser.mjs", "test/qa-platform-fit-browser.mjs"];
|
|
272
323
|
|
|
273
324
|
function verificationFiles(directory) {
|
|
274
325
|
return readdirSync(directory, { withFileTypes: true })
|
|
@@ -280,9 +331,13 @@ function verificationFiles(directory) {
|
|
|
280
331
|
.sort();
|
|
281
332
|
}
|
|
282
333
|
|
|
334
|
+
// Every suite reserves its own ports and writes under a temp dir, so files
|
|
335
|
+
// are independent of each other; running them serially cost CI five minutes
|
|
336
|
+
// (#413). `--jobs 1` restores the old interleaved live output for debugging.
|
|
283
337
|
function parseArguments(arguments_) {
|
|
284
338
|
let listOnly = false;
|
|
285
339
|
let scope = "all";
|
|
340
|
+
let jobs = Number(process.env.COZYCLAY_TEST_JOBS) || availableParallelism();
|
|
286
341
|
for (let index = 0; index < arguments_.length; index += 1) {
|
|
287
342
|
const argument = arguments_[index];
|
|
288
343
|
if (argument === "--list") {
|
|
@@ -294,23 +349,81 @@ function parseArguments(arguments_) {
|
|
|
294
349
|
index += 1;
|
|
295
350
|
continue;
|
|
296
351
|
}
|
|
352
|
+
if (argument === "--jobs") {
|
|
353
|
+
jobs = Number(arguments_[index + 1]);
|
|
354
|
+
index += 1;
|
|
355
|
+
continue;
|
|
356
|
+
}
|
|
297
357
|
throw new Error(`unknown argument: ${argument}`);
|
|
298
358
|
}
|
|
299
359
|
if (scope !== "all" && scope !== "ardy") throw new Error(`unknown test scope: ${scope}`);
|
|
300
|
-
|
|
360
|
+
if (!Number.isInteger(jobs) || jobs < 1) throw new Error(`--jobs must be a positive integer, got ${jobs}`);
|
|
361
|
+
return { listOnly, scope, jobs };
|
|
301
362
|
}
|
|
302
363
|
|
|
303
|
-
|
|
364
|
+
// One file per child. With more than one job the output is buffered per file
|
|
365
|
+
// and replayed as a block when the file finishes, so PASS/FAIL lines of
|
|
366
|
+
// different suites never interleave.
|
|
367
|
+
function run(file, { buffered }) {
|
|
304
368
|
return new Promise((resolve, reject) => {
|
|
305
|
-
const
|
|
369
|
+
const chunks = [];
|
|
370
|
+
const child = spawn(process.execPath, [file], { stdio: buffered ? ["ignore", "pipe", "pipe"] : "inherit" });
|
|
371
|
+
if (buffered) {
|
|
372
|
+
child.stdout.on("data", (chunk) => chunks.push(chunk));
|
|
373
|
+
child.stderr.on("data", (chunk) => chunks.push(chunk));
|
|
374
|
+
}
|
|
306
375
|
child.once("error", reject);
|
|
307
376
|
child.once("exit", (code, signal) => {
|
|
377
|
+
if (buffered) process.stdout.write(`\nRUNNING ${file}\n${Buffer.concat(chunks)}`);
|
|
308
378
|
if (code === 0) resolve();
|
|
309
379
|
else reject(new Error(`${file} failed${signal ? ` with ${signal}` : ` with exit code ${code}`}`));
|
|
310
380
|
});
|
|
311
381
|
});
|
|
312
382
|
}
|
|
313
383
|
|
|
384
|
+
// These suites reserve a port by binding :0, release it, and hand the number
|
|
385
|
+
// to a child that binds it again (or an adjacent one). Any concurrent suite
|
|
386
|
+
// can take it in between, so they run one at a time after the parallel wave
|
|
387
|
+
// instead of by luck. Everything else picks its port inside the process that
|
|
388
|
+
// keeps it.
|
|
389
|
+
const SERIAL_ONLY = new Set([
|
|
390
|
+
"test/process/verify-bridge-launch.mjs",
|
|
391
|
+
"mcp/verify-http-origin.mjs",
|
|
392
|
+
"mcp/verify-live-controller.mjs",
|
|
393
|
+
"mcp/verify-live-motion-job.mjs",
|
|
394
|
+
"mcp/verify-live-p0.mjs",
|
|
395
|
+
"mcp/verify-live-port.mjs",
|
|
396
|
+
"mcp/verify-live-routing.mjs",
|
|
397
|
+
]);
|
|
398
|
+
|
|
399
|
+
// Longest files first so the tail of the run is not one slow suite on its own.
|
|
400
|
+
const SLOW_FIRST = [
|
|
401
|
+
"test/verify-studio-agent-motion.mjs",
|
|
402
|
+
"test/verify-studio-agent-binding.mjs",
|
|
403
|
+
"test/ardy/verify-gvhmr-floor.mjs",
|
|
404
|
+
"test/verify-part-colours.mjs",
|
|
405
|
+
"test/verify-agent-runner-errors.mjs",
|
|
406
|
+
];
|
|
407
|
+
|
|
408
|
+
async function runAll(files, jobs) {
|
|
409
|
+
const parallel = files.filter((file) => !SERIAL_ONLY.has(file));
|
|
410
|
+
const queue = [...SLOW_FIRST.filter((file) => parallel.includes(file)), ...parallel.filter((file) => !SLOW_FIRST.includes(file))];
|
|
411
|
+
let failure = null;
|
|
412
|
+
const worker = async () => {
|
|
413
|
+
while (queue.length > 0 && !failure) {
|
|
414
|
+
const file = queue.shift();
|
|
415
|
+
try {
|
|
416
|
+
await run(file, { buffered: jobs > 1 });
|
|
417
|
+
} catch (error) {
|
|
418
|
+
failure ??= error;
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
};
|
|
422
|
+
await Promise.all(Array.from({ length: Math.min(jobs, queue.length) }, worker));
|
|
423
|
+
if (failure) throw failure;
|
|
424
|
+
for (const file of files.filter((file) => SERIAL_ONLY.has(file))) await run(file, { buffered: true });
|
|
425
|
+
}
|
|
426
|
+
|
|
314
427
|
// node:sqlite's DatabaseSync only ships unflagged from Node 22.13.0 (it lived
|
|
315
428
|
// behind --experimental-sqlite before that). package.json requires >=22.19,
|
|
316
429
|
// but older 22.x installs are still common enough that the manifest should
|
|
@@ -346,6 +459,8 @@ function hasMcpRuntimeDeps() {
|
|
|
346
459
|
}
|
|
347
460
|
|
|
348
461
|
const mcpDepsInstalled = hasMcpRuntimeDeps();
|
|
462
|
+
// Starts the repository hub through mcp/live-hub.mjs, so it needs that tree too.
|
|
463
|
+
const MCP_DEPENDENT_NODE_FILES = new Set(["test/verify-agent-live-runtime.mjs"]);
|
|
349
464
|
|
|
350
465
|
const categories = new Map([
|
|
351
466
|
...NODE_FILES.map((file) => [file, { kind: "node", reason: "runs directly under Node" }]),
|
|
@@ -367,7 +482,7 @@ const categories = new Map([
|
|
|
367
482
|
]);
|
|
368
483
|
if (!mcpDepsInstalled) {
|
|
369
484
|
for (const [file, category] of categories) {
|
|
370
|
-
if (!file.startsWith("mcp/") || category.kind !== "node") continue;
|
|
485
|
+
if (!(file.startsWith("mcp/") || MCP_DEPENDENT_NODE_FILES.has(file)) || category.kind !== "node") continue;
|
|
371
486
|
categories.set(file, {
|
|
372
487
|
kind: "mcp-deps",
|
|
373
488
|
reason: "requires the MCP server dependencies; run `npm --prefix mcp ci` (or `cd mcp && npm install`) first",
|
|
@@ -375,8 +490,11 @@ if (!mcpDepsInstalled) {
|
|
|
375
490
|
}
|
|
376
491
|
}
|
|
377
492
|
|
|
378
|
-
const { listOnly, scope } = parseArguments(process.argv.slice(2));
|
|
493
|
+
const { listOnly, scope, jobs } = parseArguments(process.argv.slice(2));
|
|
379
494
|
const inventory = [...verificationFiles("test"), ...verificationFiles("mcp"), ...EXTRA_INVENTORY].sort();
|
|
495
|
+
for (const file of inventory) {
|
|
496
|
+
if (/^test\/bus\/verify-.*\.mjs$/.test(file)) categories.set(file, { kind: "node", reason: "command bus contract verification" });
|
|
497
|
+
}
|
|
380
498
|
const unclassified = inventory.filter((file) => !categories.has(file));
|
|
381
499
|
const stale = [...categories.keys()].filter((file) => !inventory.includes(file));
|
|
382
500
|
if (unclassified.length > 0 || stale.length > 0) {
|
|
@@ -388,16 +506,20 @@ if (unclassified.length > 0 || stale.length > 0) {
|
|
|
388
506
|
|
|
389
507
|
const scoped = inventory.filter((file) => scope === "all" || file.startsWith("test/ardy/") || file.startsWith("test/ik/"));
|
|
390
508
|
const runnable = scoped.filter((file) => categories.get(file).kind === "node");
|
|
391
|
-
console.log(`TEST MANIFEST scope=${scope} runnable=${runnable.length} total=${scoped.length}`);
|
|
509
|
+
console.log(`TEST MANIFEST scope=${scope} runnable=${runnable.length} total=${scoped.length} jobs=${jobs}`);
|
|
392
510
|
for (const file of scoped) {
|
|
393
511
|
const { kind, reason } = categories.get(file);
|
|
394
512
|
console.log(`${kind === "node" ? "RUN" : "EXCLUDE"} ${kind} ${file} - ${reason}`);
|
|
395
513
|
}
|
|
396
514
|
|
|
397
515
|
if (!listOnly) {
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
516
|
+
if (jobs === 1) {
|
|
517
|
+
for (const file of runnable) {
|
|
518
|
+
console.log(`\nRUNNING ${file}`);
|
|
519
|
+
await run(file, { buffered: false });
|
|
520
|
+
}
|
|
521
|
+
} else {
|
|
522
|
+
await runAll(runnable, jobs);
|
|
401
523
|
}
|
|
402
524
|
console.log(`\nPASS ${runnable.length} Node verification files`);
|
|
403
525
|
}
|