cozyclay 3.1.0 → 3.1.2

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 (154) hide show
  1. package/CHANGELOG.md +65 -0
  2. package/bin/agent/agent-routes.mjs +12 -11
  3. package/bin/agent/main-agent.mjs +21 -7
  4. package/bin/agent/main-prompt.mjs +7 -6
  5. package/bin/agent/plan-tool.mjs +114 -0
  6. package/bin/agent/script-tool.mjs +4 -1
  7. package/bin/agent/sculpt-sketch.mjs +190 -0
  8. package/bin/agent/session-store.mjs +2 -1
  9. package/bin/agent/sketch-code.mjs +151 -0
  10. package/bin/agent/sketch-sandbox.mjs +102 -0
  11. package/bin/agent/studio-prompt.mjs +1 -1
  12. package/bin/agent/studio-rebase.mjs +5 -4
  13. package/bin/agent/studio-task-routes.mjs +1 -1
  14. package/bin/agent/studio-tasks.mjs +116 -25
  15. package/bin/agent/studio-tools.mjs +3 -2
  16. package/bin/agent/turn-frames.mjs +4 -0
  17. package/bin/cozyclay.mjs +4 -2
  18. package/bin/live-endpoint.mjs +2 -0
  19. package/dist/app/index.html +6 -6
  20. package/dist/assets/{TaskBoard-DdDXMgZm.js → TaskBoard-GR8xZm5c.js} +1 -1
  21. package/dist/assets/{app-BlwOpest.css → app-Bhe0TpGz.css} +1 -1
  22. package/dist/assets/app-C4QTcDcb.js +5144 -0
  23. package/dist/assets/compile-worker-oy_P9HHh.js +6 -0
  24. package/dist/assets/motion3-compile-dgGhrvPK.js +1 -0
  25. package/dist/assets/scene-asset-sync-BEjjhNEo.css +1 -0
  26. package/dist/assets/scene-asset-sync-qoxcdrhj.js +13 -0
  27. package/dist/assets/task-board-BqReHzOi.js +15 -0
  28. package/dist/assets/workflow-C87p6E1E.js +179 -0
  29. package/dist/cozyclay-package.json +1 -1
  30. package/dist/index.html +1 -1
  31. package/dist/sitemap.xml +1 -1
  32. package/dist/workflow/index.html +4 -4
  33. package/mcp/README.md +1 -1
  34. package/mcp/live-hub.mjs +5 -3
  35. package/mcp/tool-handlers.mjs +7 -7
  36. package/package.json +3 -1
  37. package/src/App.jsx +44 -66
  38. package/src/bus-task-scopes.js +59 -11
  39. package/src/bus-task-targets.js +35 -9
  40. package/src/bus-tasks.js +23 -10
  41. package/src/command-bus.js +7 -4
  42. package/src/commands/ai.js +1 -1
  43. package/src/commands/elements.js +4 -3
  44. package/src/commands/export.js +1 -1
  45. package/src/commands/motion3.js +27 -7
  46. package/src/commands/objects.js +1 -1
  47. package/src/export-workspace.js +244 -0
  48. package/src/keyframe-pack.js +5 -1
  49. package/src/live-control.js +14 -7
  50. package/src/material-look.js +189 -0
  51. package/src/material-presets.js +78 -0
  52. package/src/material-textures.js +157 -0
  53. package/src/motion3/compile-job.js +15 -3
  54. package/src/motion3/compiler/channels.js +74 -24
  55. package/src/motion3/compiler/compile.js +2 -1
  56. package/src/motion3/compiler/idle.js +2 -0
  57. package/src/motion3/compiler/overlap.js +180 -0
  58. package/src/motion3/compiler/pose.js +6 -4
  59. package/src/motion3/compiler/validate-common.js +1 -0
  60. package/src/motion3/compiler/validate-parts.js +5 -1
  61. package/src/motion3/compiler/validate.js +30 -10
  62. package/src/motion3/correct.js +236 -0
  63. package/src/motion3/docs.js +8 -6
  64. package/src/motion3/face-lean.js +31 -0
  65. package/src/motion3/fix/index.js +5 -1
  66. package/src/motion3/fix/reach-body.js +172 -0
  67. package/src/motion3/hint-check.js +44 -0
  68. package/src/motion3/json-patch.js +120 -12
  69. package/src/motion3/lenient.js +46 -4
  70. package/src/motion3/object-keys.js +17 -5
  71. package/src/motion3/pipeline.js +46 -9
  72. package/src/motion3/qa/arm-checks.js +96 -0
  73. package/src/motion3/qa/asked.js +113 -0
  74. package/src/motion3/qa/goals.js +37 -8
  75. package/src/motion3/qa/hints-goal.js +6 -5
  76. package/src/motion3/qa/index.js +5 -2
  77. package/src/motion3/qa/key-checks.js +4 -3
  78. package/src/motion3/qa/motion-life.js +243 -0
  79. package/src/motion3/qa/spec-checks.js +15 -9
  80. package/src/motion3/qa/verdict.js +50 -0
  81. package/src/motion3/refs.js +38 -14
  82. package/src/motion3/repair-watch.js +132 -0
  83. package/src/motion3/repair.js +52 -19
  84. package/src/motion3/report.js +50 -9
  85. package/src/motion3/schema/topics.js +6 -4
  86. package/src/motion3/schema/types.js +1 -1
  87. package/src/motion3/skills/basic.js +15 -8
  88. package/src/motion3/skills/index.js +52 -18
  89. package/src/motion3/skills/info.js +1 -1
  90. package/src/motion3/skills/stance.js +6 -0
  91. package/src/motion3/skills/walk-fit.js +170 -0
  92. package/src/object-look.js +9 -5
  93. package/src/panels/PoseImagePanel.jsx +3 -2
  94. package/src/panels/SculptPanel.jsx +2 -2
  95. package/src/primitive-look.js +38 -0
  96. package/src/props.jsx +20 -28
  97. package/src/render-passes.js +7 -1
  98. package/src/result-modal.jsx +3 -3
  99. package/src/scene-objects.js +2 -2
  100. package/src/sculpt-colours.js +65 -0
  101. package/src/sculpt-compare.js +13 -50
  102. package/src/sculpt-csg.js +112 -0
  103. package/src/sculpt-curve.js +123 -0
  104. package/src/sculpt-cutters.js +43 -0
  105. package/src/sculpt-detail.js +207 -0
  106. package/src/sculpt-geometry-loft-convex.js +100 -0
  107. package/src/sculpt-geometry-shapes.js +250 -0
  108. package/src/sculpt-geometry.js +33 -15
  109. package/src/sculpt-loft-rings.js +225 -0
  110. package/src/sculpt-noise.js +65 -0
  111. package/src/sculpt-part-fields.js +27 -0
  112. package/src/sculpt-recipe-read.js +65 -0
  113. package/src/sculpt-recipe.js +33 -75
  114. package/src/sculpt-run.js +1 -1
  115. package/src/sculpt-scatter-items.js +183 -0
  116. package/src/sculpt-scatter-shape.js +57 -0
  117. package/src/sculpt-scatter.js +124 -0
  118. package/src/sculpt-shapes-curved.js +211 -0
  119. package/src/sculpt-shapes-loft-convex.js +218 -0
  120. package/src/sculpt-shapes.js +138 -0
  121. package/src/sculpt-sketch-state.js +76 -0
  122. package/src/sculpt-sketch.jsx +124 -0
  123. package/src/sculpt-surface-fields.js +65 -0
  124. package/src/shell/ExportFolderPreference.jsx +103 -0
  125. package/src/shell/PreferencesDialog.jsx +3 -166
  126. package/src/shell/StatusBar.jsx +1 -1
  127. package/src/shell/preference-controls.jsx +114 -0
  128. package/src/shell/preference-pages.jsx +72 -0
  129. package/src/shell/preferences.css +46 -0
  130. package/src/shot-prompt.js +29 -9
  131. package/src/studio-actions.js +2 -2
  132. package/src/studio-agent-motion.js +19 -9
  133. package/src/studio-agent-protocol.js +1 -1
  134. package/src/studio-app-binding.js +3 -2
  135. package/src/studio-elements.js +5 -1
  136. package/src/workflow/AgentPanel.jsx +6 -6
  137. package/src/workflow/AgentPlanCard.jsx +41 -0
  138. package/src/workflow/CozySceneNode.jsx +1 -1
  139. package/src/workflow/WorkflowBuilder.jsx +2 -2
  140. package/src/workflow/agent-client.js +14 -11
  141. package/src/workflow/agent-plan.css +93 -0
  142. package/src/workflow/agent-plan.js +59 -0
  143. package/src/workflow/keyframe-pack-request.js +3 -10
  144. package/src/workflow/task-board.css +1 -1
  145. package/src/workflow/task-board.js +7 -5
  146. package/tools/loc-baseline.json +1 -2
  147. package/tools/run-tests.mjs +8 -8
  148. package/dist/assets/app-B2BpfCl2.js +0 -5088
  149. package/dist/assets/compile-worker-D0pKioa0.js +0 -5
  150. package/dist/assets/motion3-compile-B887n77J.js +0 -1
  151. package/dist/assets/scene-asset-sync-COGOlF5T.css +0 -1
  152. package/dist/assets/scene-asset-sync-CQzEdsqu.js +0 -13
  153. package/dist/assets/task-board-BKaM7d-9.js +0 -14
  154. package/dist/assets/workflow-B8Dhzexj.js +0 -179
