@agent-native/core 0.85.6 → 0.86.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 (1069) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +130 -1
  3. package/corpus/core/README.md +0 -11
  4. package/corpus/core/docs/content/cloneable-saas.mdx +0 -1
  5. package/corpus/core/docs/content/locales/ar-SA/cloneable-saas.mdx +0 -1
  6. package/corpus/core/docs/content/locales/ar-SA/plan-plugin.mdx +10 -9
  7. package/corpus/core/docs/content/locales/ar-SA/sharing.mdx +1 -2
  8. package/corpus/core/docs/content/locales/ar-SA/skills-guide.mdx +2 -3
  9. package/corpus/core/docs/content/locales/ar-SA/template-plan.mdx +23 -7
  10. package/corpus/core/docs/content/locales/ar-SA/tracking.mdx +1 -1
  11. package/corpus/core/docs/content/locales/ar-SA/workspace-connections.mdx +11 -11
  12. package/corpus/core/docs/content/locales/de-DE/cloneable-saas.mdx +0 -1
  13. package/corpus/core/docs/content/locales/de-DE/plan-plugin.mdx +10 -9
  14. package/corpus/core/docs/content/locales/de-DE/sharing.mdx +1 -2
  15. package/corpus/core/docs/content/locales/de-DE/skills-guide.mdx +2 -3
  16. package/corpus/core/docs/content/locales/de-DE/template-plan.mdx +23 -7
  17. package/corpus/core/docs/content/locales/de-DE/tracking.mdx +1 -1
  18. package/corpus/core/docs/content/locales/de-DE/workspace-connections.mdx +1 -1
  19. package/corpus/core/docs/content/locales/es-ES/cloneable-saas.mdx +0 -1
  20. package/corpus/core/docs/content/locales/es-ES/plan-plugin.mdx +10 -9
  21. package/corpus/core/docs/content/locales/es-ES/sharing.mdx +1 -2
  22. package/corpus/core/docs/content/locales/es-ES/skills-guide.mdx +2 -3
  23. package/corpus/core/docs/content/locales/es-ES/template-plan.mdx +23 -7
  24. package/corpus/core/docs/content/locales/es-ES/tracking.mdx +1 -1
  25. package/corpus/core/docs/content/locales/es-ES/workspace-connections.mdx +1 -1
  26. package/corpus/core/docs/content/locales/fr-FR/cloneable-saas.mdx +0 -1
  27. package/corpus/core/docs/content/locales/fr-FR/plan-plugin.mdx +10 -9
  28. package/corpus/core/docs/content/locales/fr-FR/sharing.mdx +1 -2
  29. package/corpus/core/docs/content/locales/fr-FR/skills-guide.mdx +2 -3
  30. package/corpus/core/docs/content/locales/fr-FR/template-plan.mdx +23 -7
  31. package/corpus/core/docs/content/locales/fr-FR/tracking.mdx +1 -1
  32. package/corpus/core/docs/content/locales/fr-FR/workspace-connections.mdx +1 -1
  33. package/corpus/core/docs/content/locales/hi-IN/cloneable-saas.mdx +0 -1
  34. package/corpus/core/docs/content/locales/hi-IN/plan-plugin.mdx +10 -9
  35. package/corpus/core/docs/content/locales/hi-IN/sharing.mdx +1 -2
  36. package/corpus/core/docs/content/locales/hi-IN/skills-guide.mdx +2 -3
  37. package/corpus/core/docs/content/locales/hi-IN/template-plan.mdx +23 -7
  38. package/corpus/core/docs/content/locales/hi-IN/tracking.mdx +1 -1
  39. package/corpus/core/docs/content/locales/hi-IN/workspace-connections.mdx +1 -1
  40. package/corpus/core/docs/content/locales/ja-JP/cloneable-saas.mdx +0 -1
  41. package/corpus/core/docs/content/locales/ja-JP/plan-plugin.mdx +10 -9
  42. package/corpus/core/docs/content/locales/ja-JP/sharing.mdx +1 -2
  43. package/corpus/core/docs/content/locales/ja-JP/skills-guide.mdx +2 -3
  44. package/corpus/core/docs/content/locales/ja-JP/template-plan.mdx +23 -7
  45. package/corpus/core/docs/content/locales/ja-JP/tracking.mdx +1 -1
  46. package/corpus/core/docs/content/locales/ja-JP/workspace-connections.mdx +1 -1
  47. package/corpus/core/docs/content/locales/ko-KR/cloneable-saas.mdx +0 -1
  48. package/corpus/core/docs/content/locales/ko-KR/plan-plugin.mdx +10 -9
  49. package/corpus/core/docs/content/locales/ko-KR/sharing.mdx +1 -2
  50. package/corpus/core/docs/content/locales/ko-KR/skills-guide.mdx +2 -3
  51. package/corpus/core/docs/content/locales/ko-KR/template-plan.mdx +23 -7
  52. package/corpus/core/docs/content/locales/ko-KR/tracking.mdx +1 -1
  53. package/corpus/core/docs/content/locales/ko-KR/workspace-connections.mdx +1 -1
  54. package/corpus/core/docs/content/locales/pt-BR/cloneable-saas.mdx +0 -1
  55. package/corpus/core/docs/content/locales/pt-BR/plan-plugin.mdx +10 -9
  56. package/corpus/core/docs/content/locales/pt-BR/sharing.mdx +1 -2
  57. package/corpus/core/docs/content/locales/pt-BR/skills-guide.mdx +2 -3
  58. package/corpus/core/docs/content/locales/pt-BR/template-plan.mdx +23 -7
  59. package/corpus/core/docs/content/locales/pt-BR/tracking.mdx +1 -1
  60. package/corpus/core/docs/content/locales/pt-BR/workspace-connections.mdx +1 -1
  61. package/corpus/core/docs/content/locales/zh-CN/cloneable-saas.mdx +0 -1
  62. package/corpus/core/docs/content/locales/zh-CN/plan-plugin.mdx +10 -9
  63. package/corpus/core/docs/content/locales/zh-CN/sharing.mdx +1 -2
  64. package/corpus/core/docs/content/locales/zh-CN/skills-guide.mdx +2 -3
  65. package/corpus/core/docs/content/locales/zh-CN/template-plan.mdx +23 -7
  66. package/corpus/core/docs/content/locales/zh-CN/tracking.mdx +1 -1
  67. package/corpus/core/docs/content/locales/zh-CN/workspace-connections.mdx +1 -1
  68. package/corpus/core/docs/content/locales/zh-TW/cloneable-saas.mdx +0 -1
  69. package/corpus/core/docs/content/locales/zh-TW/plan-plugin.mdx +10 -9
  70. package/corpus/core/docs/content/locales/zh-TW/sharing.mdx +1 -2
  71. package/corpus/core/docs/content/locales/zh-TW/skills-guide.mdx +2 -3
  72. package/corpus/core/docs/content/locales/zh-TW/template-plan.mdx +23 -7
  73. package/corpus/core/docs/content/locales/zh-TW/tracking.mdx +1 -1
  74. package/corpus/core/docs/content/locales/zh-TW/workspace-connections.mdx +1 -1
  75. package/corpus/core/docs/content/plan-plugin.mdx +12 -11
  76. package/corpus/core/docs/content/sharing.mdx +1 -2
  77. package/corpus/core/docs/content/skills-guide.mdx +4 -3
  78. package/corpus/core/docs/content/template-plan.mdx +37 -6
  79. package/corpus/core/docs/content/tracking.mdx +1 -1
  80. package/corpus/core/docs/content/workspace-connections.mdx +1 -1
  81. package/corpus/core/package.json +6 -6
  82. package/corpus/core/src/agent/run-store.ts +1 -1
  83. package/corpus/core/src/chat-threads/store.ts +73 -11
  84. package/corpus/core/src/checkpoints/store.ts +13 -2
  85. package/corpus/core/src/cli/create.ts +3 -4
  86. package/corpus/core/src/cli/design-connect.ts +469 -9
  87. package/corpus/core/src/cli/index.ts +13 -0
  88. package/corpus/core/src/cli/plan-local.ts +281 -24
  89. package/corpus/core/src/cli/skills.ts +177 -21
  90. package/corpus/core/src/cli/templates-meta.ts +0 -13
  91. package/corpus/core/src/cli/visualize-repo.ts +715 -0
  92. package/corpus/core/src/client/AssistantChat.tsx +126 -17
  93. package/corpus/core/src/client/agent-chat-adapter.ts +6 -5
  94. package/corpus/core/src/client/app-providers.tsx +2 -2
  95. package/corpus/core/src/client/collab/index.ts +31 -0
  96. package/corpus/core/src/client/components/LiveCursorOverlay.tsx +16 -1
  97. package/corpus/core/src/client/components/PresenceBar.tsx +14 -1
  98. package/corpus/core/src/client/components/RecentEditHighlights.tsx +219 -0
  99. package/corpus/core/src/client/components/RemoteSelectionRings.tsx +40 -6
  100. package/corpus/core/src/client/index.ts +48 -0
  101. package/corpus/core/src/client/org/OrgSwitcher.tsx +0 -4
  102. package/corpus/core/src/client/rich-markdown-editor/SharedRichEditor.tsx +49 -32
  103. package/corpus/core/src/client/rich-markdown-editor/index.ts +6 -0
  104. package/corpus/core/src/client/rich-markdown-editor/surgical-apply.ts +192 -0
  105. package/corpus/core/src/client/rich-markdown-editor/useCollabReconcile.ts +59 -8
  106. package/corpus/core/src/client/session-replay.ts +181 -15
  107. package/corpus/core/src/client/sse-event-processor.ts +90 -1
  108. package/corpus/core/src/client/use-action.ts +123 -25
  109. package/corpus/core/src/client/use-agent-engine-configured.ts +7 -1
  110. package/corpus/core/src/client/use-chat-threads.ts +18 -7
  111. package/corpus/core/src/client/use-db-sync.ts +104 -19
  112. package/corpus/core/src/client/use-pinch-zoom.ts +76 -11
  113. package/corpus/core/src/client/visual-style-controls.tsx +475 -0
  114. package/corpus/core/src/collab/agent-presence.ts +191 -62
  115. package/corpus/core/src/collab/awareness.ts +83 -6
  116. package/corpus/core/src/collab/client.ts +89 -146
  117. package/corpus/core/src/collab/index.ts +34 -0
  118. package/corpus/core/src/collab/presence.ts +63 -3
  119. package/corpus/core/src/collab/recent-edits.ts +171 -0
  120. package/corpus/core/src/collab/undo.ts +432 -0
  121. package/corpus/core/src/collab/ydoc-manager.ts +68 -0
  122. package/corpus/core/src/connections/catalog.ts +2 -3
  123. package/corpus/core/src/db/create-get-db.ts +86 -1
  124. package/corpus/core/src/db/ensure-additive-columns.ts +430 -0
  125. package/corpus/core/src/db/index.ts +6 -0
  126. package/corpus/core/src/db/migrations.ts +236 -35
  127. package/corpus/core/src/jobs/scheduler.ts +17 -14
  128. package/corpus/core/src/observability/traces.ts +182 -1
  129. package/corpus/core/src/org/context.ts +79 -2
  130. package/corpus/core/src/server/agent-chat-plugin.ts +10 -6
  131. package/corpus/core/src/server/auth-marketing.ts +0 -11
  132. package/corpus/core/src/server/auth.ts +11 -4
  133. package/corpus/core/src/server/collab-plugin.ts +56 -13
  134. package/corpus/core/src/server/design-token-utils.ts +1 -1
  135. package/corpus/core/src/server/fusion-app.ts +447 -0
  136. package/corpus/core/src/server/index.ts +13 -0
  137. package/corpus/core/src/server/onboarding-html.ts +3 -4
  138. package/corpus/core/src/server/poll-events.ts +14 -2
  139. package/corpus/core/src/server/poll.ts +219 -12
  140. package/corpus/core/src/server/schema-prompt.ts +28 -9
  141. package/corpus/core/src/settings/store.ts +33 -2
  142. package/corpus/core/src/sharing/actions/set-resource-visibility.ts +2 -0
  143. package/corpus/core/src/sharing/actions/share-resource.ts +3 -0
  144. package/corpus/core/src/sharing/actions/unshare-resource.ts +2 -0
  145. package/corpus/core/src/styles/agent-native.css +0 -5
  146. package/corpus/core/src/templates/default/.agents/skills/real-time-collab/SKILL.md +82 -19
  147. package/corpus/core/src/templates/default/.agents/skills/real-time-sync/SKILL.md +15 -0
  148. package/corpus/core/src/templates/default/.agents/skills/storing-data/SKILL.md +8 -0
  149. package/corpus/core/src/templates/default/package.json +3 -3
  150. package/corpus/core/src/templates/workspace-core/.agents/skills/client-methods/SKILL.md +8 -0
  151. package/corpus/core/src/templates/workspace-core/.agents/skills/observability/SKILL.md +22 -0
  152. package/corpus/core/src/templates/workspace-core/.agents/skills/real-time-collab/SKILL.md +82 -19
  153. package/corpus/core/src/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +15 -0
  154. package/corpus/core/src/templates/workspace-core/.agents/skills/storing-data/SKILL.md +8 -0
  155. package/corpus/core/src/templates/workspace-core/.agents/skills/tracking/SKILL.md +1 -0
  156. package/corpus/core/src/tracking/providers.ts +22 -1
  157. package/corpus/templates/analytics/.agents/skills/real-time-sync/SKILL.md +15 -0
  158. package/corpus/templates/analytics/.agents/skills/session-replay/SKILL.md +20 -5
  159. package/corpus/templates/analytics/.agents/skills/storing-data/SKILL.md +8 -0
  160. package/corpus/templates/analytics/AGENTS.md +33 -6
  161. package/corpus/templates/analytics/actions/navigate.ts +14 -4
  162. package/corpus/templates/analytics/actions/query-agent-native-analytics.ts +1 -1
  163. package/corpus/templates/analytics/actions/view-screen.ts +57 -0
  164. package/corpus/templates/analytics/app/components/layout/CommandPalette.tsx +23 -1
  165. package/corpus/templates/analytics/app/components/layout/Header.tsx +1 -0
  166. package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +21 -0
  167. package/corpus/templates/analytics/app/hooks/use-navigation-state.ts +7 -0
  168. package/corpus/templates/analytics/app/i18n/zh-TW.ts +15 -1
  169. package/corpus/templates/analytics/app/i18n-data.ts +151 -10
  170. package/corpus/templates/analytics/app/pages/Agents.tsx +118 -0
  171. package/corpus/templates/analytics/app/pages/DataSources.tsx +11 -1
  172. package/corpus/templates/analytics/app/pages/sessions/SessionDevToolsPanel.tsx +76 -40
  173. package/corpus/templates/analytics/app/pages/sessions/session-replay-devtools.ts +5 -0
  174. package/corpus/templates/analytics/app/routes/agents.tsx +10 -0
  175. package/corpus/templates/analytics/changelog/2026-07-03-agent-admin-tools-page.md +6 -0
  176. package/corpus/templates/analytics/changelog/2026-07-03-agent-llm-observability-dashboard.md +6 -0
  177. package/corpus/templates/analytics/changelog/2026-07-03-session-recordings-now-include-response-bodies-for-5xx-error.md +6 -0
  178. package/corpus/templates/analytics/docs/schemas/first-party-analytics.md +34 -0
  179. package/corpus/templates/analytics/docs/schemas/tracked-events.md +6 -0
  180. package/corpus/templates/analytics/package.json +3 -3
  181. package/corpus/templates/analytics/seeds/dashboards/agent-observability-llm.json +173 -0
  182. package/corpus/templates/analytics/server/jobs/analytics-alerts.ts +23 -5
  183. package/corpus/templates/analytics/server/lib/analytics-alerts.ts +58 -13
  184. package/corpus/templates/analytics/server/lib/dashboard-catalog.ts +23 -0
  185. package/corpus/templates/analytics/server/lib/dashboard-seeds.ts +5 -0
  186. package/corpus/templates/analytics/server/lib/session-replay-agent-context.ts +120 -8
  187. package/corpus/templates/analytics/server/lib/session-replay.ts +3 -2
  188. package/corpus/templates/analytics/server/plugins/db.ts +93 -2
  189. package/corpus/templates/analytics/server/routes/api/session-replay/agent-diagnostics.json.get.ts +45 -1
  190. package/corpus/templates/analytics/shared/session-replay-diagnostics.ts +10 -0
  191. package/corpus/templates/assets/.agents/skills/real-time-collab/SKILL.md +82 -19
  192. package/corpus/templates/assets/.agents/skills/real-time-sync/SKILL.md +15 -0
  193. package/corpus/templates/assets/.agents/skills/storing-data/SKILL.md +8 -0
  194. package/corpus/templates/assets/package.json +3 -3
  195. package/corpus/templates/assets/server/plugins/db.ts +63 -2
  196. package/corpus/templates/brain/.agents/skills/real-time-sync/SKILL.md +15 -0
  197. package/corpus/templates/brain/package.json +3 -3
  198. package/corpus/templates/brain/server/plugins/db.ts +75 -2
  199. package/corpus/templates/calendar/.agents/skills/real-time-sync/SKILL.md +15 -0
  200. package/corpus/templates/calendar/.agents/skills/storing-data/SKILL.md +8 -0
  201. package/corpus/templates/calendar/package.json +3 -3
  202. package/corpus/templates/calendar/server/plugins/db.ts +64 -2
  203. package/corpus/templates/chat/.agents/skills/real-time-sync/SKILL.md +15 -0
  204. package/corpus/templates/chat/package.json +3 -3
  205. package/corpus/templates/clips/actions/finalize-recording.ts +50 -40
  206. package/corpus/templates/clips/app/routes/r.$recordingId.tsx +8 -6
  207. package/corpus/templates/clips/app/routes/share.$shareId.tsx +3 -3
  208. package/corpus/templates/clips/changelog/2026-07-03-mobile-recording-pages-keep-videos-in-a-16-9-player-with-act.md +6 -0
  209. package/corpus/templates/clips/desktop/src/lib/recorder.ts +245 -77
  210. package/corpus/templates/clips/package.json +3 -3
  211. package/corpus/templates/clips/server/lib/recording-upload-state.ts +56 -0
  212. package/corpus/templates/clips/server/plugins/db.ts +68 -1
  213. package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/chunk.post.ts +27 -3
  214. package/corpus/templates/content/.agents/skills/real-time-sync/SKILL.md +15 -0
  215. package/corpus/templates/content/.agents/skills/storing-data/SKILL.md +8 -0
  216. package/corpus/templates/content/actions/edit-document.ts +48 -1
  217. package/corpus/templates/content/actions/list-documents.ts +101 -94
  218. package/corpus/templates/content/actions/search-documents.ts +19 -3
  219. package/corpus/templates/content/actions/update-document.ts +54 -1
  220. package/corpus/templates/content/app/components/editor/DocumentEditor.tsx +127 -7
  221. package/corpus/templates/content/app/components/editor/VisualEditor.tsx +97 -2
  222. package/corpus/templates/content/changelog/2026-07-03-agent-document-edits-now-appear-as-a-live-collaborator-prese.md +6 -0
  223. package/corpus/templates/content/changelog/2026-07-03-document-search-and-list-views-load-faster-on-large-workspac.md +6 -0
  224. package/corpus/templates/content/package.json +3 -3
  225. package/corpus/templates/content/server/plugins/db.ts +57 -1
  226. package/corpus/templates/design/.agents/skills/design-generation/SKILL.md +190 -13
  227. package/corpus/templates/design/.agents/skills/design-systems/SKILL.md +16 -4
  228. package/corpus/templates/design/.agents/skills/export-handoff/SKILL.md +46 -3
  229. package/corpus/templates/design/.agents/skills/full-app-build/SKILL.md +140 -0
  230. package/corpus/templates/design/.agents/skills/visual-edit/SKILL.md +20 -0
  231. package/corpus/templates/design/AGENTS.md +83 -13
  232. package/corpus/templates/design/actions/add-fusion-screens.ts +91 -0
  233. package/corpus/templates/design/actions/apply-a11y-fix.ts +5 -1
  234. package/corpus/templates/design/actions/apply-component-prop-edit.ts +24 -69
  235. package/corpus/templates/design/actions/apply-fusion-edits.ts +161 -0
  236. package/corpus/templates/design/actions/apply-motion-edit.ts +29 -2
  237. package/corpus/templates/design/actions/apply-visual-edit.ts +38 -3
  238. package/corpus/templates/design/actions/connect-localhost.ts +25 -18
  239. package/corpus/templates/design/actions/create-component.ts +5 -1
  240. package/corpus/templates/design/actions/create-fusion-app.ts +202 -0
  241. package/corpus/templates/design/actions/deploy-fusion-app.ts +123 -0
  242. package/corpus/templates/design/actions/edit-design.ts +13 -16
  243. package/corpus/templates/design/actions/export-pdf.ts +8 -1
  244. package/corpus/templates/design/actions/export-zip.ts +10 -1
  245. package/corpus/templates/design/actions/get-fusion-deploy-status.ts +86 -0
  246. package/corpus/templates/design/actions/get-motion-timeline.ts +26 -20
  247. package/corpus/templates/design/actions/grant-localhost-write-consent.ts +10 -0
  248. package/corpus/templates/design/actions/insert-asset.ts +190 -7
  249. package/corpus/templates/design/actions/list-fusion-edits.ts +96 -0
  250. package/corpus/templates/design/actions/list-local-files.ts +133 -0
  251. package/corpus/templates/design/actions/open-visual-edit.ts +27 -5
  252. package/corpus/templates/design/actions/present-design-variants.ts +2 -2
  253. package/corpus/templates/design/actions/push-fusion-app.ts +62 -0
  254. package/corpus/templates/design/actions/queue-fusion-edit.ts +112 -0
  255. package/corpus/templates/design/actions/read-local-file.ts +139 -0
  256. package/corpus/templates/design/actions/revoke-localhost-write-consent.ts +18 -14
  257. package/corpus/templates/design/actions/run-design-audit.ts +7 -4
  258. package/corpus/templates/design/actions/send-fusion-message.ts +69 -0
  259. package/corpus/templates/design/actions/sync-fusion-app.ts +196 -0
  260. package/corpus/templates/design/actions/write-local-file.ts +162 -36
  261. package/corpus/templates/design/app/components/design/CanvasContextMenu.tsx +12 -0
  262. package/corpus/templates/design/app/components/design/DesignCanvas.tsx +600 -66
  263. package/corpus/templates/design/app/components/design/EditPanel.tsx +793 -304
  264. package/corpus/templates/design/app/components/design/FusionAppBanner.tsx +328 -0
  265. package/corpus/templates/design/app/components/design/LayersPanel.tsx +671 -154
  266. package/corpus/templates/design/app/components/design/LocalhostWriteConsentDialog.tsx +1 -1
  267. package/corpus/templates/design/app/components/design/MotionDock.tsx +234 -46
  268. package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +2070 -420
  269. package/corpus/templates/design/app/components/design/StatesPanel.tsx +25 -2
  270. package/corpus/templates/design/app/components/design/TweaksPanel.tsx +7 -98
  271. package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +640 -72
  272. package/corpus/templates/design/app/components/design/bridge/motion-preview.bridge.ts +605 -0
  273. package/corpus/templates/design/app/components/design/canvas-primitive-style.ts +50 -26
  274. package/corpus/templates/design/app/components/design/code-workbench/ActivityBar.tsx +85 -0
  275. package/corpus/templates/design/app/components/design/code-workbench/CodeWorkbench.tsx +466 -0
  276. package/corpus/templates/design/app/components/design/code-workbench/SideBar.tsx +53 -0
  277. package/corpus/templates/design/app/components/design/code-workbench/commands.ts +339 -0
  278. package/corpus/templates/design/app/components/design/code-workbench/editor/Breadcrumbs.tsx +42 -0
  279. package/corpus/templates/design/app/components/design/code-workbench/editor/BufferSync.tsx +128 -0
  280. package/corpus/templates/design/app/components/design/code-workbench/editor/EditorTabs.tsx +363 -0
  281. package/corpus/templates/design/app/components/design/code-workbench/editor/MonacoHost.tsx +268 -0
  282. package/corpus/templates/design/app/components/design/code-workbench/editor/StatusBar.tsx +208 -0
  283. package/corpus/templates/design/app/components/design/code-workbench/editor/monaco-setup.ts +61 -0
  284. package/corpus/templates/design/app/components/design/code-workbench/editor/monaco-theme-palette.ts +191 -0
  285. package/corpus/templates/design/app/components/design/code-workbench/editor/monaco-theme.ts +29 -0
  286. package/corpus/templates/design/app/components/design/code-workbench/editor/status-bar-lang.ts +21 -0
  287. package/corpus/templates/design/app/components/design/code-workbench/editor/tab-drag.ts +27 -0
  288. package/corpus/templates/design/app/components/design/code-workbench/explorer/ExplorerView.tsx +155 -0
  289. package/corpus/templates/design/app/components/design/code-workbench/explorer/FileTree.tsx +551 -0
  290. package/corpus/templates/design/app/components/design/code-workbench/explorer/file-icons.tsx +115 -0
  291. package/corpus/templates/design/app/components/design/code-workbench/format/format-on-open.ts +65 -0
  292. package/corpus/templates/design/app/components/design/code-workbench/format/prettier-format.ts +182 -0
  293. package/corpus/templates/design/app/components/design/code-workbench/model-registry.ts +133 -0
  294. package/corpus/templates/design/app/components/design/code-workbench/quickinput/QuickInput.tsx +563 -0
  295. package/corpus/templates/design/app/components/design/code-workbench/quickinput/fuzzy.ts +170 -0
  296. package/corpus/templates/design/app/components/design/code-workbench/search/SearchView.tsx +508 -0
  297. package/corpus/templates/design/app/components/design/code-workbench/search/search-engine.ts +280 -0
  298. package/corpus/templates/design/app/components/design/code-workbench/store.tsx +734 -0
  299. package/corpus/templates/design/app/components/design/code-workbench/workspace/create-providers.ts +39 -0
  300. package/corpus/templates/design/app/components/design/code-workbench/workspace/inline-provider.ts +196 -0
  301. package/corpus/templates/design/app/components/design/code-workbench/workspace/localhost-provider.ts +177 -0
  302. package/corpus/templates/design/app/components/design/code-workbench/workspace/tree.ts +110 -0
  303. package/corpus/templates/design/app/components/design/code-workbench/workspace/types.ts +103 -0
  304. package/corpus/templates/design/app/components/design/code-workbench-theme.ts +68 -0
  305. package/corpus/templates/design/app/components/design/inspector/AutoLayoutMatrix.tsx +16 -4
  306. package/corpus/templates/design/app/components/design/inspector/DesignColorPicker.tsx +217 -113
  307. package/corpus/templates/design/app/components/design/inspector/GradientEditor.tsx +111 -5
  308. package/corpus/templates/design/app/components/design/inspector/ImageFillControls.tsx +13 -2
  309. package/corpus/templates/design/app/components/design/inspector/ScrubInput.tsx +79 -16
  310. package/corpus/templates/design/app/components/design/inspector/index.ts +9 -0
  311. package/corpus/templates/design/app/components/design/inspector/scrub-input-utils.ts +67 -2
  312. package/corpus/templates/design/app/components/design/types.ts +16 -0
  313. package/corpus/templates/design/app/components/editor/PromptDialog.tsx +80 -1
  314. package/corpus/templates/design/app/components/visual-editor/CanvasCommentPins.tsx +24 -6
  315. package/corpus/templates/design/app/components/visual-editor/DrawOverlay.tsx +15 -1
  316. package/corpus/templates/design/app/components/visual-editor/SaveStatusIndicator.tsx +6 -16
  317. package/corpus/templates/design/app/hooks/useDesignHotkeys.ts +77 -0
  318. package/corpus/templates/design/app/i18n/zh-TW.ts +2 -0
  319. package/corpus/templates/design/app/i18n-data.ts +31 -0
  320. package/corpus/templates/design/app/lib/design-import.ts +95 -0
  321. package/corpus/templates/design/app/pages/DesignEditor.tsx +5586 -1112
  322. package/corpus/templates/design/app/pages/Index.tsx +90 -17
  323. package/corpus/templates/design/changelog/2026-07-03-canvas-interactions-now-match-figma-rotation-aware-resizing-.md +6 -0
  324. package/corpus/templates/design/changelog/2026-07-03-inspector-fixes-mixed-selections-show-mixed-instead-of-wrong.md +6 -0
  325. package/corpus/templates/design/changelog/2026-07-03-keyframe-timeline-works-reliably-drag-keyframes-smoothly-pic.md +6 -0
  326. package/corpus/templates/design/changelog/2026-07-03-layers-panel-matches-figma-top-layer-on-top-drag-with-auto-s.md +6 -0
  327. package/corpus/templates/design/changelog/2026-07-03-much-faster-editor-smooth-dragging-zooming-and-panel-updates.md +6 -0
  328. package/corpus/templates/design/changelog/2026-07-03-pen-tool-refinements-click-the-first-point-to-close-with-a-d.md +6 -0
  329. package/corpus/templates/design/changelog/2026-07-03-text-editing-enter-adds-a-line-break-international-ime-typin.md +6 -0
  330. package/corpus/templates/design/changelog/2026-07-03-the-ai-now-edits-like-a-collaborator-on-canvas-its-cursor-gl.md +6 -0
  331. package/corpus/templates/design/changelog/2026-07-03-the-code-panel-is-now-a-full-vs-code-style-editor-with-a-fil.md +6 -0
  332. package/corpus/templates/design/changelog/2026-07-03-undo-and-redo-are-dependable-across-agent-edits-screen-switc.md +6 -0
  333. package/corpus/templates/design/package.json +4 -3
  334. package/corpus/templates/design/server/db/schema.ts +31 -0
  335. package/corpus/templates/design/server/lib/design-export.ts +43 -1
  336. package/corpus/templates/design/server/lib/fusion-screens.ts +246 -0
  337. package/corpus/templates/design/server/plugins/db.ts +89 -2
  338. package/corpus/templates/design/shared/board-file.ts +25 -5
  339. package/corpus/templates/design/shared/canvas-math.ts +754 -9
  340. package/corpus/templates/design/shared/code-layer.ts +304 -26
  341. package/corpus/templates/design/shared/collab-selection.ts +52 -0
  342. package/corpus/templates/design/shared/color-utils.ts +84 -0
  343. package/corpus/templates/design/shared/design-source-capabilities.ts +16 -7
  344. package/corpus/templates/design/shared/full-app.ts +126 -0
  345. package/corpus/templates/design/shared/motion-compiler.ts +75 -31
  346. package/corpus/templates/design/shared/motion-timeline.ts +335 -0
  347. package/corpus/templates/design/shared/pen-path.ts +496 -23
  348. package/corpus/templates/dispatch/package.json +3 -3
  349. package/corpus/templates/forms/.agents/skills/real-time-sync/SKILL.md +15 -0
  350. package/corpus/templates/forms/.agents/skills/storing-data/SKILL.md +8 -0
  351. package/corpus/templates/forms/package.json +3 -3
  352. package/corpus/templates/forms/server/plugins/db.ts +62 -2
  353. package/corpus/templates/macros/package.json +3 -3
  354. package/corpus/templates/macros/server/plugins/db.ts +63 -2
  355. package/corpus/templates/mail/.agents/skills/real-time-sync/SKILL.md +15 -0
  356. package/corpus/templates/mail/.agents/skills/storing-data/SKILL.md +8 -0
  357. package/corpus/templates/mail/package.json +3 -3
  358. package/corpus/templates/mail/server/lib/contact-frequency.ts +42 -15
  359. package/corpus/templates/mail/server/plugins/db.ts +63 -2
  360. package/corpus/templates/plan/.agents/skills/real-time-sync/SKILL.md +15 -0
  361. package/corpus/templates/plan/.agents/skills/visual-plan/SKILL.md +9 -3
  362. package/corpus/templates/plan/.agents/skills/visualize-repo/SKILL.md +92 -0
  363. package/corpus/templates/plan/actions/export-visual-plan.ts +5 -0
  364. package/corpus/templates/plan/actions/get-local-plan-folder.ts +4 -22
  365. package/corpus/templates/plan/actions/get-plan-version.ts +6 -16
  366. package/corpus/templates/plan/actions/list-plan-versions.ts +48 -20
  367. package/corpus/templates/plan/actions/patch-visual-plan-source.ts +41 -1
  368. package/corpus/templates/plan/actions/promote-local-plan-folder.ts +4 -22
  369. package/corpus/templates/plan/actions/update-local-plan-comments.ts +4 -2
  370. package/corpus/templates/plan/actions/update-local-plan-folder.ts +4 -22
  371. package/corpus/templates/plan/actions/update-visual-plan.ts +60 -1
  372. package/corpus/templates/plan/agent-native.app-skill.json +10 -0
  373. package/corpus/templates/plan/app/components/editor/PlanDocumentEditor.tsx +138 -39
  374. package/corpus/templates/plan/app/components/editor/usePlanUndoStack.ts +165 -23
  375. package/corpus/templates/plan/app/components/plan/PlanContentRenderer.tsx +80 -4
  376. package/corpus/templates/plan/app/global.css +11 -9
  377. package/corpus/templates/plan/app/hooks/use-navigation-state.ts +10 -1
  378. package/corpus/templates/plan/app/hooks/use-plan-presence.ts +66 -0
  379. package/corpus/templates/plan/app/pages/PlansPage.tsx +215 -63
  380. package/corpus/templates/plan/changelog/2026-07-03-local-visual-plans-and-recaps-can-save-comments-without-sign.md +6 -0
  381. package/corpus/templates/plan/changelog/2026-07-03-plan-tabs-render-nested-text-instead-of-raw-json.md +6 -0
  382. package/corpus/templates/plan/changelog/2026-07-03-plans-are-now-fully-real-time-collaborative-multiple-people-.md +6 -0
  383. package/corpus/templates/plan/changelog/2026-07-03-plans-open-and-refresh-faster-especially-long-lived-plans-wi.md +6 -0
  384. package/corpus/templates/plan/changelog/2026-07-03-undo-now-survives-agent-edits-cmd-z-keeps-working-on-your-ow.md +6 -0
  385. package/corpus/templates/plan/package.json +5 -3
  386. package/corpus/templates/plan/server/db/schema.ts +12 -0
  387. package/corpus/templates/plan/server/lib/local-plan-kind.ts +25 -0
  388. package/corpus/templates/plan/server/lib/plan-versions.ts +83 -1
  389. package/corpus/templates/plan/server/lib/public-action-paths.ts +0 -2
  390. package/corpus/templates/plan/server/plans.ts +26 -3
  391. package/corpus/templates/plan/server/plugins/db.ts +105 -2
  392. package/corpus/templates/slides/.agents/skills/slide-editing/SKILL.md +8 -4
  393. package/corpus/templates/slides/AGENTS.md +4 -0
  394. package/corpus/templates/slides/actions/_agent-presence.ts +48 -0
  395. package/corpus/templates/slides/actions/add-slide.ts +16 -18
  396. package/corpus/templates/slides/actions/patch-deck.ts +4 -2
  397. package/corpus/templates/slides/actions/update-slide.ts +114 -77
  398. package/corpus/templates/slides/actions/view-screen.ts +39 -0
  399. package/corpus/templates/slides/app/components/editor/EditorSidebar.tsx +47 -3
  400. package/corpus/templates/slides/app/components/editor/EditorToolbar.tsx +32 -35
  401. package/corpus/templates/slides/app/components/editor/SlideEditor.tsx +625 -199
  402. package/corpus/templates/slides/app/components/editor/SlideStyleInspector.tsx +342 -0
  403. package/corpus/templates/slides/app/components/editor/TweaksPanel.tsx +46 -96
  404. package/corpus/templates/slides/app/components/visual-editor/SaveStatusIndicator.tsx +8 -1
  405. package/corpus/templates/slides/app/context/DeckContext.tsx +589 -176
  406. package/corpus/templates/slides/app/hooks/use-deck-presence.ts +84 -42
  407. package/corpus/templates/slides/app/i18n/ar-SA.ts +46 -0
  408. package/corpus/templates/slides/app/i18n/de-DE.ts +46 -0
  409. package/corpus/templates/slides/app/i18n/en-US.ts +46 -0
  410. package/corpus/templates/slides/app/i18n/es-ES.ts +46 -0
  411. package/corpus/templates/slides/app/i18n/fr-FR.ts +46 -0
  412. package/corpus/templates/slides/app/i18n/hi-IN.ts +46 -0
  413. package/corpus/templates/slides/app/i18n/ja-JP.ts +46 -0
  414. package/corpus/templates/slides/app/i18n/ko-KR.ts +46 -0
  415. package/corpus/templates/slides/app/i18n/pt-BR.ts +46 -0
  416. package/corpus/templates/slides/app/i18n/zh-CN.ts +46 -0
  417. package/corpus/templates/slides/app/i18n/zh-TW.ts +46 -0
  418. package/corpus/templates/slides/app/pages/DeckEditor.tsx +25 -13
  419. package/corpus/templates/slides/changelog/2026-07-03-figma-style-slide-editing.md +6 -0
  420. package/corpus/templates/slides/changelog/2026-07-03-see-the-ai-working-with-you-when-the-agent-edits-a-slide-it-.md +6 -0
  421. package/corpus/templates/slides/changelog/2026-07-03-undo-redo-is-now-precise-and-safe-with-collaborators-it-only.md +6 -0
  422. package/corpus/templates/slides/package.json +3 -3
  423. package/corpus/templates/slides/server/handlers/decks.ts +31 -3
  424. package/corpus/templates/slides/server/plugins/db.ts +65 -2
  425. package/corpus/templates/videos/netlify.toml +1 -12
  426. package/dist/agent/run-store.js +1 -1
  427. package/dist/agent/run-store.js.map +1 -1
  428. package/dist/chat-threads/store.d.ts +9 -1
  429. package/dist/chat-threads/store.d.ts.map +1 -1
  430. package/dist/chat-threads/store.js +63 -11
  431. package/dist/chat-threads/store.js.map +1 -1
  432. package/dist/checkpoints/store.d.ts.map +1 -1
  433. package/dist/checkpoints/store.js +10 -2
  434. package/dist/checkpoints/store.js.map +1 -1
  435. package/dist/cli/create.d.ts.map +1 -1
  436. package/dist/cli/create.js +3 -5
  437. package/dist/cli/create.js.map +1 -1
  438. package/dist/cli/design-connect.d.ts +49 -1
  439. package/dist/cli/design-connect.d.ts.map +1 -1
  440. package/dist/cli/design-connect.js +414 -9
  441. package/dist/cli/design-connect.js.map +1 -1
  442. package/dist/cli/index.js +12 -0
  443. package/dist/cli/index.js.map +1 -1
  444. package/dist/cli/plan-local.d.ts +24 -0
  445. package/dist/cli/plan-local.d.ts.map +1 -1
  446. package/dist/cli/plan-local.js +188 -20
  447. package/dist/cli/plan-local.js.map +1 -1
  448. package/dist/cli/skills.d.ts +3 -1
  449. package/dist/cli/skills.d.ts.map +1 -1
  450. package/dist/cli/skills.js +173 -21
  451. package/dist/cli/skills.js.map +1 -1
  452. package/dist/cli/templates-meta.d.ts.map +1 -1
  453. package/dist/cli/templates-meta.js +0 -14
  454. package/dist/cli/templates-meta.js.map +1 -1
  455. package/dist/cli/visualize-repo.d.ts +49 -0
  456. package/dist/cli/visualize-repo.d.ts.map +1 -0
  457. package/dist/cli/visualize-repo.js +561 -0
  458. package/dist/cli/visualize-repo.js.map +1 -0
  459. package/dist/client/AssistantChat.d.ts.map +1 -1
  460. package/dist/client/AssistantChat.js +120 -15
  461. package/dist/client/AssistantChat.js.map +1 -1
  462. package/dist/client/agent-chat-adapter.d.ts.map +1 -1
  463. package/dist/client/agent-chat-adapter.js +6 -5
  464. package/dist/client/agent-chat-adapter.js.map +1 -1
  465. package/dist/client/app-providers.d.ts +2 -2
  466. package/dist/client/app-providers.js.map +1 -1
  467. package/dist/client/collab/index.d.ts +4 -1
  468. package/dist/client/collab/index.d.ts.map +1 -1
  469. package/dist/client/collab/index.js +3 -0
  470. package/dist/client/collab/index.js.map +1 -1
  471. package/dist/client/components/LiveCursorOverlay.d.ts.map +1 -1
  472. package/dist/client/components/LiveCursorOverlay.js +11 -3
  473. package/dist/client/components/LiveCursorOverlay.js.map +1 -1
  474. package/dist/client/components/PresenceBar.d.ts.map +1 -1
  475. package/dist/client/components/PresenceBar.js +6 -1
  476. package/dist/client/components/PresenceBar.js.map +1 -1
  477. package/dist/client/components/RecentEditHighlights.d.ts +43 -0
  478. package/dist/client/components/RecentEditHighlights.d.ts.map +1 -0
  479. package/dist/client/components/RecentEditHighlights.js +146 -0
  480. package/dist/client/components/RecentEditHighlights.js.map +1 -0
  481. package/dist/client/components/RemoteSelectionRings.d.ts +9 -0
  482. package/dist/client/components/RemoteSelectionRings.d.ts.map +1 -1
  483. package/dist/client/components/RemoteSelectionRings.js +22 -8
  484. package/dist/client/components/RemoteSelectionRings.js.map +1 -1
  485. package/dist/client/index.d.ts +6 -1
  486. package/dist/client/index.d.ts.map +1 -1
  487. package/dist/client/index.js +7 -0
  488. package/dist/client/index.js.map +1 -1
  489. package/dist/client/org/OrgSwitcher.d.ts.map +1 -1
  490. package/dist/client/org/OrgSwitcher.js +1 -3
  491. package/dist/client/org/OrgSwitcher.js.map +1 -1
  492. package/dist/client/rich-markdown-editor/SharedRichEditor.d.ts +8 -1
  493. package/dist/client/rich-markdown-editor/SharedRichEditor.d.ts.map +1 -1
  494. package/dist/client/rich-markdown-editor/SharedRichEditor.js +8 -2
  495. package/dist/client/rich-markdown-editor/SharedRichEditor.js.map +1 -1
  496. package/dist/client/rich-markdown-editor/index.d.ts +1 -0
  497. package/dist/client/rich-markdown-editor/index.d.ts.map +1 -1
  498. package/dist/client/rich-markdown-editor/index.js +1 -0
  499. package/dist/client/rich-markdown-editor/index.js.map +1 -1
  500. package/dist/client/rich-markdown-editor/surgical-apply.d.ts +66 -0
  501. package/dist/client/rich-markdown-editor/surgical-apply.d.ts.map +1 -0
  502. package/dist/client/rich-markdown-editor/surgical-apply.js +147 -0
  503. package/dist/client/rich-markdown-editor/surgical-apply.js.map +1 -0
  504. package/dist/client/rich-markdown-editor/useCollabReconcile.d.ts +18 -2
  505. package/dist/client/rich-markdown-editor/useCollabReconcile.d.ts.map +1 -1
  506. package/dist/client/rich-markdown-editor/useCollabReconcile.js +39 -8
  507. package/dist/client/rich-markdown-editor/useCollabReconcile.js.map +1 -1
  508. package/dist/client/session-replay.d.ts +10 -1
  509. package/dist/client/session-replay.d.ts.map +1 -1
  510. package/dist/client/session-replay.js +134 -7
  511. package/dist/client/session-replay.js.map +1 -1
  512. package/dist/client/sse-event-processor.d.ts.map +1 -1
  513. package/dist/client/sse-event-processor.js +81 -1
  514. package/dist/client/sse-event-processor.js.map +1 -1
  515. package/dist/client/use-action.d.ts +24 -0
  516. package/dist/client/use-action.d.ts.map +1 -1
  517. package/dist/client/use-action.js +109 -27
  518. package/dist/client/use-action.js.map +1 -1
  519. package/dist/client/use-agent-engine-configured.d.ts.map +1 -1
  520. package/dist/client/use-agent-engine-configured.js +7 -1
  521. package/dist/client/use-agent-engine-configured.js.map +1 -1
  522. package/dist/client/use-chat-threads.d.ts.map +1 -1
  523. package/dist/client/use-chat-threads.js +11 -3
  524. package/dist/client/use-chat-threads.js.map +1 -1
  525. package/dist/client/use-db-sync.d.ts +36 -0
  526. package/dist/client/use-db-sync.d.ts.map +1 -1
  527. package/dist/client/use-db-sync.js +68 -12
  528. package/dist/client/use-db-sync.js.map +1 -1
  529. package/dist/client/use-pinch-zoom.d.ts.map +1 -1
  530. package/dist/client/use-pinch-zoom.js +76 -11
  531. package/dist/client/use-pinch-zoom.js.map +1 -1
  532. package/dist/client/visual-style-controls.d.ts +79 -0
  533. package/dist/client/visual-style-controls.d.ts.map +1 -0
  534. package/dist/client/visual-style-controls.js +150 -0
  535. package/dist/client/visual-style-controls.js.map +1 -0
  536. package/dist/collab/agent-presence.d.ts +51 -5
  537. package/dist/collab/agent-presence.d.ts.map +1 -1
  538. package/dist/collab/agent-presence.js +144 -58
  539. package/dist/collab/agent-presence.js.map +1 -1
  540. package/dist/collab/awareness-store.d.ts +32 -0
  541. package/dist/collab/awareness-store.d.ts.map +1 -0
  542. package/dist/collab/awareness-store.js +0 -0
  543. package/dist/collab/awareness-store.js.map +1 -0
  544. package/dist/collab/awareness.d.ts +14 -3
  545. package/dist/collab/awareness.d.ts.map +1 -1
  546. package/dist/collab/awareness.js +53 -5
  547. package/dist/collab/awareness.js.map +1 -1
  548. package/dist/collab/client.d.ts +2 -0
  549. package/dist/collab/client.d.ts.map +1 -1
  550. package/dist/collab/client.js +79 -119
  551. package/dist/collab/client.js.map +1 -1
  552. package/dist/collab/index.d.ts +3 -1
  553. package/dist/collab/index.d.ts.map +1 -1
  554. package/dist/collab/index.js +5 -1
  555. package/dist/collab/index.js.map +1 -1
  556. package/dist/collab/presence.d.ts.map +1 -1
  557. package/dist/collab/presence.js +54 -3
  558. package/dist/collab/presence.js.map +1 -1
  559. package/dist/collab/recent-edits.d.ts +87 -0
  560. package/dist/collab/recent-edits.d.ts.map +1 -0
  561. package/dist/collab/recent-edits.js +116 -0
  562. package/dist/collab/recent-edits.js.map +1 -0
  563. package/dist/collab/undo.d.ts +121 -0
  564. package/dist/collab/undo.d.ts.map +1 -0
  565. package/dist/collab/undo.js +244 -0
  566. package/dist/collab/undo.js.map +1 -0
  567. package/dist/collab/ydoc-manager.d.ts +10 -0
  568. package/dist/collab/ydoc-manager.d.ts.map +1 -1
  569. package/dist/collab/ydoc-manager.js +57 -0
  570. package/dist/collab/ydoc-manager.js.map +1 -1
  571. package/dist/connections/catalog.d.ts +2 -2
  572. package/dist/connections/catalog.d.ts.map +1 -1
  573. package/dist/connections/catalog.js +1 -1
  574. package/dist/connections/catalog.js.map +1 -1
  575. package/dist/db/create-get-db.d.ts +22 -0
  576. package/dist/db/create-get-db.d.ts.map +1 -1
  577. package/dist/db/create-get-db.js +73 -1
  578. package/dist/db/create-get-db.js.map +1 -1
  579. package/dist/db/ensure-additive-columns.d.ts +93 -0
  580. package/dist/db/ensure-additive-columns.d.ts.map +1 -0
  581. package/dist/db/ensure-additive-columns.js +355 -0
  582. package/dist/db/ensure-additive-columns.js.map +1 -0
  583. package/dist/db/index.d.ts +1 -0
  584. package/dist/db/index.d.ts.map +1 -1
  585. package/dist/db/index.js +1 -0
  586. package/dist/db/index.js.map +1 -1
  587. package/dist/db/migrations.d.ts +70 -0
  588. package/dist/db/migrations.d.ts.map +1 -1
  589. package/dist/db/migrations.js +196 -33
  590. package/dist/db/migrations.js.map +1 -1
  591. package/dist/jobs/scheduler.js +17 -10
  592. package/dist/jobs/scheduler.js.map +1 -1
  593. package/dist/notifications/routes.d.ts +3 -3
  594. package/dist/observability/routes.d.ts +5 -5
  595. package/dist/observability/traces.d.ts.map +1 -1
  596. package/dist/observability/traces.js +155 -1
  597. package/dist/observability/traces.js.map +1 -1
  598. package/dist/org/context.d.ts +7 -0
  599. package/dist/org/context.d.ts.map +1 -1
  600. package/dist/org/context.js +54 -2
  601. package/dist/org/context.js.map +1 -1
  602. package/dist/progress/routes.d.ts +1 -1
  603. package/dist/resources/handlers.d.ts +3 -3
  604. package/dist/secrets/routes.d.ts +6 -6
  605. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  606. package/dist/server/agent-chat-plugin.js +10 -6
  607. package/dist/server/agent-chat-plugin.js.map +1 -1
  608. package/dist/server/auth-marketing.d.ts.map +1 -1
  609. package/dist/server/auth-marketing.js +0 -10
  610. package/dist/server/auth-marketing.js.map +1 -1
  611. package/dist/server/auth.d.ts.map +1 -1
  612. package/dist/server/auth.js +6 -4
  613. package/dist/server/auth.js.map +1 -1
  614. package/dist/server/collab-plugin.d.ts.map +1 -1
  615. package/dist/server/collab-plugin.js +45 -13
  616. package/dist/server/collab-plugin.js.map +1 -1
  617. package/dist/server/design-token-utils.d.ts +1 -1
  618. package/dist/server/design-token-utils.js +1 -1
  619. package/dist/server/design-token-utils.js.map +1 -1
  620. package/dist/server/fusion-app.d.ts +107 -0
  621. package/dist/server/fusion-app.d.ts.map +1 -0
  622. package/dist/server/fusion-app.js +371 -0
  623. package/dist/server/fusion-app.js.map +1 -0
  624. package/dist/server/index.d.ts +1 -0
  625. package/dist/server/index.d.ts.map +1 -1
  626. package/dist/server/index.js +1 -0
  627. package/dist/server/index.js.map +1 -1
  628. package/dist/server/onboarding-html.d.ts.map +1 -1
  629. package/dist/server/onboarding-html.js +3 -4
  630. package/dist/server/onboarding-html.js.map +1 -1
  631. package/dist/server/poll-events.d.ts +2 -0
  632. package/dist/server/poll-events.d.ts.map +1 -1
  633. package/dist/server/poll-events.js +7 -2
  634. package/dist/server/poll-events.js.map +1 -1
  635. package/dist/server/poll.d.ts +47 -3
  636. package/dist/server/poll.d.ts.map +1 -1
  637. package/dist/server/poll.js +176 -10
  638. package/dist/server/poll.js.map +1 -1
  639. package/dist/server/schema-prompt.d.ts.map +1 -1
  640. package/dist/server/schema-prompt.js +24 -7
  641. package/dist/server/schema-prompt.js.map +1 -1
  642. package/dist/settings/store.d.ts.map +1 -1
  643. package/dist/settings/store.js +32 -3
  644. package/dist/settings/store.js.map +1 -1
  645. package/dist/sharing/actions/set-resource-visibility.js +2 -0
  646. package/dist/sharing/actions/set-resource-visibility.js.map +1 -1
  647. package/dist/sharing/actions/share-resource.d.ts.map +1 -1
  648. package/dist/sharing/actions/share-resource.js +3 -0
  649. package/dist/sharing/actions/share-resource.js.map +1 -1
  650. package/dist/sharing/actions/unshare-resource.js +2 -0
  651. package/dist/sharing/actions/unshare-resource.js.map +1 -1
  652. package/dist/styles/agent-native.css +0 -5
  653. package/dist/templates/default/.agents/skills/real-time-collab/SKILL.md +82 -19
  654. package/dist/templates/default/.agents/skills/real-time-sync/SKILL.md +15 -0
  655. package/dist/templates/default/.agents/skills/storing-data/SKILL.md +8 -0
  656. package/dist/templates/default/package.json +3 -3
  657. package/dist/templates/workspace-core/.agents/skills/client-methods/SKILL.md +8 -0
  658. package/dist/templates/workspace-core/.agents/skills/observability/SKILL.md +22 -0
  659. package/dist/templates/workspace-core/.agents/skills/real-time-collab/SKILL.md +82 -19
  660. package/dist/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +15 -0
  661. package/dist/templates/workspace-core/.agents/skills/storing-data/SKILL.md +8 -0
  662. package/dist/templates/workspace-core/.agents/skills/tracking/SKILL.md +1 -0
  663. package/dist/tracking/providers.d.ts.map +1 -1
  664. package/dist/tracking/providers.js +17 -1
  665. package/dist/tracking/providers.js.map +1 -1
  666. package/docs/content/cloneable-saas.mdx +0 -1
  667. package/docs/content/locales/ar-SA/cloneable-saas.mdx +0 -1
  668. package/docs/content/locales/ar-SA/plan-plugin.mdx +10 -9
  669. package/docs/content/locales/ar-SA/sharing.mdx +1 -2
  670. package/docs/content/locales/ar-SA/skills-guide.mdx +2 -3
  671. package/docs/content/locales/ar-SA/template-plan.mdx +23 -7
  672. package/docs/content/locales/ar-SA/tracking.mdx +1 -1
  673. package/docs/content/locales/ar-SA/workspace-connections.mdx +11 -11
  674. package/docs/content/locales/de-DE/cloneable-saas.mdx +0 -1
  675. package/docs/content/locales/de-DE/plan-plugin.mdx +10 -9
  676. package/docs/content/locales/de-DE/sharing.mdx +1 -2
  677. package/docs/content/locales/de-DE/skills-guide.mdx +2 -3
  678. package/docs/content/locales/de-DE/template-plan.mdx +23 -7
  679. package/docs/content/locales/de-DE/tracking.mdx +1 -1
  680. package/docs/content/locales/de-DE/workspace-connections.mdx +1 -1
  681. package/docs/content/locales/es-ES/cloneable-saas.mdx +0 -1
  682. package/docs/content/locales/es-ES/plan-plugin.mdx +10 -9
  683. package/docs/content/locales/es-ES/sharing.mdx +1 -2
  684. package/docs/content/locales/es-ES/skills-guide.mdx +2 -3
  685. package/docs/content/locales/es-ES/template-plan.mdx +23 -7
  686. package/docs/content/locales/es-ES/tracking.mdx +1 -1
  687. package/docs/content/locales/es-ES/workspace-connections.mdx +1 -1
  688. package/docs/content/locales/fr-FR/cloneable-saas.mdx +0 -1
  689. package/docs/content/locales/fr-FR/plan-plugin.mdx +10 -9
  690. package/docs/content/locales/fr-FR/sharing.mdx +1 -2
  691. package/docs/content/locales/fr-FR/skills-guide.mdx +2 -3
  692. package/docs/content/locales/fr-FR/template-plan.mdx +23 -7
  693. package/docs/content/locales/fr-FR/tracking.mdx +1 -1
  694. package/docs/content/locales/fr-FR/workspace-connections.mdx +1 -1
  695. package/docs/content/locales/hi-IN/cloneable-saas.mdx +0 -1
  696. package/docs/content/locales/hi-IN/plan-plugin.mdx +10 -9
  697. package/docs/content/locales/hi-IN/sharing.mdx +1 -2
  698. package/docs/content/locales/hi-IN/skills-guide.mdx +2 -3
  699. package/docs/content/locales/hi-IN/template-plan.mdx +23 -7
  700. package/docs/content/locales/hi-IN/tracking.mdx +1 -1
  701. package/docs/content/locales/hi-IN/workspace-connections.mdx +1 -1
  702. package/docs/content/locales/ja-JP/cloneable-saas.mdx +0 -1
  703. package/docs/content/locales/ja-JP/plan-plugin.mdx +10 -9
  704. package/docs/content/locales/ja-JP/sharing.mdx +1 -2
  705. package/docs/content/locales/ja-JP/skills-guide.mdx +2 -3
  706. package/docs/content/locales/ja-JP/template-plan.mdx +23 -7
  707. package/docs/content/locales/ja-JP/tracking.mdx +1 -1
  708. package/docs/content/locales/ja-JP/workspace-connections.mdx +1 -1
  709. package/docs/content/locales/ko-KR/cloneable-saas.mdx +0 -1
  710. package/docs/content/locales/ko-KR/plan-plugin.mdx +10 -9
  711. package/docs/content/locales/ko-KR/sharing.mdx +1 -2
  712. package/docs/content/locales/ko-KR/skills-guide.mdx +2 -3
  713. package/docs/content/locales/ko-KR/template-plan.mdx +23 -7
  714. package/docs/content/locales/ko-KR/tracking.mdx +1 -1
  715. package/docs/content/locales/ko-KR/workspace-connections.mdx +1 -1
  716. package/docs/content/locales/pt-BR/cloneable-saas.mdx +0 -1
  717. package/docs/content/locales/pt-BR/plan-plugin.mdx +10 -9
  718. package/docs/content/locales/pt-BR/sharing.mdx +1 -2
  719. package/docs/content/locales/pt-BR/skills-guide.mdx +2 -3
  720. package/docs/content/locales/pt-BR/template-plan.mdx +23 -7
  721. package/docs/content/locales/pt-BR/tracking.mdx +1 -1
  722. package/docs/content/locales/pt-BR/workspace-connections.mdx +1 -1
  723. package/docs/content/locales/zh-CN/cloneable-saas.mdx +0 -1
  724. package/docs/content/locales/zh-CN/plan-plugin.mdx +10 -9
  725. package/docs/content/locales/zh-CN/sharing.mdx +1 -2
  726. package/docs/content/locales/zh-CN/skills-guide.mdx +2 -3
  727. package/docs/content/locales/zh-CN/template-plan.mdx +23 -7
  728. package/docs/content/locales/zh-CN/tracking.mdx +1 -1
  729. package/docs/content/locales/zh-CN/workspace-connections.mdx +1 -1
  730. package/docs/content/locales/zh-TW/cloneable-saas.mdx +0 -1
  731. package/docs/content/locales/zh-TW/plan-plugin.mdx +10 -9
  732. package/docs/content/locales/zh-TW/sharing.mdx +1 -2
  733. package/docs/content/locales/zh-TW/skills-guide.mdx +2 -3
  734. package/docs/content/locales/zh-TW/template-plan.mdx +23 -7
  735. package/docs/content/locales/zh-TW/tracking.mdx +1 -1
  736. package/docs/content/locales/zh-TW/workspace-connections.mdx +1 -1
  737. package/docs/content/plan-plugin.mdx +12 -11
  738. package/docs/content/sharing.mdx +1 -2
  739. package/docs/content/skills-guide.mdx +4 -3
  740. package/docs/content/template-plan.mdx +37 -6
  741. package/docs/content/tracking.mdx +1 -1
  742. package/docs/content/workspace-connections.mdx +1 -1
  743. package/package.json +6 -6
  744. package/src/templates/default/.agents/skills/real-time-collab/SKILL.md +82 -19
  745. package/src/templates/default/.agents/skills/real-time-sync/SKILL.md +15 -0
  746. package/src/templates/default/.agents/skills/storing-data/SKILL.md +8 -0
  747. package/src/templates/default/package.json +3 -3
  748. package/src/templates/workspace-core/.agents/skills/client-methods/SKILL.md +8 -0
  749. package/src/templates/workspace-core/.agents/skills/observability/SKILL.md +22 -0
  750. package/src/templates/workspace-core/.agents/skills/real-time-collab/SKILL.md +82 -19
  751. package/src/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +15 -0
  752. package/src/templates/workspace-core/.agents/skills/storing-data/SKILL.md +8 -0
  753. package/src/templates/workspace-core/.agents/skills/tracking/SKILL.md +1 -0
  754. package/corpus/core/docs/content/locales/ar-SA/template-videos.mdx +0 -336
  755. package/corpus/core/docs/content/locales/de-DE/template-videos.mdx +0 -336
  756. package/corpus/core/docs/content/locales/es-ES/template-videos.mdx +0 -336
  757. package/corpus/core/docs/content/locales/fr-FR/template-videos.mdx +0 -336
  758. package/corpus/core/docs/content/locales/hi-IN/template-videos.mdx +0 -336
  759. package/corpus/core/docs/content/locales/ja-JP/template-videos.mdx +0 -336
  760. package/corpus/core/docs/content/locales/ko-KR/template-videos.mdx +0 -336
  761. package/corpus/core/docs/content/locales/pt-BR/template-videos.mdx +0 -336
  762. package/corpus/core/docs/content/locales/zh-CN/template-videos.mdx +0 -334
  763. package/corpus/core/docs/content/locales/zh-TW/template-videos.mdx +0 -334
  764. package/corpus/core/docs/content/template-videos.mdx +0 -332
  765. package/corpus/templates/design/app/components/design/CodeWorkbenchHost.tsx +0 -697
  766. package/corpus/templates/slides/app/components/editor/CodeEditor.tsx +0 -49
  767. package/corpus/templates/videos/.agents/skills/actions/SKILL.md +0 -432
  768. package/corpus/templates/videos/.agents/skills/animation-tracks/SKILL.md +0 -99
  769. package/corpus/templates/videos/.agents/skills/capture-learnings/SKILL.md +0 -76
  770. package/corpus/templates/videos/.agents/skills/composition-management/SKILL.md +0 -106
  771. package/corpus/templates/videos/.agents/skills/create-skill/SKILL.md +0 -221
  772. package/corpus/templates/videos/.agents/skills/delegate-to-agent/SKILL.md +0 -263
  773. package/corpus/templates/videos/.agents/skills/frontend-design/SKILL.md +0 -112
  774. package/corpus/templates/videos/.agents/skills/security/SKILL.md +0 -263
  775. package/corpus/templates/videos/.agents/skills/self-modifying-code/SKILL.md +0 -88
  776. package/corpus/templates/videos/.agents/skills/shadcn-ui/SKILL.md +0 -95
  777. package/corpus/templates/videos/.builder/ANIMATED_PROPERTIES.md +0 -335
  778. package/corpus/templates/videos/.builder/KEYFRAME_SYNC.md +0 -166
  779. package/corpus/templates/videos/.builder/SEAMLESS_SYNC.md +0 -211
  780. package/corpus/templates/videos/.builder/rules/deploy-app.mdc +0 -22
  781. package/corpus/templates/videos/.builder/rules/organize-ui.mdc +0 -9
  782. package/corpus/templates/videos/.builder/skills/remotion/SKILL.md +0 -29
  783. package/corpus/templates/videos/.builder/skills/remotion/rules/animations.md +0 -27
  784. package/corpus/templates/videos/.builder/skills/remotion/rules/assets.md +0 -43
  785. package/corpus/templates/videos/.builder/skills/remotion/rules/audio.md +0 -58
  786. package/corpus/templates/videos/.builder/skills/remotion/rules/compositions.md +0 -129
  787. package/corpus/templates/videos/.builder/skills/remotion/rules/fonts.md +0 -47
  788. package/corpus/templates/videos/.builder/skills/remotion/rules/images.md +0 -41
  789. package/corpus/templates/videos/.builder/skills/remotion/rules/parameters.md +0 -59
  790. package/corpus/templates/videos/.builder/skills/remotion/rules/sequencing.md +0 -54
  791. package/corpus/templates/videos/.builder/skills/remotion/rules/tailwind.md +0 -11
  792. package/corpus/templates/videos/.builder/skills/remotion/rules/text-animations.md +0 -18
  793. package/corpus/templates/videos/.builder/skills/remotion/rules/timing.md +0 -103
  794. package/corpus/templates/videos/.builder/skills/remotion/rules/transparent-videos.md +0 -35
  795. package/corpus/templates/videos/.builder/skills/remotion/rules/trimming.md +0 -38
  796. package/corpus/templates/videos/.builder/skills/remotion/rules/videos.md +0 -54
  797. package/corpus/templates/videos/.dockerignore +0 -62
  798. package/corpus/templates/videos/.env.example +0 -4
  799. package/corpus/templates/videos/.oxfmtrc.json +0 -8
  800. package/corpus/templates/videos/AGENTS.md +0 -46
  801. package/corpus/templates/videos/CHANGELOG.md +0 -10
  802. package/corpus/templates/videos/DEVELOPING.md +0 -143
  803. package/corpus/templates/videos/README.md +0 -33
  804. package/corpus/templates/videos/actions/analyze-brand-assets.ts +0 -151
  805. package/corpus/templates/videos/actions/apply-design-system.ts +0 -35
  806. package/corpus/templates/videos/actions/create-design-system.ts +0 -84
  807. package/corpus/templates/videos/actions/create-folder.ts +0 -48
  808. package/corpus/templates/videos/actions/db-connect.ts +0 -45
  809. package/corpus/templates/videos/actions/db-health.ts +0 -24
  810. package/corpus/templates/videos/actions/db-status.ts +0 -28
  811. package/corpus/templates/videos/actions/delete-composition.ts +0 -272
  812. package/corpus/templates/videos/actions/delete-folder.ts +0 -27
  813. package/corpus/templates/videos/actions/generate-animated-component.ts +0 -470
  814. package/corpus/templates/videos/actions/get-composition.ts +0 -36
  815. package/corpus/templates/videos/actions/get-design-system.ts +0 -35
  816. package/corpus/templates/videos/actions/import-code.ts +0 -67
  817. package/corpus/templates/videos/actions/import-design-project.ts +0 -42
  818. package/corpus/templates/videos/actions/import-document.ts +0 -125
  819. package/corpus/templates/videos/actions/import-from-url.ts +0 -18
  820. package/corpus/templates/videos/actions/import-github.ts +0 -182
  821. package/corpus/templates/videos/actions/list-compositions.ts +0 -32
  822. package/corpus/templates/videos/actions/list-design-systems.ts +0 -66
  823. package/corpus/templates/videos/actions/list-folders.ts +0 -61
  824. package/corpus/templates/videos/actions/move-composition-to-folder.ts +0 -59
  825. package/corpus/templates/videos/actions/navigate.ts +0 -40
  826. package/corpus/templates/videos/actions/rename-folder.ts +0 -41
  827. package/corpus/templates/videos/actions/run.ts +0 -2
  828. package/corpus/templates/videos/actions/save-composition.ts +0 -114
  829. package/corpus/templates/videos/actions/set-default-design-system.ts +0 -40
  830. package/corpus/templates/videos/actions/update-composition.ts +0 -81
  831. package/corpus/templates/videos/actions/update-design-system.ts +0 -68
  832. package/corpus/templates/videos/actions/validate-compositions.ts +0 -502
  833. package/corpus/templates/videos/actions/view-screen.ts +0 -48
  834. package/corpus/templates/videos/app/components/CameraControls.tsx +0 -442
  835. package/corpus/templates/videos/app/components/CameraToolbar.tsx +0 -437
  836. package/corpus/templates/videos/app/components/CloudUpgrade.tsx +0 -287
  837. package/corpus/templates/videos/app/components/CollabPresenceBar.tsx +0 -81
  838. package/corpus/templates/videos/app/components/CompSettingsEditor.tsx +0 -107
  839. package/corpus/templates/videos/app/components/ComponentLibrarySidebar.tsx +0 -457
  840. package/corpus/templates/videos/app/components/ComponentPropsPanel.tsx +0 -227
  841. package/corpus/templates/videos/app/components/ComponentsSidebar.tsx +0 -70
  842. package/corpus/templates/videos/app/components/CompositionCard.tsx +0 -147
  843. package/corpus/templates/videos/app/components/CurrentElementPanel.tsx +0 -835
  844. package/corpus/templates/videos/app/components/CursorControls.tsx +0 -664
  845. package/corpus/templates/videos/app/components/CursorPositioningOverlay.tsx +0 -238
  846. package/corpus/templates/videos/app/components/LibraryFolderRow.tsx +0 -235
  847. package/corpus/templates/videos/app/components/MotionCurveSelect.tsx +0 -61
  848. package/corpus/templates/videos/app/components/NewCompositionPopover.tsx +0 -192
  849. package/corpus/templates/videos/app/components/PropsEditor.tsx +0 -210
  850. package/corpus/templates/videos/app/components/QuestionFlow.tsx +0 -40
  851. package/corpus/templates/videos/app/components/Sidebar.tsx +0 -609
  852. package/corpus/templates/videos/app/components/StudioHeader.tsx +0 -109
  853. package/corpus/templates/videos/app/components/Timeline.tsx +0 -2067
  854. package/corpus/templates/videos/app/components/TrackPropertiesPanel.tsx +0 -922
  855. package/corpus/templates/videos/app/components/TweaksPanel.tsx +0 -277
  856. package/corpus/templates/videos/app/components/VideoPlayer.tsx +0 -487
  857. package/corpus/templates/videos/app/components/design-system/DesignSystemCard.tsx +0 -134
  858. package/corpus/templates/videos/app/components/design-system/DesignSystemPreview.tsx +0 -176
  859. package/corpus/templates/videos/app/components/design-system/DesignSystemSetup.tsx +0 -707
  860. package/corpus/templates/videos/app/components/keyframes/KeyframeActionButtons.tsx +0 -78
  861. package/corpus/templates/videos/app/components/keyframes/KeyframeNavigation.tsx +0 -59
  862. package/corpus/templates/videos/app/components/keyframes/PropertyNumberInput.tsx +0 -56
  863. package/corpus/templates/videos/app/components/layout/Header.tsx +0 -64
  864. package/corpus/templates/videos/app/components/layout/HeaderActions.tsx +0 -84
  865. package/corpus/templates/videos/app/components/layout/Layout.tsx +0 -132
  866. package/corpus/templates/videos/app/components/layout/NavSidebar.tsx +0 -180
  867. package/corpus/templates/videos/app/components/ui/accordion.tsx +0 -56
  868. package/corpus/templates/videos/app/components/ui/alert-dialog.tsx +0 -139
  869. package/corpus/templates/videos/app/components/ui/alert.tsx +0 -59
  870. package/corpus/templates/videos/app/components/ui/aspect-ratio.tsx +0 -5
  871. package/corpus/templates/videos/app/components/ui/avatar.tsx +0 -48
  872. package/corpus/templates/videos/app/components/ui/badge.tsx +0 -37
  873. package/corpus/templates/videos/app/components/ui/breadcrumb.tsx +0 -115
  874. package/corpus/templates/videos/app/components/ui/button.tsx +0 -57
  875. package/corpus/templates/videos/app/components/ui/calendar.tsx +0 -68
  876. package/corpus/templates/videos/app/components/ui/card.tsx +0 -86
  877. package/corpus/templates/videos/app/components/ui/carousel.tsx +0 -260
  878. package/corpus/templates/videos/app/components/ui/chart.tsx +0 -375
  879. package/corpus/templates/videos/app/components/ui/checkbox.tsx +0 -28
  880. package/corpus/templates/videos/app/components/ui/collapsible.tsx +0 -9
  881. package/corpus/templates/videos/app/components/ui/command.tsx +0 -154
  882. package/corpus/templates/videos/app/components/ui/context-menu.tsx +0 -202
  883. package/corpus/templates/videos/app/components/ui/dialog.tsx +0 -130
  884. package/corpus/templates/videos/app/components/ui/drawer.tsx +0 -116
  885. package/corpus/templates/videos/app/components/ui/dropdown-menu.tsx +0 -212
  886. package/corpus/templates/videos/app/components/ui/form.tsx +0 -177
  887. package/corpus/templates/videos/app/components/ui/hover-card.tsx +0 -27
  888. package/corpus/templates/videos/app/components/ui/input-otp.tsx +0 -69
  889. package/corpus/templates/videos/app/components/ui/input.tsx +0 -22
  890. package/corpus/templates/videos/app/components/ui/label.tsx +0 -24
  891. package/corpus/templates/videos/app/components/ui/menubar.tsx +0 -234
  892. package/corpus/templates/videos/app/components/ui/navigation-menu.tsx +0 -128
  893. package/corpus/templates/videos/app/components/ui/pagination.tsx +0 -121
  894. package/corpus/templates/videos/app/components/ui/popover.tsx +0 -44
  895. package/corpus/templates/videos/app/components/ui/progress.tsx +0 -26
  896. package/corpus/templates/videos/app/components/ui/radio-group.tsx +0 -42
  897. package/corpus/templates/videos/app/components/ui/resizable.tsx +0 -43
  898. package/corpus/templates/videos/app/components/ui/scroll-area.tsx +0 -46
  899. package/corpus/templates/videos/app/components/ui/select.tsx +0 -158
  900. package/corpus/templates/videos/app/components/ui/separator.tsx +0 -29
  901. package/corpus/templates/videos/app/components/ui/sheet.tsx +0 -160
  902. package/corpus/templates/videos/app/components/ui/sidebar.tsx +0 -782
  903. package/corpus/templates/videos/app/components/ui/skeleton.tsx +0 -15
  904. package/corpus/templates/videos/app/components/ui/slider.tsx +0 -26
  905. package/corpus/templates/videos/app/components/ui/sonner.tsx +0 -58
  906. package/corpus/templates/videos/app/components/ui/spinner.tsx +0 -17
  907. package/corpus/templates/videos/app/components/ui/switch.tsx +0 -27
  908. package/corpus/templates/videos/app/components/ui/table.tsx +0 -117
  909. package/corpus/templates/videos/app/components/ui/tabs.tsx +0 -53
  910. package/corpus/templates/videos/app/components/ui/textarea.tsx +0 -23
  911. package/corpus/templates/videos/app/components/ui/toast.tsx +0 -127
  912. package/corpus/templates/videos/app/components/ui/toaster.tsx +0 -33
  913. package/corpus/templates/videos/app/components/ui/toggle-group.tsx +0 -59
  914. package/corpus/templates/videos/app/components/ui/toggle.tsx +0 -43
  915. package/corpus/templates/videos/app/components/ui/tooltip.tsx +0 -30
  916. package/corpus/templates/videos/app/components/ui/use-toast.ts +0 -3
  917. package/corpus/templates/videos/app/config/constants.ts +0 -204
  918. package/corpus/templates/videos/app/contexts/CompositionContext.tsx +0 -437
  919. package/corpus/templates/videos/app/contexts/CurrentElementContext.tsx +0 -247
  920. package/corpus/templates/videos/app/contexts/PlaybackContext.tsx +0 -65
  921. package/corpus/templates/videos/app/contexts/TimelineContext.tsx +0 -433
  922. package/corpus/templates/videos/app/entry.client.tsx +0 -19
  923. package/corpus/templates/videos/app/entry.server.tsx +0 -10
  924. package/corpus/templates/videos/app/global.css +0 -171
  925. package/corpus/templates/videos/app/hooks/use-composition-collab.ts +0 -269
  926. package/corpus/templates/videos/app/hooks/use-composition-design-system.ts +0 -47
  927. package/corpus/templates/videos/app/hooks/use-database-compositions.ts +0 -144
  928. package/corpus/templates/videos/app/hooks/use-db-status.ts +0 -30
  929. package/corpus/templates/videos/app/hooks/use-design-systems.ts +0 -21
  930. package/corpus/templates/videos/app/hooks/use-folders.ts +0 -199
  931. package/corpus/templates/videos/app/hooks/use-mobile.tsx +0 -21
  932. package/corpus/templates/videos/app/hooks/use-navigation-state.ts +0 -52
  933. package/corpus/templates/videos/app/hooks/use-question-flow.ts +0 -14
  934. package/corpus/templates/videos/app/hooks/use-toast.ts +0 -188
  935. package/corpus/templates/videos/app/hooks/useUnsavedChanges.ts +0 -48
  936. package/corpus/templates/videos/app/i18n/ar-SA.ts +0 -446
  937. package/corpus/templates/videos/app/i18n/de-DE.ts +0 -470
  938. package/corpus/templates/videos/app/i18n/en-US.ts +0 -452
  939. package/corpus/templates/videos/app/i18n/es-ES.ts +0 -468
  940. package/corpus/templates/videos/app/i18n/fr-FR.ts +0 -469
  941. package/corpus/templates/videos/app/i18n/hi-IN.ts +0 -446
  942. package/corpus/templates/videos/app/i18n/index.ts +0 -34
  943. package/corpus/templates/videos/app/i18n/ja-JP.ts +0 -460
  944. package/corpus/templates/videos/app/i18n/ko-KR.ts +0 -453
  945. package/corpus/templates/videos/app/i18n/pt-BR.ts +0 -461
  946. package/corpus/templates/videos/app/i18n/zh-CN.ts +0 -437
  947. package/corpus/templates/videos/app/i18n/zh-TW.ts +0 -437
  948. package/corpus/templates/videos/app/lib/database-compositions.ts +0 -67
  949. package/corpus/templates/videos/app/lib/design-systems.ts +0 -234
  950. package/corpus/templates/videos/app/lib/tab-id.ts +0 -1
  951. package/corpus/templates/videos/app/lib/utils.ts +0 -1
  952. package/corpus/templates/videos/app/pages/ComponentLibrary.tsx +0 -134
  953. package/corpus/templates/videos/app/pages/ComponentLibraryView.tsx +0 -362
  954. package/corpus/templates/videos/app/pages/CompositionView.tsx +0 -715
  955. package/corpus/templates/videos/app/pages/DesignSystems.tsx +0 -180
  956. package/corpus/templates/videos/app/pages/Index.tsx +0 -258
  957. package/corpus/templates/videos/app/pages/NewComposition.tsx +0 -95
  958. package/corpus/templates/videos/app/pages/NotFound.tsx +0 -36
  959. package/corpus/templates/videos/app/remotion/CameraHost.tsx +0 -223
  960. package/corpus/templates/videos/app/remotion/animations/useElementAnimations.ts +0 -231
  961. package/corpus/templates/videos/app/remotion/componentRegistry.ts +0 -473
  962. package/corpus/templates/videos/app/remotion/components/AnimatedElement.tsx +0 -436
  963. package/corpus/templates/videos/app/remotion/components/InteractiveElement.tsx +0 -159
  964. package/corpus/templates/videos/app/remotion/components/InteractiveZoneEditor.tsx +0 -273
  965. package/corpus/templates/videos/app/remotion/compositions/BlankComposition.tsx +0 -204
  966. package/corpus/templates/videos/app/remotion/compositions/index.ts +0 -2
  967. package/corpus/templates/videos/app/remotion/createComponentCursorTrack.ts +0 -132
  968. package/corpus/templates/videos/app/remotion/docs/CURSOR_TRACKS.md +0 -285
  969. package/corpus/templates/videos/app/remotion/easingFunctions.ts +0 -255
  970. package/corpus/templates/videos/app/remotion/hooks/createInteractiveComposition.tsx +0 -283
  971. package/corpus/templates/videos/app/remotion/hooks/useCursorHistory.ts +0 -72
  972. package/corpus/templates/videos/app/remotion/hooks/useCursorTypeFromHover.ts +0 -35
  973. package/corpus/templates/videos/app/remotion/hooks/useEditableZones.tsx +0 -267
  974. package/corpus/templates/videos/app/remotion/hooks/useHoverAnimation.ts +0 -90
  975. package/corpus/templates/videos/app/remotion/hooks/useHoverAnimationSmooth.ts +0 -146
  976. package/corpus/templates/videos/app/remotion/hooks/useInteractiveComponent.ts +0 -711
  977. package/corpus/templates/videos/app/remotion/hooks/useRegisterInteractiveElement.ts +0 -56
  978. package/corpus/templates/videos/app/remotion/library-components/Button.tsx +0 -252
  979. package/corpus/templates/videos/app/remotion/library-components/Card.tsx +0 -241
  980. package/corpus/templates/videos/app/remotion/library-components/CodePanel.tsx +0 -1005
  981. package/corpus/templates/videos/app/remotion/library-components/FileItem.tsx +0 -196
  982. package/corpus/templates/videos/app/remotion/library-components/FolderItem.tsx +0 -199
  983. package/corpus/templates/videos/app/remotion/library-components/PrimaryButton.tsx +0 -177
  984. package/corpus/templates/videos/app/remotion/library-components/SecondaryButton.tsx +0 -167
  985. package/corpus/templates/videos/app/remotion/library-components/SectionHeader.tsx +0 -108
  986. package/corpus/templates/videos/app/remotion/library-components/TEMPLATE.tsx +0 -211
  987. package/corpus/templates/videos/app/remotion/library-components/index.ts +0 -10
  988. package/corpus/templates/videos/app/remotion/registry.ts +0 -91
  989. package/corpus/templates/videos/app/remotion/testing/animationTestUtils.ts +0 -366
  990. package/corpus/templates/videos/app/remotion/trackAnimation.ts +0 -179
  991. package/corpus/templates/videos/app/remotion/trackHelpers.ts +0 -110
  992. package/corpus/templates/videos/app/remotion/ui-components/Cursor.tsx +0 -182
  993. package/corpus/templates/videos/app/remotion/ui-components/InteractiveButton.tsx +0 -116
  994. package/corpus/templates/videos/app/remotion/ui-components/InteractiveCard.tsx +0 -126
  995. package/corpus/templates/videos/app/remotion/ui-components/index.ts +0 -16
  996. package/corpus/templates/videos/app/remotion/utils/animationHelpers.ts +0 -444
  997. package/corpus/templates/videos/app/remotion/utils/interactiveElements.ts +0 -235
  998. package/corpus/templates/videos/app/remotion/utils/springAnimation.ts +0 -76
  999. package/corpus/templates/videos/app/root.tsx +0 -165
  1000. package/corpus/templates/videos/app/routes/$.tsx +0 -10
  1001. package/corpus/templates/videos/app/routes/_index.tsx +0 -25
  1002. package/corpus/templates/videos/app/routes/c.$compositionId.tsx +0 -10
  1003. package/corpus/templates/videos/app/routes/components.tsx +0 -10
  1004. package/corpus/templates/videos/app/routes/design-systems.tsx +0 -10
  1005. package/corpus/templates/videos/app/routes/extensions.$id.$slug.tsx +0 -2
  1006. package/corpus/templates/videos/app/routes/extensions.$id.tsx +0 -5
  1007. package/corpus/templates/videos/app/routes/extensions._index.tsx +0 -5
  1008. package/corpus/templates/videos/app/routes/extensions.tsx +0 -5
  1009. package/corpus/templates/videos/app/routes/settings.tsx +0 -88
  1010. package/corpus/templates/videos/app/routes/team.tsx +0 -11
  1011. package/corpus/templates/videos/app/routes.ts +0 -4
  1012. package/corpus/templates/videos/app/state.ts +0 -77
  1013. package/corpus/templates/videos/app/types/elementAnimations.ts +0 -121
  1014. package/corpus/templates/videos/app/types.ts +0 -200
  1015. package/corpus/templates/videos/app/utils/compositionHelpers.ts +0 -445
  1016. package/corpus/templates/videos/app/utils/debug.ts +0 -63
  1017. package/corpus/templates/videos/app/utils/keyframeUtils.ts +0 -331
  1018. package/corpus/templates/videos/app/utils/timelineCoordinates.ts +0 -79
  1019. package/corpus/templates/videos/app/vite-env.d.ts +0 -6
  1020. package/corpus/templates/videos/changelog/2026-06-24-a-new-settings-page-gives-quick-access-to-language-workspace.md +0 -6
  1021. package/corpus/templates/videos/changelog/2026-06-24-added-a-language-picker-and-localized-app-chrome-for-support.md +0 -6
  1022. package/corpus/templates/videos/changelog/2026-06-27-traditional-chinese-copy-uses-taiwan-terminology.md +0 -6
  1023. package/corpus/templates/videos/changelog/2026-06-28-left-sidebar-collapses-into-an-animated-icon-rail.md +0 -6
  1024. package/corpus/templates/videos/changelog/2026-06-29-video-layouts-adapt-when-the-agent-sidebar-is-open.md +0 -6
  1025. package/corpus/templates/videos/components.json +0 -20
  1026. package/corpus/templates/videos/data/sync-config.json +0 -3
  1027. package/corpus/templates/videos/docs/examples/create-composition.example.ts +0 -128
  1028. package/corpus/templates/videos/drizzle.config.ts +0 -3
  1029. package/corpus/templates/videos/learnings.defaults.md +0 -5
  1030. package/corpus/templates/videos/package.json +0 -114
  1031. package/corpus/templates/videos/public/agent-native-icon-dark.svg +0 -10
  1032. package/corpus/templates/videos/public/agent-native-icon-light.svg +0 -10
  1033. package/corpus/templates/videos/public/agent-native-logo-dark.svg +0 -21
  1034. package/corpus/templates/videos/public/agent-native-logo-light.svg +0 -21
  1035. package/corpus/templates/videos/public/favicon.svg +0 -1
  1036. package/corpus/templates/videos/public/icon-180.svg +0 -1
  1037. package/corpus/templates/videos/public/icon-192.svg +0 -1
  1038. package/corpus/templates/videos/public/icon-512.svg +0 -1
  1039. package/corpus/templates/videos/public/manifest.json +0 -21
  1040. package/corpus/templates/videos/public/placeholder.svg +0 -1
  1041. package/corpus/templates/videos/public/robots.txt +0 -14
  1042. package/corpus/templates/videos/react-router.config.ts +0 -7
  1043. package/corpus/templates/videos/server/db/index.ts +0 -37
  1044. package/corpus/templates/videos/server/db/schema.ts +0 -55
  1045. package/corpus/templates/videos/server/middleware/auth.ts +0 -15
  1046. package/corpus/templates/videos/server/plugins/agent-chat.ts +0 -29
  1047. package/corpus/templates/videos/server/plugins/auth.ts +0 -14
  1048. package/corpus/templates/videos/server/plugins/collab.ts +0 -11
  1049. package/corpus/templates/videos/server/plugins/core-routes.ts +0 -22
  1050. package/corpus/templates/videos/server/plugins/db.ts +0 -160
  1051. package/corpus/templates/videos/server/routes/[...page].get.ts +0 -5
  1052. package/corpus/templates/videos/server/routes/[...page].head.ts +0 -1
  1053. package/corpus/templates/videos/server/routes/api/save-composition-defaults.post.ts +0 -274
  1054. package/corpus/templates/videos/shared/api.ts +0 -75
  1055. package/corpus/templates/videos/ssr-entry.ts +0 -15
  1056. package/corpus/templates/videos/tsconfig.json +0 -21
  1057. package/corpus/templates/videos/vite.config.ts +0 -19
  1058. package/corpus/templates/videos/vitest.config.ts +0 -16
  1059. package/docs/content/locales/ar-SA/template-videos.mdx +0 -336
  1060. package/docs/content/locales/de-DE/template-videos.mdx +0 -336
  1061. package/docs/content/locales/es-ES/template-videos.mdx +0 -336
  1062. package/docs/content/locales/fr-FR/template-videos.mdx +0 -336
  1063. package/docs/content/locales/hi-IN/template-videos.mdx +0 -336
  1064. package/docs/content/locales/ja-JP/template-videos.mdx +0 -336
  1065. package/docs/content/locales/ko-KR/template-videos.mdx +0 -336
  1066. package/docs/content/locales/pt-BR/template-videos.mdx +0 -336
  1067. package/docs/content/locales/zh-CN/template-videos.mdx +0 -334
  1068. package/docs/content/locales/zh-TW/template-videos.mdx +0 -334
  1069. package/docs/content/template-videos.mdx +0 -332
