cozyclay 3.0.3 → 3.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +93 -0
- package/INSTALL_FOR_AGENTS.md +146 -0
- package/README.md +74 -192
- package/THIRD_PARTY_NOTICES.md +0 -21
- package/bin/agent/agent-routes.mjs +29 -62
- package/bin/agent/agent-runner.mjs +5 -3
- package/bin/agent/main-agent.mjs +70 -0
- package/bin/agent/main-prompt.mjs +17 -0
- package/bin/agent/plan-tool.mjs +114 -0
- package/bin/agent/script-tool.mjs +2 -0
- package/bin/agent/sculpt-sketch.mjs +190 -0
- package/bin/agent/session-store.mjs +4 -3
- package/bin/agent/sketch-code.mjs +151 -0
- package/bin/agent/sketch-sandbox.mjs +102 -0
- package/bin/agent/studio-prompt.mjs +1 -1
- package/bin/agent/studio-task-routes.mjs +185 -0
- package/bin/agent/studio-tasks.mjs +156 -0
- package/bin/agent/studio-tools.mjs +3 -2
- package/bin/agent/studio-turn-transaction.mjs +76 -0
- package/bin/agent/turn-frames.mjs +4 -0
- package/bin/cozyclay.mjs +5 -7
- package/dist/app/index.html +7 -6
- package/dist/assets/TaskBoard-ngdqiu7u.js +1 -0
- package/dist/assets/app-BlwOpest.css +1 -0
- package/dist/assets/app-DmR7jBkz.js +5144 -0
- package/dist/assets/compile-worker-D0pKioa0.js +5 -0
- package/dist/assets/landing-y3EqDgSZ.js +1 -0
- package/dist/assets/modulepreload-polyfill-P2Xu9kJm.js +1 -0
- package/dist/assets/motion3-compile-BB3_1-EB.js +1 -0
- package/dist/assets/scene-asset-sync-CBx7XRti.css +1 -0
- package/dist/assets/scene-asset-sync-Cgdtr1Yw.js +13 -0
- package/dist/assets/task-board-ErQvfoaz.js +14 -0
- package/dist/assets/workflow-zQM-EKW1.js +179 -0
- package/dist/assets/x-bot-tpose-body-BusyR3eg.json +1 -0
- package/dist/assets/y-bot-tpose-body-Dy1VKChZ.json +1 -0
- package/dist/cozyclay-package.json +1 -1
- package/dist/greybox-to-video/index.html +2 -3
- package/dist/index.html +7 -57
- package/dist/llms.txt +2 -1
- package/dist/previs-software/index.html +2 -2
- package/dist/privacy/index.html +3 -7
- package/dist/seedance-camera-control/index.html +2 -2
- package/dist/sitemap.xml +5 -5
- package/dist/sw.js +5 -1
- package/dist/thumbs/blank-stage-dark.webp +0 -0
- package/dist/thumbs/blank-stage-light.webp +0 -0
- package/dist/workflow/index.html +5 -4
- package/mcp/mesh-file.mjs +3 -1
- package/mcp/server.mjs +3 -0
- package/mcp/tool-handlers.mjs +2 -2
- package/package.json +5 -3
- package/src/App.jsx +51 -282
- package/src/analytics.js +3 -148
- package/src/app-stage.jsx +1 -1
- package/src/asset-pane.jsx +5 -10
- package/src/auto-flat.js +10 -0
- package/src/bus-tasks.js +11 -5
- package/src/command-bus.js +1 -1
- package/src/commands/elements.js +4 -3
- package/src/commands/motion3-compile.js +51 -27
- package/src/commands/motion3.js +3 -3
- package/src/commands/objects.js +1 -1
- package/src/commands/project.js +1 -1
- package/src/commands/shot.js +16 -4
- package/src/controls.jsx +0 -11
- package/src/cuts.js +11 -0
- package/src/domains/cast.js +3 -2
- package/src/domains/motion.js +3 -10
- package/src/domains/playback.js +32 -0
- package/src/domains/scenes.js +3 -22
- package/src/domains/shots.js +5 -5
- package/src/dualview.jsx +11 -15
- package/src/hierarchy-panel.css +18 -4
- package/src/hierarchy-panel.jsx +12 -11
- package/src/kits/held.js +3 -2
- package/src/light-blockers.js +2 -2
- package/src/main.jsx +5 -0
- package/src/material-look.js +189 -0
- package/src/material-presets.js +78 -0
- package/src/material-textures.js +157 -0
- package/src/motion/ground.js +5 -14
- package/src/motion/playback-frame-store.js +79 -0
- package/src/motion/playback-probe.js +16 -0
- package/src/motion/playback-subject.js +7 -0
- package/src/motion/timeline.css +43 -5
- package/src/motion/timeline.jsx +4 -3
- package/src/motion3/body.js +37 -5
- package/src/motion3/carried.js +11 -3
- package/src/motion3/compile-job.js +1 -1
- package/src/motion3/compiler/compile.js +7 -1
- package/src/motion3/compiler/finger-close.js +137 -0
- package/src/motion3/compiler/limbs.js +18 -3
- package/src/motion3/compiler/pose.js +6 -0
- package/src/motion3/compiler/validate-objects.js +17 -2
- package/src/motion3/compiler/validate-parts.js +2 -1
- package/src/motion3/compiler/vocab.js +4 -4
- package/src/motion3/describe.js +2 -2
- package/src/motion3/fix/index.js +5 -3
- package/src/motion3/flight.js +38 -0
- package/src/motion3/free-motion.js +10 -7
- package/src/motion3/load.js +125 -0
- package/src/motion3/mass.js +23 -0
- package/src/motion3/object-keys.js +11 -6
- package/src/motion3/object-pose.js +11 -3
- package/src/motion3/pipeline.js +3 -0
- package/src/motion3/qa/explain.js +3 -1
- package/src/motion3/qa/grasp-checks.js +123 -0
- package/src/motion3/qa/hints-grasp.js +71 -0
- package/src/motion3/qa/index.js +3 -1
- package/src/motion3/qa/object-checks.js +7 -2
- package/src/motion3/qa/patch.js +2 -1
- package/src/motion3/qa/spec-checks.js +10 -1
- package/src/motion3/schema/fields.js +3 -3
- package/src/motion3/schema/topics.js +9 -8
- package/src/motion3/schema/types.js +4 -1
- package/src/motion3/seat.js +84 -0
- package/src/motion3/settle.js +11 -6
- package/src/motion3/shapes.js +70 -0
- package/src/motion3/skills/catch.js +71 -0
- package/src/motion3/skills/index.js +10 -3
- package/src/motion3/skills/info.js +13 -0
- package/src/motion3/skills/throw.js +72 -0
- package/src/object-catalog.jsx +0 -4
- package/src/object-gizmo.jsx +2 -1
- package/src/object-look.js +9 -5
- package/src/object-path.js +1 -1
- package/src/panels/ProjectPanel.jsx +42 -21
- package/src/panels/details.css +15 -4
- package/src/popover.js +37 -0
- package/src/posestudio.jsx +15 -10
- package/src/primitive-look.js +38 -0
- package/src/project-browser-art.jsx +19 -0
- package/src/project-browser.css +74 -121
- package/src/project-browser.jsx +36 -60
- package/src/props.jsx +24 -35
- package/src/render-passes.js +7 -1
- package/src/retired-kinds.js +37 -0
- package/src/scene-objects.js +5 -9
- package/src/scenes.js +4 -5
- package/src/sculpt-colours.js +65 -0
- package/src/sculpt-compare.js +13 -50
- package/src/sculpt-csg.js +112 -0
- package/src/sculpt-curve.js +123 -0
- package/src/sculpt-cutters.js +43 -0
- package/src/sculpt-detail.js +207 -0
- package/src/sculpt-geometry-loft-convex.js +100 -0
- package/src/sculpt-geometry-shapes.js +250 -0
- package/src/sculpt-geometry.js +33 -15
- package/src/sculpt-loft-rings.js +225 -0
- package/src/sculpt-noise.js +65 -0
- package/src/sculpt-part-fields.js +27 -0
- package/src/sculpt-recipe-read.js +65 -0
- package/src/sculpt-recipe.js +33 -75
- package/src/sculpt-run.js +1 -1
- package/src/sculpt-scatter-items.js +183 -0
- package/src/sculpt-scatter-shape.js +57 -0
- package/src/sculpt-scatter.js +124 -0
- package/src/sculpt-shapes-curved.js +211 -0
- package/src/sculpt-shapes-loft-convex.js +218 -0
- package/src/sculpt-shapes.js +138 -0
- package/src/sculpt-sketch-state.js +76 -0
- package/src/sculpt-sketch.jsx +124 -0
- package/src/sculpt-surface-fields.js +65 -0
- package/src/settings-menu.jsx +1 -20
- package/src/shell/BottomDock.jsx +9 -9
- package/src/shell/MenuBar.jsx +1 -9
- package/src/shell/PreferencesDialog.jsx +3 -4
- package/src/shell/ViewportToolbar.jsx +3 -3
- package/src/shell/add-camera-shot.js +11 -0
- package/src/shell/glass-regions.css +3 -2
- package/src/shell/glass.css +0 -5
- package/src/shell/lens-scrub-math.js +51 -0
- package/src/shell/lens-scrub.css +73 -0
- package/src/shell/lens-scrub.jsx +98 -0
- package/src/shell/mode.css +6 -5
- package/src/shell/preferences.css +1 -32
- package/src/shell/shell.css +18 -1
- package/src/shell/studio-shell-context.js +5 -0
- package/src/shot-frame.js +26 -0
- package/src/stage-canvas-rigs.jsx +7 -8
- package/src/stage-characters.jsx +26 -0
- package/src/stage-gizmo.js +43 -0
- package/src/stage-labels-ko.js +0 -6
- package/src/stage-startup-defaults.js +3 -9
- package/src/starter-scenes.js +5 -11
- package/src/studio-agent-commands.js +2 -2
- package/src/studio-agent-protocol.js +2 -7
- package/src/studio-app-binding.js +1 -1
- package/src/studio-elements.js +6 -2
- package/src/styles/themes.css +13 -0
- package/src/styles.css +6 -674
- package/src/text/text-object.jsx +1 -1
- package/src/ui.jsx +8 -16
- package/src/use-embed-bridge.js +3 -6
- package/src/use-render-activity.js +3 -1
- package/src/view-ghosts.jsx +5 -3
- package/src/viewport-visible-rect.js +37 -0
- package/src/workflow/AgentPanel.jsx +79 -46
- package/src/workflow/AgentPlanCard.jsx +41 -0
- package/src/workflow/AgentProgressCard.jsx +1 -1
- package/src/workflow/TaskBoard.jsx +102 -0
- package/src/workflow/TaskInline.jsx +114 -0
- package/src/workflow/agent-client.js +25 -36
- package/src/workflow/agent-panel.css +14 -1
- package/src/workflow/agent-plan.css +93 -0
- package/src/workflow/agent-plan.js +59 -0
- package/src/workflow/attachment-image.js +10 -3
- package/src/workflow/attachment-video.js +91 -0
- package/src/workflow/task-board.css +98 -0
- package/src/workflow/task-board.js +169 -0
- package/tools/check-eslint.mjs +2 -1
- package/tools/check-knip.mjs +2 -1
- package/tools/dev/pages/greybox-to-video.html +2 -3
- package/tools/dev/pages/previs-software.html +2 -2
- package/tools/dev/pages/privacy.html +3 -7
- package/tools/dev/pages/seedance-camera-control.html +2 -2
- package/tools/dev-full.mjs +11 -2
- package/tools/eslint-baseline.json +6 -6
- package/tools/knip-baseline.json +0 -11
- package/tools/loc-baseline.json +30 -31
- package/tools/metrics-snapshot.mjs +43 -5
- package/tools/render-start-thumbs.mjs +175 -0
- package/tools/run-tests.mjs +10 -17
- package/tools/sitemap.mjs +1 -1
- package/dist/assets/analytics-BibyE5ar.js +0 -6
- package/dist/assets/app-DhRJ-PBz.js +0 -5088
- package/dist/assets/app-f-fkV5uP.css +0 -1
- package/dist/assets/compile-worker-DqiA4AaN.js +0 -5
- package/dist/assets/first-shot-handoff-Qx7SKl38.js +0 -1
- package/dist/assets/landing-DYg87MDY.js +0 -1
- package/dist/assets/scene-asset-sync-DBYQBR0T.js +0 -20
- package/dist/assets/scene-asset-sync-_S8NQl5B.css +0 -1
- package/dist/assets/workflow-BSA22Ofr.js +0 -179
- package/dist/scenes/city-block.cclayproject +0 -1
- package/src/burn-in.js +0 -91
- package/src/camera-tutorial.jsx +0 -520
- package/src/facing-marks.js +0 -88
- package/src/first-shot-handoff.js +0 -44
- package/src/panels/motion.css +0 -197
- package/src/set-pieces.jsx +0 -183
- package/src/tutorial-analytics.js +0 -86
- package/src/tutorial-walk.js +0 -17
- package/src/use-camera-tutorial.js +0 -50
- package/src/use-semantic-state.js +0 -12
- package/tools/metrics/archive-traffic.mjs +0 -138
- package/tools/perf/ik-camera-drag.mjs +0 -138
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/* Task mode in the chat (TaskInline.jsx): one quiet line per task, a count line under the header, the open task's
|
|
2
|
+
view over the chat, and the outliner mark on rows inside a running task. Studio tokens first, agent tokens after. */
|
|
3
|
+
.task-rows {
|
|
4
|
+
display: grid;
|
|
5
|
+
margin: 2px 0 2px 2px;
|
|
6
|
+
padding-left: 6px;
|
|
7
|
+
border-left: 2px solid var(--hairline, var(--agent-border, rgba(127, 127, 127, 0.25)));
|
|
8
|
+
min-width: 0;
|
|
9
|
+
}
|
|
10
|
+
.task-row {
|
|
11
|
+
display: flex;
|
|
12
|
+
align-items: center;
|
|
13
|
+
gap: 6px;
|
|
14
|
+
min-width: 0;
|
|
15
|
+
height: 24px;
|
|
16
|
+
padding: 0 6px;
|
|
17
|
+
border: 0;
|
|
18
|
+
border-radius: 6px;
|
|
19
|
+
background: none;
|
|
20
|
+
color: inherit;
|
|
21
|
+
font: inherit;
|
|
22
|
+
font-size: 12px;
|
|
23
|
+
text-align: left;
|
|
24
|
+
cursor: pointer;
|
|
25
|
+
}
|
|
26
|
+
.task-row:hover, .task-row:focus-visible { background: var(--chip-fill, rgba(127, 127, 127, 0.1)); outline: none; }
|
|
27
|
+
.task-row-title { flex: 0 1 auto; min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; font-weight: 550; }
|
|
28
|
+
.task-row-line { flex: 1 1 0; min-width: 64px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; color: var(--text-2, var(--agent-text-muted)); }
|
|
29
|
+
.task-row[data-status="failed"] .task-row-line { color: var(--danger, var(--agent-alert)); }
|
|
30
|
+
.task-row[data-status="cancelled"], .task-row[data-status="done"] .task-row-title { opacity: 0.8; }
|
|
31
|
+
|
|
32
|
+
.task-dot { flex: none; width: 7px; height: 7px; border-radius: 50%; background: var(--text-3, var(--agent-text-dim)); }
|
|
33
|
+
[data-status="running"] > .task-dot, [data-status="starting"] > .task-dot { background: var(--select, var(--agent-accent)); animation: task-dot-pulse 1.2s ease-in-out infinite; }
|
|
34
|
+
[data-status="waiting"] > .task-dot, [data-status="queued"] > .task-dot { background: none; box-shadow: inset 0 0 0 1.5px var(--text-3, var(--agent-text-dim)); }
|
|
35
|
+
[data-status="done"] > .task-dot { background: var(--ok, var(--agent-ok)); }
|
|
36
|
+
[data-status="failed"] > .task-dot, [data-status="paused"] > .task-dot { background: var(--danger, var(--agent-alert)); }
|
|
37
|
+
@keyframes task-dot-pulse { 50% { opacity: 0.35; } }
|
|
38
|
+
@media (prefers-reduced-motion: reduce) { [data-status] > .task-dot { animation: none; } }
|
|
39
|
+
|
|
40
|
+
.task-strip { flex: none; border-bottom: 1px solid var(--hairline, var(--agent-border, rgba(127, 127, 127, 0.2))); padding: 0 8px; }
|
|
41
|
+
.task-strip-head {
|
|
42
|
+
display: flex;
|
|
43
|
+
align-items: center;
|
|
44
|
+
gap: 10px;
|
|
45
|
+
width: 100%;
|
|
46
|
+
height: 26px;
|
|
47
|
+
padding: 0 6px;
|
|
48
|
+
border: 0;
|
|
49
|
+
background: none;
|
|
50
|
+
color: var(--text-2, var(--agent-text-muted));
|
|
51
|
+
font: inherit;
|
|
52
|
+
font-size: 11.5px;
|
|
53
|
+
cursor: pointer;
|
|
54
|
+
}
|
|
55
|
+
.task-strip-count { display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; }
|
|
56
|
+
.task-strip-caret { margin-left: auto; transition: transform 0.15s; }
|
|
57
|
+
.task-strip[data-expanded="true"] .task-strip-caret { transform: rotate(180deg); }
|
|
58
|
+
.task-strip-list { margin: 0 0 6px; max-height: 168px; overflow-y: auto; }
|
|
59
|
+
|
|
60
|
+
.task-detail {
|
|
61
|
+
position: absolute;
|
|
62
|
+
inset: 0;
|
|
63
|
+
z-index: 6;
|
|
64
|
+
display: flex;
|
|
65
|
+
flex-direction: column;
|
|
66
|
+
background: var(--surface-raised, var(--agent-bg));
|
|
67
|
+
border-radius: inherit;
|
|
68
|
+
}
|
|
69
|
+
.task-detail-head { display: flex; align-items: center; gap: 6px; height: 44px; padding: 0 10px; border-bottom: 1px solid var(--hairline, var(--agent-border)); }
|
|
70
|
+
.task-detail-back { display: inline-flex; align-items: center; gap: 2px; flex: none; }
|
|
71
|
+
.task-detail-title { min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; font-weight: 600; }
|
|
72
|
+
.task-detail-body { flex: 1; min-height: 0; overflow-y: auto; display: grid; align-content: start; gap: 6px; padding: 10px 14px; font-size: 12px; }
|
|
73
|
+
.task-detail-meta { display: flex; align-items: center; gap: 6px; color: var(--text-2, var(--agent-text-muted)); }
|
|
74
|
+
.task-detail-meta .agent-ghost-button { margin-left: auto; }
|
|
75
|
+
.task-detail-scope, .task-detail-reason, .task-detail-note, .task-detail-summary, .task-detail-notice { margin: 0; overflow-wrap: anywhere; }
|
|
76
|
+
.task-detail-scope, .task-detail-reason, .task-detail-note, .task-detail-notice { color: var(--text-2, var(--agent-text-muted)); }
|
|
77
|
+
.task-detail-steer { padding: 8px 10px 10px; border-top: 1px solid var(--hairline, var(--agent-border)); }
|
|
78
|
+
.task-detail-steer input {
|
|
79
|
+
width: 100%;
|
|
80
|
+
box-sizing: border-box;
|
|
81
|
+
padding: 7px 10px;
|
|
82
|
+
border: 1px solid var(--hairline, var(--agent-border));
|
|
83
|
+
border-radius: 10px;
|
|
84
|
+
background: transparent;
|
|
85
|
+
color: inherit;
|
|
86
|
+
font: inherit;
|
|
87
|
+
}
|
|
88
|
+
.task-frames { margin: 4px 0 0; padding-left: 18px; display: grid; gap: 2px; }
|
|
89
|
+
.task-frames li[data-kind="error"] { color: var(--danger, var(--agent-alert)); }
|
|
90
|
+
.task-frames li[data-kind="reply"], .task-frames li[data-kind="said"] { list-style: none; margin-left: -18px; }
|
|
91
|
+
.task-frames-empty { margin: 0; color: var(--text-3, var(--agent-text-dim)); }
|
|
92
|
+
|
|
93
|
+
[data-task-scope]::after {
|
|
94
|
+
content: "●";
|
|
95
|
+
margin-left: 6px;
|
|
96
|
+
color: var(--select, var(--agent-accent));
|
|
97
|
+
font-size: 9px;
|
|
98
|
+
}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
// The Studio task board in the agent panel (parallel tasks, P3). Task mode is a per-browser switch (the panel's Tasks
|
|
2
|
+
// toggle) or the server's COZYCLAY_STUDIO_TASKS flag: the chat then talks to the main agent (POST /agent/main), which
|
|
3
|
+
// answers at once and dispatches tasks; this board shows them. Pure parts here (the reducer, labels, the switch's
|
|
4
|
+
// storage); the network side is createTaskBoardClient; the view is TaskBoard.jsx.
|
|
5
|
+
// server events (GET /agent/main/<sessionId>/events): task.queued|waiting|started|resumed|paused|done|failed|cancelled
|
|
6
|
+
// carry the task's view { taskId, title, status, scope, reason?, turnId?, usage, summary? }; task.sceneChanged
|
|
7
|
+
// { taskId, keys, midCommand }; main.turn { turnId } (the main agent reporting on its own)
|
|
8
|
+
// editor events (the command bus): task.userEdit { taskId, keys } (the user changed something in its scope)
|
|
9
|
+
// compile activity (motion3-compile.js): { running, waiting } of { taskId, characterId }
|
|
10
|
+
import { ko } from "../locale.js";
|
|
11
|
+
import { sidecarUrl } from "../agent-image-client.js";
|
|
12
|
+
import { parseSseChunk } from "./agent-client.js";
|
|
13
|
+
|
|
14
|
+
const TASKS_KEY = "cozyclay.agent.tasks";
|
|
15
|
+
export function readStoredTaskMode(storage = globalThis.localStorage) {
|
|
16
|
+
try { return storage?.getItem(TASKS_KEY) === "on"; } catch { return false; }
|
|
17
|
+
}
|
|
18
|
+
export function storeTaskMode(enabled, storage = globalThis.localStorage) {
|
|
19
|
+
try { storage?.setItem(TASKS_KEY, enabled ? "on" : "off"); } catch { /* storage may be unavailable */ }
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export const TASK_STATUS_COPY = {
|
|
23
|
+
queued: ko("Queued", "대기열"),
|
|
24
|
+
waiting: ko("Waiting for scope", "영역 대기"),
|
|
25
|
+
starting: ko("Starting", "시작 중"),
|
|
26
|
+
running: ko("Running", "작업 중"),
|
|
27
|
+
paused: ko("Paused: Studio lost", "일시정지: Studio 연결 끊김"),
|
|
28
|
+
done: ko("Done", "완료"),
|
|
29
|
+
failed: ko("Failed", "실패"),
|
|
30
|
+
cancelled: ko("Cancelled", "취소됨"),
|
|
31
|
+
};
|
|
32
|
+
export const ACTIVE_STATUSES = new Set(["queued", "waiting", "starting", "running", "paused"]);
|
|
33
|
+
|
|
34
|
+
export const emptyBoard = () => ({ order: [], tasks: {}, after: 0 });
|
|
35
|
+
|
|
36
|
+
/** The board after one event (server, editor or compile). Unknown events leave it as it is. */
|
|
37
|
+
export function reduceBoard(board, event) {
|
|
38
|
+
if (!event || typeof event !== "object") return board;
|
|
39
|
+
const after = Number.isFinite(event.eventSeq) ? Math.max(board.after, event.eventSeq) : board.after;
|
|
40
|
+
const patch = (taskId, change) => {
|
|
41
|
+
const known = board.tasks[taskId];
|
|
42
|
+
if (!known && !change.title) return { ...board, after };
|
|
43
|
+
const task = { notes: [], ...known, ...change, taskId };
|
|
44
|
+
return { ...board, after, order: known ? board.order : [...board.order, taskId], tasks: { ...board.tasks, [taskId]: task } };
|
|
45
|
+
};
|
|
46
|
+
const note = (taskId, text) => (board.tasks[taskId] ? patch(taskId, { notes: [...board.tasks[taskId].notes, text].slice(-4) }) : { ...board, after });
|
|
47
|
+
if (event.type === "task.sceneChanged") return note(event.taskId, ko(`The scene changed during a reload: ${event.keys.join(", ")}`, `새로고침 중에 장면이 바뀜: ${event.keys.join(", ")}`));
|
|
48
|
+
if (event.type === "task.userEdit") return note(event.taskId, ko(`You changed ${event.keys.join(", ")}; the task reads it again`, `${event.keys.join(", ")}을(를) 직접 바꿈: 작업이 다시 읽어요`));
|
|
49
|
+
if (event.type === "task.undone") return board.tasks[event.taskId] ? patch(event.taskId, { undone: true }) : board;
|
|
50
|
+
if (typeof event.type === "string" && event.type.startsWith("task.") && event.taskId && event.status) {
|
|
51
|
+
const { type, at, eventSeq, ...view } = event;
|
|
52
|
+
return patch(event.taskId, { ...view, ...(type === "task.started" || type === "task.resumed" ? { progress: "" } : {}) });
|
|
53
|
+
}
|
|
54
|
+
return { ...board, after };
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** A board read (GET .../board) merged under what the events already said. */
|
|
58
|
+
export function seedBoard(board, tasks = []) {
|
|
59
|
+
return tasks.reduce((acc, view) => (acc.tasks[view.taskId] ? acc : reduceBoard(acc, { type: "task.seed", ...view })), board);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** The line a running card shows: the last tool it started, or the compile it waits for. */
|
|
63
|
+
export function progressLine(frame, labelOf = call => call.name) {
|
|
64
|
+
if (frame?.type === "tool.start") return labelOf(frame);
|
|
65
|
+
if (frame?.type === "error") return ko(`Error: ${frame.message ?? frame.code}`, `오류: ${frame.message ?? frame.code}`);
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** A task's wait or failure reason in the author's words: the server names the blocking task by id and title. */
|
|
70
|
+
export function taskReason(reason) {
|
|
71
|
+
// Greedy to the last ")": a title may hold parentheses of its own.
|
|
72
|
+
const after = /(?:waits for|held by) task \S+ \((.+)\)/.exec(String(reason ?? ""))?.[1];
|
|
73
|
+
if (after) return ko(`Starts after "${after}"`, `'${after}' 끝나면 시작`);
|
|
74
|
+
if (/scope is held/.test(String(reason ?? ""))) return ko("Starts when another task frees its part", "다른 작업이 끝나면 시작");
|
|
75
|
+
return reason ?? "";
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/** The one line a task row shows after its title. */
|
|
79
|
+
export function taskLine(task) {
|
|
80
|
+
if (task.status === "running") return task.progress || ko("Working…", "작업 중…");
|
|
81
|
+
if (task.status === "done") return task.undone ? ko("Undone", "되돌림") : String(task.summary?.reply ?? "").split(/(?<=[.!?。])\s/)[0] || TASK_STATUS_COPY.done;
|
|
82
|
+
if (task.reason) return taskReason(task.reason);
|
|
83
|
+
return TASK_STATUS_COPY[task.status] ?? task.status;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const SCOPE_NAMES = { timeline: ko("timeline", "타임라인"), stage: ko("stage", "무대"), scene: ko("scene", "장면"), object: ko("object", "오브젝트"), character: ko("character", "캐릭터"), shot: ko("shot", "샷") };
|
|
87
|
+
/** A scope key (object:<id>, timeline, ...) as a word; the raw key stays in the tooltip. */
|
|
88
|
+
export const scopeLabel = key => SCOPE_NAMES[String(key).split(":")[0]] ?? String(key);
|
|
89
|
+
|
|
90
|
+
/** Rows by state for the status line: what needs a look first, then what runs, waits and ended. */
|
|
91
|
+
export function boardGroups(board) {
|
|
92
|
+
const groups = { failed: [], running: [], waiting: [], done: [] };
|
|
93
|
+
for (const id of board.order) {
|
|
94
|
+
const task = board.tasks[id];
|
|
95
|
+
const group = task.status === "failed" || task.status === "paused" ? "failed" : task.status === "running" || task.status === "starting" ? "running" : ACTIVE_STATUSES.has(task.status) ? "waiting" : "done";
|
|
96
|
+
groups[group].push(task);
|
|
97
|
+
}
|
|
98
|
+
return groups;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/** The task ids a turn's dispatch_task steps started, in order (a duplicate points at the task it repeats). */
|
|
102
|
+
export const dispatchedTaskIds = steps => (steps ?? []).filter(step => step.kind === "tool" && step.name === "dispatch_task")
|
|
103
|
+
.map(step => step.result?.taskId ?? step.result?.duplicateOf).filter(Boolean);
|
|
104
|
+
|
|
105
|
+
/** What the task view shares between the headless board (TaskBoard.jsx) and the rows in the chat (TaskInline.jsx). */
|
|
106
|
+
function createTaskViewStore() {
|
|
107
|
+
let state = { board: emptyBoard(), activity: null, client: null, undo: null, open: null };
|
|
108
|
+
const listeners = new Set();
|
|
109
|
+
return {
|
|
110
|
+
get: () => state,
|
|
111
|
+
set: patch => { state = { ...state, ...patch }; for (const listener of listeners) listener(); },
|
|
112
|
+
subscribe: listener => { listeners.add(listener); return () => listeners.delete(listener); },
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
// One agent panel per page, so one view.
|
|
116
|
+
export const taskView = createTaskViewStore();
|
|
117
|
+
|
|
118
|
+
/** "$0.12" for a task's cost, or "" when nothing is known yet. */
|
|
119
|
+
export const costLabel = usage => (Number.isFinite(usage?.cost) && usage.cost > 0 ? `$${usage.cost.toFixed(2)}` : "");
|
|
120
|
+
|
|
121
|
+
/** The compile a task waits for: how many of its compiles wait and how many run. */
|
|
122
|
+
export function compileState(activity, taskId) {
|
|
123
|
+
const mine = list => (list ?? []).filter(meta => meta?.taskId === taskId).length;
|
|
124
|
+
return { waiting: mine(activity?.waiting), running: mine(activity?.running) };
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/** The open scopes the editor's bus reports: taskId -> keys (task.begun / task.scope / task.finished|cancelled). */
|
|
128
|
+
export function reduceScopes(scopes, event) {
|
|
129
|
+
if (event?.type === "task.begun" || event?.type === "task.scope") return { ...scopes, [event.taskId]: event.scope ?? [] };
|
|
130
|
+
if (event?.type === "task.finished" || event?.type === "task.cancelled") { const { [event.taskId]: _gone, ...rest } = scopes; return rest; }
|
|
131
|
+
return scopes;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* The sidecar side of the board. All requests are same-origin with the Studio session's owner cookie.
|
|
136
|
+
* fetchImpl(url, init) -> Response; url(path) -> the sidecar URL.
|
|
137
|
+
*/
|
|
138
|
+
export function createTaskBoardClient({ fetchImpl = globalThis.fetch?.bind(globalThis), url = sidecarUrl } = {}) {
|
|
139
|
+
const json = async (path, init) => {
|
|
140
|
+
const response = await fetchImpl(url(path), { credentials: "same-origin", headers: { accept: "application/json", "content-type": "application/json" }, ...init });
|
|
141
|
+
const body = await response.json().catch(() => ({}));
|
|
142
|
+
if (!response.ok) throw Object.assign(new Error(body?.error?.message ?? `${response.status}`), { status: response.status, code: body?.error?.code });
|
|
143
|
+
return body;
|
|
144
|
+
};
|
|
145
|
+
/** Streams an SSE route to onEvent until it ends or signal aborts. */
|
|
146
|
+
async function stream(path, onEvent, signal) {
|
|
147
|
+
const response = await fetchImpl(url(path), { credentials: "same-origin", headers: { accept: "text/event-stream" }, signal });
|
|
148
|
+
if (!response.ok || !response.body) throw Object.assign(new Error(`${response.status}`), { status: response.status });
|
|
149
|
+
const reader = response.body.getReader(), decoder = new TextDecoder();
|
|
150
|
+
let buffer = "";
|
|
151
|
+
try {
|
|
152
|
+
while (true) {
|
|
153
|
+
const { value, done } = await reader.read();
|
|
154
|
+
if (done) break;
|
|
155
|
+
const parsed = parseSseChunk(buffer + decoder.decode(value, { stream: true }));
|
|
156
|
+
buffer = parsed.tail;
|
|
157
|
+
for (const event of parsed.events) onEvent(event);
|
|
158
|
+
}
|
|
159
|
+
} finally { reader.releaseLock(); }
|
|
160
|
+
}
|
|
161
|
+
const id = value => encodeURIComponent(value);
|
|
162
|
+
return {
|
|
163
|
+
board: sessionId => json(`/agent/main/${id(sessionId)}/board`),
|
|
164
|
+
events: (sessionId, after, onEvent, signal) => stream(`/agent/main/${id(sessionId)}/events?after=${after}`, onEvent, signal),
|
|
165
|
+
frames: (turnId, onEvent, signal) => stream(`/agent/turn/${id(turnId)}/events?after=0`, onEvent, signal),
|
|
166
|
+
cancel: taskId => json(`/agent/task/${id(taskId)}/cancel`, { method: "POST", body: "{}" }),
|
|
167
|
+
steer: (taskId, text) => json(`/agent/task/${id(taskId)}/steer`, { method: "POST", body: JSON.stringify({ text }) }),
|
|
168
|
+
};
|
|
169
|
+
}
|
package/tools/check-eslint.mjs
CHANGED
|
@@ -10,7 +10,8 @@ import { fileURLToPath } from "node:url";
|
|
|
10
10
|
const root = join(dirname(fileURLToPath(import.meta.url)), "..");
|
|
11
11
|
const baselinePath = join(root, "tools", "eslint-baseline.json");
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
// Run the package's JS entry through node: the .bin shim is a .cmd on Windows, which spawnSync cannot start without a shell.
|
|
14
|
+
const run = spawnSync(process.execPath, [join(root, "node_modules", "eslint", "bin", "eslint.js"), ".", "--format", "json"], {
|
|
14
15
|
cwd: root,
|
|
15
16
|
encoding: "utf8",
|
|
16
17
|
maxBuffer: 512 * 1024 * 1024,
|
package/tools/check-knip.mjs
CHANGED
|
@@ -11,7 +11,8 @@ const root = join(dirname(fileURLToPath(import.meta.url)), '..');
|
|
|
11
11
|
const baselinePath = join(root, 'tools', 'knip-baseline.json');
|
|
12
12
|
|
|
13
13
|
// knip exits 1 when it finds issues; only a missing/unparseable report is a failure.
|
|
14
|
-
|
|
14
|
+
// Run the package's JS entry through node: the .bin shim is a .cmd on Windows, which spawnSync cannot start without a shell.
|
|
15
|
+
const run = spawnSync(process.execPath, [join(root, 'node_modules', 'knip', 'bin', 'knip.js'), '--reporter', 'json', '--no-progress'], {
|
|
15
16
|
cwd: root,
|
|
16
17
|
encoding: 'utf8',
|
|
17
18
|
maxBuffer: 256 * 1024 * 1024,
|
|
@@ -107,9 +107,8 @@
|
|
|
107
107
|
<h2>Do it in the browser</h2>
|
|
108
108
|
<p>
|
|
109
109
|
CozyClay is open source previs that runs in a Chromium tab. It exists for exactly this loop: block,
|
|
110
|
-
camera, export, generate. The <a href="/#try">playground on the home page</a>
|
|
111
|
-
|
|
112
|
-
opens that set on your machine.
|
|
110
|
+
camera, export, generate. The <a href="/#try">playground on the home page</a> runs the studio in the page, and
|
|
111
|
+
<code>npx cozyclay</code> runs it on your machine.
|
|
113
112
|
</p>
|
|
114
113
|
<div class="cta">
|
|
115
114
|
<a class="btn primary" href="/#try">Try it in your browser</a>
|
|
@@ -64,8 +64,8 @@
|
|
|
64
64
|
<p>
|
|
65
65
|
The honest split is time, not money. Blender can do everything on this page and will take an
|
|
66
66
|
afternoon to learn just the camera. CozyClay does one thing (block, camera, cut, export) and expects
|
|
67
|
-
you to be productive in the first ten minutes;
|
|
68
|
-
|
|
67
|
+
you to be productive in the first ten minutes; the <a href="/#try">playground on the home page</a>
|
|
68
|
+
runs it in the page.
|
|
69
69
|
</p>
|
|
70
70
|
</section>
|
|
71
71
|
|
|
@@ -86,12 +86,11 @@ cclay telemetry on</code></pre>
|
|
|
86
86
|
<thead><tr><th>Event</th><th>Purpose</th></tr></thead>
|
|
87
87
|
<tbody>
|
|
88
88
|
<tr><td>install:first_launch, app:session_started, app:session_ended</td><td>Counting installs and sessions; duration and action counts are bucketed. install:first_launch may carry heard_from (x, hn, reddit, github, friend, other, site or playground), from the first-launch prompt or a copied <code>npx cozyclay --via</code> command. app:session_ended also carries per-session edit gesture counts in five groups, pose_edit_bucket, camera_edit_bucket, object_edit_bucket, shot_edit_bucket and prompt_edit_bucket, each bucketed (0, 1-3, 4-10 or gte11); never what was edited</td></tr>
|
|
89
|
-
<tr><td>feature:used</td><td>One signal per feature per session: a fixed feature name such as pose_edit (a real bone or pose change), pose_save (saving a pose to the library),
|
|
89
|
+
<tr><td>feature:used</td><td>One signal per feature per session: a fixed feature name such as pose_edit (a real bone or pose change), pose_save (saving a pose to the library), camera_fly or export_video</td></tr>
|
|
90
90
|
<tr><td>$pageview, scene:created, scene:loaded, craft:first_action, activation:completed</td><td>Funnel and drop-off analysis</td></tr>
|
|
91
91
|
<tr><td>craft:first_edit</td><td>First successful Studio authoring change per editor mount; only a fixed edit-kind label and definition version 1 (not camera navigation, playback, loading, restore, or undo/redo)</td></tr>
|
|
92
92
|
<tr><td>playground:first_edit</td><td>The same versioned first-edit definition for Playground, counted separately from Studio; no prompts or scene contents</td></tr>
|
|
93
93
|
<tr><td>project:saved, project:opened</td><td>Whether people keep their work (object counts and ages are bucketed; never names or paths)</td></tr>
|
|
94
|
-
<tr><td>motion:backend_state</td><td>Session capability baseline: backend (none, local_kimodo or hosted) and boolean host_configured, never a host address</td></tr>
|
|
95
94
|
<tr><td>motion:generate_requested</td><td>Explicit generation intent, not prompt-block editing: initiating surface (timeline, line_edit, trail, mcp, fal_card or agent), input_mode (prompt, pose, edit, a_to_b or still) and an ephemeral random request_id</td></tr>
|
|
96
95
|
<tr><td>motion:preflight_blocked</td><td>Request readiness refusal: request_id, surface and normalized reason (unconfigured, unreachable, unsupported_route, locked or missing_input). locked means the AI video route is not enabled for the account yet; missing_input means the A/B captures were incomplete</td></tr>
|
|
97
96
|
<tr><td>motion:preflight_passed</td><td>Request readiness accepted, before job start: request_id, surface and backend (none, local_kimodo, hosted or fal)</td></tr>
|
|
@@ -117,10 +116,6 @@ cclay telemetry on</code></pre>
|
|
|
117
116
|
<tr><td>device:profile</td><td>Once per session, whether the studio can run smoothly: gpu_vendor (nvidia, amd, intel, apple, qualcomm, arm, software, other or unknown), gpu_class (discrete, integrated, software or unknown), webgl (webgl2, webgl1 or none), cpu_bucket (1-4, 5-8, 9-16, gte17 or unknown), memory_bucket (lt4, 4-7, gte8 or unknown) and frame_rate_bucket (lt20, 20-40, 40-55, gte55 or unknown) from one three-second sample. The GPU renderer string and exact hardware values never leave the browser.</td></tr>
|
|
118
117
|
<tr><td>survey:use_case</td><td>An optional question shown at most once after a successful export, only while telemetry is on: use_case (animation, film, game, ad_mv, personal, other or skip) and team (team, solo or skip). Closed choices only; no free text.</td></tr>
|
|
119
118
|
<tr><td>hosted:composer_viewed, hosted:login_started, hosted:ticket_created, hosted:result_opened, hosted:opened_in_studio</td><td>Hosted demo funnel</td></tr>
|
|
120
|
-
<tr><td>tutorial:started</td><td>Camera tutorial attempts on surface (studio or playground), with numeric tutorial_version 1 and start_source (query, settings or landing). Restarting starts a new attempt; no tutorial attempt identifier or user text is sent.</td></tr>
|
|
121
|
-
<tr><td>tutorial:step_entered, tutorial:dismissed</td><td>Entered steps and explicit dismissal of an unfinished tutorial; surface (studio or playground), numeric tutorial_version 1 and step_kind (fly, walk, dolly, orbit, shot, rail or play). Missing completion can indicate abandonment or missing telemetry; browser close does not promise a dismissal event.</td></tr>
|
|
122
|
-
<tr><td>tutorial:step_completed</td><td>One completion per step per attempt; surface (studio or playground), numeric tutorial_version 1, step_kind (fly, walk, dolly, orbit, shot, rail or play) and elapsed_bucket (lt1s, 1-3s, 3-10s, 10-30s or gte30s) since entering that step. No raw timing, prompts, scene contents, names or paths.</td></tr>
|
|
123
|
-
<tr><td>tutorial:completed</td><td>All seven steps completed; surface (studio or playground), numeric tutorial_version 1 and elapsed_bucket (lt1s, 1-3s, 3-10s, 10-30s or gte30s) since tutorial start. Sample loading and camera playback do not count as a user edit.</td></tr>
|
|
124
119
|
</tbody>
|
|
125
120
|
</table>
|
|
126
121
|
</div>
|
|
@@ -132,7 +127,8 @@ cclay telemetry on</code></pre>
|
|
|
132
127
|
<section>
|
|
133
128
|
<h2>The hosted demo (Google sign-in)</h2>
|
|
134
129
|
<p>
|
|
135
|
-
The hosted
|
|
130
|
+
The hosted demo is not open to the public right now. This section describes what it handled while it
|
|
131
|
+
was running. The hosted motion demo asks you to sign in with Google so that the daily generation cap can be
|
|
136
132
|
enforced per account. It receives your Google account's email address and basic profile only, stores
|
|
137
133
|
a session cookie signed by our server, and keeps your prompt and the generated result for up to 30
|
|
138
134
|
days so the ticket link keeps working. Results are stored on Cloudflare R2 and deleted after that
|
|
@@ -87,8 +87,8 @@
|
|
|
87
87
|
Any 3D tool that renders flat can make the reference. Blender works with a clay material and a
|
|
88
88
|
workbench render. CozyClay, open source and in the browser, exports the flat clip directly with the
|
|
89
89
|
delivery ratio and a camera timeline built in; the reel at the top of this page came out of it.
|
|
90
|
-
The <a href="/#try">home-page playground</a>
|
|
91
|
-
|
|
90
|
+
The <a href="/#try">home-page playground</a> runs the studio in the page, and
|
|
91
|
+
<code>npx cozyclay</code> runs it locally.
|
|
92
92
|
</p>
|
|
93
93
|
<div class="cta">
|
|
94
94
|
<a class="btn primary" href="/#try">Try it in your browser</a>
|
package/tools/dev-full.mjs
CHANGED
|
@@ -45,7 +45,6 @@ await new Promise((resolvePromise, reject) => {
|
|
|
45
45
|
});
|
|
46
46
|
|
|
47
47
|
const children = [];
|
|
48
|
-
const removeSignalCleanup = installSignalCleanup(() => children, () => {});
|
|
49
48
|
const agentHandler = createAgentHandler({ port: mainPort });
|
|
50
49
|
const oauthServer = createServer((req, res) => {
|
|
51
50
|
const path = (req.url || "").split("?")[0];
|
|
@@ -62,6 +61,16 @@ const oauthPort = configuredOAuthPort ? Number(configuredOAuthPort) : 0;
|
|
|
62
61
|
await new Promise((resolvePromise, reject) => { oauthServer.once("error", reject); oauthServer.listen({ port: oauthPort, host: "127.0.0.1" }, resolvePromise); });
|
|
63
62
|
const actualOAuthPort = oauthServer.address().port;
|
|
64
63
|
|
|
64
|
+
// The oauth/agent HTTP server and the agent's live hub (its own listener on
|
|
65
|
+
// COZYCLAY_LIVE_PORT) keep the event loop alive, so shutdown must close both
|
|
66
|
+
// (dropping open keep-alive/SSE sockets) or the process never exits.
|
|
67
|
+
const closeServers = async () => {
|
|
68
|
+
const httpClosed = new Promise((resolvePromise) => oauthServer.close(() => resolvePromise()));
|
|
69
|
+
oauthServer.closeAllConnections();
|
|
70
|
+
await Promise.allSettled([httpClosed, agentHandler.close()]);
|
|
71
|
+
};
|
|
72
|
+
const removeSignalCleanup = installSignalCleanup(() => children, closeServers);
|
|
73
|
+
|
|
65
74
|
const vite = spawnOwned(process.execPath, ["node_modules/vite/bin/vite.js", ...viteArgs], {
|
|
66
75
|
cwd: REPO,
|
|
67
76
|
env: {
|
|
@@ -77,7 +86,7 @@ const first = await Promise.race(
|
|
|
77
86
|
);
|
|
78
87
|
|
|
79
88
|
removeSignalCleanup();
|
|
80
|
-
await
|
|
89
|
+
await closeServers();
|
|
81
90
|
await Promise.allSettled(
|
|
82
91
|
children.filter((child) => child !== first.child).map((child) => terminateOwned(child)),
|
|
83
92
|
);
|
|
@@ -7,16 +7,16 @@
|
|
|
7
7
|
"no-regex-spaces": 2,
|
|
8
8
|
"no-undef": 24,
|
|
9
9
|
"no-unsafe-finally": 2,
|
|
10
|
-
"no-unused-vars":
|
|
11
|
-
"no-useless-assignment":
|
|
10
|
+
"no-unused-vars": 98,
|
|
11
|
+
"no-useless-assignment": 9,
|
|
12
12
|
"no-useless-escape": 6,
|
|
13
13
|
"preserve-caught-error": 6,
|
|
14
|
-
"react-hooks/immutability":
|
|
15
|
-
"react-hooks/preserve-manual-memoization":
|
|
14
|
+
"react-hooks/immutability": 81,
|
|
15
|
+
"react-hooks/preserve-manual-memoization": 28,
|
|
16
16
|
"react-hooks/purity": 5,
|
|
17
|
-
"react-hooks/refs":
|
|
17
|
+
"react-hooks/refs": 102,
|
|
18
18
|
"react-hooks/rules-of-hooks": 2,
|
|
19
|
-
"react-hooks/set-state-in-effect":
|
|
19
|
+
"react-hooks/set-state-in-effect": 26,
|
|
20
20
|
"react-hooks/use-memo": 1,
|
|
21
21
|
"require-yield": 2
|
|
22
22
|
}
|
package/tools/knip-baseline.json
CHANGED
|
@@ -7,14 +7,7 @@
|
|
|
7
7
|
"export mcp/image-file.mjs#REFERENCE_MAX_BYTES",
|
|
8
8
|
"export src/asset-pane.jsx#CHARACTER_ASSETS",
|
|
9
9
|
"export src/asset-pane.jsx#FolderGrid",
|
|
10
|
-
"export src/burn-in.js#burnInCapture",
|
|
11
10
|
"export src/camera-block.js#CAMERA_MODES",
|
|
12
|
-
"export src/camera-tutorial.jsx#CAMERA_TUTORIAL_STEPS",
|
|
13
|
-
"export src/camera-tutorial.jsx#GestureCue",
|
|
14
|
-
"export src/camera-tutorial.jsx#TUTORIAL_BEACONS",
|
|
15
|
-
"export src/camera-tutorial.jsx#TutorialBeacon",
|
|
16
|
-
"export src/camera-tutorial.jsx#WALK_KEYS",
|
|
17
|
-
"export src/camera-tutorial.jsx#default",
|
|
18
11
|
"export src/domains/motion.js#createMotionDomain",
|
|
19
12
|
"export src/domains/objects.js#createObjectsDomain",
|
|
20
13
|
"export src/grid-view.js#STAGE_BACKGROUND_LIGHT",
|
|
@@ -23,13 +16,10 @@
|
|
|
23
16
|
"export src/mesh-sniff.js#looksLikeObj",
|
|
24
17
|
"export src/mesh-sniff.js#readFbxVersion",
|
|
25
18
|
"export src/object-catalog.jsx#default",
|
|
26
|
-
"export src/object-path.js#MAX_PATH_HEIGHT",
|
|
27
19
|
"export src/project.js#storeProjectHandle",
|
|
28
20
|
"export src/range-pin-panel.jsx#RANGE_PIN_TRACKS",
|
|
29
21
|
"export src/scene-asset-cache.js#loadAssetTexture",
|
|
30
22
|
"export src/scene-mesh-cache.js#loadMeshScene",
|
|
31
|
-
"export src/scenes.js#CHARACTER_SCALE_MAX",
|
|
32
|
-
"export src/scenes.js#CHARACTER_SCALE_MIN",
|
|
33
23
|
"export src/scenes.js#LEGACY_FRAME_FPS",
|
|
34
24
|
"export src/scenes.js#toTimelineFrame",
|
|
35
25
|
"export src/stage-attach-frames.js#ATTACH_BONE_NAMES",
|
|
@@ -55,7 +45,6 @@
|
|
|
55
45
|
"export src/stage-editor-gizmos.jsx#GizmoLabel",
|
|
56
46
|
"export src/stage-editor-gizmos.jsx#prepareRailBend",
|
|
57
47
|
"export src/ui-scrub.js#SCRUB_RANGE_STEPS",
|
|
58
|
-
"export src/use-semantic-state.js#useSemanticState",
|
|
59
48
|
"export src/workflow/AgentPanel.jsx#AGENT_PANEL_RAIL_WIDTH",
|
|
60
49
|
"export src/workflow/AgentPanel.jsx#AGENT_STATES",
|
|
61
50
|
"export src/workflow/video-contract.js#falVideoContract",
|
package/tools/loc-baseline.json
CHANGED
|
@@ -1,34 +1,33 @@
|
|
|
1
1
|
{
|
|
2
|
-
"bin/agent/agent-routes.mjs":
|
|
3
|
-
"bin/agent/agent-runner.mjs":
|
|
4
|
-
"bin/agent/providers.mjs":
|
|
2
|
+
"bin/agent/agent-routes.mjs": 804,
|
|
3
|
+
"bin/agent/agent-runner.mjs": 495,
|
|
4
|
+
"bin/agent/providers.mjs": 338,
|
|
5
5
|
"bin/agent/session-store.mjs": 324,
|
|
6
6
|
"bin/agent/supervisor.mjs": 283,
|
|
7
7
|
"bin/agent/video-adapters.mjs": 334,
|
|
8
|
-
"bin/cozyclay.mjs":
|
|
8
|
+
"bin/cozyclay.mjs": 438,
|
|
9
9
|
"bin/live/cli.mjs": 456,
|
|
10
10
|
"mcp/live-hub.mjs": 529,
|
|
11
11
|
"mcp/tool-handlers.mjs": 1730,
|
|
12
|
-
"mcp/verify-live-batch.mjs":
|
|
12
|
+
"mcp/verify-live-batch.mjs": 485,
|
|
13
13
|
"mcp/verify-live-capture.mjs": 268,
|
|
14
14
|
"mcp/verify-live-controller.mjs": 340,
|
|
15
15
|
"mcp/verify-live-p0.mjs": 264,
|
|
16
16
|
"mcp/verify-live.mjs": 416,
|
|
17
|
-
"src/analytics.js":
|
|
18
|
-
"src/App.jsx":
|
|
19
|
-
"src/asset-pane.jsx":
|
|
17
|
+
"src/analytics.js": 1038,
|
|
18
|
+
"src/App.jsx": 4476,
|
|
19
|
+
"src/asset-pane.jsx": 643,
|
|
20
20
|
"src/camera-follow.js": 505,
|
|
21
21
|
"src/camera-move.js": 289,
|
|
22
|
-
"src/
|
|
23
|
-
"src/
|
|
24
|
-
"src/controls.jsx": 340,
|
|
22
|
+
"src/command-bus.js": 356,
|
|
23
|
+
"src/controls.jsx": 330,
|
|
25
24
|
"src/domains/cast.js": 717,
|
|
26
|
-
"src/domains/motion.js":
|
|
25
|
+
"src/domains/motion.js": 806,
|
|
27
26
|
"src/domains/objects.js": 907,
|
|
28
|
-
"src/domains/scenes.js":
|
|
27
|
+
"src/domains/scenes.js": 740,
|
|
29
28
|
"src/domains/shots.js": 411,
|
|
30
|
-
"src/dualview.jsx":
|
|
31
|
-
"src/hierarchy-panel.jsx":
|
|
29
|
+
"src/dualview.jsx": 365,
|
|
30
|
+
"src/hierarchy-panel.jsx": 777,
|
|
32
31
|
"src/live-control.js": 338,
|
|
33
32
|
"src/matte-editor.js": 486,
|
|
34
33
|
"src/matte.js": 472,
|
|
@@ -36,41 +35,41 @@
|
|
|
36
35
|
"src/motion/fix-collisions.js": 748,
|
|
37
36
|
"src/motion/ik.js": 1135,
|
|
38
37
|
"src/motion/range-pin.js": 277,
|
|
39
|
-
"src/motion/timeline.jsx":
|
|
40
|
-
"src/object-gizmo.jsx":
|
|
38
|
+
"src/motion/timeline.jsx": 2042,
|
|
39
|
+
"src/object-gizmo.jsx": 740,
|
|
41
40
|
"src/object-path.js": 410,
|
|
42
41
|
"src/panels/ObjectTransformPanel.jsx": 545,
|
|
43
42
|
"src/panels/SculptPanel.jsx": 370,
|
|
44
43
|
"src/planview.jsx": 887,
|
|
45
44
|
"src/poses.js": 321,
|
|
46
45
|
"src/posestudio.jsx": 1240,
|
|
47
|
-
"src/project-browser.jsx":
|
|
46
|
+
"src/project-browser.jsx": 371,
|
|
48
47
|
"src/project.js": 603,
|
|
49
|
-
"src/props.jsx":
|
|
48
|
+
"src/props.jsx": 414,
|
|
50
49
|
"src/range-pin-panel.jsx": 305,
|
|
51
50
|
"src/scene-assets.js": 400,
|
|
52
51
|
"src/scene-mesh.js": 350,
|
|
53
|
-
"src/scene-objects.js":
|
|
54
|
-
"src/scenes.js":
|
|
52
|
+
"src/scene-objects.js": 1134,
|
|
53
|
+
"src/scenes.js": 385,
|
|
55
54
|
"src/sculpt-compare.js": 357,
|
|
56
55
|
"src/sculpt-recipe.js": 363,
|
|
57
56
|
"src/sculpt-run.js": 309,
|
|
58
57
|
"src/shell/BoardSlot.jsx": 316,
|
|
59
58
|
"src/shell/BottomDock.jsx": 416,
|
|
60
59
|
"src/shell/DetailsSlot.jsx": 334,
|
|
61
|
-
"src/shell/MenuBar.jsx":
|
|
62
|
-
"src/shell/PreferencesDialog.jsx":
|
|
60
|
+
"src/shell/MenuBar.jsx": 632,
|
|
61
|
+
"src/shell/PreferencesDialog.jsx": 269,
|
|
63
62
|
"src/shell/ViewportToolbar.jsx": 567,
|
|
64
|
-
"src/shot-authoring.js":
|
|
65
|
-
"src/stage-canvas-rigs.jsx":
|
|
63
|
+
"src/shot-authoring.js": 345,
|
|
64
|
+
"src/stage-canvas-rigs.jsx": 350,
|
|
66
65
|
"src/stage-editor-gizmos.jsx": 1116,
|
|
67
|
-
"src/studio-agent-commands.js":
|
|
68
|
-
"src/studio-agent-protocol.js":
|
|
66
|
+
"src/studio-agent-commands.js": 487,
|
|
67
|
+
"src/studio-agent-protocol.js": 480,
|
|
69
68
|
"src/studio-app-binding.js": 346,
|
|
70
|
-
"src/ui.jsx":
|
|
71
|
-
"src/workflow/agent-client.js":
|
|
72
|
-
"src/workflow/AgentPanel.jsx":
|
|
69
|
+
"src/ui.jsx": 385,
|
|
70
|
+
"src/workflow/agent-client.js": 1369,
|
|
71
|
+
"src/workflow/AgentPanel.jsx": 811,
|
|
73
72
|
"src/workflow/WorkflowBuilder.jsx": 592,
|
|
74
73
|
"tools/qa/css-rule-usage.mjs": 251,
|
|
75
|
-
"tools/run-tests.mjs":
|
|
74
|
+
"tools/run-tests.mjs": 441
|
|
76
75
|
}
|