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.
Files changed (286) hide show
  1. package/CHANGELOG.md +171 -0
  2. package/bin/agent/agent-routes.mjs +74 -70
  3. package/bin/agent/agent-runner.mjs +10 -3
  4. package/bin/agent/motion-runtime.mjs +32 -260
  5. package/bin/agent/providers.mjs +46 -3
  6. package/bin/agent/session-store.mjs +41 -5
  7. package/bin/agent/studio-prompt.mjs +1 -1
  8. package/bin/agent/studio-tools.mjs +48 -11
  9. package/bin/cozyclay.mjs +26 -8
  10. package/bin/live/cli.mjs +22 -3
  11. package/bin/mcp-runtime.mjs +35 -20
  12. package/bin/telemetry-state.mjs +5 -2
  13. package/bin/update-check.mjs +15 -0
  14. package/dist/app/index.html +6 -6
  15. package/dist/assets/analytics-MVZOEW8O.js +1 -0
  16. package/dist/assets/app-C1sdVbg4.css +1 -0
  17. package/dist/assets/app-CA55tcI3.js +4876 -0
  18. package/dist/assets/{demo-B-eg1CT8.js → demo-ByeYp-dY.js} +1 -1
  19. package/dist/assets/{first-shot-handoff-CGgnvNu8.js → first-shot-handoff-DgT28ZiV.js} +1 -1
  20. package/dist/assets/{landing-IbRp3FnQ.js → landing-BaXkpFip.js} +1 -1
  21. package/dist/assets/shot-prompt-CbqWcWYi.css +1 -0
  22. package/dist/assets/shot-prompt-Yrt99wZx.js +17 -0
  23. package/dist/assets/{ticket-BgIzOBOf.js → ticket-BcmsnHn5.js} +1 -1
  24. package/dist/assets/workflow-DRdwoDBT.css +1 -0
  25. package/dist/assets/workflow-dNPGY9xz.js +179 -0
  26. package/dist/cozyclay-package.json +1 -1
  27. package/dist/fonts/IBM-Plex-Sans-OFL.txt +92 -0
  28. package/dist/fonts/JetBrains-Mono-OFL.txt +93 -0
  29. package/dist/fonts/README.md +13 -9
  30. package/dist/fonts/ibm-plex-sans-400-latin.woff2 +0 -0
  31. package/dist/fonts/ibm-plex-sans-500-latin.woff2 +0 -0
  32. package/dist/fonts/ibm-plex-sans-600-latin.woff2 +0 -0
  33. package/dist/fonts/jetbrains-mono-400-latin.woff2 +0 -0
  34. package/dist/fonts/jetbrains-mono-500-latin.woff2 +0 -0
  35. package/dist/index.html +7 -7
  36. package/dist/privacy/index.html +13 -8
  37. package/dist/sitemap.xml +6 -6
  38. package/dist/workflow/index.html +5 -5
  39. package/mcp/LIVE-PROTOCOL.md +1 -1
  40. package/mcp/live-hub.mjs +35 -93
  41. package/mcp/mesh-file.mjs +48 -0
  42. package/mcp/server.mjs +6 -77
  43. package/mcp/tool-handlers.mjs +224 -377
  44. package/package.json +2 -1
  45. package/src/App.jsx +1273 -9075
  46. package/src/analytics.js +393 -9
  47. package/src/app-context.js +211 -0
  48. package/src/app-stage.jsx +25 -24
  49. package/src/ardy/auto-fix-panel.css +108 -0
  50. package/src/ardy/collision-blockers.js +9 -3
  51. package/src/ardy/fix-collisions.js +10 -66
  52. package/src/ardy/ground.js +4 -4
  53. package/src/ardy/ik-drag.js +101 -0
  54. package/src/ardy/ik-key-json.js +43 -0
  55. package/src/ardy/ik.js +122 -76
  56. package/src/ardy/physics-panel.css +2 -0
  57. package/src/ardy/physics-panel.jsx +17 -5
  58. package/src/ardy/platform-fit-panel.css +64 -0
  59. package/src/ardy/platform-fit-panel.jsx +40 -0
  60. package/src/ardy/platform-fit.js +326 -0
  61. package/src/ardy/playback.js +166 -20
  62. package/src/ardy/range-pin.js +299 -0
  63. package/src/ardy/timeline-coordinates.js +26 -0
  64. package/src/ardy/timeline.css +1199 -0
  65. package/src/ardy/timeline.jsx +149 -41
  66. package/src/ardy/waypoints.js +2 -2
  67. package/src/asset-pane.css +462 -0
  68. package/src/asset-pane.jsx +461 -232
  69. package/src/command-bus.js +349 -0
  70. package/src/commands/ai.js +31 -0
  71. package/src/commands/cast.js +140 -0
  72. package/src/commands/elements/character.js +13 -0
  73. package/src/commands/elements/motion.js +14 -0
  74. package/src/commands/elements/object.js +22 -0
  75. package/src/commands/elements/scene.js +16 -0
  76. package/src/commands/elements/shot.js +9 -0
  77. package/src/commands/elements/stage.js +11 -0
  78. package/src/commands/elements.js +155 -0
  79. package/src/commands/export.js +20 -0
  80. package/src/commands/index.js +40 -0
  81. package/src/commands/motion.js +231 -0
  82. package/src/commands/objects.js +174 -0
  83. package/src/commands/project.js +53 -0
  84. package/src/commands/scene.js +81 -0
  85. package/src/commands/shared.js +19 -0
  86. package/src/commands/shot.js +103 -0
  87. package/src/commands/stage.js +17 -0
  88. package/src/commands/view.js +42 -0
  89. package/src/document-store.js +144 -0
  90. package/src/domains/cast.js +1007 -0
  91. package/src/domains/motion.js +3219 -0
  92. package/src/domains/objects.js +932 -0
  93. package/src/domains/scenes.js +817 -0
  94. package/src/domains/shots.js +404 -0
  95. package/src/domains/stage.js +93 -0
  96. package/src/dualview.jsx +113 -57
  97. package/src/facing-marks.js +3 -0
  98. package/src/first-success-guide.jsx +14 -14
  99. package/src/grid-view.js +18 -5
  100. package/src/hierarchy-model.js +24 -16
  101. package/src/hierarchy-panel.css +386 -0
  102. package/src/hierarchy-panel.jsx +150 -21
  103. package/src/{fal-motion-client.js → i2v-motion-client.js} +13 -13
  104. package/src/i2v-motion-studio.jsx +180 -0
  105. package/src/ik-camera.js +3 -0
  106. package/src/main.jsx +6 -0
  107. package/src/motion/generation.js +105 -0
  108. package/src/motion-readiness-ui.jsx +4 -4
  109. package/src/motion-readiness.js +11 -0
  110. package/src/motion-trail.js +366 -9
  111. package/src/object-gizmo.jsx +7 -1
  112. package/src/otio.js +2 -1
  113. package/src/panels/CameraPanel.jsx +60 -0
  114. package/src/panels/CharacterTransformPanel.jsx +48 -0
  115. package/src/panels/EnvironmentPanel.jsx +40 -0
  116. package/src/panels/Foldout.jsx +32 -0
  117. package/src/panels/LightPanel.jsx +24 -0
  118. package/src/panels/ObjectTransformPanel.jsx +554 -0
  119. package/src/panels/PosePanel.jsx +97 -0
  120. package/src/panels/ProjectPanel.jsx +33 -0
  121. package/src/panels/PromptBlocksPanel.jsx +442 -0
  122. package/src/panels/PropsPanel.jsx +70 -0
  123. package/src/panels/ReferenceImageField.jsx +91 -0
  124. package/src/panels/RigControlPanel.jsx +78 -0
  125. package/src/panels/RigPanel.jsx +37 -0
  126. package/src/panels/SubjectBox.jsx +47 -0
  127. package/src/panels/SubjectsPanel.jsx +39 -0
  128. package/src/panels/VideoCapturePanel.jsx +180 -0
  129. package/src/panels/details.css +1171 -0
  130. package/src/panels/motion.css +197 -0
  131. package/src/panels/pose.css +39 -0
  132. package/src/planview.jsx +60 -31
  133. package/src/posestudio.jsx +59 -4
  134. package/src/project-browser.css +1073 -0
  135. package/src/project-browser.jsx +284 -123
  136. package/src/range-pin-object-transform.js +19 -0
  137. package/src/range-pin-panel.css +518 -0
  138. package/src/range-pin-panel.jsx +344 -0
  139. package/src/result-modal.jsx +5 -5
  140. package/src/room.jsx +79 -51
  141. package/src/scene-objects.js +37 -1
  142. package/src/scenes.js +5 -0
  143. package/src/semantic-edit.js +2 -0
  144. package/src/settings-menu.jsx +39 -105
  145. package/src/shell/BottomDock.jsx +450 -0
  146. package/src/shell/DetailsSlot.jsx +513 -0
  147. package/src/shell/LibrarySlot.jsx +86 -0
  148. package/src/shell/MenuBar.jsx +601 -0
  149. package/src/shell/OutlinerSlot.jsx +50 -0
  150. package/src/shell/PreferencesDialog.jsx +538 -0
  151. package/src/shell/PreferencesSlot.jsx +40 -0
  152. package/src/shell/StatusBar.jsx +125 -0
  153. package/src/shell/StudioShell.jsx +92 -0
  154. package/src/shell/TopBar.jsx +129 -0
  155. package/src/shell/ViewportToolbar.jsx +656 -0
  156. package/src/shell/agent-glass.css +296 -0
  157. package/src/shell/dock.css +93 -0
  158. package/src/shell/glass-regions.css +985 -0
  159. package/src/shell/glass.css +687 -0
  160. package/src/shell/log-store.js +52 -0
  161. package/src/shell/mode.css +9 -0
  162. package/src/shell/preferences.css +651 -0
  163. package/src/shell/shell.css +282 -0
  164. package/src/shell/studio-shell-context.js +19 -0
  165. package/src/shell/topbar.css +435 -0
  166. package/src/shell/viewport.css +451 -0
  167. package/src/store/authored-intent.js +22 -0
  168. package/src/store/runtime-adapters.js +92 -0
  169. package/src/store/scene-stage.js +21 -0
  170. package/src/store/use-document-store.js +14 -0
  171. package/src/studio-actions.js +210 -0
  172. package/src/studio-agent-commands.js +41 -271
  173. package/src/studio-agent-context.js +39 -10
  174. package/src/studio-agent-motion.js +122 -373
  175. package/src/studio-agent-protocol.js +67 -31
  176. package/src/studio-app-binding.js +379 -0
  177. package/src/studio-contact-sheet.js +73 -0
  178. package/src/studio-elements.js +58 -51
  179. package/src/styles/themes.css +200 -0
  180. package/src/styles/tokens.css +69 -0
  181. package/src/styles.css +460 -1742
  182. package/src/theme.js +44 -0
  183. package/src/timeline-extent.js +16 -0
  184. package/src/trail-key-conflicts.js +39 -0
  185. package/src/trail-pick.js +59 -0
  186. package/src/ui.jsx +8 -8
  187. package/src/use-case-question.jsx +66 -0
  188. package/src/workflow/AgentPanel.jsx +82 -69
  189. package/src/workflow/agent-client.js +12 -2
  190. package/src/workflow/agent-panel.css +34 -32
  191. package/src/workflow/cozy-scene-node.css +2 -0
  192. package/src/workflow/workflow.css +2 -0
  193. package/tools/ardy/__pycache__/cclay_gvhmr_worker.cpython-313.pyc +0 -0
  194. package/tools/ardy/bridge.mjs +164 -146
  195. package/tools/ardy/visual-qa.mjs +5 -5
  196. package/tools/bench/EXP3.md +61 -0
  197. package/tools/bench/cclay_bench_extract_incam.py +125 -0
  198. package/tools/bench/cclay_bench_extract_obs.py +204 -0
  199. package/tools/bench/cclay_bench_runner.py +42 -0
  200. package/tools/bench/cube-contact.mjs +162 -0
  201. package/tools/bench/exp3.mjs +152 -0
  202. package/tools/bench/extract-bench-lib.mjs +216 -0
  203. package/tools/bench/extract-bench.mjs +302 -0
  204. package/tools/bench/fal-generate.mjs +88 -0
  205. package/tools/bench/fit/README.md +189 -0
  206. package/tools/bench/fit/camera.mjs +59 -0
  207. package/tools/bench/fit/contact.mjs +419 -0
  208. package/tools/bench/fit/footlock.mjs +234 -0
  209. package/tools/bench/fit/motion.mjs +85 -0
  210. package/tools/bench/fit/pin.mjs +27 -0
  211. package/tools/bench/fit/remote.mjs +105 -0
  212. package/tools/bench/fit-bench.mjs +126 -0
  213. package/tools/bench/fit-sanity.mjs +45 -0
  214. package/tools/bench/metrics.mjs +313 -0
  215. package/tools/bench/obs/depth.mjs +258 -0
  216. package/tools/bench/obs/extrinsics.mjs +175 -0
  217. package/tools/bench/obs/fit_mannequin_betas.py +340 -0
  218. package/tools/bench/obs/ground.mjs +294 -0
  219. package/tools/bench/obs/heading.mjs +151 -0
  220. package/tools/bench/obs/ladder.mjs +555 -0
  221. package/tools/bench/obs/mannequin-betas.json +124 -0
  222. package/tools/bench/obs/remote.mjs +83 -0
  223. package/tools/bench/obs/rest_joints.py +52 -0
  224. package/tools/bench/obs/ybot-targets.mjs +49 -0
  225. package/tools/bench/obs-bench.mjs +520 -0
  226. package/tools/bench/score.mjs +343 -0
  227. package/tools/bench/summarize.mjs +86 -0
  228. package/tools/dev/pages/privacy.html +13 -8
  229. package/tools/gt-render/browser.mjs +159 -0
  230. package/tools/gt-render/camera-math.mjs +276 -0
  231. package/tools/gt-render/page.mjs +267 -0
  232. package/tools/gt-render/render.mjs +514 -0
  233. package/tools/gt-render/scene-box.mjs +31 -0
  234. package/tools/gt-render/take-transform.mjs +87 -0
  235. package/tools/morphgs/assets/gen_truth.py +39 -0
  236. package/tools/morphgs/assets/mesh_ori_rig.txt +27 -0
  237. package/tools/morphgs/assets/playback-check.mjs +30 -0
  238. package/tools/morphgs/demo-gate.sh +26 -0
  239. package/tools/morphgs/fbx2morphgs.mjs +68 -0
  240. package/tools/morphgs/morphgs-to-cskel27.mjs +105 -0
  241. package/tools/morphgs/patches/preprocess_src-none-mode.patch +76 -0
  242. package/tools/morphgs/setup-on-cluster.sh +126 -0
  243. package/tools/qa/css-rule-usage.mjs +283 -0
  244. package/tools/qa/studio-control-count.mjs +70 -32
  245. package/tools/run-tests.mjs +134 -12
  246. package/tools/track/DESIGN.md +513 -0
  247. package/tools/track/backfill-provenance.mjs +116 -0
  248. package/tools/track/budget.mjs +8 -0
  249. package/tools/track/check-rig.mjs +209 -0
  250. package/tools/track/diagnostics.schema.json +60 -0
  251. package/tools/track/export-rig.mjs +256 -0
  252. package/tools/track/fallback.mjs +7 -0
  253. package/tools/track/fk-parity-fixture.mjs +161 -0
  254. package/tools/track/gate.mjs +349 -0
  255. package/tools/track/masks.mjs +318 -0
  256. package/tools/track/metrics.mjs +201 -0
  257. package/tools/track/publish-obs.mjs +108 -0
  258. package/tools/track/py/check_env.py +61 -0
  259. package/tools/track/py/eval_lr.py +229 -0
  260. package/tools/track/py/lr_viterbi.py +294 -0
  261. package/tools/track/py/masks.py +405 -0
  262. package/tools/track/py/objective.py +382 -0
  263. package/tools/track/py/rig.py +508 -0
  264. package/tools/track/py/scene.py +326 -0
  265. package/tools/track/py/test_joint_indices.py +123 -0
  266. package/tools/track/py/test_lr_viterbi.py +195 -0
  267. package/tools/track/py/test_masks.py +229 -0
  268. package/tools/track/py/test_rig.py +288 -0
  269. package/tools/track/py/test_scene.py +354 -0
  270. package/tools/track/py/test_track.py +328 -0
  271. package/tools/track/py/track.py +411 -0
  272. package/tools/track/remote.mjs +140 -0
  273. package/tools/track/rig-dump.mjs +227 -0
  274. package/tools/track/run-box-tests.mjs +14 -0
  275. package/tools/track/run-box.mjs +168 -0
  276. package/tools/track/setup-box.sh +59 -0
  277. package/tools/track/study-2d.mjs +728 -0
  278. package/dist/assets/analytics-B1hnH66c.js +0 -1
  279. package/dist/assets/app-BWusbqgO.js +0 -4861
  280. package/dist/assets/app-qKDo4PBX.css +0 -1
  281. package/dist/assets/shot-prompt-CHUtw6af.js +0 -17
  282. package/dist/assets/shot-prompt-C_g2BHVc.css +0 -1
  283. package/dist/assets/workflow-CVwzMhz2.js +0 -179
  284. package/dist/assets/workflow-DsudxKHF.css +0 -1
  285. package/src/fal-motion-studio.jsx +0 -180
  286. package/src/scene-history.js +0 -129
package/bin/cozyclay.mjs CHANGED
@@ -26,9 +26,9 @@ import { homedir } from "node:os";
26
26
  import { extname, join, normalize, resolve } from "node:path";
27
27
  import { createInterface } from "node:readline";
28
28
  import { fileURLToPath } from "node:url";
29
- import { runMcp } from "./mcp-runtime.mjs";
29
+ import { ensureMcpRuntime, runMcp } from "./mcp-runtime.mjs";
30
30
  import { openBrowser } from "./open-browser.mjs";
31
- import { checkForUpdate, runUpdate } from "./update-check.mjs";
31
+ import { checkForUpdate, readUpdateStatus, runUpdate } from "./update-check.mjs";
32
32
  import { handleOAuthRequest } from "./codex-auth.mjs";
33
33
  import { createAgentHandler } from "./agent/agent-routes.mjs";
34
34
  import { verifyPackageMarker } from "./package-signature.mjs";
@@ -42,6 +42,7 @@ import {
42
42
  setTelemetryInternalQa,
43
43
  takeRuntimeTelemetryConfig,
44
44
  TELEMETRY_NOTICE_VERSION,
45
+ FIRST_LAUNCH_SOURCES,
45
46
  } from "./telemetry-state.mjs";
46
47
 