@@ -0,0 +1,147 @@
1
+ /**
2
+ * Surgical reconcile — apply an authoritative external document into the live
3
+ * editor by replacing only the changed top-level node run, instead of a
4
+ * whole-document `setContent`.
5
+ *
6
+ * Why: under the Collaboration extension, `setContent` routes through
7
+ * y-prosemirror and rewrites the ENTIRE `Y.XmlFragment`. Every block-level
8
+ * NodeView is torn down and recreated (each `ReactRenderer` constructor calls
9
+ * `flushSync`, firing inside a React lifecycle), remote carets jump, and the
10
+ * CRDT sees a delete-all + insert-all instead of a small edit. Diffing the
11
+ * top-level children and dispatching one `tr.replaceWith(from, to, changed)`
12
+ * leaves unchanged NodeViews untouched and produces minimal Yjs ops.
13
+ *
14
+ * This is the core mechanism behind re-enabling single-doc collab in the plan
15
+ * editor (see templates/plan/shared/plan-doc.collab-stability.spec.ts, "Option
16
+ * B") and removing agent-edit NodeView churn in content.
17
+ */
18
+ import { createNodeFromContent } from "@tiptap/core";
19
+ /**
20
+ * Transaction meta marking programmatic (non-user) rich-markdown transactions.
21
+ * Declared here (not in useCollabReconcile) so the module dependency stays
22
+ * one-directional; useCollabReconcile re-exports it for consumers.
23
+ */
24
+ export const RICH_MARKDOWN_PROGRAMMATIC_TRANSACTION = "an-rich-md-programmatic-transaction";
25
+ /**
26
+ * Diff two documents at top-level-node granularity: trim the common prefix and
27
+ * suffix (node equality via ProseMirror's `Node.eq`, which is deep) and return
28
+ * the remaining changed run. Returns null when the documents are equal.
29
+ */
30
+ export function diffTopLevel(oldDoc, newDoc) {
31
+ const oldCount = oldDoc.childCount;
32
+ const newCount = newDoc.childCount;
33
+ let prefix = 0;
34
+ const maxPrefix = Math.min(oldCount, newCount);
35
+ while (prefix < maxPrefix && oldDoc.child(prefix).eq(newDoc.child(prefix))) {
36
+ prefix++;
37
+ }
38
+ if (prefix === oldCount && prefix === newCount)
39
+ return null; // identical
40
+ let suffix = 0;
41
+ const maxSuffix = Math.min(oldCount, newCount) - prefix;
42
+ while (suffix < maxSuffix &&
43
+ oldDoc.child(oldCount - 1 - suffix).eq(newDoc.child(newCount - 1 - suffix))) {
44
+ suffix++;
45
+ }
46
+ const fromIndex = prefix;
47
+ const oldToIndex = oldCount - suffix;
48
+ const newToIndex = newCount - suffix;
49
+ // Positions: sum nodeSize of the preserved prefix, then of the changed run.
50
+ let fromPos = 0;
51
+ for (let i = 0; i < fromIndex; i++)
52
+ fromPos += oldDoc.child(i).nodeSize;
53
+ let toPos = fromPos;
54
+ for (let i = fromIndex; i < oldToIndex; i++) {
55
+ toPos += oldDoc.child(i).nodeSize;
56
+ }
57
+ return { fromIndex, oldToIndex, newToIndex, fromPos, toPos };
58
+ }
59
+ function changedFragment(newDoc, diff) {
60
+ return newDoc.content.cut(positionOfChild(newDoc, diff.fromIndex), positionOfChild(newDoc, diff.newToIndex));
61
+ }
62
+ function positionOfChild(doc, index) {
63
+ let pos = 0;
64
+ for (let i = 0; i < index; i++)
65
+ pos += doc.child(i).nodeSize;
66
+ return pos;
67
+ }
68
+ function isEmptyParagraph(node) {
69
+ return !!node && node.type.name === "paragraph" && node.content.size === 0;
70
+ }
71
+ /**
72
+ * Markdown can't represent a trailing empty paragraph (the cursor line users
73
+ * keep below a list/code block), so a parsed authoritative value never has
74
+ * one — but the live doc often does, and the legacy `setContent` path
75
+ * preserves it. Without this, every surgical reconcile whose old doc ends
76
+ * with an empty paragraph would DELETE the user's trailing cursor line.
77
+ */
78
+ function withPreservedTrailingParagraph(oldDoc, newDoc) {
79
+ const oldLast = oldDoc.childCount > 0 ? oldDoc.child(oldDoc.childCount - 1) : null;
80
+ if (!isEmptyParagraph(oldLast))
81
+ return newDoc;
82
+ const newLast = newDoc.childCount > 0 ? newDoc.child(newDoc.childCount - 1) : null;
83
+ if (isEmptyParagraph(newLast))
84
+ return newDoc;
85
+ return newDoc.copy(newDoc.content.addToEnd(oldLast.type.create()));
86
+ }
87
+ /**
88
+ * Replace only the changed top-level run of the live document with the
89
+ * corresponding run from `newDoc`, in one programmatic, history-free
90
+ * transaction. Returns:
91
+ * - "applied" — a targeted replacement was dispatched
92
+ * - "noop" — the documents were already equal (nothing dispatched)
93
+ * - "failed" — the diff/transaction could not be applied (schema mismatch,
94
+ * invalid content, …); caller should fall back to setContent.
95
+ */
96
+ export function applyDocSurgically(editor, newDoc) {
97
+ try {
98
+ const oldDoc = editor.state.doc;
99
+ // The parsed doc MUST come from this editor's schema — NodeType identity
100
+ // is per-Schema-instance, so a foreign-schema doc can never diff or apply.
101
+ if (newDoc.type.schema !== editor.schema || newDoc.type !== oldDoc.type) {
102
+ return "failed";
103
+ }
104
+ const target = withPreservedTrailingParagraph(oldDoc, newDoc);
105
+ const diff = diffTopLevel(oldDoc, target);
106
+ if (!diff)
107
+ return "noop";
108
+ const fragment = changedFragment(target, diff);
109
+ const tr = editor.state.tr;
110
+ tr.replaceWith(diff.fromPos, diff.toPos, fragment);
111
+ tr.setMeta("addToHistory", false);
112
+ tr.setMeta(RICH_MARKDOWN_PROGRAMMATIC_TRANSACTION, true);
113
+ editor.view.dispatch(tr);
114
+ return "applied";
115
+ }
116
+ catch {
117
+ return "failed";
118
+ }
119
+ }
120
+ /**
121
+ * Best-effort default parser for the surgical path: use the tiptap-markdown
122
+ * storage parser (present when the shared editor's `features.markdown` is on)
123
+ * to turn the authoritative markdown into a ProseMirror document. Returns null
124
+ * when unavailable or when parsing fails — the caller falls back to the full
125
+ * `setContent` path.
126
+ *
127
+ * Apps with their own serializers (Content's NFM, Plan's blocks[] doc) should
128
+ * pass an explicit `parseValue` producing the exact doc their `setContent`
129
+ * would have written.
130
+ */
131
+ export function defaultParseValue(editor, value) {
132
+ try {
133
+ const storage = editor.storage.markdown;
134
+ const parsed = storage?.parser?.parse?.(value, { inline: false });
135
+ if (typeof parsed !== "string" || !parsed)
136
+ return null;
137
+ const node = createNodeFromContent(parsed, editor.schema, {
138
+ slice: false,
139
+ });
140
+ // createNodeFromContent with slice:false returns a Node (the doc).
141
+ return node ?? null;
142
+ }
143
+ catch {
144
+ return null;
145
+ }
146
+ }
147
+ //# sourceMappingURL=surgical-apply.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"surgical-apply.js","sourceRoot":"","sources":["../../../src/client/rich-markdown-editor/surgical-apply.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Surgical reconcile — apply an authoritative external document into the live\n * editor by replacing only the changed top-level node run, instead of a\n * whole-document `setContent`.\n *\n * Why: under the Collaboration extension, `setContent` routes through\n * y-prosemirror and rewrites the ENTIRE `Y.XmlFragment`. Every block-level\n * NodeView is torn down and recreated (each `ReactRenderer` constructor calls\n * `flushSync`, firing inside a React lifecycle), remote carets jump, and the\n * CRDT sees a delete-all + insert-all instead of a small edit. Diffing the\n * top-level children and dispatching one `tr.replaceWith(from, to, changed)`\n * leaves unchanged NodeViews untouched and produces minimal Yjs ops.\n *\n * This is the core mechanism behind re-enabling single-doc collab in the plan\n * editor (see templates/plan/shared/plan-doc.collab-stability.spec.ts, \"Option\n * B\") and removing agent-edit NodeView churn in content.\n */\n\nimport { createNodeFromContent } from \"@tiptap/core\";\nimport type { Fragment, Node as ProseMirrorNode } from \"@tiptap/pm/model\";\nimport type { Editor } from \"@tiptap/react\";\n\n/**\n * Transaction meta marking programmatic (non-user) rich-markdown transactions.\n * Declared here (not in useCollabReconcile) so the module dependency stays\n * one-directional; useCollabReconcile re-exports it for consumers.\n */\nexport const RICH_MARKDOWN_PROGRAMMATIC_TRANSACTION =\n \"an-rich-md-programmatic-transaction\";\n\nexport interface TopLevelDiff {\n /** Index of the first differing top-level child. */\n fromIndex: number;\n /** Exclusive end index of the differing run in the OLD doc. */\n oldToIndex: number;\n /** Exclusive end index of the differing run in the NEW doc. */\n newToIndex: number;\n /** Document position where the differing run starts. */\n fromPos: number;\n /** Document position where the differing run ends in the OLD doc. */\n toPos: number;\n}\n\n/**\n * Diff two documents at top-level-node granularity: trim the common prefix and\n * suffix (node equality via ProseMirror's `Node.eq`, which is deep) and return\n * the remaining changed run. Returns null when the documents are equal.\n */\nexport function diffTopLevel(\n oldDoc: ProseMirrorNode,\n newDoc: ProseMirrorNode,\n): TopLevelDiff | null {\n const oldCount = oldDoc.childCount;\n const newCount = newDoc.childCount;\n\n let prefix = 0;\n const maxPrefix = Math.min(oldCount, newCount);\n while (prefix < maxPrefix && oldDoc.child(prefix).eq(newDoc.child(prefix))) {\n prefix++;\n }\n\n if (prefix === oldCount && prefix === newCount) return null; // identical\n\n let suffix = 0;\n const maxSuffix = Math.min(oldCount, newCount) - prefix;\n while (\n suffix < maxSuffix &&\n oldDoc.child(oldCount - 1 - suffix).eq(newDoc.child(newCount - 1 - suffix))\n ) {\n suffix++;\n }\n\n const fromIndex = prefix;\n const oldToIndex = oldCount - suffix;\n const newToIndex = newCount - suffix;\n\n // Positions: sum nodeSize of the preserved prefix, then of the changed run.\n let fromPos = 0;\n for (let i = 0; i < fromIndex; i++) fromPos += oldDoc.child(i).nodeSize;\n let toPos = fromPos;\n for (let i = fromIndex; i < oldToIndex; i++) {\n toPos += oldDoc.child(i).nodeSize;\n }\n\n return { fromIndex, oldToIndex, newToIndex, fromPos, toPos };\n}\n\nfunction changedFragment(\n newDoc: ProseMirrorNode,\n diff: TopLevelDiff,\n): Fragment {\n return newDoc.content.cut(\n positionOfChild(newDoc, diff.fromIndex),\n positionOfChild(newDoc, diff.newToIndex),\n );\n}\n\nfunction positionOfChild(doc: ProseMirrorNode, index: number): number {\n let pos = 0;\n for (let i = 0; i < index; i++) pos += doc.child(i).nodeSize;\n return pos;\n}\n\nfunction isEmptyParagraph(node: ProseMirrorNode | null): boolean {\n return !!node && node.type.name === \"paragraph\" && node.content.size === 0;\n}\n\n/**\n * Markdown can't represent a trailing empty paragraph (the cursor line users\n * keep below a list/code block), so a parsed authoritative value never has\n * one — but the live doc often does, and the legacy `setContent` path\n * preserves it. Without this, every surgical reconcile whose old doc ends\n * with an empty paragraph would DELETE the user's trailing cursor line.\n */\nfunction withPreservedTrailingParagraph(\n oldDoc: ProseMirrorNode,\n newDoc: ProseMirrorNode,\n): ProseMirrorNode {\n const oldLast =\n oldDoc.childCount > 0 ? oldDoc.child(oldDoc.childCount - 1) : null;\n if (!isEmptyParagraph(oldLast)) return newDoc;\n const newLast =\n newDoc.childCount > 0 ? newDoc.child(newDoc.childCount - 1) : null;\n if (isEmptyParagraph(newLast)) return newDoc;\n return newDoc.copy(newDoc.content.addToEnd(oldLast!.type.create()));\n}\n\n/**\n * Replace only the changed top-level run of the live document with the\n * corresponding run from `newDoc`, in one programmatic, history-free\n * transaction. Returns:\n * - \"applied\" — a targeted replacement was dispatched\n * - \"noop\" — the documents were already equal (nothing dispatched)\n * - \"failed\" — the diff/transaction could not be applied (schema mismatch,\n * invalid content, …); caller should fall back to setContent.\n */\nexport function applyDocSurgically(\n editor: Editor,\n newDoc: ProseMirrorNode,\n): \"applied\" | \"noop\" | \"failed\" {\n try {\n const oldDoc = editor.state.doc;\n // The parsed doc MUST come from this editor's schema — NodeType identity\n // is per-Schema-instance, so a foreign-schema doc can never diff or apply.\n if (newDoc.type.schema !== editor.schema || newDoc.type !== oldDoc.type) {\n return \"failed\";\n }\n\n const target = withPreservedTrailingParagraph(oldDoc, newDoc);\n const diff = diffTopLevel(oldDoc, target);\n if (!diff) return \"noop\";\n\n const fragment = changedFragment(target, diff);\n const tr = editor.state.tr;\n tr.replaceWith(diff.fromPos, diff.toPos, fragment);\n tr.setMeta(\"addToHistory\", false);\n tr.setMeta(RICH_MARKDOWN_PROGRAMMATIC_TRANSACTION, true);\n editor.view.dispatch(tr);\n return \"applied\";\n } catch {\n return \"failed\";\n }\n}\n\n/**\n * Best-effort default parser for the surgical path: use the tiptap-markdown\n * storage parser (present when the shared editor's `features.markdown` is on)\n * to turn the authoritative markdown into a ProseMirror document. Returns null\n * when unavailable or when parsing fails — the caller falls back to the full\n * `setContent` path.\n *\n * Apps with their own serializers (Content's NFM, Plan's blocks[] doc) should\n * pass an explicit `parseValue` producing the exact doc their `setContent`\n * would have written.\n */\nexport function defaultParseValue(\n editor: Editor,\n value: string,\n): ProseMirrorNode | null {\n try {\n const storage = (editor.storage as Record<string, any>).markdown;\n const parsed = storage?.parser?.parse?.(value, { inline: false });\n if (typeof parsed !== \"string\" || !parsed) return null;\n const node = createNodeFromContent(parsed, editor.schema, {\n slice: false,\n });\n // createNodeFromContent with slice:false returns a Node (the doc).\n return (node as ProseMirrorNode) ?? null;\n } catch {\n return null;\n }\n}\n"]}
@@ -1,9 +1,11 @@
1
+ import type { Node as ProseMirrorNode } from "@tiptap/pm/model";
1
2
  import type { Transaction } from "@tiptap/pm/state";
