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
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
@layer legacy {
|
|
1
2
|
/* Agent panel (#126).
|
|
2
3
|
*
|
|
3
4
|
* workflow.css is shipped minified on one line, so the panel keeps its own
|
|
@@ -215,14 +216,14 @@
|
|
|
215
216
|
height: 58px;
|
|
216
217
|
padding: 0 var(--agent-space-4);
|
|
217
218
|
border-bottom: 1px solid var(--agent-border);
|
|
218
|
-
background: #171921;
|
|
219
|
+
background: var(--agent-chrome, #171921);
|
|
219
220
|
}
|
|
220
221
|
|
|
221
222
|
.agent-title {
|
|
222
223
|
margin: 0;
|
|
223
224
|
font-size: var(--agent-font-xl);
|
|
224
225
|
font-weight: 700;
|
|
225
|
-
color: #f5f7ff;
|
|
226
|
+
color: var(--agent-text-strong, #f5f7ff);
|
|
226
227
|
}
|
|
227
228
|
|
|
228
229
|
.agent-header-spacer { flex: 1; }
|
|
@@ -234,8 +235,8 @@
|
|
|
234
235
|
gap: var(--agent-space-1);
|
|
235
236
|
border: 1px solid var(--agent-border-strong);
|
|
236
237
|
border-radius: var(--agent-radius-md);
|
|
237
|
-
background: #20232d;
|
|
238
|
-
color: #c8ccdb;
|
|
238
|
+
background: var(--agent-panel, #20232d);
|
|
239
|
+
color: var(--agent-text-soft, #c8ccdb);
|
|
239
240
|
padding: var(--agent-space-2) var(--agent-space-3);
|
|
240
241
|
font: inherit;
|
|
241
242
|
font-size: var(--agent-font-md);
|
|
@@ -246,9 +247,9 @@
|
|
|
246
247
|
|
|
247
248
|
.agent-icon-button:hover,
|
|
248
249
|
.agent-ghost-button:hover {
|
|
249
|
-
border-color: #606b9a;
|
|
250
|
-
background: #2b3040;
|
|
251
|
-
color: #f5f7ff;
|
|
250
|
+
border-color: var(--agent-border-strong, #606b9a);
|
|
251
|
+
background: var(--agent-hover, #2b3040);
|
|
252
|
+
color: var(--agent-text-strong, #f5f7ff);
|
|
252
253
|
}
|
|
253
254
|
|
|
254
255
|
.agent-ghost-button[disabled],
|
|
@@ -278,7 +279,7 @@
|
|
|
278
279
|
border: 0;
|
|
279
280
|
border-radius: var(--agent-radius-sm);
|
|
280
281
|
background: transparent;
|
|
281
|
-
color: #c8ccdb;
|
|
282
|
+
color: var(--agent-text-soft, #c8ccdb);
|
|
282
283
|
padding: var(--agent-space-2) var(--agent-space-3);
|
|
283
284
|
font: inherit;
|
|
284
285
|
font-size: var(--agent-font-md);
|
|
@@ -286,7 +287,7 @@
|
|
|
286
287
|
cursor: pointer;
|
|
287
288
|
}
|
|
288
289
|
|
|
289
|
-
.agent-menu button:hover { background: #2b3040; color: #f5f7ff; }
|
|
290
|
+
.agent-menu button:hover { background: var(--agent-hover, #2b3040); color: var(--agent-text-strong, #f5f7ff); }
|
|
290
291
|
|
|
291
292
|
/* --- account strip ----------------------------------------------------- */
|
|
292
293
|
|
|
@@ -313,7 +314,7 @@
|
|
|
313
314
|
padding: 2px var(--agent-space-2);
|
|
314
315
|
border: 1px solid var(--agent-accent-edge);
|
|
315
316
|
border-radius: var(--agent-radius-pill);
|
|
316
|
-
color: #cfd5ff;
|
|
317
|
+
color: var(--agent-text-strong, #cfd5ff);
|
|
317
318
|
font-size: var(--agent-font-xs);
|
|
318
319
|
letter-spacing: 0.06em;
|
|
319
320
|
text-transform: uppercase;
|
|
@@ -462,7 +463,7 @@
|
|
|
462
463
|
.agent-bubble {
|
|
463
464
|
max-width: 86%;
|
|
464
465
|
padding: var(--agent-space-3) var(--agent-space-4);
|
|
465
|
-
border: 1px solid #343b58;
|
|
466
|
+
border: 1px solid var(--agent-border-strong, #343b58);
|
|
466
467
|
border-radius: var(--agent-radius-lg);
|
|
467
468
|
background: var(--agent-bubble);
|
|
468
469
|
color: var(--agent-text);
|
|
@@ -473,7 +474,7 @@
|
|
|
473
474
|
}
|
|
474
475
|
|
|
475
476
|
.agent-assistant-text {
|
|
476
|
-
color: #dfe3f2;
|
|
477
|
+
color: var(--agent-text-soft, #dfe3f2);
|
|
477
478
|
font-size: var(--agent-font-lg);
|
|
478
479
|
line-height: 1.6;
|
|
479
480
|
white-space: pre-wrap;
|
|
@@ -495,7 +496,7 @@
|
|
|
495
496
|
.agent-card {
|
|
496
497
|
border: 1px solid var(--agent-border-strong);
|
|
497
498
|
border-radius: var(--agent-radius-lg);
|
|
498
|
-
background: #20232d;
|
|
499
|
+
background: var(--agent-panel, #20232d);
|
|
499
500
|
overflow: hidden;
|
|
500
501
|
}
|
|
501
502
|
|
|
@@ -504,7 +505,7 @@
|
|
|
504
505
|
align-items: center;
|
|
505
506
|
gap: var(--agent-space-3);
|
|
506
507
|
padding: var(--agent-space-3) var(--agent-space-4);
|
|
507
|
-
color: #ccd1e2;
|
|
508
|
+
color: var(--agent-text-soft, #ccd1e2);
|
|
508
509
|
font-size: var(--agent-font-md);
|
|
509
510
|
cursor: pointer;
|
|
510
511
|
list-style: none;
|
|
@@ -518,9 +519,9 @@
|
|
|
518
519
|
.agent-tool-detail {
|
|
519
520
|
margin: 0;
|
|
520
521
|
padding: var(--agent-space-3) var(--agent-space-4);
|
|
521
|
-
border-top: 1px solid #2c3140;
|
|
522
|
+
border-top: 1px solid var(--agent-border, #2c3140);
|
|
522
523
|
background: var(--agent-bg-sunken);
|
|
523
|
-
color: #98a0b8;
|
|
524
|
+
color: var(--agent-text-muted, #98a0b8);
|
|
524
525
|
font: var(--agent-font-sm) ui-monospace, monospace;
|
|
525
526
|
white-space: pre-wrap;
|
|
526
527
|
word-break: break-all;
|
|
@@ -556,7 +557,7 @@
|
|
|
556
557
|
flex-wrap: wrap;
|
|
557
558
|
gap: var(--agent-space-2);
|
|
558
559
|
padding: var(--agent-space-3);
|
|
559
|
-
border-top: 1px solid #2c3140;
|
|
560
|
+
border-top: 1px solid var(--agent-border, #2c3140);
|
|
560
561
|
}
|
|
561
562
|
|
|
562
563
|
.agent-image-actions button,
|
|
@@ -566,8 +567,8 @@
|
|
|
566
567
|
gap: var(--agent-space-1);
|
|
567
568
|
border: 1px solid var(--agent-border-strong);
|
|
568
569
|
border-radius: var(--agent-radius-sm);
|
|
569
|
-
background: #292d39;
|
|
570
|
-
color: #ccd1e2;
|
|
570
|
+
background: var(--agent-hover, #292d39);
|
|
571
|
+
color: var(--agent-text-soft, #ccd1e2);
|
|
571
572
|
padding: var(--agent-space-2) var(--agent-space-3);
|
|
572
573
|
font: inherit;
|
|
573
574
|
font-size: var(--agent-font-sm);
|
|
@@ -578,18 +579,18 @@
|
|
|
578
579
|
.agent-image-actions button.primary {
|
|
579
580
|
border-color: var(--agent-accent-edge);
|
|
580
581
|
background: var(--agent-accent-deep);
|
|
581
|
-
color: #e6e9ff;
|
|
582
|
+
color: var(--agent-text-strong, #e6e9ff);
|
|
582
583
|
}
|
|
583
584
|
|
|
584
585
|
.agent-image-actions button:hover,
|
|
585
|
-
.agent-image-actions a:hover { border-color: #606b9a; }
|
|
586
|
+
.agent-image-actions a:hover { border-color: var(--agent-border-strong, #606b9a); }
|
|
586
587
|
|
|
587
588
|
.agent-placed {
|
|
588
589
|
display: flex;
|
|
589
590
|
align-items: center;
|
|
590
591
|
gap: var(--agent-space-2);
|
|
591
592
|
padding: var(--agent-space-3);
|
|
592
|
-
border-top: 1px solid #2c3140;
|
|
593
|
+
border-top: 1px solid var(--agent-border, #2c3140);
|
|
593
594
|
color: var(--agent-ok);
|
|
594
595
|
font-size: var(--agent-font-md);
|
|
595
596
|
}
|
|
@@ -598,8 +599,8 @@
|
|
|
598
599
|
margin-left: auto;
|
|
599
600
|
border: 1px solid var(--agent-border-strong);
|
|
600
601
|
border-radius: var(--agent-radius-sm);
|
|
601
|
-
background: #292d39;
|
|
602
|
-
color: #ccd1e2;
|
|
602
|
+
background: var(--agent-hover, #292d39);
|
|
603
|
+
color: var(--agent-text-soft, #ccd1e2);
|
|
603
604
|
padding: var(--agent-space-1) var(--agent-space-3);
|
|
604
605
|
font: inherit;
|
|
605
606
|
font-size: var(--agent-font-sm);
|
|
@@ -644,7 +645,7 @@
|
|
|
644
645
|
display: flex;
|
|
645
646
|
align-items: center;
|
|
646
647
|
gap: var(--agent-space-2);
|
|
647
|
-
color: #ccd1e2;
|
|
648
|
+
color: var(--agent-text-soft, #ccd1e2);
|
|
648
649
|
}
|
|
649
650
|
|
|
650
651
|
.agent-job-label { font-weight: 600; }
|
|
@@ -778,7 +779,7 @@
|
|
|
778
779
|
margin: 0;
|
|
779
780
|
font-size: var(--agent-font-xl);
|
|
780
781
|
font-weight: 700;
|
|
781
|
-
color: #f5f7ff;
|
|
782
|
+
color: var(--agent-text-strong, #f5f7ff);
|
|
782
783
|
}
|
|
783
784
|
|
|
784
785
|
.agent-state-card p {
|
|
@@ -793,7 +794,7 @@
|
|
|
793
794
|
border: 1px solid var(--agent-accent-edge);
|
|
794
795
|
border-radius: var(--agent-radius-md);
|
|
795
796
|
background: var(--agent-accent-deep);
|
|
796
|
-
color: #e6e9ff;
|
|
797
|
+
color: var(--agent-text-strong, #e6e9ff);
|
|
797
798
|
padding: var(--agent-space-3) var(--agent-space-5);
|
|
798
799
|
font: inherit;
|
|
799
800
|
font-size: var(--agent-font-lg);
|
|
@@ -856,7 +857,7 @@
|
|
|
856
857
|
.agent-chip {
|
|
857
858
|
border: 1px solid var(--agent-border-strong);
|
|
858
859
|
border-radius: var(--agent-radius-pill);
|
|
859
|
-
background: #20232d;
|
|
860
|
+
background: var(--agent-panel, #20232d);
|
|
860
861
|
color: #bcc2d4;
|
|
861
862
|
padding: var(--agent-space-2) var(--agent-space-4);
|
|
862
863
|
font: inherit;
|
|
@@ -865,7 +866,7 @@
|
|
|
865
866
|
cursor: pointer;
|
|
866
867
|
}
|
|
867
868
|
|
|
868
|
-
.agent-chip:hover { border-color: #606b9a; background: #2b3040; color: #f5f7ff; }
|
|
869
|
+
.agent-chip:hover { border-color: var(--agent-border-strong, #606b9a); background: var(--agent-hover, #2b3040); color: var(--agent-text-strong, #f5f7ff); }
|
|
869
870
|
|
|
870
871
|
/* --- activity line ------------------------------------------------------ */
|
|
871
872
|
|
|
@@ -1048,7 +1049,7 @@
|
|
|
1048
1049
|
gap: var(--agent-space-2);
|
|
1049
1050
|
border: 1px solid var(--agent-border-strong);
|
|
1050
1051
|
border-radius: var(--agent-radius-pill);
|
|
1051
|
-
background: #20232d;
|
|
1052
|
+
background: var(--agent-panel, #20232d);
|
|
1052
1053
|
color: #b6bcd0;
|
|
1053
1054
|
padding: var(--agent-space-1) var(--agent-space-3);
|
|
1054
1055
|
font: inherit;
|
|
@@ -1059,7 +1060,7 @@
|
|
|
1059
1060
|
.agent-attach-chip[aria-pressed="true"] {
|
|
1060
1061
|
border-color: var(--agent-accent-edge);
|
|
1061
1062
|
background: var(--agent-accent-deep);
|
|
1062
|
-
color: #e6e9ff;
|
|
1063
|
+
color: var(--agent-text-strong, #e6e9ff);
|
|
1063
1064
|
}
|
|
1064
1065
|
|
|
1065
1066
|
.agent-attach-thumb {
|
|
@@ -1105,7 +1106,7 @@
|
|
|
1105
1106
|
border: 1px solid var(--agent-accent-edge);
|
|
1106
1107
|
border-radius: var(--agent-radius-md);
|
|
1107
1108
|
background: var(--agent-accent-deep);
|
|
1108
|
-
color: #e6e9ff;
|
|
1109
|
+
color: var(--agent-text-strong, #e6e9ff);
|
|
1109
1110
|
padding: var(--agent-space-2) var(--agent-space-5);
|
|
1110
1111
|
font: inherit;
|
|
1111
1112
|
font-size: var(--agent-font-md);
|
|
@@ -1169,3 +1170,4 @@
|
|
|
1169
1170
|
|
|
1170
1171
|
.agent-resize { display: none; }
|
|
1171
1172
|
}
|
|
1173
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
@layer legacy {
|
|
1
2
|
.cozy-scene-node {
|
|
2
3
|
position: relative;
|
|
3
4
|
width: 318px;
|
|
@@ -61,3 +62,4 @@
|
|
|
61
62
|
.cozy-scene-reactflow-handle-motion { top: 115px !important; }
|
|
62
63
|
.cozy-scene-reactflow-handle-render { top: 108px !important; }
|
|
63
64
|
.cozy-scene-reactflow-handle-scene { top: 140px !important; }
|
|
65
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
@layer legacy {
|
|
1
2
|
:root{font-family:Inter,ui-sans-serif,system-ui,-apple-system,"Segoe UI",sans-serif;color:#edf0fb;background:#101116;font-synthesis:none}*{box-sizing:border-box}body{margin:0;min-width:900px;background:#101116}#workflow-root{height:100vh}.workflow-app{height:100vh;display:flex;flex-direction:column;background:#101116;color:#edf0fb}.workflow-topbar{height:58px;display:flex;align-items:center;justify-content:space-between;padding:0 22px;border-bottom:1px solid #292d38;background:#171921}.workflow-brand{display:flex;align-items:center;gap:9px;font-size:14px;color:#afb4c6}.workflow-brand strong{font-size:14px;color:#f5f7ff}.workflow-brand-mark{display:grid;place-items:center;width:23px;height:23px;border-radius:7px;background:linear-gradient(135deg,#ef759d,#6c7cff);font-size:12px;font-weight:800;color:white}.workflow-divider{color:#555b70;margin-left:3px}.workflow-top-actions{display:flex;align-items:center;gap:9px}.workflow-top-actions button,.workflow-sidebar-bottom button,.workflow-sidebar-bottom a{border:1px solid #353a4a;border-radius:6px;background:#20232d;color:#c8ccdb;padding:7px 12px;font:inherit;font-size:12px;cursor:pointer;text-decoration:none}.workflow-top-actions button:hover,.workflow-sidebar-bottom button:hover,.workflow-sidebar-bottom a:hover{border-color:#606b9a;background:#2b3040}.workflow-status{display:flex;align-items:center;gap:7px;margin-right:8px;color:#7f879e;font-size:11px}.workflow-status i{width:6px;height:6px;border-radius:50%;background:#4dcda4;box-shadow:0 0 8px #4dcda4}.workflow-main{display:flex;flex:1;min-height:0}.workflow-sidebar{width:232px;display:flex;flex-direction:column;flex:none;padding:22px 14px;border-right:1px solid #292d38;background:#171921}.workflow-sidebar-title{font-size:12px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:#f3f5fd}.workflow-sidebar-copy{margin:8px 6px 18px 0;color:#737b92;line-height:1.5;font-size:11px}.workflow-node-menu{display:flex;flex-direction:column;gap:5px}.workflow-add-node{display:flex;align-items:center;gap:10px;width:100%;padding:9px 10px;border:1px solid transparent;border-radius:6px;background:transparent;color:#bcc2d4;font:inherit;font-size:12px;text-align:left;cursor:pointer}.workflow-add-node:hover{border-color:#373d50;background:#222631;color:#f5f7ff}.workflow-add-node span:nth-child(2){flex:1}.workflow-sidebar-bottom{display:flex;flex-direction:column;gap:8px;margin-top:auto}.workflow-sidebar-bottom button,.workflow-sidebar-bottom a{text-align:center;font-size:11px}.workflow-canvas{position:relative;flex:1;min-width:0}.workflow-canvas .react-flow{background:#11141c}.workflow-canvas .react-flow__controls{bottom:22px;left:20px;box-shadow:0 5px 18px #0005}.workflow-canvas .react-flow__controls-button{width:28px;height:28px;border-bottom:1px solid #323744;background:#20242e;fill:#aeb5c9;color:#aeb5c9}.workflow-canvas .react-flow__minimap{right:20px;bottom:20px;border:1px solid #353a49;border-radius:7px;overflow:hidden}.workflow-canvas-panel{margin:14px}.workflow-canvas-panel button{display:flex;align-items:center;gap:6px;padding:8px 11px;border:1px solid #454d70;border-radius:6px;background:#27304a;color:#e7eaff;font:inherit;font-size:11px;cursor:pointer}.workflow-node{position:relative;width:230px;overflow:visible;border:1px solid #3c4152;border-radius:9px;background:#20232d;box-shadow:0 10px 30px #0004;color:#e5e8f5}.workflow-node:hover{border-color:#6877bd}.workflow-node-header{display:flex;align-items:center;gap:8px;padding:10px 11px;border-bottom:1px solid #343946;background:#252935;border-radius:9px 9px 0 0;font-size:12px}.workflow-node-icon{display:grid;place-items:center;width:23px;height:23px;border-radius:6px;background:#303648;color:#aeb8ff}.workflow-node-image .workflow-node-icon{color:#67d8b6}.workflow-node-video .workflow-node-icon{color:#eca56e}.workflow-node-upload .workflow-node-icon{color:#c4a8ef}.workflow-node-concat .workflow-node-icon{color:#e3c969}.workflow-node-scene .workflow-node-icon{color:#ef82a7}.workflow-node-id{margin-left:auto;color:#6c7389;font:10px ui-monospace,monospace}.workflow-node-body{display:flex;flex-direction:column;gap:7px;padding:11px}.workflow-node label{color:#8d95ab;font-size:10px}.workflow-node input,.workflow-node textarea,.workflow-node select{width:100%;border:1px solid #3a3f4e;border-radius:5px;background:#171a21;color:#e5e8f5;padding:7px 8px;outline:0;font:inherit;font-size:11px;resize:vertical}.workflow-node input:focus,.workflow-node textarea:focus,.workflow-node select:focus{border-color:#707dce}.workflow-textarea{height:65px}.workflow-node-foot{display:flex;align-items:center;justify-content:space-between;margin-top:3px;color:#737b92;font-size:10px}.workflow-mini-button,.workflow-run-button{display:flex;align-items:center;gap:4px;border:1px solid #4c5aab;border-radius:5px;background:#303b71;color:#e6e9ff;padding:5px 8px;font:inherit;font-size:10px;cursor:pointer}.workflow-dropzone{display:flex;align-items:center;justify-content:center;gap:7px;height:74px;border:1px dashed #49516a;border-radius:6px;color:#78819c;font-size:10px;text-align:center}.workflow-upload{position:relative;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:5px;height:90px;border:1px dashed #525b79;border-radius:6px;color:#a89ce4;cursor:pointer}.workflow-upload input{position:absolute;inset:0;opacity:0;cursor:pointer}.workflow-schema-fields{display:flex;flex-direction:column;gap:6px;padding-top:4px;border-top:1px solid #323746}.workflow-schema-title{color:#8d95ab;font-size:9px;text-transform:uppercase;letter-spacing:.08em}.workflow-schema-fields label{display:flex;flex-direction:column;gap:4px}.workflow-schema-check{display:flex!important;flex-direction:row!important;align-items:center;gap:6px!important}.workflow-schema-check input{width:auto}.workflow-node-cost{margin-left:4px;color:#78d9b0}.workflow-hint{margin:0;color:#666e83;font-size:9px;line-height:1.35}.workflow-scene-preview{position:relative;display:flex;align-items:center;justify-content:center;height:80px;overflow:hidden;border:1px solid #3d4357;border-radius:6px;background:#171a23;color:#7b849e;font-size:10px}.workflow-scene-grid{position:absolute;inset:0;opacity:.32;background:linear-gradient(135deg,transparent 46%,#687090 47%,transparent 49%),linear-gradient(45deg,transparent 46%,#687090 47%,transparent 49%);background-size:22px 22px}.workflow-scene-preview span{position:relative}.workflow-scene-controls{display:flex;gap:4px}.workflow-scene-controls button{flex:1;border:1px solid #3b4050;border-radius:4px;background:#292d39;color:#9da5ba;padding:5px 2px;font:inherit;font-size:9px;cursor:pointer}.workflow-handle{width:9px;height:9px;border:2px solid #20232d;background:#8994ff}.workflow-handle.target{background:#4c566f}.workflow-node-image .workflow-handle{background:#44c2a4}.workflow-node-video .workflow-handle{background:#d9955b}.workflow-node-scene .workflow-handle{background:#ef759d}.workflow-node-upload .workflow-handle{background:#a88cdb}.workflow-video-preview{display:block;width:100%;max-height:150px;border:1px solid #3d4357;border-radius:6px;background:#11141c}.workflow-provider-hint{margin-top:-3px;color:#737b92;font-size:9px}
|
|
2
3
|
.workflow-node-search{width:100%;margin:0 0 8px;padding:8px 9px;border:1px solid #353a4a;border-radius:6px;background:#11141b;color:#e5e8f5;font:inherit;font-size:11px;outline:0}.workflow-node-search:focus{border-color:#707dce}.workflow-model-results{display:flex;flex-direction:column;gap:2px;margin:0 0 7px;padding:4px;border:1px solid #303545;border-radius:6px;background:#12151d}.workflow-model-results .workflow-hint{padding:6px}
|
|
3
4
|
.workflow-node-motion-input .workflow-node-icon{color:#79b5ed}.workflow-motion-upload{height:70px}.workflow-node-motion-input .workflow-handle{background:#79b5ed}
|
|
@@ -9,3 +10,4 @@
|
|
|
9
10
|
.workflow-node-shot-prompt .workflow-node-icon{color:#8fd4b0}.workflow-node-shot-prompt .workflow-handle{background:#8fd4b0}.workflow-shot-prompt-text{height:92px;font:11px ui-monospace,monospace;color:#cfe6da}.workflow-shot-prompt-copy{display:flex;align-items:center;justify-content:center;gap:5px;border:1px solid #4c8f7c;border-radius:5px;background:#25443c;color:#a9e6c8;padding:5px 8px;font:inherit;font-size:10px;cursor:pointer}.workflow-shot-prompt-copy:hover{border-color:#6fc0a2;background:#2e564b}
|
|
10
11
|
|
|
11
12
|
.workflow-warning{margin:0;padding:6px 7px;border:1px solid #8d6b3d;border-radius:5px;background:#2b2419;color:#e8c78c;font-size:9px;line-height:1.35}
|
|
13
|
+
}
|
|
Binary file
|
package/tools/ardy/bridge.mjs
CHANGED
|
@@ -37,9 +37,9 @@
|
|
|
37
37
|
import { createServer } from "node:http";
|
|
38
38
|
import { spawn } from "node:child_process";
|
|
39
39
|
import { randomBytes } from "node:crypto";
|
|
40
|
-
import { createReadStream, existsSync, readFileSync, statSync, writeFileSync } from "node:fs";
|
|
40
|
+
import { createReadStream, existsSync, readFileSync, realpathSync, statSync, writeFileSync } from "node:fs";
|
|
41
41
|
import { basename, dirname, join, resolve, sep } from "node:path";
|
|
42
|
-
import { fileURLToPath } from "node:url";
|
|
42
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
43
43
|
import { decodeMotionNpz } from "../../src/ardy/npz.js";
|
|
44
44
|
import { motionArraysToNpzMembers, replaceMotionSegment, writeNpz } from "./npz.mjs";
|
|
45
45
|
import { globalChildren, killGroup, runStreaming, track } from "./runners/proc.mjs";
|
|
@@ -781,6 +781,16 @@ function registerMotion(runId, absPath) {
|
|
|
781
781
|
}
|
|
782
782
|
}
|
|
783
783
|
|
|
784
|
+
// The Studio agent runtime pins the artifact URL to this bridge's own origin
|
|
785
|
+
// (bin/agent/motion-runtime.mjs), so the editor page on the dev/launcher port
|
|
786
|
+
// fetches it cross-origin. Only loopback pages are granted read access.
|
|
787
|
+
const LOOPBACK_ORIGIN = /^http:\/\/(127\.0\.0\.1|localhost|\[::1\]):\d{1,5}$/;
|
|
788
|
+
|
|
789
|
+
/** CORS headers for a generated-motion download requested from `origin`. */
|
|
790
|
+
export function motionCorsHeaders(origin) {
|
|
791
|
+
return LOOPBACK_ORIGIN.test(origin ?? "") ? { "Access-Control-Allow-Origin": origin } : {};
|
|
792
|
+
}
|
|
793
|
+
|
|
784
794
|
// Serves /ardy/motions/<run-id>; returns the HTTP status to log.
|
|
785
795
|
function serveMotion(req, res, pathname) {
|
|
786
796
|
const match = /^\/ardy\/motions\/([^/]+)$/.exec(pathname);
|
|
@@ -813,6 +823,8 @@ function serveMotion(req, res, pathname) {
|
|
|
813
823
|
"Content-Length": size,
|
|
814
824
|
"Content-Disposition": `attachment; filename="${basename(absPath)}"`,
|
|
815
825
|
"Cache-Control": "no-store",
|
|
826
|
+
Vary: "Origin",
|
|
827
|
+
...motionCorsHeaders(req.headers.origin),
|
|
816
828
|
});
|
|
817
829
|
createReadStream(absPath)
|
|
818
830
|
.on("error", (err) => {
|
|
@@ -1559,156 +1571,162 @@ if (process.env.COZYCLAY_BRIDGE_PORT !== undefined) {
|
|
|
1559
1571
|
return DEFAULT_PORT;
|
|
1560
1572
|
}
|
|
1561
1573
|
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
}
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
//
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
}
|
|
1574
|
+
// Importing the module (tests) must not bind a port or pick a runner.
|
|
1575
|
+
function startBridge() {
|
|
1576
|
+
const port = resolvePort(process.argv.slice(2));
|
|
1577
|
+
try {
|
|
1578
|
+
runner = createRunner();
|
|
1579
|
+
} catch (err) {
|
|
1580
|
+
die(err.message);
|
|
1581
|
+
}
|
|
1582
|
+
// Beside the selected backend, never instead of it. A missing ProjFlow
|
|
1583
|
+
// configuration is NOT fatal — the bridge's other run modes do not need it —
|
|
1584
|
+
// so the failure is reported once at startup and the capability stays off.
|
|
1585
|
+
try {
|
|
1586
|
+
projflowRunner = createProjflowRunner();
|
|
1587
|
+
} catch (err) {
|
|
1588
|
+
console.error(`[bridge] line editing is unavailable: ${err.message}`);
|
|
1589
|
+
}
|
|
1576
1590
|
|
|
1577
|
-
const server = createServer((req, res) => {
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1591
|
+
const server = createServer((req, res) => {
|
|
1592
|
+
const started = Date.now();
|
|
1593
|
+
const pathname = (req.url || "/").split("?")[0];
|
|
1594
|
+
const log = (status) => {
|
|
1595
|
+
console.log(`[bridge] ${req.method} ${pathname} -> ${status} (${Date.now() - started} ms)`);
|
|
1596
|
+
};
|
|
1583
1597
|
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1598
|
+
if (req.method === "OPTIONS") {
|
|
1599
|
+
// 204 with NO CORS headers on purpose: a cross-origin browser
|
|
1600
|
+
// preflight must fail, and the same-origin Vite proxy never
|
|
1601
|
+
// preflights the bridge (it forwards server-side).
|
|
1602
|
+
res.writeHead(204);
|
|
1603
|
+
res.end();
|
|
1604
|
+
log(204);
|
|
1605
|
+
return;
|
|
1606
|
+
}
|
|
1607
|
+
if (pathname === "/ardy/health" && req.method === "GET") {
|
|
1608
|
+
// `capabilities` is how the app learns that an OPTIONAL run mode is wired
|
|
1609
|
+
// on this box. The draw-a-line affordance is gated on capabilities.lineEdit
|
|
1610
|
+
// (App.jsx accepts the object or an array spelling), so a bridge whose
|
|
1611
|
+
// ProjFlow env is missing keeps the feature dark instead of letting the
|
|
1612
|
+
// artist draw a stroke that would 503. Probed, never assumed.
|
|
1613
|
+
Promise.all([getHealth(), getLineEditCapability()])
|
|
1614
|
+
.then(([value, lineEdit]) => {
|
|
1615
|
+
sendJson(res, 200, {
|
|
1616
|
+
...value,
|
|
1617
|
+
extractionBackend: EXTRACT_BACKEND_SUPPORTED ? EXTRACT_BACKEND : "unsupported",
|
|
1618
|
+
capabilities: { lineEdit, extractionBackend: EXTRACT_BACKEND_SUPPORTED ? EXTRACT_BACKEND : "unsupported" },
|
|
1619
|
+
});
|
|
1620
|
+
log(200);
|
|
1621
|
+
})
|
|
1622
|
+
.catch((err) => {
|
|
1623
|
+
// The selected Kimodo route is configured even when its probe fails;
|
|
1624
|
+
// expose only the safe backend bucket and boolean configuration state.
|
|
1625
|
+
sendJson(res, 503, {
|
|
1626
|
+
ok: false,
|
|
1627
|
+
backend: "local_kimodo",
|
|
1628
|
+
host_configured: Boolean(process.env.CCLAY_KIMODO_HOST?.trim()),
|
|
1629
|
+
reason: err.message,
|
|
1630
|
+
});
|
|
1631
|
+
log(503);
|
|
1605
1632
|
});
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
reason: err.message
|
|
1633
|
+
return;
|
|
1634
|
+
}
|
|
1635
|
+
if (pathname === "/ardy/bases" && req.method === "GET") {
|
|
1636
|
+
getBases()
|
|
1637
|
+
.then((value) => {
|
|
1638
|
+
sendJson(res, 200, value);
|
|
1639
|
+
log(200);
|
|
1640
|
+
})
|
|
1641
|
+
.catch((err) => {
|
|
1642
|
+
sendJson(res, 503, { ok: false, reason: err.message });
|
|
1643
|
+
log(503);
|
|
1616
1644
|
});
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
respondInternalError(res, err, `${req.method} ${pathname}`)
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
pathname === "/ardy/bases" ||
|
|
1663
|
-
pathname === "/ardy/generate" ||
|
|
1664
|
-
pathname === "/ardy/footage" ||
|
|
1665
|
-
pathname === "/ardy/extract" ||
|
|
1666
|
-
/^\/ardy\/motions\//.test(pathname) ||
|
|
1667
|
-
/^\/ardy\/footage\//.test(pathname)
|
|
1668
|
-
) {
|
|
1669
|
-
sendJson(res, 405, { ok: false, reason: `method ${req.method} not allowed on ${pathname}` });
|
|
1670
|
-
log(405);
|
|
1671
|
-
return;
|
|
1672
|
-
}
|
|
1673
|
-
sendJson(res, 404, { ok: false, reason: `not found: ${req.method} ${pathname}` });
|
|
1674
|
-
log(404);
|
|
1675
|
-
});
|
|
1676
|
-
|
|
1677
|
-
server.on("clientError", (err, socket) => {
|
|
1678
|
-
if (socket.writable) {
|
|
1679
|
-
socket.end("HTTP/1.1 400 Bad Request\r\nConnection: close\r\n\r\n");
|
|
1680
|
-
}
|
|
1681
|
-
console.error(`[bridge] client error: ${err.message}`);
|
|
1682
|
-
});
|
|
1645
|
+
return;
|
|
1646
|
+
}
|
|
1647
|
+
if (pathname === "/ardy/generate" && req.method === "POST") {
|
|
1648
|
+
handleGenerate(req, res).catch((err) => respondInternalError(res, err, `${req.method} ${pathname}`));
|
|
1649
|
+
return;
|
|
1650
|
+
}
|
|
1651
|
+
if (/^\/ardy\/motions\//.test(pathname) && req.method === "GET") {
|
|
1652
|
+
log(serveMotion(req, res, pathname));
|
|
1653
|
+
return;
|
|
1654
|
+
}
|
|
1655
|
+
if (pathname === "/ardy/footage" && req.method === "POST") {
|
|
1656
|
+
handleFootage(req, res, (request) => readBody(request, MAX_BODY_BYTES)).catch((err) =>
|
|
1657
|
+
respondInternalError(res, err, `${req.method} ${pathname}`),
|
|
1658
|
+
);
|
|
1659
|
+
return;
|
|
1660
|
+
}
|
|
1661
|
+
if (/^\/ardy\/footage\//.test(pathname) && req.method === "GET") {
|
|
1662
|
+
log(serveFootage(req, res, pathname));
|
|
1663
|
+
return;
|
|
1664
|
+
}
|
|
1665
|
+
if (pathname === "/ardy/extract" && req.method === "POST") {
|
|
1666
|
+
handleExtract(req, res, {
|
|
1667
|
+
readBody: (request) => readBody(request, MAX_BODY_BYTES),
|
|
1668
|
+
footagePath,
|
|
1669
|
+
registerMotion,
|
|
1670
|
+
artifactRoot: OUT_DIR,
|
|
1671
|
+
}).catch((err) => respondInternalError(res, err, `${req.method} ${pathname}`));
|
|
1672
|
+
return;
|
|
1673
|
+
}
|
|
1674
|
+
if (
|
|
1675
|
+
pathname === "/ardy/health" ||
|
|
1676
|
+
pathname === "/ardy/bases" ||
|
|
1677
|
+
pathname === "/ardy/generate" ||
|
|
1678
|
+
pathname === "/ardy/footage" ||
|
|
1679
|
+
pathname === "/ardy/extract" ||
|
|
1680
|
+
/^\/ardy\/motions\//.test(pathname) ||
|
|
1681
|
+
/^\/ardy\/footage\//.test(pathname)
|
|
1682
|
+
) {
|
|
1683
|
+
sendJson(res, 405, { ok: false, reason: `method ${req.method} not allowed on ${pathname}` });
|
|
1684
|
+
log(405);
|
|
1685
|
+
return;
|
|
1686
|
+
}
|
|
1687
|
+
sendJson(res, 404, { ok: false, reason: `not found: ${req.method} ${pathname}` });
|
|
1688
|
+
log(404);
|
|
1689
|
+
});
|
|
1683
1690
|
|
|
1684
|
-
server.
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
console.log(`[bridge] ${runner.mode} backend: ${runner.describe()}`);
|
|
1691
|
-
});
|
|
1691
|
+
server.on("clientError", (err, socket) => {
|
|
1692
|
+
if (socket.writable) {
|
|
1693
|
+
socket.end("HTTP/1.1 400 Bad Request\r\nConnection: close\r\n\r\n");
|
|
1694
|
+
}
|
|
1695
|
+
console.error(`[bridge] client error: ${err.message}`);
|
|
1696
|
+
});
|
|
1692
1697
|
|
|
1693
|
-
server.
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
} else {
|
|
1702
|
-
process.exit(1);
|
|
1703
|
-
}
|
|
1704
|
-
});
|
|
1698
|
+
server.listen(port, BIND_HOST, () => {
|
|
1699
|
+
const address = server.address();
|
|
1700
|
+
const boundPort = typeof address === "object" && address ? address.port : port;
|
|
1701
|
+
process.send?.({ type: "cozyclay-bridge-ready", port: boundPort });
|
|
1702
|
+
console.log(`[bridge] motion dev bridge listening on http://${BIND_HOST}:${boundPort}`);
|
|
1703
|
+
console.log("[bridge] dev-only sidecar: the static dist/ build does not need it; stop with Ctrl-C");
|
|
1704
|
+
console.log(`[bridge] ${runner.mode} backend: ${runner.describe()}`);
|
|
1705
|
+
});
|
|
1705
1706
|
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
process.
|
|
1707
|
+
server.on("error", (err) => {
|
|
1708
|
+
const override = "set COZYCLAY_BRIDGE_PORT to a free port or pass --port <n>";
|
|
1709
|
+
console.error(
|
|
1710
|
+
`[bridge] cannot listen on ${BIND_HOST}:${port}: ${err.message}` +
|
|
1711
|
+
(err?.code === "EADDRINUSE" ? `; ${override}` : ""),
|
|
1712
|
+
);
|
|
1713
|
+
if (process.send && process.connected) {
|
|
1714
|
+
process.send({ type: "cozyclay-bridge-listen-error", port, code: err?.code }, () => process.exit(1));
|
|
1715
|
+
} else {
|
|
1716
|
+
process.exit(1);
|
|
1717
|
+
}
|
|
1713
1718
|
});
|
|
1719
|
+
|
|
1720
|
+
// Ctrl-C / SIGTERM: take the in-flight process groups down with us; ssh dies,
|
|
1721
|
+
// sshd closes the session, and the remote generation is not orphaned.
|
|
1722
|
+
for (const signal of ["SIGINT", "SIGTERM"]) {
|
|
1723
|
+
process.on(signal, () => {
|
|
1724
|
+
console.error(`[bridge] received ${signal}; killing ${globalChildren.size} in-flight child process group(s)`);
|
|
1725
|
+
for (const child of globalChildren) killGroup(child);
|
|
1726
|
+
process.exit(signal === "SIGINT" ? 130 : 143);
|
|
1727
|
+
});
|
|
1728
|
+
}
|
|
1714
1729
|
}
|
|
1730
|
+
|
|
1731
|
+
const isEntry = Boolean(process.argv[1]) && import.meta.url === pathToFileURL(realpathSync(process.argv[1])).href;
|
|
1732
|
+
if (isEntry) startBridge();
|
package/tools/ardy/visual-qa.mjs
CHANGED
|
@@ -78,7 +78,7 @@ await sleep(6000);
|
|
|
78
78
|
|
|
79
79
|
// Prompt Blocks replaced the old single "Generate motion" field. Select the
|
|
80
80
|
// first character, open the Prompt Blocks foldout, then add a block before
|
|
81
|
-
// looking for its prompt input and
|
|
81
|
+
// looking for its prompt input and the top-bar Generate Motion action.
|
|
82
82
|
await evaluate(tab, `(() => {
|
|
83
83
|
const character = [...document.querySelectorAll('.hierarchy-row')].find((row) => /Character 1|Subject 1|인물 1/.test(row.textContent));
|
|
84
84
|
character?.click();
|
|
@@ -92,8 +92,8 @@ await sleep(400);
|
|
|
92
92
|
const state0 = await evaluate(tab, `(() => {
|
|
93
93
|
const seed = document.querySelector('input[placeholder="empty = random"]');
|
|
94
94
|
const promptEl = document.querySelector('input[placeholder*="motion block"], input[placeholder*="모션 블록"]');
|
|
95
|
-
const gen = document.querySelector('
|
|
96
|
-
return { seedValue: seed?.value ?? null, hasGenerate: !!gen, generateDisabled:
|
|
95
|
+
const gen = document.querySelector('[data-testid=topbar-generate]');
|
|
96
|
+
return { seedValue: seed?.value ?? null, hasGenerate: !!gen, generateDisabled: gen?.getAttribute('aria-disabled') === 'true', hasPrompt: !!promptEl };
|
|
97
97
|
})()`);
|
|
98
98
|
console.log("initial:", JSON.stringify(state0));
|
|
99
99
|
|
|
@@ -119,8 +119,8 @@ for (const key of ["a", " ", "p", "e", "r", "s", "o", "n", " ", "w", "a", "l", "
|
|
|
119
119
|
await sleep(300);
|
|
120
120
|
await shot(tab, "01-before-generate");
|
|
121
121
|
const clicked = await evaluate(tab, `(() => {
|
|
122
|
-
const gen = document.querySelector('
|
|
123
|
-
if (!gen || gen.disabled) return false;
|
|
122
|
+
const gen = document.querySelector('[data-testid=topbar-generate]');
|
|
123
|
+
if (!gen || gen.getAttribute('aria-disabled') === 'true') return false;
|
|
124
124
|
gen.click();
|
|
125
125
|
return true;
|
|
126
126
|
})()`);
|