47
48
  const PKG_ROOT = resolve(fileURLToPath(new URL("..", import.meta.url)));
@@ -101,6 +102,8 @@ function parseArgs(argv) {
101
102
  else if (arg.startsWith("--scene=")) opts.scene = arg.slice(8);
102
103
  else if (arg === "--no-star") opts.star = false;
103
104
  else if (arg === "--no-update-check") opts.updateCheck = false;
105
+ else if (arg === "--via") opts.via = String(argv[++i] ?? "");
106
+ else if (arg.startsWith("--via=")) opts.via = arg.slice(6);
104
107
  else if (arg === "--help" || arg === "-h") opts.help = true;
105
108
  else if (arg === "--version" || arg === "-v") opts.version = true;
106
109
  else {
@@ -114,6 +117,12 @@ function parseArgs(argv) {
114
117
  opts.help = true;
115
118
  opts.invalid = true;
116
119
  }
120
+ // Attribution never blocks a launch: an unknown source is dropped, not an error.
121
+ if (opts.via !== undefined) {
122
+ const via = String(opts.via).trim().toLowerCase();
123
+ opts.via = FIRST_LAUNCH_SOURCES.includes(via) ? via : null;
124
+ if (!opts.via) console.error(`cozyclay: ignoring --via ${via || "(empty)"}; expected one of ${FIRST_LAUNCH_SOURCES.join(", ")}`);
125
+ }
117
126
  if (opts.host !== "127.0.0.1") {
118
127
  console.error("cozyclay: --host is restricted to 127.0.0.1");
119
128
  opts.help = true;
@@ -133,12 +142,12 @@ async function askFirstLaunchSource() {
133
142
  if (!process.stdin.isTTY || !process.stdout.isTTY) return null;
134
143
  const answer = await new Promise((resolve) => {
135
144
  const rl = createInterface({ input: process.stdin, output: process.stdout });
136
- rl.question("How did you hear about CozyClay? [x/hn/reddit/github/friend/other/skip] ", (value) => {
145
+ rl.question("How did you hear about CozyClay? [x/hn/reddit/github/site/friend/other/skip] ", (value) => {
137
146
  rl.close();
138
147
  resolve(value.trim().toLowerCase());
139
148
  });
140
149
  });
141
- return ["x", "hn", "reddit", "github", "friend", "other"].includes(answer) ? answer : null;
150
+ return FIRST_LAUNCH_SOURCES.includes(answer) ? answer : null;
142
151
  }
143
152
 
144
153
  const HELP = `cozyclay - browser-based 3D staging studio
@@ -157,6 +166,9 @@ const HELP = `cozyclay - browser-based 3D staging studio
157
166
  npx cozyclay --no-star never ask about starring the repo
158
167
  npx cozyclay --no-update-check
159
168
  do not look for a newer release
169
+ npx cozyclay --via site say where you found CozyClay (site, playground, x,
170
+ hn, reddit, github, friend or other); recorded once,
171
+ with the anonymous first launch
160
172
  cclay telemetry status show anonymous telemetry status
161
173
  cclay telemetry off disable anonymous telemetry
162
174
  cclay telemetry on enable anonymous telemetry
@@ -339,7 +351,8 @@ let runtimeTelemetry = takeRuntimeTelemetryConfig(STATE_FILE, {
339
351
  installKind: INSTALL_KIND,
340
352
  });
341
353
  if (runtimeTelemetry.firstLaunch && !readTelemetryState(STATE_FILE).firstLaunchHeardFrom) {
342
- const heardFrom = await askFirstLaunchSource();
354
+ // A copied `--via` command already says where the install came from.
355
+ const heardFrom = opts.via || await askFirstLaunchSource();
343
356
  if (heardFrom) {
344
357
  setTelemetryFirstLaunchSource(STATE_FILE, heardFrom);
345
358
  runtimeTelemetry = takeRuntimeTelemetryConfig(STATE_FILE, {
@@ -362,7 +375,8 @@ if (
362
375
  }
363
376
  // Fired before anything blocking and never awaited on the launch path: the
364
377
  // notice is worth a line of output, never a second of startup.
365
- const updatePending = opts.updateCheck && !process.env.CI && !process.env.COZYCLAY_NO_UPDATE_CHECK ? checkForUpdate(version, STATE_DIR) : null;
378
+ const updateChecksEnabled = Boolean(opts.updateCheck && !process.env.CI && !process.env.COZYCLAY_NO_UPDATE_CHECK);
379
+ const updatePending = updateChecksEnabled ? checkForUpdate(version, STATE_DIR) : null;
366
380
  if (!existsSync(join(DIST, "app", "index.html"))) {
367
381
  console.error("cozyclay: this package is missing its build (dist/app/index.html).");
368
382
  console.error("cozyclay: from a clone, run `npm install && npm run build` first.");
@@ -427,7 +441,9 @@ if (opts.motion && kimodoHost && existsSync(BRIDGE)) {
427
441
  // substitute an environment/default port for a sidecar this launcher owns.
428
442
  const getBridgeOrigin = () => bridge && bridgePort !== null && bridge.exitCode === null && bridge.signalCode === null
429
443
  ? `http://127.0.0.1:${bridgePort}` : null;
430
- const agentHandler = createAgentHandler({ port: () => opts.port, getBridgeOrigin });
444
+ // A source checkout has mcp/node_modules; the package loads the Studio's live
445
+ // tools from the staged MCP runtime that `cclay mcp` also uses (#576).
446
+ const agentHandler = createAgentHandler({ port: () => opts.port, getBridgeOrigin, ...(SOURCE_CHECKOUT ? {} : { mcpRuntime: { ensure: ensureMcpRuntime } }) });
431
447
  server = createServer((req, res) => {
432
448
  const url = new URL(req.url ?? "/", "http://127.0.0.1");
433
449
  if (/^\/oauth\/(start|status|logout)$/.test(url.pathname)) {
@@ -522,7 +538,9 @@ server = createServer((req, res) => {
522
538
  officialPackage: OFFICIAL_PACKAGE,
523
539
  installKind: INSTALL_KIND,
524
540
  });
525
- const runtime = runtimeTelemetry;
541
+ // Whether this launch is the newest release, from the registry answer the
542
+ // update check already cached (#466). Never a request of its own.
543
+ const runtime = { ...runtimeTelemetry, updateStatus: updateChecksEnabled ? readUpdateStatus(version, STATE_DIR) : "unknown" };
526
544
  if (runtime.firstLaunch) {
527
545
  markTelemetryFirstLaunch(STATE_FILE);
528
546
  }
package/bin/live/cli.mjs CHANGED
@@ -32,6 +32,9 @@ const USAGE = `cclay live - drive a running CozyClay studio from a terminal
32
32
  cclay live verify --receipt <id> --checks placement,framing
33
33
  [--visual frame --out check.png]
34
34
  cclay live undo --receipt <id>
35
+ cclay live commands [--ids a,b] the commands the editor registers; ids add schemas
36
+ cclay live run <id> [--args '<json>'] any command the editor registers, admitted like
37
+ the agent's run_action; waits its declared timeout
35
38
  cclay live cmd <name> --args '<json>' any live-protocol command
36
39
  cclay live tool <name> --args '<json>' any registry tool, e.g. describe_shot
37
40
 
@@ -60,6 +63,8 @@ const VERBS = new Map([
60
63
  ["operate", { flags: ["--select", "--frame", "--mode", "--play", "--pause"] }],
61
64
  ["verify", { flags: ["--receipt", "--checks", "--visual", "--out"] }],
62
65
  ["undo", { flags: ["--receipt"] }],
66
+ ["commands", { flags: ["--ids"] }],
67
+ ["run", { flags: ["--args"], argument: "command id" }],
63
68
  ["cmd", { flags: ["--args"], argument: "command name" }],
64
69
  ["tool", { flags: ["--args"], argument: "tool name" }],
65
70
  ]);
@@ -314,10 +319,10 @@ async function runVerb({ client, verb, spec, name, flags }) {
314
319
  return { status: "unknown", reason: error.message };
315
320
  }
316
321
  };
317
- const admitted = async (commandName, args) => {
318
- const envelope = admissionEnvelope(commandName, args, (await command("inspect_studio", { scope: "selection" }))?.context);
322
+ const admitted = async (commandName, args, { context, options = forwarded } = {}) => {
323
+ const envelope = admissionEnvelope(commandName, args, context ?? (await command("inspect_studio", { scope: "selection" }))?.context);
319
324
  try {
320
- const value = await command(commandName, envelope);
325
+ const value = await command(commandName, envelope, options);
321
326
  if (value?.ok === false) throw receiptFailure(value);
322
327
  return value;
323
328
  } catch (error) {
@@ -430,6 +435,20 @@ async function runVerb({ client, verb, spec, name, flags }) {
430
435
 
431
436
  if (verb === "undo") return admitted("undo_edit", { receiptId: required(flags, "--receipt", verb) });
432
437
 
438
+ if (verb === "commands") {
439
+ const value = await command("inspect_studio", { scope: "actions", ...(flags.has("--ids") ? { ids: commaList(flags.get("--ids")) } : {}) });
440
+ return { actions: value?.actions ?? [] };
441
+ }
442
+
443
+ if (verb === "run") {
444
+ const args = flags.has("--args") ? jsonFlag(flags, "--args") : {};
445
+ // The editor declares the command: one read gives the context to admit
446
+ // at and the deadline it needs, which --timeout overrides.
447
+ const inspected = await command("inspect_studio", { scope: "actions", ids: [name] });
448
+ const deadline = timeoutMs ?? inspected?.actions?.find((row) => row.id === name)?.timeoutMs;
449
+ return admitted("run_action", { action: name, args }, { context: inspected?.context, options: deadline === undefined ? {} : { timeoutMs: deadline } });
450
+ }
451
+
433
452
  if (verb === "cmd") return raw(() => command(name, flags.has("--args") ? jsonFlag(flags, "--args") : {}));
434
453
 
435
454
  if (verb === "tool") {
@@ -90,30 +90,45 @@ function installMcpRuntime() {
90
90
  });
91
91
  }
92
92
 
93
- export async function runMcp(rest) {
93
+ /** The staged runtime root, installing it on first use. Every failure is an
94
+ * Error whose `code` names the stage (`MISSING_RUNTIME`, `INSTALL_FAILED`,
95
+ * `INCOMPLETE_RUNTIME`) and whose `lines` are the launcher's diagnostics; the
96
+ * Studio hub loader reports them and keeps serving, `cclay mcp` exits. */
97
+ export async function ensureMcpRuntime() {
94
98
  if (!existsSync(join(PKG_ROOT, "mcp", "server.mjs")) || !existsSync(join(MCP_RUNTIME_SOURCE, "package-lock.json"))) {
95
- console.error("cozyclay: this build does not include the MCP server runtime.");
96
- process.exit(1);
99
+ throw Object.assign(new Error("this build does not include the MCP server runtime."), { code: "MISSING_RUNTIME" });
97
100
  }
98
-
99
- let server;
100
101
  try {
101
- server = probeMcpRuntime();
102
+ probeMcpRuntime();
103
+ return MCP_RUNTIME;
102
104
  } catch {
103
- console.error("cozyclay: installing MCP server dependencies (one-time per CozyClay version)...");
104
- const result = await installMcpRuntime();
105
- if (result.code !== 0) {
106
- console.error(`cozyclay: npm ci failed${result.error ? `: ${result.error.message}` : ` (exit ${result.code})`}. Check your network connection and retry.`);
107
- console.error(`cozyclay: the published package was not changed; remove ${JSON.stringify(MCP_RUNTIME)} before retrying a damaged cache.`);
108
- process.exit(1);
109
- }
110
- try {
111
- server = probeMcpRuntime();
112
- } catch (error) {
113
- console.error(`cozyclay: MCP runtime is incomplete after npm ci: ${error.message}`);
114
- process.exit(1);
115
- }
105
+ // Installed below.
106
+ }
107
+ console.error("cozyclay: installing MCP server dependencies (one-time per CozyClay version)...");
108
+ const result = await installMcpRuntime();
109
+ if (result.code !== 0) {
110
+ throw Object.assign(
111
+ new Error(`npm ci failed${result.error ? `: ${result.error.message}` : ` (exit ${result.code})`}. Check your network connection and retry.`),
112
+ { code: "INSTALL_FAILED", lines: [`the published package was not changed; remove ${JSON.stringify(MCP_RUNTIME)} before retrying a damaged cache.`] },
113
+ );
114
+ }
115
+ try {
116
+ probeMcpRuntime();
117
+ } catch (error) {
118
+ throw Object.assign(new Error(`MCP runtime is incomplete after npm ci: ${error.message}`), { code: "INCOMPLETE_RUNTIME" });
119
+ }
120
+ return MCP_RUNTIME;
121
+ }
122
+
123
+ export async function runMcp(rest) {
124
+ let runtime;
125
+ try {
126
+ runtime = await ensureMcpRuntime();
127
+ } catch (error) {
128
+ console.error(`cozyclay: ${error.message}`);
129
+ for (const line of error.lines ?? []) console.error(`cozyclay: ${line}`);
130
+ process.exit(1);
116
131
  }
117
- const child = spawn(process.execPath, [server, ...rest], { stdio: "inherit" });
132
+ const child = spawn(process.execPath, [join(runtime, "mcp", "server.mjs"), ...rest], { stdio: "inherit" });
118
133
  child.on("exit", (code, signal) => process.exit(signal ? 1 : (code ?? 0)));
119
134
  }
@@ -5,6 +5,9 @@ import { dirname } from "node:path";
5
5
  export const TELEMETRY_NOTICE_VERSION = 1;
6
6
  export const POSTHOG_PROJECT_TOKEN = "phc_CpizzZ8VhSorSS8yEeQhdpUcvB2erp5xkCbnFD8HTJ5m";
7
7
  export const POSTHOG_API_HOST = "https://t.cozyclay.org";
8
+ // First-launch answers plus the `npx cozyclay --via <source>` values the
9
+ // landing page's copy commands carry (#466). Mirrors analytics HEARD_FROM_SOURCES.
10
+ export const FIRST_LAUNCH_SOURCES = Object.freeze(["x", "hn", "reddit", "github", "friend", "other", "site", "playground"]);
8
11
 
9
12
  const DEFAULT_STATE = Object.freeze({
10
13
  installationId: null,
@@ -38,7 +41,7 @@ function normalizedState(value) {
38
41
  noticeVersion: Number.isInteger(value.telemetryNoticeVersion)
39
42
  ? value.telemetryNoticeVersion
40
43
  : 0,
41
- firstLaunchHeardFrom: ["x", "hn", "reddit", "github", "friend", "other"].includes(value.telemetryFirstLaunchHeardFrom)
44
+ firstLaunchHeardFrom: FIRST_LAUNCH_SOURCES.includes(value.telemetryFirstLaunchHeardFrom)
42
45
  ? value.telemetryFirstLaunchHeardFrom
43
46
  : null,
44
47
  };
@@ -90,7 +93,7 @@ export function markTelemetryFirstLaunch(stateFile, now = () => new Date().toISO
90
93
  }
91
94
 
92
95
  export function setTelemetryFirstLaunchSource(stateFile, heardFrom) {
93
- if (!["x", "hn", "reddit", "github", "friend", "other"].includes(heardFrom)) return readTelemetryState(stateFile);
96
+ if (!FIRST_LAUNCH_SOURCES.includes(heardFrom)) return readTelemetryState(stateFile);
94
97
  writeState(stateFile, { telemetryFirstLaunchHeardFrom: heardFrom });
95
98
  return readTelemetryState(stateFile);
96
99
  }
@@ -119,6 +119,21 @@ export async function checkForUpdate(currentVersion, stateDir) {
119
119
  }
120
120
  }
121
121
 
122
+ /**
123
+ * "latest", "outdated" or "unknown" for the running version, read from the
124
+ * cache checkForUpdate keeps. Synchronous and offline: the studio page asks on
125
+ * every load, and a launch whose first check has not landed yet is "unknown".
126
+ */
127
+ export function readUpdateStatus(currentVersion, stateDir) {
128
+ try {
129
+ const latest = readCache(join(stateDir, "update-check.json"))?.latest;
130
+ if (typeof latest !== "string" || !/^\d+\.\d+\.\d+/.test(latest)) return "unknown";
131
+ return compareVersions(latest, currentVersion) > 0 ? "outdated" : "latest";
132
+ } catch {
133
+ return "unknown";
134
+ }
135
+ }
136
+
122
137
  // npx/bunx runs from a temp dir, so there is no local install to upgrade in
123
138
  // place; `npm install -g` is the one command that is right either way.
124
139
  export function runUpdate() {
@@ -34,13 +34,13 @@
34
34
  <title>CozyClay Studio — 3D staging and previs in your browser</title>
35
35
 
36
36
  <script defer src="https://static.cloudflareinsights.com/beacon.min.js" data-cf-beacon='{"token": "6a4384d1375d4ffc8a30a6346a8ad1a0"}'></script>
37
- <script type="module" crossorigin src="/assets/app-BWusbqgO.js"></script>
37
+ <script type="module" crossorigin src="/assets/app-CA55tcI3.js"></script>
38
38
  <link rel="modulepreload" crossorigin href="/assets/rolldown-runtime-hePW80VL.js">
39
- <link rel="modulepreload" crossorigin href="/assets/analytics-B1hnH66c.js">
40
- <link rel="modulepreload" crossorigin href="/assets/first-shot-handoff-CGgnvNu8.js">
41
- <link rel="modulepreload" crossorigin href="/assets/shot-prompt-CHUtw6af.js">
42
- <link rel="stylesheet" crossorigin href="/assets/shot-prompt-C_g2BHVc.css">
43
- <link rel="stylesheet" crossorigin href="/assets/app-qKDo4PBX.css">
39
+ <link rel="modulepreload" crossorigin href="/assets/analytics-MVZOEW8O.js">
40
+ <link rel="modulepreload" crossorigin href="/assets/first-shot-handoff-DgT28ZiV.js">
41
+ <link rel="modulepreload" crossorigin href="/assets/shot-prompt-Yrt99wZx.js">
42
+ <link rel="stylesheet" crossorigin href="/assets/shot-prompt-CbqWcWYi.css">
43
+ <link rel="stylesheet" crossorigin href="/assets/app-C1sdVbg4.css">
44
44
  </head>
45
45
  <body>
46
46
  <div id="root">
@@ -0,0 +1 @@
1
+ (function(){let e=document.createElement(`link`).relList;if(e&&e.supports&&e.supports(`modulepreload`))return;for(let e of document.querySelectorAll(`link[rel="modulepreload"]`))n(e);new MutationObserver(e=>{for(let t of e)if(t.type===`childList`)for(let e of t.addedNodes)e.tagName===`LINK`&&e.rel===`modulepreload`&&n(e)}).observe(document,{childList:!0,subtree:!0});function t(e){let t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),t.credentials=e.crossOrigin===`use-credentials`?`include`:e.crossOrigin===`anonymous`?`omit`:`same-origin`,t}function n(e){if(e.ep)return;e.ep=!0;let n=t(e);fetch(e.href,n)}})();var e=.02,t=(e,t,n)=>Math.min(n,Math.max(t,e)),n=(e,t=0)=>typeof e==`number`&&Number.isFinite(e)?e:t;function r(e){let t=0;for(let n=0;n<e.length-1;n+=1)t+=(e[n]+e[n+1])/2;return t}function i(e,n){let r=t(n,0,1)*(e.length-1),i=Math.min(e.length-2,Math.floor(r)),a=r-i;return e[i]*(1-a)+e[i+1]*a}function a(e,t=24){if(!e.length)return Array(t).fill(1);if(e.length===1)return Array(t).fill(e[0]);let n=Array(t);for(let r=0;r<t;r+=1)n[r]=i(e,r/(t-1));return n}function o(e){let t=e.map(e=>Math.max(0,n(e,0))),i=r(t)/(t.length-1);return i<=1e-9?t.map(()=>1):t.map(e=>e/i)}function s(e){return e.every(e=>Math.abs(e-1)<1e-6)}function c(){return{cuts:[],envelopes:[Array(24).fill(1)]}}function l(e){return!e||e.cuts.length===0&&e.envelopes.every(s)}function u(e){if(!e||typeof e!=`object`)return null;let t=Array.isArray(e.cuts)?e.cuts:[],r=[];for(let e of t){let t=n(e?.t,NaN),i=n(e?.d,NaN);if(!(t>0&&t<1&&i>0&&i<1))continue;let a=r[r.length-1];a&&(t<=a.t+1e-6||i<=a.d+1e-6)||r.push({t,d:i})}let i=Array.isArray(e.envelopes)?e.envelopes:[],s=[];for(let e=0;e<=r.length;e+=1){let t=Array.isArray(i[e])?i[e].map(e=>n(e,1)):[];s.push(o(a(t.length>=2?t:[1,1])))}return{cuts:r,envelopes:s}}function d(e,r,i,a=.18){let o=e.length,s=Math.max(0,n(i,0)),c=t(n(r,0),0,1),l=a/3,u=Array(o);for(let e=0;e<o;e+=1){let t=Math.abs(e/(o-1)-c);u[e]=t<=l?1:t>=a?0:.5*(1+Math.cos((t-l)/(a-l)*Math.PI))}let d=e.map((e,t)=>Math.max(0,e*(1-u[t])+s*u[t])),f=e=>e===0||e===o-1?.5:1,p=o-1,m=0,h=0;for(let e=0;e<o;e+=1)u[e]>1e-9?m+=f(e)*d[e]:h+=f(e)*d[e];if(h>1e-9){let e=Math.max(0,(p-m)/h);for(let t=0;t<o;t+=1)u[t]<=1e-9&&(d[t]*=e);if(p-m<0){let e=p/m;for(let t=0;t<o;t+=1)u[t]>1e-9&&(d[t]*=e)}}else if(m>1e-9){let e=p/m;for(let t=0;t<o;t+=1)d[t]*=e}else return Array(o).fill(1);return d}function f(e,n){let i=e.length,a=r(e);if(a<=1e-9)return t(n,0,1);let o=t(n,0,1)*(i-1),s=Math.min(i-2,Math.floor(o)),c=o-s,l=0;for(let t=0;t<s;t+=1)l+=(e[t]+e[t+1])/2;let u=e[s]*(1-c)+e[s+1]*c;return l+=(e[s]+u)/2*c,l/a}function p(e,r){let i=t(n(r,0),0,1);if(!e)return i;let a=[{t:0,d:0},...e.cuts,{t:1,d:1}],o=0;for(;o<a.length-2&&i>a[o+1].t;)o+=1;let s=a[o],c=a[o+1],l=c.t-s.t,u=l>1e-9?(i-s.t)/l:1;return s.d+(c.d-s.d)*f(e.envelopes[o],u)}function m(e,t,n){let r=Array(24);for(let a=0;a<24;a+=1)r[a]=i(e,t+(n-t)*(a/23));return r}function h(e,t){let r=e??c(),i=n(t,NaN);if(!(i>.02&&i<.98))return e;for(let t of r.cuts)if(Math.abs(t.t-i)<.02)return e;let a=p(r,i);if(!(a>1e-6&&a<1-1e-6))return e;let s=0;for(;s<r.cuts.length&&i>r.cuts[s].t;)s+=1;let l=s===0?{t:0}:r.cuts[s-1],u=s===r.cuts.length?{t:1}:r.cuts[s],d=(i-l.t)/(u.t-l.t),f=r.envelopes[s];return{cuts:[...r.cuts.slice(0,s),{t:i,d:a},...r.cuts.slice(s)],envelopes:[...r.envelopes.slice(0,s),o(m(f,0,d)),o(m(f,d,1)),...r.envelopes.slice(s+1)]}}function ee(e,t){if(!e||!e.cuts[t])return e;let n=[{t:0,d:0},...e.cuts,{t:1,d:1}],r=n[t],a=n[t+1],s=n[t+2],c=(a.t-r.t)/(s.t-r.t),l=(a.d-r.d)/(s.d-r.d),u=1-c,d=1-l,f=e.envelopes[t],p=e.envelopes[t+1],m=Array(24);for(let e=0;e<24;e+=1){let t=e/23;if(t<=c){let n=i(f,c>1e-9?t/c:0);m[e]=l/Math.max(1e-9,c)*n}else{let n=i(p,u>1e-9?(t-c)/u:0);m[e]=d/Math.max(1e-9,u)*n}}return{cuts:[...e.cuts.slice(0,t),...e.cuts.slice(t+1)],envelopes:[...e.envelopes.slice(0,t),o(m),...e.envelopes.slice(t+2)]}}var te=Object.freeze([`keys`,`follow`,`rail`]),g=Object.freeze({distance:3,height:1.6,response:.7,lead:.25,railStartMode:`head`,maxDollySpeed:4,pitchOffsetDeg:0,orbitOffsetDeg:0});function ne(e){return Array.isArray(e)?e.map(e=>({x:e.x,z:e.z})):null}function re(e){if(!e||typeof e!=`object`)return null;let t=Array.isArray(e.points)?e.points:Number.isFinite(e.start)&&Number.isFinite(e.end)?[{t:0,height:e.start},{t:1,height:e.end}]:null;if(!t)return null;let n=t.filter(e=>e&&Number.isFinite(e.t)&&Number.isFinite(e.height)).map(e=>({t:Math.max(0,Math.min(1,e.t)),height:Math.max(.1,e.height)})).sort((e,t)=>e.t-t.t).filter((e,t,n)=>t===n.length-1||n[t+1].t-e.t>1e-6).slice(0,8);return n.length<2?null:(n[0]={...n[0],t:0},n[n.length-1]={...n[n.length-1],t:1},{points:n})}function ie(e){return!e||typeof e!=`object`?null:e.mode===`off`?{mode:`off`}:e.mode===`range`?{mode:`range`,startFrame:e.startFrame,endFrame:e.endFrame}:null}function _(e={}){let t=e&&typeof e==`object`?e:{},n=te.includes(t.mode)?t.mode:`keys`,r={...g,...t.followCam??{}},i=ne(t.cameraRail),a=re(t.craneHeight)??(n===`rail`&&i?{points:[{t:0,height:r.height},{t:1,height:r.height}]}:null),o=u(t.dollyTiming);return{mode:n,followCam:r,cameraRail:i,railFollow:ie(t.railFollow),craneHeight:a,dollyTiming:l(o)?null:o}}function v(e){return _(e)}function ae(e,t={}){let n=_(e),r=t&&typeof t==`object`?t:{};return _({...n,...r,followCam:r.followCam?{...n.followCam,...r.followCam}:n.followCam,cameraRail:Object.hasOwn(r,`cameraRail`)?r.cameraRail:n.cameraRail,railFollow:Object.hasOwn(r,`railFollow`)?r.railFollow:n.railFollow,craneHeight:Object.hasOwn(r,`craneHeight`)?r.craneHeight:n.craneHeight,dollyTiming:Object.hasOwn(r,`dollyTiming`)?r.dollyTiming:n.dollyTiming})}function oe(e){let t=_(e);return ae(t,{mode:t.mode===`rail`?`follow`:t.mode,cameraRail:null,railFollow:null,craneHeight:null})}var y=e=>e&&typeof e==`object`?Object.freeze({...e}):e,se=Object.freeze([{path:`character.position`,type:`vec3`,persisted:!0,undoDomain:`cast`,normalizer:`createCharacterEntry`,min:{x:-240,y:0,z:-240},max:{x:240,y:240,z:240},gizmo:{min:{x:-4,y:0,z:-4},max:{x:4,y:240,z:4}},note:`y is the feet`},{path:`character.rot`,type:`number`,persisted:!0,undoDomain:`cast`,normalizer:`createCharacterEntry`,min:-180,max:180,angle:!0,note:`yaw degrees, wrapped at the upper bound`},{path:`character.scale`,type:`number`,persisted:!0,undoDomain:`cast`,normalizer:`createCharacterEntry`,min:.2,max:3},{path:`character.subject`,type:`string`,persisted:!0,undoDomain:`cast`,normalizer:`createCharacterEntry`},{path:`character.hidden`,type:`boolean`,persisted:!0,undoDomain:`cast`,normalizer:`createCharacterEntry`},{path:`character.model`,type:`enum`,persisted:!0,undoDomain:`cast`,normalizer:`createCharacterEntry`,enum:[`y-bot-tpose`,`x-bot-tpose`]},{path:`character.tint`,type:`color`,persisted:!0,undoDomain:`cast`,normalizer:`createCharacterEntry`},{path:`character.identityImage`,type:`image`,persisted:!0,undoDomain:`cast`,normalizer:`createCharacterEntry`,note:`data:image only`},{path:`character.pose`,type:`id`,persisted:!0,undoDomain:`cast`,normalizer:`createCharacterEntry`},{path:`character.waypoints`,type:`array`,persisted:!0,undoDomain:`cast`,normalizer:`createCharacterEntry`,actions:[`character.addWaypoint`,`character.moveWaypoint`,`character.removeWaypoint`,`character.clearWaypoints`],note:`root path pins, addressed by frame`},{path:`character.promptBlocks`,type:`array`,persisted:!0,undoDomain:`cast`,normalizer:`createCharacterEntry`,note:`stored at layer.promptClips`},{path:`character.motionRef.url`,type:`string`,persisted:!0,undoDomain:`cast`,normalizer:`createCharacterEntry`},{path:`character.motionRef.motionId`,type:`id`,persisted:!0,undoDomain:`cast`,normalizer:`createCharacterEntry`},{path:`character.sessionMotion`,type:`array`,persisted:!1,undoDomain:`cast`,normalizer:`createCharacterEntry`,note:`dropped by createCharacterEntry`},{path:`character.ikKeys`,type:`array`,persisted:!1,undoDomain:`cast`,normalizer:`createCharacterEntry`,actions:[`character.setIkKey`,`character.removeIkKey`,`character.clearIkKeys`],note:`dropped by createCharacterEntry; keys travel as JSON quaternions/positions`},{path:`object.renderer`,type:`enum`,persisted:!0,undoDomain:`objects`,normalizer:`normalizeSceneObject`,enum:[`cube`,`sphere`,`capsule`,`cylinder`,`cone`,`plane`,`chair`,`car`,`small-plane`]},{path:`object.position`,type:`vec3`,persisted:!0,undoDomain:`objects`,normalizer:`normalizeSceneObject`,min:{x:-240,y:0,z:-240},max:{x:240,y:240,z:240},note:`y is the object's base: y=0 rests on the floor; height/supportY rise from it`},{path:`object.rotation`,type:`vec3`,persisted:!0,undoDomain:`objects`,normalizer:`normalizeSceneObject`,min:{x:-180,y:-180,z:-180},max:{x:180,y:180,z:180},note:`rot/rotX/rotZ degrees, wrapped at the upper bound`},{path:`object.scale`,type:`vec3`,persisted:!0,undoDomain:`objects`,normalizer:`normalizeSceneObject`,min:{x:.1,y:.1,z:.1},max:{x:100,y:100,z:100}},{path:`object.name`,type:`string`,persisted:!0,undoDomain:`objects`,normalizer:`normalizeSceneObject`},{path:`object.color`,type:`color`,persisted:!0,undoDomain:`objects`,normalizer:`normalizeSceneObject`},{path:`object.parent`,type:`id`,persisted:!0,undoDomain:`objects`,normalizer:`normalizeSceneObject`},{path:`object.attach`,type:`id`,persisted:!0,undoDomain:`objects`,normalizer:`normalizeSceneObject`,actions:[`object.attach`,`object.detach`],note:`carried by a character's root or bone; channels convert so the prop stays put`},{path:`object.path`,type:`array`,persisted:!0,undoDomain:`objects`,normalizer:`normalizeSceneObject`},{path:`object.remove`,type:`boolean`,persisted:!0,undoDomain:`objects`,normalizer:null,note:`lifecycle operation, not a document field`},{path:`object.cutout`,type:`image`,persisted:!0,undoDomain:`objects`,normalizer:`normalizeSceneObject`,actions:[`asset.import`],note:`assetId-backed cutout record; imported pictures and models are placed by asset.import`},{path:`stage.keyLight.x`,type:`number`,persisted:!0,undoDomain:`stage`,normalizer:`createSceneStage`,min:-30,max:30},{path:`stage.keyLight.y`,type:`number`,persisted:!0,undoDomain:`stage`,normalizer:`createSceneStage`,min:.5,max:30},{path:`stage.keyLight.z`,type:`number`,persisted:!0,undoDomain:`stage`,normalizer:`createSceneStage`,min:-30,max:30},{path:`stage.keyLight.intensity`,type:`number`,persisted:!0,undoDomain:`stage`,normalizer:`createSceneStage`,min:0,max:4},{path:`stage.keyLight.warmth`,type:`number`,persisted:!0,undoDomain:`stage`,normalizer:`createSceneStage`,min:0,max:1},{path:`stage.environmentImage`,type:`image`,persisted:!0,undoDomain:`stage`,normalizer:`createSceneStage`,note:`data:image only`},{path:`stage.environment`,type:`string`,persisted:!0,undoDomain:`stage`,normalizer:`createSceneStage`,note:`location description every shot prompt is built from`},{path:`stage.style`,type:`string`,persisted:!0,undoDomain:`stage`,normalizer:`createSceneStage`,note:`look / style line for shot prompts`},{path:`stage.hasEnvSheet`,type:`boolean`,persisted:!0,undoDomain:`stage`,normalizer:`createSceneStage`,note:`author supplies an environment sheet instead of a description`},{path:`stage.camera`,documentPath:`shotAspect`,type:`enum`,persisted:!0,undoDomain:`stage`,normalizer:`createSceneStage`,enum:[`16:9`,`2.39:1`,`9:16`,`1:1`,`4:3`,`12:7`,`fal 480P`],note:`output aspect ratio`},{path:`stage.cameraPresetId`,type:`id`,nullable:!0,persisted:!0,undoDomain:`stage`,normalizer:`createSceneStage`},{path:`stage.sensorId`,type:`enum`,persisted:!0,undoDomain:`stage`,normalizer:`createSceneStage`,enum:[`super16`,`super35`,`fullFrame`,`65mm`]},{path:`shot.crud`,type:`array`,persisted:!0,undoDomain:`shot`,normalizer:null,actions:[`shot.create`,`shot.split`,`shot.duplicate`,`shot.remove`,`shot.setRange`,`shot.reorder`],note:`create/split/duplicate/reorder/remove/range through the shared action registry`},{path:`shot.cameraKeys`,type:`array`,persisted:!0,undoDomain:`shot`,normalizer:null,frameMin:0},{path:`shot.cameraRail`,type:`array`,persisted:!0,undoDomain:`shot`,normalizer:`repairCamera`,actions:[`shot.setCameraRail`,`shot.clearCameraRail`],note:`rail points; crane/dolly timing follow the shot's camera block`},{path:`shot.targetModel`,type:`id`,persisted:!0,undoDomain:`shot`,normalizer:`repairCamera`},{path:`shot.freeCamera`,type:`vec3`,persisted:!1,undoDomain:`shot`,normalizer:null,note:`transient until keyed`},{path:`scenes`,type:`array`,persisted:!0,undoDomain:null,normalizer:null,actions:[`scene.create`,`scene.duplicate`,`scene.rename`,`scene.delete`,`scene.switch`],note:`the project's scene list and the open scene; outside the undo history`},{path:`project`,type:`string`,persisted:!0,undoDomain:null,normalizer:null,actions:[`project.save`],note:`save to the current project file; opening one needs the user's file picker`},{path:`selection`,type:`id`,persisted:!1,undoDomain:null,normalizer:null},{path:`timeline`,type:`number`,persisted:!1,undoDomain:null,normalizer:null},{path:`view.mode`,type:`enum`,persisted:!1,undoDomain:null,normalizer:null,enum:[`scene`,`pose`,`camera`,`motion`]},{path:`view.partColoursGuideModeInset`,type:`array`,persisted:!1,undoDomain:null,normalizer:null,actions:[`view.setPartColours`,`view.setGuideMode`,`view.setInset`],note:`partColours/guideMode/inset; viewer settings, not document fields`},{path:`read.sceneDescription`,type:`string`,persisted:!1,undoDomain:null,normalizer:null},{path:`read.captureFrame`,type:`image`,persisted:!1,undoDomain:null,normalizer:null},{path:`undo`,type:`boolean`,persisted:!1,undoDomain:null,normalizer:null}].map(e=>Object.freeze({...e,...e.enum?{enum:Object.freeze([...e.enum])}:{},...e.actions?{actions:Object.freeze([...e.actions])}:{},...e.min&&typeof e.min==`object`?{min:y(e.min)}:{},...e.max&&typeof e.max==`object`?{max:y(e.max)}:{},...e.gizmo?{gizmo:Object.freeze({min:y(e.gizmo.min),max:y(e.gizmo.max)})}:{}})));function ce(e){return se.find(t=>t.path===e)}var le=e=>e.persisted!==!1&&!e.actions&&!e.readOnly,ue=65536,de=Object.freeze({entities:24,entityIndex:400,shots:8,assets:48,recentReceipts:3,jobs:8}),b=Object.freeze([`inspect_studio`,`run_action`,`verify_result`]);Object.freeze([`operate_studio`,`arrange_objects`,`arrange_characters`,`patch_elements`,`frame_shot`,`generate_motion`,`undo_edit`]);var x=Object.freeze({inspect_studio:`Read the scene`,operate_studio:`Selection and view`,arrange_objects:`Arrange objects`,arrange_characters:`Arrange characters`,patch_elements:`Edit properties`,frame_shot:`Frame the shot`,generate_motion:`Generate motion`,verify_result:`Verify the result`,undo_edit:`Undo an edit`,run_action:`Run an editor action`}),S=Object.freeze(Object.keys(x)),fe=Object.freeze([`character`,`object`,`shot`,`stage`]);Object.freeze({character:`cast`,object:`objects`,shot:`shot`,stage:`stage`});var pe=Object.freeze(`INVALID_ARGUMENT.INVALID_CONTEXT.INVALID_IDENTITY.INVALID_TURN_ID.INVALID_SESSION_ID.INVALID_RECEIPT.INVALID_RANGE.INVALID_REQUEST.UNKNOWN_TOOL.UNKNOWN_VARIANT.DUPLICATE_NAME.CONTEXT_LIMIT.CONTEXT_TOO_LARGE.AMBIGUOUS_TARGET.AMBIGUOUS_BASIS.TARGET_NOT_READY.TARGET_BUSY.STALE_TARGET.STALE_SCENE.STALE_ENVIRONMENT.STALE_CURSOR.CAPABILITY_MISSING.LIVE_HUB_UNAVAILABLE.AUTH_REQUIRED.GENERATION_LIMIT.RATE_LIMITED.BACKEND_UNAVAILABLE.VERIFICATION_FAILED.REPAIR_REGRESSED.CANCELLED.UNCERTAIN_APPLY.UNDO_CONFLICT.CONFIRMATION_REQUIRED.TIMEOUT.UNDO_EXPIRED`.split(`.`)),C=E({selectionKinds:[`scene`,`object`,`character`,`rig`,`camera`],modes:[`scene`,`pose`,`camera`,`motion`],shotModes:[`keys`,`follow`,`rail`],framingSizes:[`extreme close-up`,`close-up`,`medium close-up`,`medium shot`,`medium-wide shot`,`wide shot`,`extreme wide shot`],framingViews:[`front`,`front three-quarter`,`profile`,`rear three-quarter`,`back`],framingLevels:[`ground`,`low`,`hip`,`eye`,`high`,`overhead`],framingSides:[`left`,`right`],positionSides:[`left`,`right`,`front`,`behind`],positionBases:[`world`,`subject`,`shot_camera`],collisionPolicies:[`report`,`avoid`],objectOps:[`create`,`update`,`remove`,`group`,`ungroup`],characterOps:[`create`,`update`,`remove`],inspectionScopes:[`selection`,`scene`,`entities`,`shot`,`motion`,`catalogue`,`actions`,`document`],receiptStatuses:[`applied`,`partial`,`noop`,`transient`,`installed`,`undone`],opStatuses:[`applied`,`partial`,`noop`],jobStates:[`queued`,`generating`,`preparing`,`verifying`,`repairing`,`committing`,`reconciling`,`installed`,`review_required`,`failed`,`cancelled`,`stale_target`,`stale_environment`]}),w=class extends Error{constructor(e,t,n={}){super(t),this.name=`StudioProtocolError`,this.code=e,this.details=n}toJSON(){return{code:this.code,message:this.message,...Object.keys(this.details).length?{details:this.details}:{}}}},T=e=>new TextEncoder().encode(e).byteLength;function E(e){if(e&&typeof e==`object`&&!Object.isFrozen(e)){for(let t of Object.values(e))E(t);Object.freeze(e)}return e}var D=(e,t,n=`$`,r={})=>{throw new w(e,t,{path:n,...r})},O=e=>typeof e==`object`&&!!e&&!Array.isArray(e),k=(e=120)=>({type:`string`,minLength:1,maxLength:e}),A=(e,t)=>({type:`number`,...e===void 0?{}:{minimum:e},...t===void 0?{}:{maximum:t}}),j=(e=0,t=2**53-1)=>({...A(e,t),type:`integer`}),M={type:`boolean`},N=e=>({const:e}),P=e=>({type:`string`,enum:e}),F=e=>({oneOf:[e,{type:`null`}]}),I=(e,t,n=0,r=!1)=>({type:`array`,items:e,minItems:n,maxItems:t,...r?{uniqueItems:r}:{}}),L=(e,t={})=>({type:`object`,properties:{...e,...t},required:Object.keys(e),additionalProperties:!1}),R=(...e)=>({oneOf:e}),me={type:`object`,properties:{},required:[],additionalProperties:!0},z={...k(),pattern:`^[A-Za-z0-9][A-Za-z0-9._:-]*$`},he={...k(36),pattern:`^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$`},B=L({x:A(),y:A(),z:A()}),V={type:`number`,exclusiveMinimum:0},ge=L({x:V,y:V,z:V}),_e={...L({startFrame:j(),endFrameExclusive:j(1)}),"x-studio-range":!0},H=(e=100,t=1)=>I(z,e,t,!0),U=k(120),ve={workspaceId:z,documentEpoch:z,sceneId:z,sceneEpoch:z},ye=L(ve),be=L({surface:N(`studio`),...ve,workspaceHandle:F(z)}),xe=L({scene:j(),physics:j(),view:j()}),Se=F(L({kind:P(C.selectionKinds),id:z},{hierarchyId:z})),Ce=L({mode:P(C.modes),frame:j(),playing:M,lookThrough:M,grid:M,autoColor:M}),we=R(L({world:B}),L({relativeTo:z,basis:P(C.positionBases),side:P(C.positionSides),gapM:A(0),support:R(N(`floor`),L({objectId:z}))}),L({between:H(2,2),fraction:A(0,1),support:N(`floor`)}),L({onObject:z},{offsetXZ:L({x:A(),z:A()})})),Te=R(L({yawDeg:A()}),L({towardId:z}),L({sameAsId:z}),L({awayFromId:z})),Ee=R(L({intent:L({size:P(C.framingSizes),view:P(C.framingViews),level:P(C.framingLevels),side:P(C.framingSides)},{focalMm:V})}),L({exact:L({position:B,lookAt:B,focalMm:V})})),De=R(L({op:N(`create`),source:L({kind:z}),position:we},{name:U,facing:Te,scale:ge}),L({op:N(`update`),id:z},{position:we,facing:Te,rotationDeg:B,scale:ge,color:k(32),name:U,hidden:M}),L({op:N(`remove`),id:z}),L({op:N(`group`),parentId:z,childIds:H()}),L({op:N(`ungroup`),childIds:H()})),Oe=R(L({op:N(`create`),name:U,position:we},{facing:Te,scale:V}),L({op:N(`update`),characterId:z},{position:we,facing:Te,scale:V,name:U,hidden:M}),L({op:N(`remove`),characterId:z})),ke=L({kind:N(`generate`),beats:I(L({text:k(2e3)},{seconds:A(.5,60)}),8,1)},{durationSeconds:A(2,60),seed:j(-2147483648,2147483647)}),Ae=R(ke,L({kind:N(`reuse`),artifactId:z})),je={...k(2097152),pattern:`^data:image/[A-Za-z0-9.+-]+[;,]`},Me=L({startFrame:j(),endFrame:j(1),text:k(2e3)},{id:z}),Ne=L({frame:j(),framing:L({pos:B,yaw:A(),pitch:A(),fovDeg:A(1,179)})},{id:z}),Pe=F(L({points:I(B,64,2)},{speed:A(0,50),faceTravel:M,loop:M,extend:M})),Fe={"character.pose":F(z),"character.identityImage":F(je),"character.promptBlocks":I(Me,64),"object.parent":F(z),"object.path":Pe,"stage.environmentImage":F(je),"shot.cameraKeys":I(Ne,64),"shot.targetModel":F(z)};function Ie(e){if(Object.hasOwn(Fe,e.path))return Fe[e.path];if(e.type===`number`)return A(e.min,e.max);if(e.type===`boolean`)return M;if(e.type===`enum`)return P([...e.enum]);if(e.type===`id`)return z;if(e.type===`color`)return{...k(32),pattern:`^#[0-9a-fA-F]{6}$`};if(e.type===`image`)return F(je);if(e.type===`vec3`){let t=e.gizmo??e;return t.min&&typeof t.min==`object`&&t.max&&typeof t.max==`object`?L({x:A(t.min.x,t.max.x),y:A(t.min.y,t.max.y),z:A(t.min.z,t.max.z)}):B}return e.type===`string`?k(240):null}function Le(e){return e.filter(le).map(({path:e,type:t,min:n,max:r,enum:i,gizmo:a,note:o})=>({path:e,type:t,...a?.min===void 0?n===void 0?{}:{min:n&&typeof n==`object`?{...n}:n}:{min:{...a.min}},...a?.max===void 0?r===void 0?{}:{max:r&&typeof r==`object`?{...r}:r}:{max:{...a.max}},...i?{enum:[...i]}:{},...o?{note:o}:{}}))}var Re=E(Le(se));function ze(e){let t={};for(let n of fe){let r={};for(let t of e){if(!le(t)||!t.path.startsWith(`${n}.`))continue;let e=Ie(t);e&&(r[t.path.slice(n.length+1)]=e)}t[n]={type:`object`,properties:r,required:[],additionalProperties:!1}}return t}var Be=E(ze(se)),Ve=E(Object.fromEntries(fe.map(e=>[e,Object.keys(Be[e].properties).map(t=>`${e}.${t}`)]))),He=R(L({target:L({kind:N(`character`),id:z}),set:Be.character}),L({target:L({kind:N(`object`),id:z}),set:Be.object}),L({target:L({kind:N(`shot`)},{id:z}),set:Be.shot}),L({target:L({kind:N(`stage`)}),set:Be.stage})),Ue={inspect_studio:L({scope:P(C.inspectionScopes)},{ids:H(32),select:H(32),query:U,cursor:k(512),limit:{...j(1,32),default:12}}),operate_studio:L({},{selection:Se,shotId:z,frame:j(),playing:M,mode:P(C.modes),view:L({},{lookThrough:M,grid:M,autoColor:M})}),arrange_objects:L({ops:I(De,100,1)},{collisionPolicy:{...P(C.collisionPolicies),default:`report`}}),arrange_characters:L({ops:I(Oe,8,1)}),patch_elements:L({ops:I(He,32,1)}),frame_shot:L({subjectIds:H(1),framing:Ee},{shotId:z,keyAtFrame:j()}),generate_motion:L({characterId:z,source:Ae},{repair:{...P([`bounded`,`none`]),default:`bounded`}}),verify_result:L({checks:I(P([`placement`,`framing`,`motion`]),3,1,!0)},{receiptId:z,targets:H(),range:R(N(`whole_clip`),_e),visual:{...P([`none`,`frame`,`contact_sheet`]),default:`none`}}),undo_edit:L({receiptId:z}),run_action:L({action:z},{args:me,confirmationToken:z})},We=E(Ue),Ge=E(S.map(e=>({name:e,slice:1,parameters:Ue[e]}))),Ke=L({min:B,max:B}),qe=L({id:z,kind:P([`object`,`character`,`rig`]),token:z},{name:U,detailsOmitted:M,position:B,yawDeg:A(),rotationDeg:B,scale:R(V,ge),bounds:F(Ke),libraryKind:z,renderer:z,color:F(k(32)),tint:F(k(32)),modelId:F(k(120)),assetId:z,parentId:F(z),attachment:F(L({characterId:z,bone:F(z)})),pathPointCount:j(0,64),motion:L({takeId:F(z),frames:j(),ikKeyCount:j(),promptBlockCount:j()},{poseId:F(z),keyIds:H(8,0)}),capabilities:L({rigReady:M,ik:M,measuredFeet:M})}),Je=L({id:z,kind:P([`object`,`character`,`rig`])},{name:U,position:B}),Ye=L({id:z},{label:U,generation:N(`motion`),timeoutMs:j(1,3e5)}),Xe=L({id:z,name:U,range:_e,keyCount:j()},{subjectIds:H(24,0)}),Ze=L({id:z,name:U,range:_e,mode:P(C.shotModes)},{subjectIds:H(24,0)}),Qe=L({position:B,lookAt:B,focalMm:V,sensorId:z,slate:U}),$e=P([`primitive`,`set-piece`,`image`,`mesh`]),et=R(L({kind:z,name:U,type:$e}),L({id:z,name:U,type:$e})),tt=L({id:z,characterId:z,state:P(C.jobStates)},{targetIds:H(24,0),progress:F(A(0,1)),phase:U}),nt=L({schema:N(`studio-context-v1`),host:be,revision:xe,units:L({distance:N(`m`),angle:N(`deg`),up:N(`+Y`),yawZero:N(`+Z`),yawPositiveToward:N(`+X`),pivot:N(`base`),fps:N(24),rangeEnd:N(`exclusive`)}),scene:L({name:U,aspect:k(40),floorY:A(),frameCount:j(),objectCount:j(),characterCount:j()}),selection:Se,activeCharacterId:F(z),view:Ce,shot:F(Ze),camera:F(Qe),entities:I(qe,24),entityPage:L({returned:j(0,24),total:j(),truncated:M,nextCursor:F(k(512))}),shots:I(Xe,8),shotsTruncated:M,assets:I(et,de.assets),recentReceipts:I(L({id:z,summary:U,canUndoDirect:M}),3),jobs:I(tt,8),capabilities:L({profile:N(`studio-slice-1`),tools:I(P(S),S.length,0,!0)},{rigReady:M,cameraReady:M,bridgeReady:M})},{entityIndex:I(Je,de.entityIndex),actionIndex:I(Ye,512)}),rt=L({...ve,targetId:z,token:z}),it=[`none`,`minimal`,`low`,`medium`,`high`,`xhigh`,`max`,`ultra`],at=L({dataUrl:{...k(6e6),pattern:`^data:image/(png|jpeg|webp);base64,`}},{name:k(120)}),ot=L({surface:N(`studio`),sessionId:he,turnId:he,text:k(16e3),context:nt},{model:k(120),effort:P(it),attachFrame:M,attachments:I(at,4,1)}),st=L({surface:N(`studio`),sessionId:he,turnId:he},{jobId:z}),ct=L({before:j(),after:j()}),lt=L({historyEntryId:z,entries:N(1),canUndoDirect:M}),ut=L({characterId:z,beforeTakeId:F(z),takeId:z,targetToken:z,frameCount:j(1),fps:N(24),durationSeconds:V,blocks:I(L({sourceBeat:j(0,7),startFrame:j(),endFrameExclusive:j(1)}),120,1),selectionChanged:N(!1)}),dt=L({id:z,status:P([`verified`,`unverified`]),profile:N(`studio-motion-v1`),range:_e,evaluatedFrames:j(),physicsRevision:j(),limitations:I(U,12)},{surfaceMeasured:M,maxFloorPenetrationM:A(0),maxContactSlipM:A(0),maxContactFloatM:A(0),unsupportedFrames:j(),supportedCollisionFrames:j(),continuityRegressed:M,semanticStatus:P([`pending_image_review`,`passed`,`failed`,`unavailable`])}),ft=L({path:k(120)},{number:A(),text:F(k(512)),flag:M,vec:B,count:j(),bytes:j()}),pt=L({},{position:B,yawDeg:A(),rotationDeg:B,scale:R(V,ge),name:U,color:k(32),hidden:M,modelId:z,renderer:z,parentId:F(z),childIds:H(100,0),removed:M,range:_e,camera:Qe,keyId:z,frame:j(),subjectIds:H(24,0),selection:Se,activeCharacterId:F(z),shotId:F(z),view:Ce,token:z,takeId:F(z),statureM:V,patched:I(ft,32,1)}),mt=L({coverage:U},{relationSatisfied:M,overlapIds:H(100,0),actualGapM:A(),requestedGapM:A(0),maximumFootprintOverlapM:A(0),basis:P(C.positionBases),clipped:M,occluded:M,behindCamera:M,screenFraction:A(0),derivedSize:P(C.framingSizes),support:U,baseY:A(),facesTargetId:z}),ht=L({code:z},{id:z,message:U,suggestedOutwardDeltaM:A(),count:j()}),gt={ok:N(!0),commandId:z,receiptId:z,host:ye,status:P(C.receiptStatuses),authored:M,revision:ct,affectedIds:H(100,0),delta:I(L({id:z,after:pt}),8),checks:mt,undo:F(lt),warnings:I(ht,12)},_t={counts:L({created:j(),updated:j(),deleted:j()}),detailCursor:F(k(512))},vt=I(L({index:j(),status:P(C.opStatuses)},{droppedPaths:I(k(120),32,1)}),32,1),yt={...gt,authored:N(!0),undo:lt},bt={action:z,summary:k(240)},xt={completed:L({...gt,status:N(`completed`),kind:P([`job`,`document`,`transaction`,`mutation`])},{...bt,..._t,output:me,jobId:z,txId:z,nextHost:ye}),started:L({...gt,status:N(`started`),kind:N(`job`),jobId:z,authored:N(!1),undo:N(null)},{...bt}),applied:L({...yt,status:N(`applied`)},{mutated:N(!0),ops:vt,..._t,...bt}),partial:L({...yt,status:N(`partial`),ops:vt},{mutated:N(!0),..._t}),noop:L({...gt,status:N(`noop`),authored:N(!1),mutated:N(!1),undo:N(null)},{ops:vt,...bt}),transient:L({...gt,status:N(`transient`),authored:N(!1),view:ct,undo:N(null)},{mutated:M,...bt}),installed:L({...yt,status:N(`installed`),jobId:z,artifactId:z,installed:ut,verification:dt},{mutated:N(!0),explicitUnverifiedAcceptance:M,acceptance:N(`advisory-policy`),repairs:L({autoPhysicsInvocations:j(0,1),fixCollisionsInvocations:j(0,1),remaining:j(0,2)}),..._t}),undone:L({...yt,status:N(`undone`),undoneReceiptId:z,restoredTargets:I(rt,100,1)},{mutated:N(!0),..._t})},St=R(...Object.values(xt)),Ct=L({ok:N(!1),commandId:z,host:ye,code:P(pe),phase:P([`admission`,`execution`,`prepare`,`verify`,`repair`,`commit`,`reconcile`,`undo`]),affectedIds:H(100,0),expectedTargets:I(rt,24),currentTargets:I(rt,24),mutated:R(M,N(`unknown`)),preserved:L({authoredState:P([`unchanged`,`changed`,`unknown`])}),recovery:L({action:P([`none`,`inspect`,`retry`,`new_intent`,`reconcile`,`sign_in`])},{retryAllowed:M})},{message:k(500),jobId:z,txId:z,candidates:I(L({id:z,kind:P([`object`,`character`,`rig`]),position:F(B)}),5)}),wt=E({catalogue:Ge,variants:C,Vec3:B,FrameRange:_e,PositionSpec:we,FacingSpec:Te,ObjectOp:De,CharacterOp:Oe,Framing:Ee,GenerateSource:ke,Source:Ae,Identity:ye,Host:be,TargetGuard:rt,Entity:qe,ShotSummary:Xe,StudioContextV1:nt,StudioTurn:ot,StudioStop:st,Receipt:St,ReceiptVariants:xt,Failure:Ct});function W(e,t,n=`INVALID_ARGUMENT`,r=`$`){if(e.oneOf){let i=[],a=[];for(let o of e.oneOf)try{i.push(W(o,t,n,r))}catch(e){if(!(e instanceof w))throw e;a.push({branch:o,error:e})}if(i.length===0&&a.length){let e=O(t)&&O(t.target)?t.target.kind:void 0;throw(e!==void 0&&a.find(({branch:t})=>t.properties?.target?.properties?.kind?.const===e)||a.reduce((e,t)=>t.error.details.path.length>e.error.details.path.length?t:e)).error}return i.length!==1&&D(n,`Expected exactly one supported variant.`,r),i[0]}if(Object.hasOwn(e,`const`))return t!==e.const&&D(n,`Invalid constant.`,r),t;if(e.type===`null`)return t!==null&&D(n,`Expected null.`,r),null;if(e.type===`object`){O(t)||D(n,`Expected object.`,r);let i=e.additionalProperties===!0;for(let a of Object.keys(t))!Object.hasOwn(e.properties,a)&&!i&&D(n,`Unexpected field.`,r);let a={};if(i)for(let n of Object.keys(t))Object.hasOwn(e.properties,n)||(a[n]=structuredClone(t[n]));for(let[i,o]of Object.entries(e.properties))Object.hasOwn(t,i)?a[i]=W(o,t[i],n,`${r}.${i}`):e.required.includes(i)?D(n,`Required field missing.`,`${r}.${i}`):Object.hasOwn(o,`default`)&&(a[i]=structuredClone(o.default));return e[`x-studio-range`]&&a.endFrameExclusive<=a.startFrame&&D(n,`Frame range must be nonempty and half-open.`,r),a}if(e.type===`array`){(!Array.isArray(t)||t.length<e.minItems||t.length>e.maxItems)&&D(n,`Array outside supported bounds.`,r);let i=t.map((t,i)=>W(e.items,t,n,`${r}[${i}]`));return e.uniqueItems&&new Set(i.map(e=>JSON.stringify(e))).size!==i.length&&D(n,`Duplicate array member.`,r),i}if(e.type===`string`)return(typeof t!=`string`||!t.trim()||e.maxLength!==void 0&&[...t].length>e.maxLength||e.pattern&&!new RegExp(e.pattern).test(t))&&D(n,`Invalid or oversized string.`,r),e.enum&&!e.enum.includes(t)&&D(n,`Unsupported enum value.`,r),t;if(e.type===`boolean`)return typeof t!=`boolean`&&D(n,`Expected boolean.`,r),t;if(e.type===`number`||e.type===`integer`)return(typeof t!=`number`||!Number.isFinite(t)||e.type===`integer`&&!Number.isSafeInteger(t)||e.exclusiveMinimum!==void 0&&t<=e.exclusiveMinimum)&&D(n,`Number outside supported bounds.`,r),(e.minimum!==void 0&&t<e.minimum||e.maximum!==void 0&&t>e.maximum)&&D(n,`${r}: Expected a number within [${[e.minimum,e.maximum].filter(e=>e!==void 0).join(`, `)}].`,r),t;throw Error(`Unsupported internal Studio schema.`)}var Tt=e=>W(ye,e,`INVALID_IDENTITY`);function Et(e){return[...new Set([...[`object`,`character`,`rig`].includes(e.selection?.kind)?[e.selection.id]:[],...e.activeCharacterId?[e.activeCharacterId]:[],...e.shot?.subjectIds??[],...e.jobs.flatMap(e=>[e.characterId,...e.targetIds??[]])])]}function Dt(e){let t=T(JSON.stringify(e)??``);t>65536&&D(`CONTEXT_TOO_LARGE`,`Studio context exceeds ${ue/1024} KiB.`,`$`,{bytes:t,maxBytes:ue});let n=W(nt,e,`INVALID_CONTEXT`),r=new Set(n.entities.map(e=>e.id));r.size!==n.entities.length&&D(`INVALID_CONTEXT`,`Duplicate entity ID.`);for(let e of Et(n))r.has(e)||D(`TARGET_NOT_READY`,`Mandatory target is absent from context.`);n.activeCharacterId&&!n.entities.some(e=>e.id===n.activeCharacterId&&e.kind===`character`)&&D(`INVALID_CONTEXT`,`Active target is not a character.`),[`object`,`character`,`rig`].includes(n.selection?.kind)&&!n.entities.some(e=>e.id===n.selection.id&&e.kind===n.selection.kind)&&D(`INVALID_CONTEXT`,`Selection kind disagrees with the selected entity.`),n.selection?.kind===`scene`&&n.selection.id!==n.host.sceneId&&D(`INVALID_CONTEXT`,`Selected scene is not the bound scene.`);for(let e of n.entities)e.bounds&&[`x`,`y`,`z`].some(t=>e.bounds.min[t]>e.bounds.max[t])&&D(`INVALID_CONTEXT`,`Inverted entity bounds.`),e.kind===`object`&&typeof e.scale==`number`&&D(`INVALID_CONTEXT`,`Objects use three-axis scale.`),e.kind!==`object`&&O(e.scale)&&D(`INVALID_CONTEXT`,`Cast uses scalar scale.`);let i=n.entityPage;if((i.returned!==n.entities.length||i.total<i.returned||i.truncated!==i.total>i.returned||(i.truncated?i.nextCursor===null:i.nextCursor!==null))&&D(`INVALID_CONTEXT`,`Entity pagination is inconsistent.`),n.entityIndex){let e=new Set(n.entityIndex.map(e=>e.id));e.size!==n.entityIndex.length&&D(`INVALID_CONTEXT`,`Duplicate entity index ID.`),(n.entityIndex.length>i.total||n.entities.some(t=>!e.has(t.id)))&&D(`INVALID_CONTEXT`,`Entity index must cover every detailed entity and no more than the total.`)}n.view.frame>=Math.max(1,n.scene.frameCount)&&D(`INVALID_CONTEXT`,`Playhead is outside the scene.`),new Set(n.shots.map(e=>e.id)).size!==n.shots.length&&D(`INVALID_CONTEXT`,`Duplicate shot ID.`);for(let e of[...n.shots,...n.shot?[n.shot]:[]])e.range.endFrameExclusive>n.scene.frameCount&&D(`INVALID_CONTEXT`,`Shot is outside the scene.`);return n.shot&&!n.shots.some(e=>e.id===n.shot.id&&e.range.startFrame===n.shot.range.startFrame&&e.range.endFrameExclusive===n.shot.range.endFrameExclusive)&&D(`INVALID_CONTEXT`,`Current shot and range must survive projection.`),n}function Ot(e){let t=e.beats.filter(e=>e.seconds!==void 0).length;(e.durationSeconds!==void 0&&t!==0||e.durationSeconds===void 0&&t!==e.beats.length)&&D(`INVALID_ARGUMENT`,`Use total duration or a duration for every beat, not mixed timing.`);let n=e.durationSeconds??e.beats.reduce((e,t)=>e+t.seconds,0);return(n<2||n>60||n/e.beats.length<.5)&&D(`INVALID_ARGUMENT`,`Generation must be 2-60 seconds with at least 0.5 seconds per beat.`),n}function kt(e){let t=new Set;for(let n of Array.isArray(e?.ops)?e.ops:[]){let e=O(n)?n.target?.kind:void 0;if(fe.includes(e)){t.add(e);for(let t of O(n.set)?Object.keys(n.set):[])Object.hasOwn(Be[e].properties,t)||D(`INVALID_ARGUMENT`,`Unknown ${e} path "${e}.${t}". Valid ${e} paths: ${Ve[e].join(`, `)}.`)}}t.size>1&&D(`INVALID_ARGUMENT`,`One domain per patch: split character, object, shot and stage edits into separate commands.`)}function At(e){(!O(e)||!S.includes(e.name))&&D(`UNKNOWN_TOOL`,`Unsupported Studio tool.`),e.name===`patch_elements`&&kt(e.args);let{args:t}=W(L({name:P(S),args:Ue[e.name]}),e);if(e.name===`inspect_studio`&&t.ids&&t.query!==void 0&&D(`INVALID_ARGUMENT`,`IDs and query are exclusive.`),e.name===`operate_studio`&&(!Object.keys(t).length||t.view&&!Object.keys(t.view).length)&&D(`INVALID_ARGUMENT`,`Transient operation must specify an action.`),t.ops){let e=t.ops.filter(e=>e.op===`create`&&e.name!==void 0).map(e=>e.name.normalize(`NFC`).trim());new Set(e).size!==e.length&&D(`DUPLICATE_NAME`,`Create names must be unique; resolve existing targets by ID.`);for(let e of t.ops)e.op===`update`&&Object.keys(e).length===2&&D(`INVALID_ARGUMENT`,`Update has no fields.`),e.facing&&e.rotationDeg&&D(`INVALID_ARGUMENT`,`Facing and exact rotation are exclusive.`),e.op===`group`&&e.childIds.includes(e.parentId)&&D(`INVALID_ARGUMENT`,`Cannot group an object under itself.`),t.collisionPolicy===`avoid`&&(![`create`,`update`].includes(e.op)||!e.position?.relativeTo)&&D(`INVALID_ARGUMENT`,`Avoid requires a side-relative position for every operation.`)}if(e.name===`generate_motion`&&t.source.kind===`generate`&&(t.source.beats=t.source.beats.map(e=>({...e,text:e.text.trim().replace(/\s+/g,` `)})),Ot(t.source)),e.name===`frame_shot`&&t.framing.exact&&JSON.stringify(t.framing.exact.position)===JSON.stringify(t.framing.exact.lookAt)&&D(`INVALID_ARGUMENT`,`Camera position and aim cannot coincide.`),e.name===`patch_elements`)for(let e of t.ops)Object.keys(e.set).length||D(`INVALID_ARGUMENT`,`Patch has no fields.`);return e.name===`verify_result`&&(!!t.receiptId==!!t.targets&&D(`INVALID_ARGUMENT`,`Exactly one of receiptId or targets is required.`),t.checks.includes(`motion`)&&t.range===void 0&&(t.range=`whole_clip`)),{name:e.name,args:t}}function jt(e){let t=W(ke,e),n=Ot(t),r=Math.round(n*24),i=[],a=0,o=0;for(let[e,s]of t.beats.entries()){a+=s.seconds??n/t.beats.length;let c=e===t.beats.length-1?r:Math.round(a*24),l=Math.ceil((c-o)/120),u=o;for(let t=0;t<l;t++){let n=u+Math.round((c-u)*(t+1)/l);i.push({sourceBeat:e,text:s.text.trim().replace(/\s+/g,` `),startFrame:o,endFrameExclusive:n}),o=n}}return E({fps:24,frameCount:r,durationSeconds:r/24,blocks:i})}function G(e){if(e?.ok===!1){let t=W(Ct,e,`INVALID_RECEIPT`);return T(JSON.stringify(t))>8192&&D(`INVALID_RECEIPT`,`Failure receipt exceeds 8 KiB.`),(t.mutated===!1&&t.preserved.authoredState!==`unchanged`||t.mutated===!0&&t.preserved.authoredState!==`changed`||t.mutated===`unknown`&&(t.preserved.authoredState!==`unknown`||t.recovery.action!==`reconcile`||t.recovery.retryAllowed===!0))&&D(`INVALID_RECEIPT`,`Failure must preserve uncertainty and actual state evidence.`),E(t)}let t=W(St,e,`INVALID_RECEIPT`);if(T(JSON.stringify(t))>8192&&D(`INVALID_RECEIPT`,`Receipt exceeds 8 KiB; use a detail cursor.`),t.delta.some(e=>!t.affectedIds.includes(e.id)||!Object.keys(e.after).length)&&D(`INVALID_RECEIPT`,`Readback must identify affected targets and actual state.`),t.ops){let e=t.ops.some(e=>e.status===`partial`);t.ops.some((e,t)=>e.index!==t)&&D(`INVALID_RECEIPT`,`Operation results must report every operation in order.`),t.ops.some(e=>e.status===`partial`!=!!e.droppedPaths?.length)&&D(`INVALID_RECEIPT`,`A partial operation must name the paths the domain dropped, and only a partial one may.`),t.status===`applied`&&e&&D(`INVALID_RECEIPT`,`Applied status cannot hide a dropped path.`),t.status===`partial`&&!e&&D(`INVALID_RECEIPT`,`Partial status requires at least one dropped path.`),t.status===`noop`&&t.ops.some(e=>e.status===`applied`)&&D(`INVALID_RECEIPT`,`A noop cannot report an applied operation.`)}if(t.status===`started`||t.status===`completed`?(t.revision.after<t.revision.before&&!t.nextHost&&D(`INVALID_RECEIPT`,`Completion revisions must not move backwards in one document.`),t.status===`started`&&(t.authored||t.undo||t.revision.before!==t.revision.after)&&D(`INVALID_RECEIPT`,`Started jobs cannot claim an authored commit.`),t.kind===`mutation`&&(!t.authored||!t.undo||t.revision.after<=t.revision.before||!t.delta.length)&&D(`INVALID_RECEIPT`,`A completed composite mutation needs retained undo and advancing revision evidence.`),t.undo&&(!t.authored||!t.affectedIds.length)&&D(`INVALID_RECEIPT`,`An undo entry requires an authored result and affected targets.`)):t.status===`noop`||t.status===`transient`?((t.authored||t.undo!==null||t.revision.before!==t.revision.after)&&D(`INVALID_RECEIPT`,`Non-authored operations cannot create history or advance authored revision.`),t.status===`noop`&&(t.mutated!==!1||t.delta.length)&&D(`INVALID_RECEIPT`,`Noop must prove no mutation.`),t.status===`transient`&&(!t.view||t.view.after<t.view.before||!t.delta.length)&&D(`INVALID_RECEIPT`,`Transient receipt requires view revisions and actual readback.`)):((!t.authored||!t.undo||t.revision.after!==t.revision.before+1||!t.affectedIds.length||!t.delta.length||t.mutated===!1)&&D(`INVALID_RECEIPT`,`Authored mutation requires one revision and one undo entry with actual readback.`),t.delta.length<t.affectedIds.length&&!t.detailCursor&&D(`INVALID_RECEIPT`,`Omitted batch readback requires a detail cursor.`)),t.status===`undone`&&(new Set(t.restoredTargets.map(e=>e.targetId)).size!==t.affectedIds.length||t.restoredTargets.some(e=>!t.affectedIds.includes(e.targetId)||Object.keys(ve).some(n=>e[n]!==t.host[n])))&&D(`INVALID_RECEIPT`,`Undo must identify every restored target and its new token in the bound host.`),t.status===`installed`){(!t.jobId||!t.artifactId||!t.installed||!t.verification||!t.affectedIds.includes(t.installed.characterId))&&D(`INVALID_RECEIPT`,`Installation requires correlated target, artifact and verification evidence.`);let{frameCount:e,blocks:n}=t.installed,r=0;for(let e of n)(e.startFrame!==r||e.endFrameExclusive<=r||e.endFrameExclusive-r>120)&&D(`INVALID_RECEIPT`,`Installed schedule is not contiguous or bounded.`),r=e.endFrameExclusive;(r!==e||t.installed.durationSeconds!==e/24||t.verification.range.startFrame!==0||t.verification.range.endFrameExclusive!==e||t.verification.evaluatedFrames>e)&&D(`INVALID_RECEIPT`,`Installed schedule and verification coverage disagree.`),t.verification.status===`verified`&&t.verification.evaluatedFrames!==e&&D(`INVALID_RECEIPT`,`Verified motion requires whole-clip coverage.`),t.verification.status===`unverified`&&t.explicitUnverifiedAcceptance!==!0&&t.acceptance!==`advisory-policy`&&D(`INVALID_RECEIPT`,`Unverified installation requires explicit user or advisory-policy acceptance.`)}else(t.installed||t.verification||t.jobId&&![`started`,`completed`].includes(t.status)||t.artifactId||t.repairs||t.explicitUnverifiedAcceptance!==void 0)&&D(`INVALID_RECEIPT`,`Installation evidence is exclusive to installed receipts.`);return E(t)}var K=(e,t)=>JSON.stringify(e)===JSON.stringify(t),q=(e,t)=>{throw new w(e,t)},Mt=(e,t,n)=>e?.then?e.then(t,n):t(e),Nt=e=>e.slice(-12).map(e=>({code:`STUDIO_TOAST`,message:[...e.message].slice(0,120).join(``)})),Pt=0;function Ft({registry:e,ports:t}){let n=new Map,r=new Map,i=new Map,a=new Set,o=new Map,s=new Map;function c(n,r,i){if(i.origin===`ui`)return;if(n.exposure===`ui-only`&&q(`CAPABILITY_MISSING`,`This command is available only from the Studio UI.`),n.id===`load_scenes`){let t=e=>[...new Set(e.map(e=>e.id))].sort();if(K(t(r.document.scenes),t(e.state().scenes)))return}else if(n.exposure!==`confirm`||n.requiresConfirmation?.(e.state(),r)===!1)return;let a=o.get(i.confirmationToken);(!a||a.id!==n.id||!K(a.args,r)||!K(a.host,t.read().host)||a.expires<(t.now??Date.now)())&&q(`CONFIRMATION_REQUIRED`,n.confirmationReason??`This command needs user confirmation.`),o.delete(i.confirmationToken)}let l=e=>{for(let t of a)t(e);t.emit?.(e)},u=wt.TargetGuard.properties.targetId,d=e=>({type:`object`,properties:e,required:Object.keys(e),additionalProperties:!1}),f={type:`object`,properties:{},required:[],additionalProperties:!0},p={"run.begin":d({id:u,args:f}),"run.update":d({txId:u,args:f}),"run.commit":d({txId:u}),"run.cancel":d({txId:u}),"job.await":{...d({jobId:u}),properties:{jobId:u,timeoutMs:{type:`integer`,minimum:1,maximum:3e5,default:3e4}}},"job.cancel":d({jobId:u}),"edit.undo":{...d({receiptId:u}),required:[]},"edit.redo":{...d({receiptId:u}),required:[]}},m=e=>(t.clearTimeout??clearTimeout)(e);function h(e,n=!1,i=new w(`CANCELLED`,`Transaction was cancelled.`)){r.delete(e.txId),m(e.timer),e.workTimer!==void 0&&m(e.workTimer),e.controller.abort(i),e.session.cancel({restore:K(e.before.host,t.read().host)}),l({type:`transaction.cancelled`,txId:e.txId,expired:n})}function ee(e){e.timer!==void 0&&m(e.timer),e.timer=(t.setTimeout??setTimeout)(()=>h(e,!0),t.transactionIdleMs??3e4)}function te(n,a,o,l){if(n===`edit.undo`||n===`edit.redo`){let e=n===`edit.redo`,r=t.history?.(e),i=a.receiptId?t.receipt(a.receiptId):s.get(r)??(r?{receiptId:r,host:l.host,affectedIds:[l.host.sceneId],undo:{historyEntryId:r,entries:1,canUndoDirect:!0}}:null);if(!a.receiptId&&!i)return G({ok:!0,status:`noop`,action:n,commandId:o.commandId,receiptId:crypto.randomUUID(),host:l.host,authored:!1,mutated:!1,revision:{before:l.revision,after:l.revision},affectedIds:[],delta:[],checks:{coverage:`native-history-restoration`},undo:null,warnings:[]});(!i?.undo||!t.isRetained(i))&&q(`UNDO_EXPIRED`,`The receipt no longer has a retained history entry.`),K(i.host,l.host)||q(`STALE_SCENE`,`The receipt belongs to another document.`),(e?r!==i.undo.historyEntryId:!t.canUndo(i))&&q(`UNDO_CONFLICT`,`Another edit owns the history boundary.`),(e?t.redo:t.undo)();let c=t.read(),u=i.affectedIds,d=u.map(e=>({...l.host,targetId:e,token:t.readTarget?.(e)??`removed-${crypto.randomUUID()}`}));return G({ok:!0,status:e?`applied`:`undone`,commandId:o.commandId,receiptId:crypto.randomUUID(),host:l.host,authored:!0,revision:{before:l.revision,after:c.revision},affectedIds:u,delta:u.slice(0,8).map(e=>({id:e,after:{token:d.find(t=>t.targetId===e).token}})),checks:{coverage:`native-history-restoration`},undo:{...i.undo,canUndoDirect:e},warnings:[],...e?{action:n,mutated:!0}:{undoneReceiptId:i.receiptId,restoredTargets:d},...u.length>8?{detailCursor:o.commandId}:{}})}if(n.startsWith(`job.`)){let e=i.get(a.jobId);(!e||!K(e.host,l.host))&&q(`STALE_TARGET`,`Job is not in this document.`),n===`job.cancel`&&!e.outcome&&e.controller.abort(new w(`CANCELLED`,`Job was cancelled.`));let r;return(n===`job.await`&&!e.outcome?Promise.race([e.completion,new Promise((e,n)=>{r=(t.setTimeout??setTimeout)(()=>n(new w(`TIMEOUT`,`Job is still running.`)),a.timeoutMs)})]):e.completion).then(t=>G({...t,commandId:o.commandId,...t.ok?{receiptId:crypto.randomUUID()}:{},jobId:e.id})).finally(()=>{r!==void 0&&m(r)})}let u;if(n===`run.begin`){r.size&&q(`TARGET_BUSY`,`Finish or cancel the open command transaction first.`);let n=e.prepare(a.id,a.args);c(n.entry,n.args,o),n.entry.kind!==`mutation`&&q(`INVALID_ARGUMENT`,`Only mutations can open a transaction.`),u={txId:crypto.randomUUID(),entry:n.entry,before:l,origin:o.origin,targetId:n.args.characterId??null,controller:new AbortController,session:t.beginAction(n.entry.undoDomain,n.args.characterId??null),affectedIds:new Set,toasts:[]},r.set(u.txId,u),ee(u)}else{if(u=r.get(a.txId),(!u||!K(u.before.host,l.host))&&q(`STALE_TARGET`,`Transaction is no longer open in this document.`),o.origin!==u.origin&&q(`TARGET_BUSY`,`This transaction belongs to another origin.`),u.updating&&n!==`run.cancel`&&q(`TARGET_BUSY`,`A transaction update is still running.`),n===`run.update`){let i=e.prepare(u.entry.id,a.args);u.entry.undoDomain===`motion`&&i.args.characterId!==u.targetId&&q(`INVALID_ARGUMENT`,`A motion transaction keeps its original target.`);let s=[],c=t.captureToasts?.(e=>s.push(typeof e==`string`?{message:e}:e)),d={origin:o.origin,signal:u.controller.signal,check(){u.controller.signal.throwIfAborted(),(!r.has(u.txId)||!K(u.before.host,t.read().host))&&q(`STALE_TARGET`,`Transaction is no longer current.`)}},f=e=>{c?.(),m(u.workTimer),u.updating=!1,d.check(),s.length&&t.read().revision===l.revision&&q(`TARGET_NOT_READY`,s.at(-1).message);for(let t of e.affectedIds)u.affectedIds.add(t);return u.toasts.push(...s),ee(u),g(n,u,o,l)},p=e=>{throw c?.(),m(u.workTimer),u.updating=!1,!(e instanceof w)&&s.length&&t.read().revision===l.revision&&(e=new w(`TARGET_NOT_READY`,s.at(-1).message)),r.has(u.txId)&&h(u),e};try{u.updating=!0,m(u.timer),u.workTimer=(t.setTimeout??setTimeout)(()=>h(u,!0,new w(`TIMEOUT`,`${u.entry.id} exceeded its deadline.`)),u.entry.timeoutMs??3e4);let n=u.session.run(()=>e.invoke(u.entry,i.args,d));if(!n?.then)return f(n);let r=new Promise((e,t)=>u.controller.signal.addEventListener(`abort`,()=>t(u.controller.signal.reason),{once:!0}));return Promise.race([n,r]).then(f,p)}catch(e){return p(e)}}if(n===`run.cancel`&&h(u),n===`run.commit`){r.delete(u.txId),m(u.timer);try{u.historyEntryId=u.session.commit().historyEntryId}catch(e){throw u.session.cancel({restore:!1}),e}}}return g(n,u,o,n===`run.commit`?u.before:l)}function g(e,n,r,i){let a=t.read();return G({ok:!0,status:`completed`,kind:`transaction`,commandId:r.commandId,receiptId:crypto.randomUUID(),host:i.host,action:e,txId:n.txId,authored:!!n.historyEntryId,revision:{before:i.revision,after:a.revision},affectedIds:[...n.affectedIds],delta:[],checks:{coverage:`wire-transaction`},warnings:Nt(n.toasts),undo:n.historyEntryId?{historyEntryId:n.historyEntryId,entries:1,canUndoDirect:!0}:null})}function ne(e,n,r,i){let a=i??t.read().revision!==n.revision;return G({ok:!1,commandId:e.commandId,host:n.host,code:r.code??`INVALID_ARGUMENT`,phase:a?`commit`:`admission`,affectedIds:[],expectedTargets:[],currentTargets:[],mutated:a,preserved:{authoredState:a?`changed`:`unchanged`},recovery:{action:`inspect`,retryAllowed:!1},message:[...String(r.message||r)].slice(0,500).join(``)})}function re(e,n,r,i,a,o=[]){let s=t.read(),c=s.revision!==r.revision;e.kind===`mutation`&&c&&!a&&q(`UNCERTAIN_APPLY`,`${e.id} changed the scene without one undoable entry.`);let l=e.kind===`job`||e.kind===`document`||e.kind===`mutation`&&c&&s.revision>r.revision+1,u=l||c?i.affectedIds:e.kind===`transient`?[r.host.sceneId]:[];return G({ok:!0,commandId:n.commandId,receiptId:crypto.randomUUID(),host:r.host,action:e.id,summary:i.summary,status:l?`completed`:e.kind===`transient`?`transient`:c?`applied`:`noop`,authored:c,...l?{kind:e.kind,...i.output===void 0?{}:{output:i.output},...K(r.host,s.host)?{}:{nextHost:s.host}}:e.kind===`transient`?{view:{before:r.viewRevision??0,after:s.viewRevision??0}}:{mutated:c},revision:{before:r.revision,after:s.revision},affectedIds:u,delta:u.slice(0,8).map(e=>({id:e,after:t.readback?.(e,s)??{removed:!0}})),checks:{coverage:`studio-action:${e.id}`},warnings:Nt(o),undo:a?{historyEntryId:a,entries:1,canUndoDirect:!0}:null,...u.length>8?{detailCursor:n.commandId}:{}})}function ie(a,o={},u={}){let d={origin:`ui`,commandId:crypto.randomUUID(),...u};d.origin===`ui`&&(a===`edit.undo`||a===`edit.redo`)&&t.finishHistoryGesture?.();let f=t.read(),h=t.journal(),ee=!1,g,ie,_,v,ae=!1,oe,y=new AbortController,se=()=>{ie!==void 0&&m(ie),_!==void 0&&m(_)},ce=[],le=()=>ce.length&&t.read().revision===f.revision?new w(`TARGET_NOT_READY`,ce.at(-1).message):null,ue=e=>{if(v?.background){let t=v.completionCommandId??=crypto.randomUUID();h.begin(t),e=G({...e,commandId:t,jobId:v.id})}let n=h.record(e);n.undo?.canUndoDirect&&!a.startsWith(`edit.`)&&s.set(n.undo.historyEntryId,n);for(let[e,n]of s)t.isRetained?.(n)===!1&&s.delete(e);return t.remember?.(n),n},de=e=>{se(),g?.(),g=null,e instanceof w||(e=le()??e),d.origin===`ui`&&e.uiMessage&&t.showRefusal?.(e.uiMessage);let n=ne(d,f,e,v?ae:void 0),r=ee?ue(n):n;return v&&!v.completion&&(v.outcome=r,v.completion=Promise.resolve(r),l({type:`job.completed`,jobId:v.id,receipt:r})),r};try{d.origin!==`ui`&&!K(Tt(d.host),f.host)&&q(`STALE_SCENE`,`The live document changed.`);let s=JSON.stringify({id:a,args:o,...d});if(!h.begin(d.commandId,s))return h.get(d.commandId)??n.get(d.commandId)??ne(d,f,new w(`UNCERTAIN_APPLY`,`Command is still executing.`));ee=!0;let{entry:u,args:m}=p[a]?{args:W(p[a],o)}:e.prepare(a,o);if(d.origin!==`ui`&&(![`job.await`,`job.cancel`].includes(a)&&d.expectedRevision!==f.revision&&q(`STALE_SCENE`,`Authored state changed; obtain fresh intent.`),f.busy&&!r.has(m.txId)&&!a.startsWith(`job.`)&&q(`TARGET_BUSY`,`Finish the current editor gesture first.`)),p[a])return Mt(te(a,m,d,f),ue,de);r.size&&q(`TARGET_BUSY`,`Finish or cancel the open command transaction first.`),c(u,m,d),g=t.captureToasts?.(e=>ce.push(typeof e==`string`?{message:e}:e));let b=u.domain??u.undoDomain,x=u.target?.(m,f)??m.characterId??m.shotId??m.objectId,S=x?t.readTarget?.(x):null,fe=b?f.domainRevisions?.[b]:null,pe=()=>{let e=t.read();S=x?t.readTarget?.(x):null,fe=b?e.domainRevisions?.[b]:null},C=new Set,T={origin:d.origin,signal:y.signal,check(){y.signal.throwIfAborted();let e=t.read();(!K(e.host,f.host)||b&&e.domainRevisions?.[b]!==fe||x&&t.readTarget?.(x)!==S)&&q(`STALE_TARGET`,`The target or its authored domain changed while the job was running.`)},commit(e){T.check(),b||q(`INVALID_ARGUMENT`,`A committing job must declare its domain.`);let n=t.recordAction(b,e,x??null);return n?.then&&q(`INVALID_ARGUMENT`,`Job publication must be synchronous; prepare before commit.`),oe=n.historyEntryId,ae||=!!oe,v&&pe(),n.result},run(n,r={}){v?T.check():y.signal.throwIfAborted();let i=e.prepare(n,r);c(i.entry,i.args,d);let a=()=>e.invoke(i.entry,i.args,T),o=i.entry.kind===`mutation`?t.recordAction(i.entry.undoDomain,a,i.args.characterId??null,!0):{result:a()};return v&&pe(),Mt(o,e=>Mt(e.result,t=>{v&&(T.check(),pe(),ae||=!!e.historyEntryId);for(let e of t.affectedIds)C.add(e);return t}))}};u.kind===`job`&&(v={id:crypto.randomUUID(),host:f.host,controller:y,background:!1},i.set(v.id,v)),ie=(t.setTimeout??setTimeout)(()=>{let e=new w(`TIMEOUT`,`${u.id} exceeded its deadline.`);y.abort(e)},v&&u.background===!0?3e5:u.timeoutMs??3e4);let E=()=>{let t=e.invoke(u,m,T);if(!t?.then)return t;let n=new Promise((e,t)=>y.signal.addEventListener(`abort`,()=>t(y.signal.reason),{once:!0}));return Promise.race([t,n])},D=u.kind===`mutation`?t.recordAction(u.undoDomain,E,m.characterId??null):{result:E(),historyEntryId:null},O=({result:e,historyEntryId:t})=>Mt(e,e=>{se(),g?.(),g=null;let n=le();if(n)throw n;return ue(re(u,d,f,{...e,affectedIds:[...new Set([...e.affectedIds,...C])]},t??oe,ce))}),k=D?.then?D.then(O):O(D),A=k?.then?k.catch(de):k;if(v){v.completion=Promise.resolve(A).then(e=>(v.outcome=e,l({type:`job.completed`,jobId:v.id,receipt:e}),e));let e=()=>{v.background=!0;let e=t.read();return h.record(G({ok:!0,commandId:d.commandId,receiptId:crypto.randomUUID(),host:f.host,action:u.id,status:`started`,kind:`job`,jobId:v.id,authored:!1,revision:{before:e.revision,after:e.revision},affectedIds:[],delta:[],checks:{coverage:`studio-action:${u.id}`},warnings:[],undo:null}))};if(A?.then&&d.wait===!1)return e();if(A?.then&&u.background===!0){let r=Promise.race([v.completion,new Promise(n=>{_=(t.setTimeout??setTimeout)(()=>n(e()),u.timeoutMs??3e4)})]).finally(()=>n.delete(d.commandId));return n.set(d.commandId,r),r}}if(A?.then){let e=(v?.completion??A).finally(()=>n.delete(d.commandId));return n.set(d.commandId,e),e}return A}catch(e){return de(e)}}function _(...e){Pt++;try{let t=ie(...e);return t?.then?t.finally(()=>{Pt--}):(Pt--,t)}catch(e){throw Pt--,e}}return{run:_,confirm(n,r={}){let i=e.prepare(n,r),a=crypto.randomUUID();return o.set(a,{id:n,args:i.args,host:t.read().host,expires:(t.now??Date.now)()+3e5}),a},subscribe(e){return a.add(e),()=>a.delete(e)},dispose(){for(let e of r.values())h(e);for(let e of i.values())e.outcome||e.controller.abort(new w(`CANCELLED`,`Studio closed.`));a.clear()}}}var It=Object.freeze([`pose_edit`,`object_insert`,`cutout_insert`,`object_transform`,`shot_add`,`shot_edit`,`camera_key_record`,`rail_edit`,`prompt_block_add`,`prompt_block_edit`]);function J(e,t){if(e===t)return!0;if(typeof e==`number`&&typeof t==`number`)return Math.abs(e-t)<1e-8;if(!e||!t||typeof e!=`object`||typeof t!=`object`)return!1;if(e instanceof Map||t instanceof Map)return e instanceof Map&&t instanceof Map&&e.size===t.size&&[...e].every(([e,n])=>t.has(e)&&J(n,t.get(e)));let n=Object.keys(e);return n.length===Object.keys(t).length&&n.every(n=>Object.hasOwn(t,n)&&J(e[n],t[n]))}var Lt=e=>({bones:e?.bones??{},rootY:e?.rootY??0}),Rt=e=>e.map(({id:e,...t})=>t),zt=(e=[])=>e.map(({frame:e,framing:t})=>({frame:e,framing:t})),Bt=e=>({...e,camera:_(e.camera),cameraKeys:zt(e.cameraKeys)});function Vt(e,t,n){if(t===n)return null;if(e===`pose`)return J(t,n)?null:`pose_edit`;if(e===`promptClips`)return J(Rt(t),Rt(n))?null:n.length>t.length?`prompt_block_add`:`prompt_block_edit`;if(e===`objects`){let e=n.find(e=>!t.some(t=>t.id===e.id));return e?e.renderer===`cutout`?`cutout_insert`:`object_insert`:J(t,n)?null:`object_transform`}if(e===`characters`){if(n.some(e=>!t.some(t=>t.id===e.id)))return`object_insert`;for(let e of n){let n=t.find(t=>t.id===e.id);if(n&&!J(Lt(n.pose),Lt(e.pose)))return`pose_edit`}let e=e=>e.map(({id:e,x:t,y:n=0,z:r,rot:i,scale:a=1,hidden:o=!1,model:s,tint:c,subject:l,identityImage:u})=>({id:e,x:t,y:n,z:r,rot:i,scale:a,hidden:o,model:s,tint:c,subject:l,identityImage:u}));return J(e(t),e(n))?null:`object_transform`}if(e===`shots`){if(n.some(e=>!t.some(t=>t.id===e.id)))return`shot_add`;for(let e of n){let n=t.find(t=>t.id===e.id);if(!n)continue;let r=_(e.camera),i=_(n.camera);if([`cameraRail`,`craneHeight`,`railFollow`,`dollyTiming`].some(e=>!J(r[e],i[e])))return`rail_edit`;let a=e.cameraKeys??[],o=n.cameraKeys??[];if(a.length>o.length||a.some(e=>{let t=o.find(t=>t.frame===e.frame);return t&&!J(t.framing,e.framing)}))return`camera_key_record`}return J(t.map(Bt),n.map(Bt))?null:`shot_edit`}return null}function Ht(e){let t=new Set;return(n,r,i,a)=>{if(![`craft`,`playground`].includes(n)||t.has(n))return!1;let o=Vt(r,i,a);return o?(t.add(n),e(`${n}:first_edit`,{edit_kind:o,definition_version:1}),!0):!1}}var Ut=`modulepreload`,Wt=function(e){return`/`+e},Gt={},Kt=function(e,t,n){let r=Promise.resolve();if(t&&t.length>0){let e=document.getElementsByTagName(`link`),i=document.querySelector(`meta[property=csp-nonce]`),a=i?.nonce||i?.getAttribute(`nonce`);function o(e){return Promise.all(e.map(e=>Promise.resolve(e).then(e=>({status:`fulfilled`,value:e}),e=>({status:`rejected`,reason:e}))))}function s(e){return import.meta.resolve?import.meta.resolve(e):new URL(e,import.meta.url).href}r=o(t.map(t=>{if(t=Wt(t,n),t=s(t),t in Gt)return;Gt[t]=!0;let r=t.endsWith(`.css`);for(let n=e.length-1;n>=0;n--){let i=e[n];if(i.href===t&&(!r||i.rel===`stylesheet`))return}let i=document.createElement(`link`);if(i.rel=r?`stylesheet`:Ut,r||(i.as=`script`),i.crossOrigin=``,i.href=t,a&&i.setAttribute(`nonce`,a),document.head.appendChild(i),r)return new Promise((e,n)=>{i.addEventListener(`load`,e),i.addEventListener(`error`,()=>n(Error(`Unable to preload CSS for ${t}`)))})}))}function i(e){let t=new Event(`vite:preloadError`,{cancelable:!0});if(t.payload=e,window.dispatchEvent(t),!t.defaultPrevented)throw e}return r.then(t=>{for(let e of t||[])e.status===`rejected`&&i(e.reason);return e().catch(i)})},qt=Object.freeze([`read`,`camera`,`scene_write`,`prompt_authoring`,`frame_capture`,`motion_generate`,`motion_apply`,`project_io`,`other`]),Jt=Object.freeze([`workflow_read`,`workflow_write`,`workflow_run`,`frame_capture`,`image_generate`,`scene_write`,`other`]),Yt=Object.freeze([`workflow:run_requested`,`workflow:run_succeeded`,`workflow:run_failed`,`workflow:run_cancelled`,`workflow:result_applied`,`agent:turn_requested`,`agent:tool_executed`,`agent:turn_succeeded`,`agent:turn_failed`,`agent:turn_cancelled`,`agent:result_applied`,`mcp:tool_requested`,`mcp:tool_executed`,`mcp:result_applied`]),Xt=Object.freeze({"workflow:run_requested":[`surface`,`run_id`,`node_count_bucket`],"workflow:run_succeeded":[`run_id`,`duration_bucket`],"workflow:run_failed":[`run_id`,`duration_bucket`,`failure_code`],"workflow:run_cancelled":[`run_id`,`duration_bucket`,`failure_code`],"workflow:result_applied":[`run_id`],"agent:turn_requested":[`surface`,`turn_id`],"agent:tool_executed":[`turn_id`,`tool_category`,`outcome`,`duration_bucket`],"agent:turn_succeeded":[`turn_id`,`duration_bucket`],"agent:turn_failed":[`turn_id`,`duration_bucket`,`failure_code`],"agent:turn_cancelled":[`turn_id`,`duration_bucket`,`failure_code`],"agent:result_applied":[`turn_id`],"mcp:tool_requested":[`tool_category`,`request_id`],"mcp:tool_executed":[`tool_category`,`outcome`,`duration_bucket`,`request_id`],"mcp:result_applied":[`request_id`]}),Zt=Object.freeze({surface:new Set([`studio`,`workflow`]),node_count_bucket:new Set([`0`,`1-3`,`4-10`,`gte11`]),duration_bucket:new Set([`lt1s`,`1-3s`,`3-10s`,`10-30s`,`gte30s`]),tool_category:new Set([...qt,...Jt]),outcome:new Set([`succeeded`,`failed`,`uncertain`,`cancelled`])}),Qt=`cozyclay.analyticsOptOut`,$t=`cozyclay.internalQa`,en=`cozyclay.analyticsActivation`,tn=`cozyclay.useCaseAsked`,nn=Object.freeze({pose:Object.freeze([`pose_edit`]),camera:Object.freeze([`camera_key_record`,`rail_edit`]),object:Object.freeze([`object_insert`,`cutout_insert`,`object_transform`]),shot:Object.freeze([`shot_add`,`shot_edit`]),prompt:Object.freeze([`prompt_block_add`,`prompt_block_edit`])}),rn=Object.freeze(Object.keys(nn).map(e=>`${e}_edit_bucket`)),an=Object.freeze([`animation`,`film`,`game`,`ad_mv`,`personal`,`other`,`skip`]),on=Object.freeze([`team`,`solo`,`skip`]),sn=Object.freeze([`latest`,`outdated`,`unknown`]),cn=Object.freeze([`https://cozyclay.org`,`https://www.cozyclay.org`]),ln=Object.freeze({"install:first_launch":[`heard_from`],"app:session_started":[],"app:session_ended":[`duration_bucket`,`action_count_bucket`,`scenes_touched`,...rn],"app:error":[`error_kind`,`error_type`,`error_source`,`error_file`,`error_line`,`error_col`],"device:profile":[`gpu_vendor`,`gpu_class`,`webgl`,`cpu_bucket`,`memory_bucket`,`frame_rate_bucket`],"survey:use_case":[`use_case`,`team`],"feature:used":[`name`],"hosted:composer_viewed":[],"hosted:login_started":[],"hosted:ticket_created":[],"hosted:result_opened":[],"hosted:opened_in_studio":[],"scene:created":[`scene_source`],"scene:loaded":[`scene_source`],"project:saved":[`object_count_bucket`,`shot_count_bucket`],"project:opened":[`age_bucket`],"craft:first_action":[`action_kind`],"craft:first_edit":[`edit_kind`,`definition_version`],"motion:backend_state":[`backend`,`host_configured`],"motion:generate_requested":[`surface`,`input_mode`,`request_id`],"motion:preflight_blocked":[`reason`,`surface`,`request_id`],"motion:preflight_passed":[`backend`,`surface`,`request_id`],"motion:job_started":[`backend`,`input_mode`,`request_id`],"motion:job_succeeded":[`backend`,`duration_bucket`,`input_mode`,`request_id`],"motion:job_failed":[`backend`,`duration_bucket`,`input_mode`,`error_code`,`request_id`],"motion:result_applied":[`request_id`,`backend`],"export:blocking_frame_succeeded":[`format`],"export:video_succeeded":[`format`],"export:keyframe_pack":[`entries`,`source`],"export:attempt_started":[`attempt_id`,`export_kind`,`format`,`surface`],"export:attempt_succeeded":[`attempt_id`,`export_kind`,`format`,`surface`,`duration_bucket`],"export:attempt_failed":[`attempt_id`,`export_kind`,`format`,`surface`,`duration_bucket`,`failure_code`],"export:attempt_cancelled":[`attempt_id`,`export_kind`,`format`,`surface`,`duration_bucket`,`failure_code`],"sample:played":[`from`],"playground:opened":[],"playground:first_action":[`action_kind`],"playground:first_edit":[`edit_kind`,`definition_version`],"activation:completed":[`activation_path`],"tutorial:started":[`surface`,`tutorial_version`,`start_source`],"tutorial:step_entered":[`surface`,`tutorial_version`,`step_kind`],"tutorial:step_completed":[`surface`,`tutorial_version`,`step_kind`,`elapsed_bucket`],"tutorial:completed":[`surface`,`tutorial_version`,`elapsed_bucket`],"tutorial:dismissed":[`surface`,`tutorial_version`,`step_kind`],...Xt}),un=new Set([`pose_edit`,`pose_save`,`camera_fly`,`orbit`,`dolly_rail`,`crane_graph`,`timeline_scrub`,`prompt_block_add`,`shot_add`,`shot_cut`,`export_pose`,`export_frame`,`export_video`,`export_depth_video`,`export_keyframe_pack`,`fal_motion_open`,`mcp_connected`,`auto_color`,`plan_view`,`camera_tutorial`]),dn=Object.freeze([`x`,`hn`,`reddit`,`github`,`friend`,`other`,`site`,`playground`]),fn=new Set(dn),pn=new Set([`prompt`,`text`,`url`,`path`,`file`]),mn=new Set([`aborted`,`unsupported_route`,`generation_failed`,`quota`,`unknown`]),hn=Object.freeze({backend:new Set([`none`,`local_kimodo`,`hosted`,`fal`]),host_configured:new Set([!0,!1]),surface:new Set([`timeline`,`line_edit`,`trail`,`mcp`,`fal_card`,`agent`]),input_mode:new Set([`prompt`,`pose`,`edit`,`a_to_b`,`still`]),reason:new Set([`unconfigured`,`unreachable`,`unsupported_route`,`locked`,`missing_input`]),error_code:mn,duration_bucket:new Set([`lt1s`,`1-3s`,`3-10s`,`10-30s`,`gte30s`])}),gn=new Set([`unsupported_codec`,`encode_failed`,`render_failed`,`aborted`,`unknown`]),_n=Object.freeze({export_kind:new Set([`video`,`depth_video`,`frame`,`keyframe_pack`]),format:new Set([`mp4`,`png`,`zip`]),surface:new Set([`studio`,`workflow`,`embed`]),duration_bucket:new Set([`lt1s`,`1-3s`,`3-10s`,`10-30s`,`gte30s`]),failure_code:gn}),vn=Object.freeze({surface:new Set([`studio`,`playground`]),tutorial_version:new Set([1]),start_source:new Set([`query`,`settings`,`landing`]),step_kind:new Set([`fly`,`walk`,`dolly`,`orbit`,`shot`,`rail`,`play`]),elapsed_bucket:new Set([`lt1s`,`1-3s`,`3-10s`,`10-30s`,`gte30s`])}),yn=Object.freeze({workflow:new Set([`aborted`,`capture_failed`,`generation_failed`,`unknown`]),agent:new Set([`aborted`,`auth`,`rate_limited`,`tool_failed`,`upstream`,`unknown`])}),bn=Object.freeze({error_kind:new Set([`error`,`unhandled_rejection`]),error_type:new Set([`Error`,`TypeError`,`RangeError`,`ReferenceError`,`SyntaxError`,`EvalError`,`URIError`,`AggregateError`,`AbortError`,`TimeoutError`,`NotAllowedError`,`NotSupportedError`,`NotFoundError`,`NotReadableError`,`InvalidStateError`,`QuotaExceededError`,`SecurityError`,`NetworkError`,`DataCloneError`,`OperationError`,`EncodingError`,`UnknownError`,`DOMException`,`non_error`,`other`]),error_source:new Set([`app`,`extension`,`external`,`unknown`])}),xn=/^[A-Za-z0-9_.-]{1,80}\.(?:m?js|jsx|ts|tsx)$/,Sn=Object.freeze({gpu_vendor:new Set([`nvidia`,`amd`,`intel`,`apple`,`qualcomm`,`arm`,`software`,`other`,`unknown`]),gpu_class:new Set([`discrete`,`integrated`,`software`,`unknown`]),webgl:new Set([`webgl2`,`webgl1`,`none`]),cpu_bucket:new Set([`1-4`,`5-8`,`9-16`,`gte17`,`unknown`]),memory_bucket:new Set([`lt4`,`4-7`,`gte8`,`unknown`]),frame_rate_bucket:new Set([`lt20`,`20-40`,`40-55`,`gte55`,`unknown`])}),Y=null,X=!1,Z=!1,Cn=!1,wn=null,Tn=!1,En=!1,Dn=0,On=0,kn=0,An=!1,jn=!1,Mn=new Set,Nn=new Map(Object.entries(nn).flatMap(([e,t])=>t.map(t=>[t,e]))),Pn=1e3,Fn=Object.fromEntries(Object.keys(nn).map(e=>[e,0])),In=null,Ln=-1/0,Rn=10,zn=new Set,Bn=!1,Vn=!1,Hn=new Set([`app:session_started`,`app:session_ended`,`install:first_launch`,`motion:backend_state`,`app:error`,`device:profile`]);function Un(){try{return globalThis.localStorage??null}catch{return null}}function Wn(e){try{return Un()?.getItem(e)??null}catch{return null}}function Gn(e,t){try{Un()?.setItem(e,t)}catch{}}function Kn(e){return typeof e==`string`?e.trim().toLowerCase().replace(/[/.]+$/g,``):``}function qn(e){return e===void 0?[...cn]:e.split(`,`).map(Kn).filter(Boolean)}function Jn(e,t){let n=Kn(e);return Array.isArray(t)&&t.some(e=>n===Kn(e))}var Yn=e=>typeof e==`boolean`?!0:typeof e==`number`?Number.isFinite(e):typeof e==`string`&&e.length<=32&&!/\s/.test(e);function Xn(e,t){let n=ln[e]??[];if(!t||typeof t!=`object`||Array.isArray(t))return{};let r={};for(let i of n)if(!(pn.has(i)||!Object.hasOwn(t,i))&&!(e===`feature:used`&&(i!==`name`||!un.has(t[i])))&&!(e===`install:first_launch`&&(i!==`heard_from`||!fn.has(t[i])))){if(e.startsWith(`export:attempt_`)){if(i===`attempt_id`){if(typeof t[i]!=`string`||!/^[a-f0-9]{32}$/.test(t[i]))continue}else if(!_n[i]?.has(t[i]))continue}if(!(e===`export:keyframe_pack`&&(i===`source`&&t[i]!==`workflow`||i===`entries`&&(!Number.isFinite(t[i])||t[i]<0)))&&!((e===`craft:first_edit`||e===`playground:first_edit`)&&(i===`edit_kind`&&!It.includes(t[i])||i===`definition_version`&&t[i]!==1))){if(e.startsWith(`motion:`)){if(i===`request_id`){if(typeof t[i]!=`string`||!/^[a-f0-9]{32}$/.test(t[i]))continue}else if(!hn[i]?.has(t[i]))continue}if(!(e.startsWith(`tutorial:`)&&!vn[i]?.has(t[i]))){if(e.startsWith(`workflow:`)||e.startsWith(`agent:`)||e.startsWith(`mcp:`)){if(i===`run_id`||i===`turn_id`||i===`request_id`){if(typeof t[i]!=`string`||!/^[a-f0-9]{32}$/.test(t[i]))continue}else if(i===`surface`){if(!Zt.surface.has(t[i])||e.startsWith(`workflow:`)&&t[i]!==`workflow`)continue}else if(i===`node_count_bucket`&&!Zt.node_count_bucket.has(t[i]))continue;else if(i===`duration_bucket`&&!Zt.duration_bucket.has(t[i]))continue;else if(i===`tool_category`){if(!(e.startsWith(`agent:`)?Jt:qt).includes(t[i]))continue}else if(i===`outcome`){if(!(e===`mcp:tool_executed`?[`succeeded`,`failed`,`uncertain`,`cancelled`]:[`succeeded`,`failed`,`cancelled`]).includes(t[i]))continue}else if(i===`failure_code`&&!yn[e.startsWith(`agent:`)?`agent`:`workflow`].has(t[i]))continue}if(e===`app:error`){if(i===`error_file`){typeof t[i]==`string`&&xn.test(t[i])&&(r[i]=t[i]);continue}if(i===`error_line`||i===`error_col`){Number.isInteger(t[i])&&t[i]>=0&&t[i]<=1e7&&(r[i]=t[i]);continue}if(!bn[i]?.has(t[i]))continue}e===`device:profile`&&!Sn[i]?.has(t[i])||e===`survey:use_case`&&(i===`use_case`&&!an.includes(t[i])||i===`team`&&!on.includes(t[i]))||Yn(t[i])&&(r[i]=t[i])}}}return r}function Zn(e){return!e||e.ok!==!0?{backend:`none`,host_configured:!1}:typeof e.backend==`string`&&[`none`,`local_kimodo`,`hosted`].includes(e.backend)?{backend:e.backend,host_configured:e.host_configured===!0||typeof e.host==`string`&&e.host.trim().length>0}:{backend:`local_kimodo`,host_configured:!!(typeof e.host==`string`&&e.host.trim())}}function Qn(e,{body:t={},lineEditSupported:n=!1}={}){return!e||e.backend===`none`||e.ok!==!0&&(e.host_configured===!1||e.reason===`unconfigured`)?`unconfigured`:e.ok===!0?(t.lineEdit||t.replay?.length)&&!n||!t.lineEdit&&e.host===`local`&&e.device===`local`&&(t.segments?.length>1||t.posePin||t.waypoints?.length||t.motionEdit||t.preserve)?`unsupported_route`:null:`unreachable`}function $n(e,t){try{if(e?.name===`AbortError`)return`aborted`;if(mn.has(t))return t;if(e instanceof Error)return`generation_failed`}catch{}return`unknown`}function er(e,t={}){let n=`requested`,r=null,i=NaN,a=()=>performance.now(),o=$,s=()=>{try{return a()}catch{return NaN}},c=(e,t={})=>{if(r)try{Promise.resolve(o(e,Xn(e,{...r,...t}))).catch(()=>{})}catch{}};try{a=t.now??a,o=t.capture??o;let n=[...globalThis.crypto.getRandomValues(new Uint8Array(16))].map(e=>e.toString(16).padStart(2,`0`)).join(``);r={...Xn(`motion:generate_requested`,e),request_id:n},c(`motion:generate_requested`)}catch{r=null}return{preflight(e,t){if(n===`requested`)try{let i=Qn(e,t);n=i?`blocked`:`passed`,r&&(r.backend=Zn(e).backend),c(i?`motion:preflight_blocked`:`motion:preflight_passed`,i?{reason:i}:{})}catch{}},block(e){n===`requested`&&(n=`blocked`,c(`motion:preflight_blocked`,{reason:e}))},pass(e){n===`requested`&&(n=`passed`,r&&(r.backend=e),c(`motion:preflight_passed`))},start(){n===`passed`&&(n=`started`,i=s(),c(`motion:job_started`))},succeed(){n===`started`&&(n=`succeeded`,c(`motion:job_succeeded`,{duration_bucket:ar(s()-i)}))},fail(e,t){n===`started`&&(n=`failed`,c(`motion:job_failed`,{duration_bucket:ar(s()-i),error_code:$n(e,t)}))},apply(){n===`succeeded`&&(n=`applied`,c(`motion:result_applied`))}}}Object.freeze([...un]);function tr(e){let t=Number.isFinite(e)?Math.max(0,Math.floor(e)):0;return t===0?`0`:t<=3?`1-3`:t<=10?`4-10`:`gte11`}function nr(e){return!Number.isFinite(e)||e<6e4?`lt1m`:e<3e5?`1-5m`:e<9e5?`5-15m`:e<18e5?`15-30m`:`gte30m`}function rr(e){return!Number.isFinite(e)||e<0||e<36e5?`lt1h`:e<864e5?`1-24h`:e<6048e5?`1-7d`:e<2592e6?`7-30d`:`gte30d`}function ir(){let e=String(globalThis.navigator?.userAgentData?.platform||globalThis.navigator?.platform||``).toLowerCase();return e.includes(`mac`)?`macos`:e.includes(`win`)?`windows`:e.includes(`linux`)?`linux`:e.includes(`android`)?`android`:e.includes(`iphone`)||e.includes(`ipad`)||e.includes(`ios`)?`ios`:`unknown`}function ar(e){return!Number.isFinite(e)||e<1e3?`lt1s`:e<3e3?`1-3s`:e<1e4?`3-10s`:e<3e4?`10-30s`:`gte30s`}function or(e){return!Number.isFinite(e)||e<=0?`unknown`:e<=4?`1-4`:e<=8?`5-8`:e<=16?`9-16`:`gte17`}function sr(e){return!Number.isFinite(e)||e<=0?`unknown`:e<4?`lt4`:e<8?`4-7`:`gte8`}function cr(e){return!Number.isFinite(e)||e<=0?`unknown`:e<20?`lt20`:e<40?`20-40`:e<55?`40-55`:`gte55`}function lr(e){let t=String(e??``).toLowerCase();return t.trim()?/swiftshader|llvmpipe|softpipe|software|basic render driver/.test(t)?{gpu_vendor:`software`,gpu_class:`software`}:/nvidia|geforce|quadro|\brtx\b|\bgtx\b|tesla/.test(t)?{gpu_vendor:`nvidia`,gpu_class:`discrete`}:/\bamd\b|radeon|\bati\b/.test(t)?{gpu_vendor:`amd`,gpu_class:/radeon\(tm\) graphics|radeon graphics|vega \d+ graphics|\b(?:610|660|680|740|760|780|880|890)m\b/.test(t)?`integrated`:`discrete`}:/intel|iris|uhd graphics|hd graphics/.test(t)?{gpu_vendor:`intel`,gpu_class:/arc(?:\(tm\))? [ab]\d{3}/.test(t)?`discrete`:`integrated`}:/apple|\bm[1-9](?: pro| max| ultra)?\b/.test(t)?{gpu_vendor:`apple`,gpu_class:`integrated`}:/adreno|qualcomm/.test(t)?{gpu_vendor:`qualcomm`,gpu_class:`integrated`}:/\bmali\b|\barm\b|powervr/.test(t)?{gpu_vendor:`arm`,gpu_class:`integrated`}:{gpu_vendor:`other`,gpu_class:`unknown`}:{gpu_vendor:`unknown`,gpu_class:`unknown`}}var ur=/((?:https?|chrome-extension|moz-extension|safari-extension|safari-web-extension):\/\/[^\s()]+?):(\d+):(\d+)/g;function dr(e,t){if(typeof e!=`string`||!e)return`unknown`;if(/^(?:chrome|moz|safari|safari-web)-extension:/.test(e))return`extension`;try{return t&&new URL(e).origin===t?`app`:`external`}catch{return`unknown`}}function fr(e){try{let t=new URL(e).pathname.split(`/`).pop()??``;return xn.test(t)?t:null}catch{return null}}function pr(e){try{if(e===null||typeof e!=`object`&&typeof e!=`function`)return`non_error`;let t=typeof e.name==`string`?e.name:``;return t&&t!==`non_error`&&t!==`other`&&bn.error_type.has(t)?t:typeof DOMException<`u`&&e instanceof DOMException?`DOMException`:e instanceof Error?`other`:`non_error`}catch{return`other`}}function mr({error:e,filename:t,lineno:n,colno:r,kind:i=`error`}={},a=globalThis.location?.origin??``){let o={error_kind:i===`unhandled_rejection`?`unhandled_rejection`:`error`,error_type:pr(e),error_source:`unknown`},s=typeof t==`string`&&t?{url:t,line:n,col:r}:null;if(!s||dr(s.url,a)!==`app`){let t=``;try{t=typeof e?.stack==`string`?e.stack.slice(0,4e3):``}catch{t=``}let n=[...t.matchAll(ur)].map(e=>({url:e[1],line:Number(e[2]),col:Number(e[3])}));s=n.find(e=>dr(e.url,a)===`app`)??s??n[0]??null}if(!s||(o.error_source=dr(s.url,a),o.error_source!==`app`))return o;let c=fr(s.url);return c&&(o.error_file=c),Number.isInteger(s.line)&&s.line>=0&&(o.error_line=s.line),Number.isInteger(s.col)&&s.col>=0&&(o.error_col=s.col),o}function hr(e,t=Date.now()){let n=Nn.get(e);if(!n)return!1;let r=n===In&&t-Ln<Pn;return In=n,Ln=t,r||(Fn[n]+=1),e===`pose_edit`&&Fr(`pose_edit`),!r}function gr(){return Object.fromEntries(Object.entries(Fn).map(([e,t])=>[`${e}_edit_bucket`,tr(t)]))}function _r(e,t=`unknown`){try{if(e?.name===`AbortError`)return`aborted`;if(gn.has(e?.exportFailureCode))return e.exportFailureCode}catch{}return gn.has(t)?t:`unknown`}function vr(e,t={}){let n=!1,r=null,i=NaN,a=()=>performance.now(),o=$,s=()=>{try{return a()}catch{return NaN}},c=(e,t)=>{try{Promise.resolve(o(e,Xn(e,t))).catch(()=>{})}catch{}};try{a=t.now??a,o=t.capture??o;let n=[...globalThis.crypto.getRandomValues(new Uint8Array(16))].map(e=>e.toString(16).padStart(2,`0`)).join(``);r={...Xn(`export:attempt_started`,e),attempt_id:n},i=s(),c(`export:attempt_started`,r)}catch{r=null}let l=(e,t,a)=>{if(!n&&(n=!0,r))try{let n={...r,duration_bucket:ar(s()-i)};e===`failed`&&(n.failure_code=_r(t,a),n.failure_code===`aborted`&&(e=`cancelled`)),c(`export:attempt_${e}`,n)}catch{}};return{succeed(){l(`succeeded`)},fail(e,t=`unknown`){l(`failed`,e,t)}}}var yr=[`$current_url`,`$initial_current_url`,`$referrer`,`$initial_referrer`],br=[`utm_source`,`utm_medium`,`utm_campaign`,`utm_content`,`utm_term`,`gad_source`,`mc_cid`,`gclid`,`gclsrc`,`dclid`,`gbraid`,`wbraid`,`fbclid`,`msclkid`,`twclid`,`li_fat_id`,`igshid`,`ttclid`,`rdt_cid`,`epik`,`qclid`,`sccid`,`irclid`,`_kx`,`ph_keyword`];function xr(e){return typeof e==`string`?e.split(`#`)[0].split(`?`)[0]:e}function Sr(e){if(!e||typeof e!=`object`||!e.properties)return e;let t=[e.properties,e.properties.$set,e.properties.$set_once,e.$set,e.$set_once].filter(e=>e&&typeof e==`object`&&!Array.isArray(e));for(let e of t){for(let t of yr)typeof e[t]==`string`&&(e[t]=xr(e[t]));for(let t of br)delete e[t],delete e[`$initial_${t}`];for(let t of Object.keys(e))t.startsWith(`$session_entry_`)&&delete e[t]}return e}function Cr(e){return e?.activationTracked!==!0}function Q(){return Cn?!0:Or()?.distribution===`npm`?Or()?.telemetryEnabled!==!0:Wn(Qt)===`1`}function wr(){try{let e=Un();if(!e)return;let t=[];for(let n=0;n<e.length;n+=1){let r=e.key(n);r&&r.startsWith(`ph_`)&&r.endsWith(`_posthog`)&&t.push(r)}for(let n of t)e.removeItem(n)}catch{}}async function Tr(e){if(Or()?.distribution!==`npm`)return{ok:!0,enabled:e};try{let t=await fetch(`/__cozyclay/telemetry`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({enabled:e})});if(!t.ok)return{ok:!1,enabled:!e};let n=await t.json();return globalThis.__COZYCLAY_RUNTIME__=n,{ok:!0,enabled:n.telemetryEnabled===!0}}catch{return{ok:!1,enabled:!e}}}async function Er(e){let t=e===!0,n=Or()?.distribution===`npm`;Cn=t;let r=await Tr(!t);if(Cn=!1,!r.ok)return Q();let i=!r.enabled;if(Gn(Qt,i?`1`:`0`),i&&wr(),n&&!i)return globalThis.location?.reload(),!1;if(!Y&&!i&&await Nr(),!Y)return i;try{i?(Z=!1,Y.opt_out_capturing()):(Y.opt_in_capturing(),Z=X)}catch{Z=!1}return i}function Dr(){return{BASE_URL:`/`,DEV:!1,MODE:`production`,PROD:!0,SSR:!1,VITE_COZYCLAY_LIVE_PORT:`5184`,VITE_DEMO_PROMPT_MAX_CHARS:`500`}}function Or(){let e=globalThis.__COZYCLAY_RUNTIME__;return!e||typeof e!=`object`||Array.isArray(e)?null:e}function kr(e){try{let t=new URL(e);return t.protocol===`http:`&&t.hostname===`127.0.0.1`}catch{return!1}}function Ar({env:e=Dr(),origin:t=globalThis.location?.origin??``,runtime:n=Or()}={}){return e.PROD?n?.distribution===`npm`?n.telemetryEnabled===!0?kr(t)?typeof n.apiKey!=`string`||n.apiKey.length===0?{kind:`disabled`,reason:`no key`}:typeof n.installationId!=`string`||!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(n.installationId)?{kind:`disabled`,reason:`invalid anonymous identity`}:{kind:`enabled`,distribution:`npm`,apiKey:n.apiKey,apiHost:n.apiHost||`https://t.cozyclay.org`,appVersion:n.appVersion||null,installationId:n.installationId,firstLaunch:n.firstLaunch===!0,firstLaunchHeardFrom:fn.has(n.firstLaunchHeardFrom)?n.firstLaunchHeardFrom:null,installKind:[`npx`,`global`,`clone`].includes(n.installKind)?n.installKind:`npx`,originKind:`local`,internalQa:n.internalQa===!0,updateStatus:sn.includes(n.updateStatus)?n.updateStatus:`unknown`}:{kind:`disabled`,reason:`unapproved origin`}:{kind:`disabled`,reason:`opted out`}:e.VITE_POSTHOG_KEY?Jn(t,qn(e.VITE_POSTHOG_ALLOWED_ORIGINS))?{kind:`enabled`,distribution:`hosted`,apiKey:e.VITE_POSTHOG_KEY,apiHost:e.VITE_POSTHOG_HOST||`https://us.i.posthog.com`,appVersion:e.VITE_APP_VERSION||null,installationId:null,firstLaunch:!1,firstLaunchHeardFrom:null,installKind:null,originKind:`hosted`,internalQa:Wn($t)===`1`,updateStatus:null}:{kind:`disabled`,reason:`unapproved origin`}:{kind:`disabled`,reason:`no key`}:{kind:`disabled`,reason:`not production`}}function jr(e){return{distribution:e.distribution,...e.appVersion?{app_version:e.appVersion}:{},origin_kind:e.originKind,os:ir(),...e.installKind?{install_kind:e.installKind}:{},...e.updateStatus?{update_status:e.updateStatus}:{},internal_qa:e.internalQa}}function Mr(e){let t=Ar({env:e});return t.kind===`disabled`?t.reason:Q()?`opted out`:null}async function Nr(){if(X||wn)return wn;if(Or()?.distribution!==`npm`){let e=new URLSearchParams(globalThis.location?.search??``).getAll(`internal_qa`);e.length===1&&(e[0]===`1`||e[0]===`0`)&&Gn($t,e[0])}let e=Dr(),t=Mr(e);if(t){En||=(console.info(`[analytics] disabled: `+t),!0);return}wn=(async()=>{try{let t=await Kt(()=>import(`./module-MzlRiBjI.js`),[]);if(Q())return;let n=Ar({env:e});if(n.kind===`disabled`)return;Y=t.default??t,Y.init(n.apiKey,{api_host:n.apiHost,defaults:`2025-05-24`,autocapture:!1,capture_pageview:!1,capture_pageleave:!1,person_profiles:`never`,persistence:n.distribution===`npm`?`memory`:`localStorage`,respect_dnt:!0,disable_session_recording:!0,capture_dead_clicks:!1,capture_performance:!1,disable_capture_url_hashes:!0,save_campaign_params:!1,save_referrer:!1,mask_personal_data_properties:!0,request_batching:!1,advanced_disable_feature_flags:!0,disable_external_dependency_loading:!0,disable_surveys:!0,ui_host:`https://us.posthog.com`,bootstrap:n.installationId?{distinctID:n.installationId,isIdentifiedID:!1}:void 0,before_send:Sr}),X=!0,Z=!0;let r=jr(n);if(Y.register(r),globalThis.__cozyclayAnalytics={instance:Y},Y.capture(`$pageview`),Dn=Date.now(),Kr(n,r),zr(),Gr(),n.distribution===`npm`){if($(`app:session_started`),Pr(),n.firstLaunch){let e=n.firstLaunchHeardFrom;$(`install:first_launch`,e?{heard_from:e}:{})}}else Pr()}catch{console.info(`[analytics] initialization failed`)}})(),await wn}async function Pr(){let e=null;try{let t=await fetch(`/ardy/health`,{signal:AbortSignal.timeout(5e3)});t.ok&&(e=await t.json())}catch{}$(`motion:backend_state`,Zn(e))}function $(e,t={}){if(!(!X||!Z||!Y))try{if(Q())return;let n=Xn(e,t);Hn.has(e)||(On+=1,(e===`scene:created`||e===`scene:loaded`)&&(kn+=1)),Y.capture(e,n)}catch{}}function Fr(e){return!X||!Z||!Y||!un.has(e)||Mn.has(e)?!1:(Mn.add(e),$(`feature:used`,{name:e}),!0)}function Ir(){try{return X&&Z&&!!Y&&!Q()}catch{return!1}}function Lr(){return Ir()&&Wn(tn)!==`1`}function Rr(e,t){Gn(tn,`1`),$(`survey:use_case`,{use_case:an.includes(e)?e:`skip`,team:on.includes(t)?t:`skip`})}function zr(){if(Bn||typeof window>`u`||typeof window.addEventListener!=`function`)return;Bn=!0;let e=e=>{try{let t=mr(e),n=[t.error_kind,t.error_type,t.error_source,t.error_file,t.error_line,t.error_col].join(`|`);if(zn.has(n)||zn.size>=Rn)return;zn.add(n),$(`app:error`,t)}catch{}};window.addEventListener(`error`,t=>{try{if(typeof t?.message==`string`&&t.message.startsWith(`ResizeObserver loop`)||!t?.error&&!t?.filename)return;e({error:t?.error,filename:t?.filename,lineno:t?.lineno,colno:t?.colno,kind:`error`})}catch{}}),window.addEventListener(`unhandledrejection`,t=>{e({error:t?.reason,kind:`unhandled_rejection`})})}function Br(){try{let e=globalThis.document?.createElement?.(`canvas`);if(!e?.getContext)return{webgl:`none`,renderer:``};let t=e.getContext(`webgl2`),n=t?`webgl2`:`none`;if(t||(t=e.getContext(`webgl`),t&&(n=`webgl1`)),!t)return{webgl:n,renderer:``};let r=``;try{let e=t.getExtension(`WEBGL_debug_renderer_info`);r=String(t.getParameter(e?e.UNMASKED_RENDERER_WEBGL:t.RENDERER)??``)}catch{r=``}try{t.getExtension(`WEBGL_lose_context`)?.loseContext()}catch{}return{webgl:n,renderer:r}}catch{return{webgl:`none`,renderer:``}}}var Vr=8e3,Hr=3e3,Ur=6e4;function Wr(){return new Promise(e=>{let t=globalThis.requestAnimationFrame;if(typeof t!=`function`){e(null);return}let n=()=>globalThis.document?.visibilityState===`hidden`,r=Date.now(),i=()=>{if(Date.now()-r>Ur){e(null);return}if(n()){setTimeout(i,2e3);return}let a=0,o=0,s=r=>{if(n()){setTimeout(i,2e3);return}if(o||=r,a+=1,r-o>=Hr){e((a-1)*1e3/(r-o));return}t(s)};t(s)};setTimeout(i,Vr)})}async function Gr(){if(!(Vn||globalThis.document===void 0||typeof globalThis.requestAnimationFrame!=`function`)){Vn=!0;try{let{webgl:e,renderer:t}=Br(),n=lr(t),r=await Wr();$(`device:profile`,{...n,webgl:e,cpu_bucket:or(globalThis.navigator?.hardwareConcurrency),memory_bucket:sr(globalThis.navigator?.deviceMemory),frame_rate_bucket:cr(r)})}catch{}}}function Kr(e,t){if(jn||typeof window>`u`)return;jn=!0;let n=()=>{if(!(An||!Dn)){An=!0;try{if(!Z||!Y||Q()||Y.has_opted_out_capturing())return;let n={api_key:e.apiKey,event:`app:session_ended`,properties:{...t,distinct_id:Y.get_distinct_id(),duration_bucket:nr(Date.now()-Dn),action_count_bucket:tr(On),scenes_touched:Math.min(20,kn),...gr()}},r=JSON.stringify(n),i=`${e.apiHost.replace(/\/$/,``)}/e/`;typeof globalThis.navigator?.sendBeacon==`function`?globalThis.navigator.sendBeacon(i,new Blob([r],{type:`application/json`})):fetch(i,{method:`POST`,body:r,keepalive:!0,headers:{"content-type":`application/json`}})}catch{}}};window.addEventListener(`pagehide`,n,{once:!0}),window.addEventListener(`beforeunload`,n,{once:!0})}function qr(e){if(!(!X||!Z||Tn)){if(!Cr({activationTracked:Wn(en)===`1`})){Tn=!0;return}Tn=!0,Gn(en,`1`),$(`activation:completed`,{activation_path:e})}}export{u as $,b as A,G as B,Ht as C,ue as D,de as E,jt as F,se as G,Dt as H,E as I,v as J,ce as K,Et as L,C as M,w as N,Re as O,wt as P,e as Q,Ie as R,Fr as S,Ft as T,Tt as U,At as V,W,oe as X,_ as Y,ae as Z,Lr as _,Ir as a,p as at,$ as b,rr as c,Nr as d,d as et,Qn as f,Er as g,Xn as h,Zt as i,l as it,We as j,fe as k,_r as l,Rr as m,Yt as n,h as nt,tr as o,hr as p,le as q,Xt as r,ee as rt,ar as s,Jt as t,c as tt,Q as u,vr as v,Vt as w,qr as x,er as y,T as z};