2
3
  import type { Editor } from "@tiptap/react";
3
4
  import { type MutableRefObject } from "react";
4
5
  import type { Awareness } from "y-protocols/awareness";
5
6
  import type { Doc as YDoc } from "yjs";
6
- export declare const RICH_MARKDOWN_PROGRAMMATIC_TRANSACTION = "an-rich-md-programmatic-transaction";
7
+ import { RICH_MARKDOWN_PROGRAMMATIC_TRANSACTION } from "./surgical-apply.js";
8
+ export { RICH_MARKDOWN_PROGRAMMATIC_TRANSACTION };
7
9
  /** Reads the current markdown out of the tiptap-markdown storage. */
8
10
  export declare function getEditorMarkdown(editor: Editor): string;
9
11
  export interface UseCollabReconcileOptions {
@@ -38,6 +40,20 @@ export interface UseCollabReconcileOptions {
38
40
  emitUpdate?: boolean;
39
41
  addToHistory?: boolean;
40
42
  }) => void;
43
+ /**
44
+ * Parses the authoritative `value` into a full ProseMirror document for the
45
+ * SURGICAL reconcile path: instead of a whole-document `setContent` (which
46
+ * under Collaboration rewrites the entire Y.XmlFragment and tears down every
47
+ * block NodeView), the reconcile diffs the parsed doc against the live doc
48
+ * and replaces only the changed top-level run. Return null to skip the
49
+ * surgical path for a given value (falls back to `setContent`).
50
+ *
51
+ * Defaults to a best-effort tiptap-markdown parse; apps with their own
52
+ * serializers (Content's NFM, Plan's blocks[] doc) should supply the exact
53
+ * doc their `setContent` would write. Pass `false` to disable surgical
54
+ * application entirely.
55
+ */
56
+ parseValue?: ((editor: Editor, value: string) => ProseMirrorNode | null) | false;
41
57
  /**
42
58
  * Normalizes the authoritative `value` to the canonical markdown the editor
43
59
  * would emit, so the "already in sync / our own echo" equality checks match a
@@ -88,5 +104,5 @@ export interface UseCollabReconcileResult {
88
104
  */