@@ -21,11 +21,12 @@ export function createStudioTools({ liveHub, workspaceHandle, session, resolveIm
21
21
  const rebaser = createRebaser({ session, liveHub, workspaceHandle, mutationNames, attempt: (name, args, scratch) => attempt(name, args, scratch) });
22
22
  // One admission attempt. `scratch` carries what the recovery path needs from
23
23
  // a refusal: the revision it was admitted at and the context re-read for it.
24
+ // scratch.callId: the model's tool call this command belongs to (a script's nested commands share the script's)
24
25
  const attempt = async (name, args, scratch = {}) => {
25
26
  const command = validateStudioCommand({ name, args });
26
27
  const action = name === "run_action" ? declared.get(command.args.action) : undefined;
27
28
  const payload = mutationNames.has(name) && session?.admission
28
- ? { name, args: command.args, commandId: session.admission.commandId(), host: session.admission.host, expectedRevision: session.admission.revision, ...(session.admission.turnId ? { turnId: session.admission.turnId } : {}), ...(session.admission.taskId ? { taskId: session.admission.taskId } : {}) }
29
+ ? { name, args: command.args, commandId: session.admission.commandId(), host: session.admission.host, expectedRevision: session.admission.revision, ...(session.admission.turnId ? { turnId: session.admission.turnId } : {}), ...(session.admission.taskId ? { taskId: session.admission.taskId } : {}), ...(typeof scratch.callId === "string" && scratch.callId ? { callId: scratch.callId } : {}) }
29
30
  : command.args;
30
31
  Object.assign(scratch, { refusedRevision: payload.expectedRevision });
31
32
  let result;
@@ -64,7 +65,7 @@ export function createStudioTools({ liveHub, workspaceHandle, session, resolveIm
64
65
  return result;
65
66
  };
66
67
  const availableTools = STUDIO_TOOLS;
67
- const tools = availableTools.map(name => ({ ...schema(name), handler: args => rebaser.run(name, args) }));
68
+ const tools = availableTools.map(name => ({ ...schema(name), handler: (args, call = {}) => rebaser.run(name, args, call.callId ?? call.toolCallId) }));
68
69
  tools.resolveImage = async (imageId, correlation = {}) => {
69
70
  if (typeof resolveImage !== "function") return { visualStatus: "unavailable", reason: "image resolver unavailable" };
70
71
  try {
@@ -3,6 +3,7 @@
3
3
  // tool, and for run_action the action and its subject as soon as the streamed arguments name them). A long
4
4
  // motion spec or script takes the model many seconds to write; without these the panel could only say
5
5
  // "Thinking…". Frames only: nothing here reaches the model or the scene.
6
+ import { createSculptSketch } from "./sculpt-sketch.mjs";
6
7
 
7
8
  const FLUSH_MS = 400;
8
9
  const MIN_BATCH = 16;
@@ -33,6 +34,8 @@ function composedCall(name, raw) {
33
34
  export function createReasoningFrames(push, clock = () => Date.now()) {
34
35
  let thinking = "", flushedAt = clock();
35
36
  const calls = new Map();
37
+ // The parts a call that builds sculpts has written so far, as sculpt.sketch frames (sculpt-sketch.mjs).
38
+ const sketch = createSculptSketch(push, clock);
36
39
  const flush = () => {
37
40
  if (!thinking) return;
38
41
  push({ type: "thinking.delta", text: thinking });
@@ -42,6 +45,7 @@ export function createReasoningFrames(push, clock = () => Date.now()) {
42
45
  return {
43
46
  flush,
44
47
  onMessageEvent(event) {
48
+ sketch.onMessageEvent(event);
45
49
  if (event?.type === "thinking_delta") {
46
50
  thinking += event.delta ?? "";
47
51
  // a batch says something: not a lone word at the start of a paragraph
package/bin/cozyclay.mjs CHANGED
@@ -26,6 +26,7 @@ import { openBrowser } from "./open-browser.mjs";
26
26
  import { checkForUpdate, readUpdateStatus, runUpdate } from "./update-check.mjs";
27
27
  import { handleOAuthRequest } from "./codex-auth.mjs";
28
28
  import { createAgentHandler } from "./agent/agent-routes.mjs";
29
+ import { liveHubPort } from "./live-endpoint.mjs";
29
30
  import { verifyPackageMarker } from "./package-signature.mjs";
30
31
  import {
31
32
  markTelemetryNoticeShown,
@@ -455,8 +456,9 @@ server = createServer((req, res) => {
455
456
  // __COZYCLAY_LIVE__ opts the production build into the loopback live
456
457
  // socket (src/App.jsx gates on DEV || this flag); without it an
457
458
  // npx-served studio can never attach to the MCP server's live hub.
458
- const script = `<script>window.__COZYCLAY_RUNTIME__ = ${JSON.stringify(runtime).replaceAll("<", "\\u003c")}; window.__COZYCLAY_LIVE__ = true;</script>`;
459
- const html = readFileSync(target, "utf8").replace("</head>", `${script}\n</head>`);
459
+ // __COZYCLAY_LIVE_PORT__ tells the prebuilt bundle which hub port this
460
+ // launch chose (COZYCLAY_LIVE_PORT), since the build baked its own (#862).
461
+ const html = readFileSync(target, "utf8").replace("</head>", `<script>window.__COZYCLAY_RUNTIME__ = ${JSON.stringify(runtime).replaceAll("<", "\\u003c")}; window.__COZYCLAY_LIVE__ = true; window.__COZYCLAY_LIVE_PORT__ = ${JSON.stringify(liveHubPort())};</script>\n</head>`);
460
462
  res.writeHead(200, {
461
463
  "content-type": "text/html; charset=utf-8",
462
464
  "content-length": Buffer.byteLength(html),
@@ -13,6 +13,8 @@ import { join } from "node:path";
13
13
 
14
14
  const liveDirectory = () => join(process.env.XDG_CONFIG_HOME || join(homedir(), ".config"), "cozyclay", "live");
15
15
 
16
+ // The live hub port this launch uses; the served Studio is told the same port (#862).
17
+ export const liveHubPort = (env = process.env) => Number(env.COZYCLAY_LIVE_PORT ?? 5184);
16
18
  export const liveEndpointPath = (port) => join(liveDirectory(), `${port}.json`);
17
19
 
18
20
  /** Ports this process published, so exit cleans up exactly its own files. */
@@ -34,15 +34,15 @@
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-B2BpfCl2.js"></script>
37
+ <script type="module" crossorigin src="/assets/app-C4QTcDcb.js"></script>
38
38
  <link rel="modulepreload" crossorigin href="/assets/rolldown-runtime-hePW80VL.js">
39
39
  <link rel="modulepreload" crossorigin href="/assets/modulepreload-polyfill-P2Xu9kJm.js">
40
- <link rel="modulepreload" crossorigin href="/assets/task-board-BKaM7d-9.js">
40
+ <link rel="modulepreload" crossorigin href="/assets/task-board-BqReHzOi.js">
41
41
  <link rel="modulepreload" crossorigin href="/assets/fflate.module-KbGj5-H6.js">
42
- <link rel="modulepreload" crossorigin href="/assets/scene-asset-sync-CQzEdsqu.js">
43
- <link rel="modulepreload" crossorigin href="/assets/motion3-compile-B887n77J.js">
44
- <link rel="stylesheet" crossorigin href="/assets/scene-asset-sync-COGOlF5T.css">
45
- <link rel="stylesheet" crossorigin href="/assets/app-BlwOpest.css">
42
+ <link rel="modulepreload" crossorigin href="/assets/scene-asset-sync-qoxcdrhj.js">
43
+ <link rel="modulepreload" crossorigin href="/assets/motion3-compile-dgGhrvPK.js">
44
+ <link rel="stylesheet" crossorigin href="/assets/scene-asset-sync-BEjjhNEo.css">
45
+ <link rel="stylesheet" crossorigin href="/assets/app-Bhe0TpGz.css">
46
46
  </head>
47
47
  <body>
48
48
  <div id="root">
@@ -1 +1 @@
1
- import{r as e}from"./rolldown-runtime-hePW80VL.js";import{Pr as t,c as n,d as r,f as i,l as a,m as o,o as s,v as c,xi as l}from"./task-board-BKaM7d-9.js";import{o as u,r as d,t as f}from"./motion3-compile-B887n77J.js";var p=e(l(),1),m=2e3,h=(e,t)=>new Promise(n=>{let r=setTimeout(n,e);t.addEventListener(`abort`,()=>{clearTimeout(r),n()},{once:!0})});function g(e,n){(0,p.useEffect)(()=>{let r=new Map;for(let[t,i]of Object.entries(e))for(let e of i)r.set(e,n[t]??t);let i=()=>{for(let e of document.querySelectorAll(`[data-node-id]`)){let n=r.get(e.getAttribute(`data-node-id`));n?(e.setAttribute(`data-task-scope`,n),e.setAttribute(`title`,t(`In task: ${n}`,`작업 중: ${n}`))):e.hasAttribute(`data-task-scope`)&&(e.removeAttribute(`data-task-scope`),e.removeAttribute(`title`))}};i();let a=new MutationObserver(i);return a.observe(document.body,{childList:!0,subtree:!0}),()=>{a.disconnect(),r.clear(),i()}},[e,n])}function _({sessionId:e,pulse:t,labelOf:l,onMainNote:_}){let v=(0,p.useMemo)(()=>s(),[]),y=u(),[b,x]=(0,p.useReducer)((e,t)=>t.seed?o(e,t.seed):t.reset?n():r(e,t.event),void 0,n),[S,C]=(0,p.useState)({}),[w,T]=(0,p.useState)(f),E=(0,p.useRef)(0),D=(0,p.useRef)(_);(0,p.useEffect)(()=>{E.current=b.after,D.current=_},[b.after,_]),(0,p.useEffect)(()=>{x({reset:!0}),E.current=0},[e]),(0,p.useEffect)(()=>d(T),[]),(0,p.useEffect)(()=>y.subscribe(e=>{typeof e?.type!=`string`||!e.type.startsWith(`task.`)||(C(t=>i(t,e)),(e.type===`task.userEdit`||e.type===`task.undone`)&&x({event:e}))}),[y]),(0,p.useEffect)(()=>{if(!e)return;let t=new AbortController;return(async()=>{for(;!t.signal.aborted;){try{let{tasks:n}=await v.board(e);x({seed:n}),await v.events(e,E.current,e=>{if(e.type===`main.turn`&&e.turnId){let n=``;v.frames(e.turnId,e=>{e.type===`text.delta`&&(n+=e.text??``),e.type===`tool.start`&&(n=``)},t.signal).then(()=>D.current?.(n),()=>{})}x({event:e})},t.signal)}catch{}await h(m,t.signal)}})(),()=>t.abort()},[v,e,t]);let O=b.order.filter(e=>b.tasks[e]?.status===`running`&&b.tasks[e]?.turnId),k=O.map(e=>`${e}:${b.tasks[e].turnId}`).join();return(0,p.useEffect)(()=>{let e=O.map(e=>{let t=new AbortController,{turnId:n}=b.tasks[e];return v.frames(n,t=>{let n=a(t,l);n&&x({event:{type:`task.progress`,taskId:e,status:`running`,progress:n}})},t.signal).catch(()=>{}),t});return()=>e.forEach(e=>e.abort())},[v,k,l]),g(S,(0,p.useMemo)(()=>Object.fromEntries(b.order.map(e=>[e,b.tasks[e].title])),[b])),(0,p.useEffect)(()=>{c.set({client:v,labelOf:l,undo:async e=>{let t=await y.run(`task.undo`,{taskId:e});if(t?.ok===!1)throw Error(t.message??t.code);x({event:{type:`task.undone`,taskId:e}})}})},[y,v,l]),(0,p.useEffect)(()=>{c.set({board:b,activity:w})},[b,w]),(0,p.useEffect)(()=>()=>c.set({board:n(),open:null}),[e]),null}export{_ as default};
1
+ import{r as e}from"./rolldown-runtime-hePW80VL.js";import{c as t,d as n,da as r,f as i,l as a,m as o,o as s,v as c,wi as l}from"./task-board-BqReHzOi.js";import{o as u,r as d,t as f}from"./motion3-compile-dgGhrvPK.js";var p=e(r(),1),m=2e3,h=(e,t)=>new Promise(n=>{let r=setTimeout(n,e);t.addEventListener(`abort`,()=>{clearTimeout(r),n()},{once:!0})});function g(e,t){(0,p.useEffect)(()=>{let n=new Map;for(let[r,i]of Object.entries(e))for(let e of i)n.set(e,t[r]??r);let r=()=>{for(let e of document.querySelectorAll(`[data-node-id]`)){let t=n.get(e.getAttribute(`data-node-id`));t?(e.setAttribute(`data-task-scope`,t),e.setAttribute(`title`,l(`In task: ${t}`,`작업 중: ${t}`))):e.hasAttribute(`data-task-scope`)&&(e.removeAttribute(`data-task-scope`),e.removeAttribute(`title`))}};r();let i=new MutationObserver(r);return i.observe(document.body,{childList:!0,subtree:!0}),()=>{i.disconnect(),n.clear(),r()}},[e,t])}function _({sessionId:e,pulse:r,labelOf:l,onMainNote:_}){let v=(0,p.useMemo)(()=>s(),[]),y=u(),[b,x]=(0,p.useReducer)((e,r)=>r.seed?o(e,r.seed):r.reset?t():n(e,r.event),void 0,t),[S,C]=(0,p.useState)({}),[w,T]=(0,p.useState)(f),E=(0,p.useRef)(0),D=(0,p.useRef)(_);(0,p.useEffect)(()=>{E.current=b.after,D.current=_},[b.after,_]),(0,p.useEffect)(()=>{x({reset:!0}),E.current=0},[e]),(0,p.useEffect)(()=>d(T),[]),(0,p.useEffect)(()=>y.subscribe(e=>{typeof e?.type!=`string`||!e.type.startsWith(`task.`)||(C(t=>i(t,e)),(e.type===`task.userEdit`||e.type===`task.undone`)&&x({event:e}))}),[y]),(0,p.useEffect)(()=>{if(!e)return;let t=new AbortController;return(async()=>{for(;!t.signal.aborted;){try{let{tasks:n}=await v.board(e);x({seed:n}),await v.events(e,E.current,e=>{if(e.type===`main.turn`&&e.turnId){let n=``;v.frames(e.turnId,e=>{e.type===`text.delta`&&(n+=e.text??``),e.type===`tool.start`&&(n=``)},t.signal).then(()=>D.current?.(n),()=>{})}x({event:e})},t.signal)}catch{}await h(m,t.signal)}})(),()=>t.abort()},[v,e,r]);let O=b.order.filter(e=>b.tasks[e]?.status===`running`&&b.tasks[e]?.turnId),k=O.map(e=>`${e}:${b.tasks[e].turnId}`).join();return(0,p.useEffect)(()=>{let e=O.map(e=>{let t=new AbortController,{turnId:n}=b.tasks[e];return v.frames(n,t=>{let n=a(t,l);n&&x({event:{type:`task.progress`,taskId:e,status:`running`,progress:n}})},t.signal).catch(()=>{}),t});return()=>e.forEach(e=>e.abort())},[v,k,l]),g(S,(0,p.useMemo)(()=>Object.fromEntries(b.order.map(e=>[e,b.tasks[e].title])),[b])),(0,p.useEffect)(()=>{c.set({client:v,labelOf:l,undo:async e=>{let t=await y.run(`task.undo`,{taskId:e});if(t?.ok===!1)throw Error(t.message??t.code);x({event:{type:`task.undone`,taskId:e}})}})},[y,v,l]),(0,p.useEffect)(()=>{c.set({board:b,activity:w})},[b,w]),(0,p.useEffect)(()=>()=>c.set({board:t(),open:null}),[e]),null}export{_ as default};