89
105
  registerEmitted: (markdown: string) => boolean;
90
106
  }
91
- export declare function useCollabReconcile({ editor, ydoc, awareness, value, contentUpdatedAt, editable, getMarkdown, setContent, normalizeValue, shouldSeed, initialAppliedUpdatedAt, }: UseCollabReconcileOptions): UseCollabReconcileResult;
107
+ export declare function useCollabReconcile({ editor, ydoc, awareness, value, contentUpdatedAt, editable, getMarkdown, setContent, parseValue, normalizeValue, shouldSeed, initialAppliedUpdatedAt, }: UseCollabReconcileOptions): UseCollabReconcileResult;
92
108
  //# sourceMappingURL=useCollabReconcile.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useCollabReconcile.d.ts","sourceRoot":"","sources":["../../../src/client/rich-markdown-editor/useCollabReconcile.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAA+B,KAAK,gBAAgB,EAAE,MAAM,OAAO,CAAC;AAC3E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,KAAK,EAAE,GAAG,IAAI,IAAI,EAAE,MAAM,KAAK,CAAC;AAKvC,eAAO,MAAM,sCAAsC,wCACZ,CAAC;AAExC,qEAAqE;AACrE,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAKxD;AAqBD,MAAM,WAAW,yBAAyB;IACxC,gDAAgD;IAChD,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,uEAAuE;IACvE,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IACnB,8DAA8D;IAC9D,SAAS,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;IAC7B,0DAA0D;IAC1D,KAAK,EAAE,MAAM,CAAC;IACd,wEAAwE;IACxE,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,qFAAqF;IACrF,QAAQ,EAAE,OAAO,CAAC;IAClB;;;;;OAKG;IACH,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,CAAC;IACzC;;;;;;;OAOG;IACH,UAAU,CAAC,EAAE,CACX,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,EACb,OAAO,EAAE;QAAE,UAAU,CAAC,EAAE,OAAO,CAAC;QAAC,YAAY,CAAC,EAAE,OAAO,CAAA;KAAE,KACtD,IAAI,CAAC;IACV;;;;;OAKG;IACH,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IAC3C;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE;QAClB,KAAK,EAAE,MAAM,CAAC;QACd,eAAe,EAAE,MAAM,CAAC;QACxB,cAAc,EAAE,MAAM,CAAC;KACxB,KAAK,OAAO,CAAC;IACd;;;;;;;OAOG;IACH,uBAAuB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACzC;AAED,MAAM,WAAW,wBAAwB;IACvC,iEAAiE;IACjE,MAAM,EAAE,OAAO,CAAC;IAChB;;;OAGG;IACH,mBAAmB,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAC;IAC/C;;;;OAIG;IACH,kBAAkB,EAAE,CAAC,WAAW,EAAE,WAAW,KAAK,OAAO,CAAC;IAC1D;;;;OAIG;IACH,eAAe,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC;CAChD;AAoED,wBAAgB,kBAAkB,CAAC,EACjC,MAAM,EACN,IAAW,EACX,SAAgB,EAChB,KAAK,EACL,gBAAgB,EAChB,QAAQ,EACR,WAA+B,EAC/B,UAA8B,EAC9B,cAAyB,EACzB,UAA8B,EAC9B,uBAAuB,GACxB,EAAE,yBAAyB,GAAG,wBAAwB,CAyTtD"}
1
+ {"version":3,"file":"useCollabReconcile.d.ts","sourceRoot":"","sources":["../../../src/client/rich-markdown-editor/useCollabReconcile.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,IAAI,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAChE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAA+B,KAAK,gBAAgB,EAAE,MAAM,OAAO,CAAC;AAC3E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,KAAK,EAAE,GAAG,IAAI,IAAI,EAAE,MAAM,KAAK,CAAC;AAIvC,OAAO,EACL,sCAAsC,EAGvC,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,sCAAsC,EAAE,CAAC;AAElD,qEAAqE;AACrE,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAKxD;AAqBD,MAAM,WAAW,yBAAyB;IACxC,gDAAgD;IAChD,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,uEAAuE;IACvE,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IACnB,8DAA8D;IAC9D,SAAS,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;IAC7B,0DAA0D;IAC1D,KAAK,EAAE,MAAM,CAAC;IACd,wEAAwE;IACxE,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,qFAAqF;IACrF,QAAQ,EAAE,OAAO,CAAC;IAClB;;;;;OAKG;IACH,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,CAAC;IACzC;;;;;;;OAOG;IACH,UAAU,CAAC,EAAE,CACX,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,EACb,OAAO,EAAE;QAAE,UAAU,CAAC,EAAE,OAAO,CAAC;QAAC,YAAY,CAAC,EAAE,OAAO,CAAA;KAAE,KACtD,IAAI,CAAC;IACV;;;;;;;;;;;;OAYG;IACH,UAAU,CAAC,EACP,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,eAAe,GAAG,IAAI,CAAC,GAC3D,KAAK,CAAC;IACV;;;;;OAKG;IACH,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IAC3C;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE;QAClB,KAAK,EAAE,MAAM,CAAC;QACd,eAAe,EAAE,MAAM,CAAC;QACxB,cAAc,EAAE,MAAM,CAAC;KACxB,KAAK,OAAO,CAAC;IACd;;;;;;;OAOG;IACH,uBAAuB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACzC;AAED,MAAM,WAAW,wBAAwB;IACvC,iEAAiE;IACjE,MAAM,EAAE,OAAO,CAAC;IAChB;;;OAGG;IACH,mBAAmB,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAC;IAC/C;;;;OAIG;IACH,kBAAkB,EAAE,CAAC,WAAW,EAAE,WAAW,KAAK,OAAO,CAAC;IAC1D;;;;OAIG;IACH,eAAe,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC;CAChD;AAoED,wBAAgB,kBAAkB,CAAC,EACjC,MAAM,EACN,IAAW,EACX,SAAgB,EAChB,KAAK,EACL,gBAAgB,EAChB,QAAQ,EACR,WAA+B,EAC/B,UAA8B,EAC9B,UAAU,EACV,cAAyB,EACzB,UAA8B,EAC9B,uBAAuB,GACxB,EAAE,yBAAyB,GAAG,wBAAwB,CAsVtD"}
@@ -2,7 +2,8 @@ import { isChangeOrigin } from "@tiptap/extension-collaboration";
2
2
  import { useEffect, useRef, useState } from "react";
3
3
  import { AGENT_CLIENT_ID } from "../../collab/agent-identity.js";
4
4
  import { isReconcileLeadClient } from "../../collab/client.js";
5
- export const RICH_MARKDOWN_PROGRAMMATIC_TRANSACTION = "an-rich-md-programmatic-transaction";
5
+ import { RICH_MARKDOWN_PROGRAMMATIC_TRANSACTION, applyDocSurgically, defaultParseValue, } from "./surgical-apply.js";
6
+ export { RICH_MARKDOWN_PROGRAMMATIC_TRANSACTION };
6
7
  /** Reads the current markdown out of the tiptap-markdown storage. */
7
8
  export function getEditorMarkdown(editor) {
8
9
  const markdownStorage = editor.storage;
@@ -83,7 +84,7 @@ function defaultSetContent(editor, value, options) {
83
84
  }
84
85
  editor.commands.setContent(value);
85
86
  }
86
- export function useCollabReconcile({ editor, ydoc = null, awareness = null, value, contentUpdatedAt, editable, getMarkdown = getEditorMarkdown, setContent = defaultSetContent, normalizeValue = (v) => v, shouldSeed = defaultShouldSeed, initialAppliedUpdatedAt, }) {
87
+ export function useCollabReconcile({ editor, ydoc = null, awareness = null, value, contentUpdatedAt, editable, getMarkdown = getEditorMarkdown, setContent = defaultSetContent, parseValue, normalizeValue = (v) => v, shouldSeed = defaultShouldSeed, initialAppliedUpdatedAt, }) {
87
88
  const collab = !!ydoc;
88
89
  const isSettingContentRef = useRef(false);
89
90
  const lastEmittedRef = useRef("");
@@ -166,10 +167,21 @@ export function useCollabReconcile({ editor, ydoc = null, awareness = null, valu
166
167
  // Seed only when the shared doc is genuinely empty — either the fragment has
167
168
  // no nodes yet, or it holds no semantic markdown (an empty paragraph, or an
168
169
  // app's sentinel-empty filler via a custom `shouldSeed`).
169
- if (shouldSeed({ value, currentMarkdown, fragmentLength: fragment.length })) {
170
+ seededRef.current = true;
171
+ if (!shouldSeed({ value, currentMarkdown, fragmentLength: fragment.length })) {
172
+ return;
173
+ }
174
+ let cancelled = false;
175
+ queueMicrotask(() => {
176
+ if (cancelled || editor.isDestroyed)
177
+ return;
170
178
  isSettingContentRef.current = true;
171
- setContent(editor, value, {});
172
- isSettingContentRef.current = false;
179
+ try {
180
+ setContent(editor, value, {});
181
+ }
182
+ finally {
183
+ isSettingContentRef.current = false;
184
+ }
173
185
  const serialized = getMarkdown(editor);
174
186
  lastEmittedRef.current = serialized;
175
187
  pushEmittedRing(recentEmittedRef.current, serialized);
@@ -177,8 +189,10 @@ export function useCollabReconcile({ editor, ydoc = null, awareness = null, valu
177
189
  lastAppliedSerializedRef.current = serialized;
178
190
  if (contentUpdatedAt)
179
191
  lastAppliedUpdatedAtRef.current = contentUpdatedAt;
180
- }
181
- seededRef.current = true;
192
+ });
193
+ return () => {
194
+ cancelled = true;
195
+ };
182
196
  }, [
183
197
  collab,
184
198
  editor,
@@ -323,7 +337,23 @@ export function useCollabReconcile({ editor, ydoc = null, awareness = null, valu
323
337
  return;
324
338
  }
325
339
  isSettingContentRef.current = true;
326
- setContent(editor, value, { emitUpdate: false, addToHistory: false });
340
+ // Surgical path first: replace only the changed top-level run so
341
+ // unchanged block NodeViews are never torn down and (under
342
+ // Collaboration) Yjs sees a minimal edit instead of a full-fragment
343
+ // rewrite. Falls back to the classic whole-document setContent when no
344
+ // parser is available or the targeted transaction cannot be applied.
345
+ let appliedSurgically = false;
346
+ if (parseValue !== false) {
347
+ const parse = parseValue ?? defaultParseValue;
348
+ const parsedDoc = parse(editor, value);
349
+ if (parsedDoc) {
350
+ const result = applyDocSurgically(editor, parsedDoc);
351
+ appliedSurgically = result === "applied" || result === "noop";
352
+ }
353
+ }
354
+ if (!appliedSurgically) {
355
+ setContent(editor, value, { emitUpdate: false, addToHistory: false });
356
+ }
327
357
  isSettingContentRef.current = false;
328
358
  // Capture the SERIALIZED result, not the raw value. For non-idempotent
329
359
  // input these differ; recording the serialized output is what lets the
@@ -353,6 +383,7 @@ export function useCollabReconcile({ editor, ydoc = null, awareness = null, valu
353
383
  isLeadClient,
354
384
  getMarkdown,
355
385
  setContent,
386
+ parseValue,
356
387
  normalizeValue,
357
388
  ]);
358
389
  const shouldIgnoreUpdate = (transaction) => {
@@ -1 +1 @@
1
- {"version":3,"file":"useCollabReconcile.js","sourceRoot":"","sources":["../../../src/client/rich-markdown-editor/useCollabReconcile.ts"],"names":[],"mappings":"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","sourcesContent":["import { isChangeOrigin } from \"@tiptap/extension-collaboration\";\nimport type { Transaction } from \"@tiptap/pm/state\";\nimport type { Editor } from \"@tiptap/react\";\nimport { useEffect, useRef, useState, type MutableRefObject } from \"react\";\nimport type { Awareness } from \"y-protocols/awareness\";\nimport type { Doc as YDoc } from \"yjs\";\n\nimport { AGENT_CLIENT_ID } from \"../../collab/agent-identity.js\";\nimport { isReconcileLeadClient } from \"../../collab/client.js\";\n\nexport const RICH_MARKDOWN_PROGRAMMATIC_TRANSACTION =\n \"an-rich-md-programmatic-transaction\";\n\n/** Reads the current markdown out of the tiptap-markdown storage. */\nexport function getEditorMarkdown(editor: Editor): string {\n const markdownStorage = editor.storage as unknown as {\n markdown?: { getMarkdown?: () => string };\n };\n return markdownStorage.markdown?.getMarkdown?.() ?? \"\";\n}\n\n/**\n * Push a value onto the bounded ring of recently-emitted markdown (most recent\n * last, deduped, capped). The reconcile uses this to recognize a stale-but-recent\n * echo of OUR OWN edits: a debounced autosave can persist a PARTIAL burst, and\n * the next poll re-supplies that partial value with a newer timestamp — applying\n * it would clobber the freshly-typed tail. An external change (agent/peer) never\n * byte-matches one of our own recent emissions, and if it somehow did the content\n * is identical, so skipping it is safe by construction.\n */\nconst EMITTED_RING_MAX = 16;\nfunction pushEmittedRing(ring: string[], value: string): void {\n if (!value) return;\n if (ring[ring.length - 1] === value) return;\n const dupe = ring.indexOf(value);\n if (dupe !== -1) ring.splice(dupe, 1);\n ring.push(value);\n if (ring.length > EMITTED_RING_MAX) ring.shift();\n}\n\nexport interface UseCollabReconcileOptions {\n /** The live editor, or null until it mounts. */\n editor: Editor | null;\n /** Shared Y.Doc when collaborating; null disables all collab paths. */\n ydoc?: YDoc | null;\n /** Shared awareness; null keeps the sole-client lead path. */\n awareness?: Awareness | null;\n /** Authoritative markdown value (SQL source of truth). */\n value: string;\n /** Timestamp of the authoritative value; gates newer-than reconcile. */\n contentUpdatedAt?: string | null;\n /** Whether the editor accepts edits. Reconcile/seed only run for the live editor. */\n editable: boolean;\n /**\n * Reads the current markdown from the editor. Injected so a dialect could\n * swap serializers; defaults to the tiptap-markdown storage reader. For an app\n * with a custom serializer (e.g. Content's `docToNfm(editor.getJSON())`), pass\n * it here so the seed/reconcile equality checks compare like-for-like.\n */\n getMarkdown?: (editor: Editor) => string;\n /**\n * Applies the authoritative `value` into the editor. Defaults to passing the\n * raw markdown string to `editor.commands.setContent`. Apps whose serializer\n * is NOT tiptap-markdown (Content parses `nfmToDoc(value)` into a PM doc)\n * override this so seed + reconcile write the correct content shape. The\n * supplied `options` carry the history/whitespace flags the default path uses;\n * a custom implementation should forward them when relevant.\n */\n setContent?: (\n editor: Editor,\n value: string,\n options: { emitUpdate?: boolean; addToHistory?: boolean },\n ) => void;\n /**\n * Normalizes the authoritative `value` to the canonical markdown the editor\n * would emit, so the \"already in sync / our own echo\" equality checks match a\n * serializer that re-canonicalizes (Content's `canonicalizeNfm`). Defaults to\n * identity (GFM already round-trips byte-stably).\n */\n normalizeValue?: (value: string) => string;\n /**\n * Decides whether the empty-doc seed should run for the current shared\n * fragment. Defaults to \"fragment has no nodes, or the editor holds no\n * semantic markdown\". Apps with sentinel-empty content (Content's\n * `<empty-block/>` filler) override this. Receives the live fragment length\n * and the editor's current markdown.\n */\n shouldSeed?: (info: {\n value: string;\n currentMarkdown: string;\n fragmentLength: number;\n }) => boolean;\n /**\n * The initial \"applied\" watermark. Default mirrors `contentUpdatedAt`, so a\n * fresh mount whose Y.Doc already matches SQL doesn't re-apply. Pass `null`\n * to force the first reconcile pass to adopt authoritative SQL even at the\n * same timestamp — Content does this so a stale persisted Y.Doc (an agent that\n * edited the CLOSED doc) is corrected on open. The editor is keyed per\n * document upstream, so this only affects the first mount of each doc.\n */\n initialAppliedUpdatedAt?: string | null;\n}\n\nexport interface UseCollabReconcileResult {\n /** True when a Y.Doc is bound (collaborative editing active). */\n collab: boolean;\n /**\n * Set true around any programmatic `setContent` so the editor's `onUpdate`\n * can ignore the resulting transaction (it isn't a user edit).\n */\n isSettingContentRef: MutableRefObject<boolean>;\n /**\n * Call from `onUpdate` BEFORE serializing. Returns true when the update must\n * be ignored: editor not editable, mid-programmatic-setContent, or (in collab\n * mode) a remote-origin transaction. Also records the local typing time.\n */\n shouldIgnoreUpdate: (transaction: Transaction) => boolean;\n /**\n * Call from `onUpdate` AFTER computing the markdown to emit. Returns false\n * when the value must NOT be persisted yet (an empty collab doc before the\n * seed has run); records it as the last-emitted value otherwise.\n */\n registerEmitted: (markdown: string) => boolean;\n}\n\n/**\n * The subtle seed / reconcile / lead-client logic for the shared markdown\n * editor, extracted once so it can never be duplicated across embedders.\n *\n * Responsibilities (reproducing the Plan editor's behavior exactly):\n * - Track whether THIS client is the reconcile lead (sole client always leads;\n * otherwise elected via {@link isReconcileLeadClient}) and how many other\n * visible human peers are present.\n * - Seed an empty shared Y.Doc once from `value` — lead client only — so two\n * clients opening a brand-new block don't both insert the content.\n * - Reconcile authoritative external markdown (agent edit, source patch, peer\n * edit mirrored to SQL) into the editor: in collab mode only the lead client\n * applies it through `setContent` and Yjs propagates; in non-collab mode this\n * is the original controlled-value reconcile.\n * - Provide the `onUpdate` guards (`shouldIgnoreUpdate`, `registerEmitted`) so\n * the component never persists remote-origin or pre-seed empty content.\n */\n/** Default seed predicate: seed only when the shared doc is genuinely empty. */\nfunction defaultShouldSeed({\n currentMarkdown,\n fragmentLength,\n}: {\n value: string;\n currentMarkdown: string;\n fragmentLength: number;\n}): boolean {\n return fragmentLength === 0 || !currentMarkdown.trim();\n}\n\n/**\n * Default content writer: hand the raw markdown string to `setContent`, which\n * tiptap-markdown overrides to parse the markdown into a ProseMirror doc.\n *\n * IMPORTANT: do NOT pass `parseOptions: { preserveWhitespace: \"full\" }` here.\n * In tiptap v3 the core `setContent` command routes `preserveWhitespace: \"full\"`\n * through `insertContentAt`, which tiptap-markdown ALSO overrides to re-run its\n * markdown parser. That double-parse stringifies the already-parsed PM doc and\n * re-parses it as HTML, so a clean heading/list/code block comes back as the\n * escaped, non-idempotent `&lt;h1&gt;…` — which then escalates every reconcile\n * cycle (`<p>` → `&lt;p&gt;` → `&amp;lt;p&amp;gt;` …). Letting the markdown\n * override parse the string directly (no `parseOptions`) round-trips byte-stably\n * for the GFM corpus, including code-block and empty-line whitespace. Content's\n * NFM path supplies its own `setContent` (it passes a pre-parsed PM doc) and is\n * unaffected by this default.\n */\nfunction defaultSetContent(\n editor: Editor,\n value: string,\n options: { emitUpdate?: boolean; addToHistory?: boolean },\n): void {\n if (options.addToHistory === false) {\n editor\n .chain()\n .command(({ tr }) => {\n // addToHistory:false so cmd+z (or Yjs undo) doesn't erase\n // externally-loaded content.\n tr.setMeta(\"addToHistory\", false);\n return true;\n })\n .setContent(value, { emitUpdate: options.emitUpdate })\n .run();\n return;\n }\n editor.commands.setContent(value);\n}\n\nexport function useCollabReconcile({\n editor,\n ydoc = null,\n awareness = null,\n value,\n contentUpdatedAt,\n editable,\n getMarkdown = getEditorMarkdown,\n setContent = defaultSetContent,\n normalizeValue = (v) => v,\n shouldSeed = defaultShouldSeed,\n initialAppliedUpdatedAt,\n}: UseCollabReconcileOptions): UseCollabReconcileResult {\n const collab = !!ydoc;\n const isSettingContentRef = useRef(false);\n const lastEmittedRef = useRef(\"\");\n // Ring of recent local emissions (see pushEmittedRing). Lets the reconcile\n // recognize a stale-but-recent echo of our OWN (possibly partial, debounced)\n // save so a lagging poll never clobbers freshly-typed text.\n const recentEmittedRef = useRef<string[]>([]);\n const lastTypedAtRef = useRef(0);\n // The raw authoritative `value` string the reconcile last applied. When the\n // SAME raw string is re-fetched (a lagging poll, or a source-sync that keeps\n // re-supplying the same stored markdown), applying it again would only\n // reproduce the doc we already hold — and if `value` is NON-idempotent\n // (serialize(parse(value)) !== value) re-applying compounds the divergence\n // every cycle (`<p>` → `&lt;p&gt;` → `&amp;lt;p&amp;gt;` …). Tracked so the\n // identical re-fetch is recognized and skipped.\n const lastAppliedValueRef = useRef<string | null>(null);\n // The editor's SERIALIZED output captured right AFTER the last reconcile/seed\n // apply (`getMarkdown(editor)` once the content settled). For non-idempotent\n // input this is what autosave actually persists, so the NEXT poll hands it\n // back as the new `value`. Comparing the incoming value against this lets the\n // reconcile recognize its own echo even when the raw string changed once, so\n // it never re-parses content the editor already represents. This is the\n // doc-equivalence guard that breaks the escalation loop.\n const lastAppliedSerializedRef = useRef<string | null>(null);\n const lastAppliedUpdatedAtRef = useRef<string | null>(\n initialAppliedUpdatedAt !== undefined\n ? initialAppliedUpdatedAt\n : (contentUpdatedAt ?? null),\n );\n\n // Whether THIS client is the one that seeds the empty shared doc / applies an\n // authoritative external snapshot into it. Exactly one client does, so the\n // content isn't inserted once per open editor. A sole client always leads.\n const [isLeadClient, setIsLeadClient] = useState(true);\n // Count of OTHER visible human collaborators. When >0, a peer's edit also\n // arrives via Yjs, so external markdown reconcile must defer (avoid applying\n // the same change through both Yjs and setContent).\n const peerCountRef = useRef(0);\n useEffect(() => {\n if (!collab || !awareness || !ydoc) {\n setIsLeadClient(true);\n peerCountRef.current = 0;\n return;\n }\n const update = () => {\n setIsLeadClient(isReconcileLeadClient(awareness, ydoc.clientID));\n let peers = 0;\n awareness.getStates().forEach((state, clientId) => {\n if (clientId === ydoc.clientID) return; // self\n if (clientId === AGENT_CLIENT_ID) return; // agent isn't a Yjs editor\n const s = state as { user?: unknown; visible?: boolean };\n if (s && s.user && s.visible !== false) peers += 1;\n });\n peerCountRef.current = peers;\n };\n update();\n awareness.on(\"change\", update);\n document.addEventListener(\"visibilitychange\", update);\n return () => {\n awareness.off(\"change\", update);\n document.removeEventListener(\"visibilitychange\", update);\n };\n }, [collab, awareness, ydoc]);\n\n // Collab seed: populate an empty shared Y.Doc from the markdown `value` once.\n // The Collaboration extension does NOT auto-seed; only the lead client does,\n // so two clients opening a brand-new block at once don't both seed (which\n // would duplicate the content via concurrent inserts at the same position).\n const seededRef = useRef(false);\n useEffect(() => {\n if (!collab || !editor || editor.isDestroyed || !ydoc) return;\n if (seededRef.current) return;\n if (!isLeadClient) return;\n if (!value.trim()) return;\n const fragment = ydoc.getXmlFragment(\"default\");\n const currentMarkdown = getMarkdown(editor);\n // Seed only when the shared doc is genuinely empty — either the fragment has\n // no nodes yet, or it holds no semantic markdown (an empty paragraph, or an\n // app's sentinel-empty filler via a custom `shouldSeed`).\n if (\n shouldSeed({ value, currentMarkdown, fragmentLength: fragment.length })\n ) {\n isSettingContentRef.current = true;\n setContent(editor, value, {});\n isSettingContentRef.current = false;\n const serialized = getMarkdown(editor);\n lastEmittedRef.current = serialized;\n pushEmittedRing(recentEmittedRef.current, serialized);\n lastAppliedValueRef.current = value;\n lastAppliedSerializedRef.current = serialized;\n if (contentUpdatedAt) lastAppliedUpdatedAtRef.current = contentUpdatedAt;\n }\n seededRef.current = true;\n }, [\n collab,\n editor,\n ydoc,\n value,\n isLeadClient,\n contentUpdatedAt,\n getMarkdown,\n setContent,\n shouldSeed,\n ]);\n\n // Reconcile authoritative external markdown (agent edit, source patch, or a\n // peer edit mirrored to SQL) into the live editor. In collab mode only the\n // lead client applies it through setContent; Yjs propagates the result to\n // every other client. In non-collab mode this is the original controlled-value\n // reconcile, unchanged.\n useEffect(() => {\n if (!editor || editor.isDestroyed) return;\n\n let cancelled = false;\n let retry: ReturnType<typeof setTimeout> | null = null;\n // With peers present, a peer's edit also arrives via Yjs. Defer one poll\n // cycle (+margin) and re-check before applying via setContent so the same\n // change isn't inserted twice (Yjs + setContent → duplicated region).\n const PEER_SETTLE_MS = 2500;\n\n const apply = (deferred = false) => {\n if (cancelled || editor.isDestroyed) return;\n // In collab mode, defer all reconcile until the shared doc is seeded so we\n // never setContent over an unseeded fragment.\n if (collab && !seededRef.current) {\n retry = setTimeout(() => apply(deferred), 300);\n return;\n }\n const currentMarkdown = getMarkdown(editor);\n // Compare against the canonical form the editor would emit so a serializer\n // that re-normalizes (Content's NFM) still recognizes \"already in sync\".\n const normalizedValue = normalizeValue(value);\n // Whether the editor still holds exactly what THIS hook last applied (the\n // user hasn't edited since). Only then are the round-trip echo guards\n // below safe: if the user has since edited away from the applied content,\n // an external snapshot equal to a previously-applied value is a real\n // revert and must NOT be swallowed as an echo.\n const editorUnchangedSinceApply =\n lastAppliedSerializedRef.current !== null &&\n currentMarkdown === lastAppliedSerializedRef.current;\n\n // Doc-equivalence skip. Never re-apply content the editor already\n // represents — comparing by DOC EQUIVALENCE, not raw strings/timestamps:\n // 1. `currentMarkdown === normalizedValue` — the editor's CURRENT\n // serialized doc already equals the (normalized) incoming value.\n // 2. `value === lastEmittedRef.current` — the incoming value is our own\n // just-emitted markdown echoing back.\n // 3. `value === lastAppliedValueRef.current` — the SAME raw value we\n // already applied is being re-supplied (a lagging poll or a\n // source-sync re-handing the same stored markdown). Applying it again\n // would only reproduce the doc we hold; for NON-idempotent input it\n // would compound divergence. Guarded by `editorUnchangedSinceApply`\n // so a deliberate revert-to-previous after a local edit still lands.\n // 4. `normalizedValue === lastAppliedSerializedRef.current` — the\n // incoming value round-trips to the serialized output we last\n // produced (our own autosaved echo coming back from SQL). For\n // non-idempotent input the raw string differs from what we were\n // handed, but it is doc-equivalent to what the editor already shows,\n // so re-parsing it must be skipped. This is the guard that stops the\n // `<p>` → `&lt;p&gt;` → `&amp;lt;p&amp;gt;` escalation.\n if (\n currentMarkdown === normalizedValue ||\n value === lastEmittedRef.current ||\n // A stale-but-recent echo of our own (possibly partial) save — applying\n // it would clobber the freshly-typed tail. External edits never match.\n recentEmittedRef.current.includes(value) ||\n recentEmittedRef.current.includes(normalizedValue) ||\n (editorUnchangedSinceApply &&\n (value === lastAppliedValueRef.current ||\n normalizedValue === lastAppliedSerializedRef.current))\n ) {\n if (contentUpdatedAt) {\n lastAppliedUpdatedAtRef.current = contentUpdatedAt;\n }\n return;\n }\n\n const externalNewer =\n !lastAppliedUpdatedAtRef.current ||\n !contentUpdatedAt ||\n contentUpdatedAt > lastAppliedUpdatedAtRef.current;\n\n // Only the lead client applies an authoritative snapshot into the shared\n // Y.Doc; peers receive it through Yjs sync.\n if (collab && !isLeadClient) {\n if (contentUpdatedAt && !externalNewer) {\n lastAppliedUpdatedAtRef.current = contentUpdatedAt;\n }\n return;\n }\n\n // Never clobber an in-progress edit. While the user is actively typing\n // (focused and a keystroke landed within the window) defer and re-check —\n // applying external content now would yank text out from under them and,\n // for non-idempotent input, fight every keystroke. Newer external content\n // retries so it still lands once they pause; older-or-equal content is a\n // stale poll and is dropped outright while focused.\n const typingRecently =\n editor.isFocused && Date.now() - lastTypedAtRef.current < 1500;\n if (typingRecently) {\n if (externalNewer) {\n retry = setTimeout(() => apply(deferred), 700);\n }\n return;\n }\n // Older-or-equal content is a stale poll / lagging echo. Drop it while\n // focused (a peer/agent edit would be NEWER and retries above). In\n // NON-COLLAB mode there is no peer, so older-or-equal external content is\n // ALWAYS stale — dropping it regardless of focus stops a lagging\n // `get-visual-plan` poll from reverting a just-applied local structural\n // change (drag-to-columns) while the editor is blurred (the drag grips the\n // handle, not the prose, so `isFocused` is false at drop time). Gated on\n // `lastAppliedSerializedRef` so the very first seed (nothing applied yet,\n // also not-newer) still lands.\n const seeded = lastAppliedSerializedRef.current !== null;\n if (!externalNewer && (editor.isFocused || (!collab && seeded))) return;\n\n // Race guard: with peers present, let Yjs deliver a peer's edit first.\n // Defer once and re-check — a peer edit makes the equality check above\n // no-op next pass; an agent/source edit still differs and applies.\n if (collab && externalNewer && !deferred && peerCountRef.current > 0) {\n retry = setTimeout(() => apply(true), PEER_SETTLE_MS);\n return;\n }\n\n queueMicrotask(() => {\n if (cancelled || editor.isDestroyed) return;\n // Re-check doc-equivalence at apply time. Between the decision above and\n // this microtask a peer/Yjs edit (or our own prior apply) may have made\n // the editor already represent this value — re-applying would be a\n // wasted setContent that, for non-idempotent input, re-triggers the\n // loop. Skip when the editor's current serialization already matches the\n // normalized value, or the value round-trips to what we last produced.\n const beforeMarkdown = getMarkdown(editor);\n const normalized = normalizeValue(value);\n const unchangedSinceApply =\n lastAppliedSerializedRef.current !== null &&\n beforeMarkdown === lastAppliedSerializedRef.current;\n if (\n beforeMarkdown === normalized ||\n (unchangedSinceApply &&\n normalized === lastAppliedSerializedRef.current)\n ) {\n lastAppliedValueRef.current = value;\n if (contentUpdatedAt) {\n lastAppliedUpdatedAtRef.current = contentUpdatedAt;\n }\n return;\n }\n isSettingContentRef.current = true;\n setContent(editor, value, { emitUpdate: false, addToHistory: false });\n isSettingContentRef.current = false;\n // Capture the SERIALIZED result, not the raw value. For non-idempotent\n // input these differ; recording the serialized output is what lets the\n // next poll (which returns this serialized form) be recognized as our\n // own echo and skipped — stabilizing the doc after exactly one apply.\n const serialized = getMarkdown(editor);\n lastEmittedRef.current = serialized;\n pushEmittedRing(recentEmittedRef.current, serialized);\n lastAppliedValueRef.current = value;\n lastAppliedSerializedRef.current = serialized;\n if (contentUpdatedAt) {\n lastAppliedUpdatedAtRef.current = contentUpdatedAt;\n }\n });\n };\n\n apply();\n return () => {\n cancelled = true;\n if (retry) clearTimeout(retry);\n };\n }, [\n contentUpdatedAt,\n editor,\n value,\n collab,\n isLeadClient,\n getMarkdown,\n setContent,\n normalizeValue,\n ]);\n\n const shouldIgnoreUpdate = (transaction: Transaction): boolean => {\n if (!editable || isSettingContentRef.current) return true;\n if (transaction.getMeta(RICH_MARKDOWN_PROGRAMMATIC_TRANSACTION)) {\n return true;\n }\n // In collab mode, never persist remote-originated changes (the initial Yjs\n // state load or a peer's edit arriving via sync). Each client saves only its\n // OWN local edits; a peer's edit is saved by that peer. Without this, a\n // lagging Y.Doc load would write stale markdown over newer SQL.\n if (collab && transaction && isChangeOrigin(transaction)) return true;\n lastTypedAtRef.current = Date.now();\n return false;\n };\n\n const registerEmitted = (markdown: string): boolean => {\n // Don't persist an empty doc before Collaboration has seeded — that would\n // clobber the saved block content with an empty string.\n if (collab && !markdown.trim()) return false;\n lastEmittedRef.current = markdown;\n pushEmittedRing(recentEmittedRef.current, markdown);\n return true;\n };\n\n return {\n collab,\n isSettingContentRef,\n shouldIgnoreUpdate,\n registerEmitted,\n };\n}\n"]}
1
+ {"version":3,"file":"useCollabReconcile.js","sourceRoot":"","sources":["../../../src/client/rich-markdown-editor/useCollabReconcile.ts"],"names":[],"mappings":"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","sourcesContent":["import { isChangeOrigin } from \"@tiptap/extension-collaboration\";\nimport type { Node as ProseMirrorNode } from \"@tiptap/pm/model\";\nimport type { Transaction } from \"@tiptap/pm/state\";\nimport type { Editor } from \"@tiptap/react\";\nimport { useEffect, useRef, useState, type MutableRefObject } from \"react\";\nimport type { Awareness } from \"y-protocols/awareness\";\nimport type { Doc as YDoc } from \"yjs\";\n\nimport { AGENT_CLIENT_ID } from \"../../collab/agent-identity.js\";\nimport { isReconcileLeadClient } from \"../../collab/client.js\";\nimport {\n RICH_MARKDOWN_PROGRAMMATIC_TRANSACTION,\n applyDocSurgically,\n defaultParseValue,\n} from \"./surgical-apply.js\";\n\nexport { RICH_MARKDOWN_PROGRAMMATIC_TRANSACTION };\n\n/** Reads the current markdown out of the tiptap-markdown storage. */\nexport function getEditorMarkdown(editor: Editor): string {\n const markdownStorage = editor.storage as unknown as {\n markdown?: { getMarkdown?: () => string };\n };\n return markdownStorage.markdown?.getMarkdown?.() ?? \"\";\n}\n\n/**\n * Push a value onto the bounded ring of recently-emitted markdown (most recent\n * last, deduped, capped). The reconcile uses this to recognize a stale-but-recent\n * echo of OUR OWN edits: a debounced autosave can persist a PARTIAL burst, and\n * the next poll re-supplies that partial value with a newer timestamp — applying\n * it would clobber the freshly-typed tail. An external change (agent/peer) never\n * byte-matches one of our own recent emissions, and if it somehow did the content\n * is identical, so skipping it is safe by construction.\n */\nconst EMITTED_RING_MAX = 16;\nfunction pushEmittedRing(ring: string[], value: string): void {\n if (!value) return;\n if (ring[ring.length - 1] === value) return;\n const dupe = ring.indexOf(value);\n if (dupe !== -1) ring.splice(dupe, 1);\n ring.push(value);\n if (ring.length > EMITTED_RING_MAX) ring.shift();\n}\n\nexport interface UseCollabReconcileOptions {\n /** The live editor, or null until it mounts. */\n editor: Editor | null;\n /** Shared Y.Doc when collaborating; null disables all collab paths. */\n ydoc?: YDoc | null;\n /** Shared awareness; null keeps the sole-client lead path. */\n awareness?: Awareness | null;\n /** Authoritative markdown value (SQL source of truth). */\n value: string;\n /** Timestamp of the authoritative value; gates newer-than reconcile. */\n contentUpdatedAt?: string | null;\n /** Whether the editor accepts edits. Reconcile/seed only run for the live editor. */\n editable: boolean;\n /**\n * Reads the current markdown from the editor. Injected so a dialect could\n * swap serializers; defaults to the tiptap-markdown storage reader. For an app\n * with a custom serializer (e.g. Content's `docToNfm(editor.getJSON())`), pass\n * it here so the seed/reconcile equality checks compare like-for-like.\n */\n getMarkdown?: (editor: Editor) => string;\n /**\n * Applies the authoritative `value` into the editor. Defaults to passing the\n * raw markdown string to `editor.commands.setContent`. Apps whose serializer\n * is NOT tiptap-markdown (Content parses `nfmToDoc(value)` into a PM doc)\n * override this so seed + reconcile write the correct content shape. The\n * supplied `options` carry the history/whitespace flags the default path uses;\n * a custom implementation should forward them when relevant.\n */\n setContent?: (\n editor: Editor,\n value: string,\n options: { emitUpdate?: boolean; addToHistory?: boolean },\n ) => void;\n /**\n * Parses the authoritative `value` into a full ProseMirror document for the\n * SURGICAL reconcile path: instead of a whole-document `setContent` (which\n * under Collaboration rewrites the entire Y.XmlFragment and tears down every\n * block NodeView), the reconcile diffs the parsed doc against the live doc\n * and replaces only the changed top-level run. Return null to skip the\n * surgical path for a given value (falls back to `setContent`).\n *\n * Defaults to a best-effort tiptap-markdown parse; apps with their own\n * serializers (Content's NFM, Plan's blocks[] doc) should supply the exact\n * doc their `setContent` would write. Pass `false` to disable surgical\n * application entirely.\n */\n parseValue?:\n | ((editor: Editor, value: string) => ProseMirrorNode | null)\n | false;\n /**\n * Normalizes the authoritative `value` to the canonical markdown the editor\n * would emit, so the \"already in sync / our own echo\" equality checks match a\n * serializer that re-canonicalizes (Content's `canonicalizeNfm`). Defaults to\n * identity (GFM already round-trips byte-stably).\n */\n normalizeValue?: (value: string) => string;\n /**\n * Decides whether the empty-doc seed should run for the current shared\n * fragment. Defaults to \"fragment has no nodes, or the editor holds no\n * semantic markdown\". Apps with sentinel-empty content (Content's\n * `<empty-block/>` filler) override this. Receives the live fragment length\n * and the editor's current markdown.\n */\n shouldSeed?: (info: {\n value: string;\n currentMarkdown: string;\n fragmentLength: number;\n }) => boolean;\n /**\n * The initial \"applied\" watermark. Default mirrors `contentUpdatedAt`, so a\n * fresh mount whose Y.Doc already matches SQL doesn't re-apply. Pass `null`\n * to force the first reconcile pass to adopt authoritative SQL even at the\n * same timestamp — Content does this so a stale persisted Y.Doc (an agent that\n * edited the CLOSED doc) is corrected on open. The editor is keyed per\n * document upstream, so this only affects the first mount of each doc.\n */\n initialAppliedUpdatedAt?: string | null;\n}\n\nexport interface UseCollabReconcileResult {\n /** True when a Y.Doc is bound (collaborative editing active). */\n collab: boolean;\n /**\n * Set true around any programmatic `setContent` so the editor's `onUpdate`\n * can ignore the resulting transaction (it isn't a user edit).\n */\n isSettingContentRef: MutableRefObject<boolean>;\n /**\n * Call from `onUpdate` BEFORE serializing. Returns true when the update must\n * be ignored: editor not editable, mid-programmatic-setContent, or (in collab\n * mode) a remote-origin transaction. Also records the local typing time.\n */\n shouldIgnoreUpdate: (transaction: Transaction) => boolean;\n /**\n * Call from `onUpdate` AFTER computing the markdown to emit. Returns false\n * when the value must NOT be persisted yet (an empty collab doc before the\n * seed has run); records it as the last-emitted value otherwise.\n */\n registerEmitted: (markdown: string) => boolean;\n}\n\n/**\n * The subtle seed / reconcile / lead-client logic for the shared markdown\n * editor, extracted once so it can never be duplicated across embedders.\n *\n * Responsibilities (reproducing the Plan editor's behavior exactly):\n * - Track whether THIS client is the reconcile lead (sole client always leads;\n * otherwise elected via {@link isReconcileLeadClient}) and how many other\n * visible human peers are present.\n * - Seed an empty shared Y.Doc once from `value` — lead client only — so two\n * clients opening a brand-new block don't both insert the content.\n * - Reconcile authoritative external markdown (agent edit, source patch, peer\n * edit mirrored to SQL) into the editor: in collab mode only the lead client\n * applies it through `setContent` and Yjs propagates; in non-collab mode this\n * is the original controlled-value reconcile.\n * - Provide the `onUpdate` guards (`shouldIgnoreUpdate`, `registerEmitted`) so\n * the component never persists remote-origin or pre-seed empty content.\n */\n/** Default seed predicate: seed only when the shared doc is genuinely empty. */\nfunction defaultShouldSeed({\n currentMarkdown,\n fragmentLength,\n}: {\n value: string;\n currentMarkdown: string;\n fragmentLength: number;\n}): boolean {\n return fragmentLength === 0 || !currentMarkdown.trim();\n}\n\n/**\n * Default content writer: hand the raw markdown string to `setContent`, which\n * tiptap-markdown overrides to parse the markdown into a ProseMirror doc.\n *\n * IMPORTANT: do NOT pass `parseOptions: { preserveWhitespace: \"full\" }` here.\n * In tiptap v3 the core `setContent` command routes `preserveWhitespace: \"full\"`\n * through `insertContentAt`, which tiptap-markdown ALSO overrides to re-run its\n * markdown parser. That double-parse stringifies the already-parsed PM doc and\n * re-parses it as HTML, so a clean heading/list/code block comes back as the\n * escaped, non-idempotent `&lt;h1&gt;…` — which then escalates every reconcile\n * cycle (`<p>` → `&lt;p&gt;` → `&amp;lt;p&amp;gt;` …). Letting the markdown\n * override parse the string directly (no `parseOptions`) round-trips byte-stably\n * for the GFM corpus, including code-block and empty-line whitespace. Content's\n * NFM path supplies its own `setContent` (it passes a pre-parsed PM doc) and is\n * unaffected by this default.\n */\nfunction defaultSetContent(\n editor: Editor,\n value: string,\n options: { emitUpdate?: boolean; addToHistory?: boolean },\n): void {\n if (options.addToHistory === false) {\n editor\n .chain()\n .command(({ tr }) => {\n // addToHistory:false so cmd+z (or Yjs undo) doesn't erase\n // externally-loaded content.\n tr.setMeta(\"addToHistory\", false);\n return true;\n })\n .setContent(value, { emitUpdate: options.emitUpdate })\n .run();\n return;\n }\n editor.commands.setContent(value);\n}\n\nexport function useCollabReconcile({\n editor,\n ydoc = null,\n awareness = null,\n value,\n contentUpdatedAt,\n editable,\n getMarkdown = getEditorMarkdown,\n setContent = defaultSetContent,\n parseValue,\n normalizeValue = (v) => v,\n shouldSeed = defaultShouldSeed,\n initialAppliedUpdatedAt,\n}: UseCollabReconcileOptions): UseCollabReconcileResult {\n const collab = !!ydoc;\n const isSettingContentRef = useRef(false);\n const lastEmittedRef = useRef(\"\");\n // Ring of recent local emissions (see pushEmittedRing). Lets the reconcile\n // recognize a stale-but-recent echo of our OWN (possibly partial, debounced)\n // save so a lagging poll never clobbers freshly-typed text.\n const recentEmittedRef = useRef<string[]>([]);\n const lastTypedAtRef = useRef(0);\n // The raw authoritative `value` string the reconcile last applied. When the\n // SAME raw string is re-fetched (a lagging poll, or a source-sync that keeps\n // re-supplying the same stored markdown), applying it again would only\n // reproduce the doc we already hold — and if `value` is NON-idempotent\n // (serialize(parse(value)) !== value) re-applying compounds the divergence\n // every cycle (`<p>` → `&lt;p&gt;` → `&amp;lt;p&amp;gt;` …). Tracked so the\n // identical re-fetch is recognized and skipped.\n const lastAppliedValueRef = useRef<string | null>(null);\n // The editor's SERIALIZED output captured right AFTER the last reconcile/seed\n // apply (`getMarkdown(editor)` once the content settled). For non-idempotent\n // input this is what autosave actually persists, so the NEXT poll hands it\n // back as the new `value`. Comparing the incoming value against this lets the\n // reconcile recognize its own echo even when the raw string changed once, so\n // it never re-parses content the editor already represents. This is the\n // doc-equivalence guard that breaks the escalation loop.\n const lastAppliedSerializedRef = useRef<string | null>(null);\n const lastAppliedUpdatedAtRef = useRef<string | null>(\n initialAppliedUpdatedAt !== undefined\n ? initialAppliedUpdatedAt\n : (contentUpdatedAt ?? null),\n );\n\n // Whether THIS client is the one that seeds the empty shared doc / applies an\n // authoritative external snapshot into it. Exactly one client does, so the\n // content isn't inserted once per open editor. A sole client always leads.\n const [isLeadClient, setIsLeadClient] = useState(true);\n // Count of OTHER visible human collaborators. When >0, a peer's edit also\n // arrives via Yjs, so external markdown reconcile must defer (avoid applying\n // the same change through both Yjs and setContent).\n const peerCountRef = useRef(0);\n useEffect(() => {\n if (!collab || !awareness || !ydoc) {\n setIsLeadClient(true);\n peerCountRef.current = 0;\n return;\n }\n const update = () => {\n setIsLeadClient(isReconcileLeadClient(awareness, ydoc.clientID));\n let peers = 0;\n awareness.getStates().forEach((state, clientId) => {\n if (clientId === ydoc.clientID) return; // self\n if (clientId === AGENT_CLIENT_ID) return; // agent isn't a Yjs editor\n const s = state as { user?: unknown; visible?: boolean };\n if (s && s.user && s.visible !== false) peers += 1;\n });\n peerCountRef.current = peers;\n };\n update();\n awareness.on(\"change\", update);\n document.addEventListener(\"visibilitychange\", update);\n return () => {\n awareness.off(\"change\", update);\n document.removeEventListener(\"visibilitychange\", update);\n };\n }, [collab, awareness, ydoc]);\n\n // Collab seed: populate an empty shared Y.Doc from the markdown `value` once.\n // The Collaboration extension does NOT auto-seed; only the lead client does,\n // so two clients opening a brand-new block at once don't both seed (which\n // would duplicate the content via concurrent inserts at the same position).\n const seededRef = useRef(false);\n useEffect(() => {\n if (!collab || !editor || editor.isDestroyed || !ydoc) return;\n if (seededRef.current) return;\n if (!isLeadClient) return;\n if (!value.trim()) return;\n const fragment = ydoc.getXmlFragment(\"default\");\n const currentMarkdown = getMarkdown(editor);\n // Seed only when the shared doc is genuinely empty — either the fragment has\n // no nodes yet, or it holds no semantic markdown (an empty paragraph, or an\n // app's sentinel-empty filler via a custom `shouldSeed`).\n seededRef.current = true;\n if (\n !shouldSeed({ value, currentMarkdown, fragmentLength: fragment.length })\n ) {\n return;\n }\n\n let cancelled = false;\n queueMicrotask(() => {\n if (cancelled || editor.isDestroyed) return;\n isSettingContentRef.current = true;\n try {\n setContent(editor, value, {});\n } finally {\n isSettingContentRef.current = false;\n }\n const serialized = getMarkdown(editor);\n lastEmittedRef.current = serialized;\n pushEmittedRing(recentEmittedRef.current, serialized);\n lastAppliedValueRef.current = value;\n lastAppliedSerializedRef.current = serialized;\n if (contentUpdatedAt) lastAppliedUpdatedAtRef.current = contentUpdatedAt;\n });\n return () => {\n cancelled = true;\n };\n }, [\n collab,\n editor,\n ydoc,\n value,\n isLeadClient,\n contentUpdatedAt,\n getMarkdown,\n setContent,\n shouldSeed,\n ]);\n\n // Reconcile authoritative external markdown (agent edit, source patch, or a\n // peer edit mirrored to SQL) into the live editor. In collab mode only the\n // lead client applies it through setContent; Yjs propagates the result to\n // every other client. In non-collab mode this is the original controlled-value\n // reconcile, unchanged.\n useEffect(() => {\n if (!editor || editor.isDestroyed) return;\n\n let cancelled = false;\n let retry: ReturnType<typeof setTimeout> | null = null;\n // With peers present, a peer's edit also arrives via Yjs. Defer one poll\n // cycle (+margin) and re-check before applying via setContent so the same\n // change isn't inserted twice (Yjs + setContent → duplicated region).\n const PEER_SETTLE_MS = 2500;\n\n const apply = (deferred = false) => {\n if (cancelled || editor.isDestroyed) return;\n // In collab mode, defer all reconcile until the shared doc is seeded so we\n // never setContent over an unseeded fragment.\n if (collab && !seededRef.current) {\n retry = setTimeout(() => apply(deferred), 300);\n return;\n }\n const currentMarkdown = getMarkdown(editor);\n // Compare against the canonical form the editor would emit so a serializer\n // that re-normalizes (Content's NFM) still recognizes \"already in sync\".\n const normalizedValue = normalizeValue(value);\n // Whether the editor still holds exactly what THIS hook last applied (the\n // user hasn't edited since). Only then are the round-trip echo guards\n // below safe: if the user has since edited away from the applied content,\n // an external snapshot equal to a previously-applied value is a real\n // revert and must NOT be swallowed as an echo.\n const editorUnchangedSinceApply =\n lastAppliedSerializedRef.current !== null &&\n currentMarkdown === lastAppliedSerializedRef.current;\n\n // Doc-equivalence skip. Never re-apply content the editor already\n // represents — comparing by DOC EQUIVALENCE, not raw strings/timestamps:\n // 1. `currentMarkdown === normalizedValue` — the editor's CURRENT\n // serialized doc already equals the (normalized) incoming value.\n // 2. `value === lastEmittedRef.current` — the incoming value is our own\n // just-emitted markdown echoing back.\n // 3. `value === lastAppliedValueRef.current` — the SAME raw value we\n // already applied is being re-supplied (a lagging poll or a\n // source-sync re-handing the same stored markdown). Applying it again\n // would only reproduce the doc we hold; for NON-idempotent input it\n // would compound divergence. Guarded by `editorUnchangedSinceApply`\n // so a deliberate revert-to-previous after a local edit still lands.\n // 4. `normalizedValue === lastAppliedSerializedRef.current` — the\n // incoming value round-trips to the serialized output we last\n // produced (our own autosaved echo coming back from SQL). For\n // non-idempotent input the raw string differs from what we were\n // handed, but it is doc-equivalent to what the editor already shows,\n // so re-parsing it must be skipped. This is the guard that stops the\n // `<p>` → `&lt;p&gt;` → `&amp;lt;p&amp;gt;` escalation.\n if (\n currentMarkdown === normalizedValue ||\n value === lastEmittedRef.current ||\n // A stale-but-recent echo of our own (possibly partial) save — applying\n // it would clobber the freshly-typed tail. External edits never match.\n recentEmittedRef.current.includes(value) ||\n recentEmittedRef.current.includes(normalizedValue) ||\n (editorUnchangedSinceApply &&\n (value === lastAppliedValueRef.current ||\n normalizedValue === lastAppliedSerializedRef.current))\n ) {\n if (contentUpdatedAt) {\n lastAppliedUpdatedAtRef.current = contentUpdatedAt;\n }\n return;\n }\n\n const externalNewer =\n !lastAppliedUpdatedAtRef.current ||\n !contentUpdatedAt ||\n contentUpdatedAt > lastAppliedUpdatedAtRef.current;\n\n // Only the lead client applies an authoritative snapshot into the shared\n // Y.Doc; peers receive it through Yjs sync.\n if (collab && !isLeadClient) {\n if (contentUpdatedAt && !externalNewer) {\n lastAppliedUpdatedAtRef.current = contentUpdatedAt;\n }\n return;\n }\n\n // Never clobber an in-progress edit. While the user is actively typing\n // (focused and a keystroke landed within the window) defer and re-check —\n // applying external content now would yank text out from under them and,\n // for non-idempotent input, fight every keystroke. Newer external content\n // retries so it still lands once they pause; older-or-equal content is a\n // stale poll and is dropped outright while focused.\n const typingRecently =\n editor.isFocused && Date.now() - lastTypedAtRef.current < 1500;\n if (typingRecently) {\n if (externalNewer) {\n retry = setTimeout(() => apply(deferred), 700);\n }\n return;\n }\n // Older-or-equal content is a stale poll / lagging echo. Drop it while\n // focused (a peer/agent edit would be NEWER and retries above). In\n // NON-COLLAB mode there is no peer, so older-or-equal external content is\n // ALWAYS stale — dropping it regardless of focus stops a lagging\n // `get-visual-plan` poll from reverting a just-applied local structural\n // change (drag-to-columns) while the editor is blurred (the drag grips the\n // handle, not the prose, so `isFocused` is false at drop time). Gated on\n // `lastAppliedSerializedRef` so the very first seed (nothing applied yet,\n // also not-newer) still lands.\n const seeded = lastAppliedSerializedRef.current !== null;\n if (!externalNewer && (editor.isFocused || (!collab && seeded))) return;\n\n // Race guard: with peers present, let Yjs deliver a peer's edit first.\n // Defer once and re-check — a peer edit makes the equality check above\n // no-op next pass; an agent/source edit still differs and applies.\n if (collab && externalNewer && !deferred && peerCountRef.current > 0) {\n retry = setTimeout(() => apply(true), PEER_SETTLE_MS);\n return;\n }\n\n queueMicrotask(() => {\n if (cancelled || editor.isDestroyed) return;\n // Re-check doc-equivalence at apply time. Between the decision above and\n // this microtask a peer/Yjs edit (or our own prior apply) may have made\n // the editor already represent this value — re-applying would be a\n // wasted setContent that, for non-idempotent input, re-triggers the\n // loop. Skip when the editor's current serialization already matches the\n // normalized value, or the value round-trips to what we last produced.\n const beforeMarkdown = getMarkdown(editor);\n const normalized = normalizeValue(value);\n const unchangedSinceApply =\n lastAppliedSerializedRef.current !== null &&\n beforeMarkdown === lastAppliedSerializedRef.current;\n if (\n beforeMarkdown === normalized ||\n (unchangedSinceApply &&\n normalized === lastAppliedSerializedRef.current)\n ) {\n lastAppliedValueRef.current = value;\n if (contentUpdatedAt) {\n lastAppliedUpdatedAtRef.current = contentUpdatedAt;\n }\n return;\n }\n isSettingContentRef.current = true;\n // Surgical path first: replace only the changed top-level run so\n // unchanged block NodeViews are never torn down and (under\n // Collaboration) Yjs sees a minimal edit instead of a full-fragment\n // rewrite. Falls back to the classic whole-document setContent when no\n // parser is available or the targeted transaction cannot be applied.\n let appliedSurgically = false;\n if (parseValue !== false) {\n const parse = parseValue ?? defaultParseValue;\n const parsedDoc = parse(editor, value);\n if (parsedDoc) {\n const result = applyDocSurgically(editor, parsedDoc);\n appliedSurgically = result === \"applied\" || result === \"noop\";\n }\n }\n if (!appliedSurgically) {\n setContent(editor, value, { emitUpdate: false, addToHistory: false });\n }\n isSettingContentRef.current = false;\n // Capture the SERIALIZED result, not the raw value. For non-idempotent\n // input these differ; recording the serialized output is what lets the\n // next poll (which returns this serialized form) be recognized as our\n // own echo and skipped — stabilizing the doc after exactly one apply.\n const serialized = getMarkdown(editor);\n lastEmittedRef.current = serialized;\n pushEmittedRing(recentEmittedRef.current, serialized);\n lastAppliedValueRef.current = value;\n lastAppliedSerializedRef.current = serialized;\n if (contentUpdatedAt) {\n lastAppliedUpdatedAtRef.current = contentUpdatedAt;\n }\n });\n };\n\n apply();\n return () => {\n cancelled = true;\n if (retry) clearTimeout(retry);\n };\n }, [\n contentUpdatedAt,\n editor,\n value,\n collab,\n isLeadClient,\n getMarkdown,\n setContent,\n parseValue,\n normalizeValue,\n ]);\n\n const shouldIgnoreUpdate = (transaction: Transaction): boolean => {\n if (!editable || isSettingContentRef.current) return true;\n if (transaction.getMeta(RICH_MARKDOWN_PROGRAMMATIC_TRANSACTION)) {\n return true;\n }\n // In collab mode, never persist remote-originated changes (the initial Yjs\n // state load or a peer's edit arriving via sync). Each client saves only its\n // OWN local edits; a peer's edit is saved by that peer. Without this, a\n // lagging Y.Doc load would write stale markdown over newer SQL.\n if (collab && transaction && isChangeOrigin(transaction)) return true;\n lastTypedAtRef.current = Date.now();\n return false;\n };\n\n const registerEmitted = (markdown: string): boolean => {\n // Don't persist an empty doc before Collaboration has seeded — that would\n // clobber the saved block content with an empty string.\n if (collab && !markdown.trim()) return false;\n lastEmittedRef.current = markdown;\n pushEmittedRing(recentEmittedRef.current, markdown);\n return true;\n };\n\n return {\n collab,\n isSettingContentRef,\n shouldIgnoreUpdate,\n registerEmitted,\n };\n}\n"]}
@@ -15,9 +15,16 @@ export interface SessionReplayConsoleOptions {
15
15
  * `agent-native.network` custom events emitted per recording session
16
16
  * (default 2000); once hit, capture stops for the rest of the session and one
17
17
  * final truncation-notice event is emitted.
18
+ *
19
+ * `captureErrorBodies` (default true) additionally captures a bounded,
20
+ * redacted response-body snippet for 5xx responses only -- request bodies
21
+ * and headers are never captured, and non-5xx/network-failure responses
22
+ * never carry a body. `maxErrorBodyLength` (default 2048) caps that snippet.
18
23
  */
19
24
  export interface SessionReplayNetworkOptions {
20
25
  maxEvents?: number;
26
+ captureErrorBodies?: boolean;
27
+ maxErrorBodyLength?: number;
21
28
  }
22
29
  export interface SessionReplayOptions {
23
30
  enabled?: boolean;
@@ -60,7 +67,9 @@ export interface SessionReplayOptions {
60
67
  console?: boolean | SessionReplayConsoleOptions;
61
68
  /**
62
69
  * Capture fetch/XHR requests as `agent-native.network` custom rrweb
63
- * events (method, URL, status, timing -- never bodies or headers).
70
+ * events (method, URL, status, timing). Request bodies and headers are
71
+ * never captured; response bodies are captured only as a bounded,
72
+ * redacted snippet for 5xx responses (see `captureErrorBodies`).
64
73
  * Defaults to on whenever session replay is enabled. Pass `false` to
65
74
  * disable, or an options object to override caps.
66
75
  */
@@ -1 +1 @@
1
- {"version":3,"file":"session-replay.d.ts","sourceRoot":"","sources":["../../src/client/session-replay.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"session-replay.d.ts","sourceRoot":"","sources":["../../src/client/session-replay.ts"],"names":[],"mappings":"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"}