@agent-native/core 0.85.7 → 0.86.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1132) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/core/CHANGELOG.md +133 -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 +7 -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/AgentPanel.tsx +10 -0
  93. package/corpus/core/src/client/AssistantChat.tsx +194 -21
  94. package/corpus/core/src/client/ErrorBoundary.tsx +67 -12
  95. package/corpus/core/src/client/ErrorReportActions.tsx +69 -0
  96. package/corpus/core/src/client/FeedbackButton.tsx +8 -4
  97. package/corpus/core/src/client/agent-chat-adapter.ts +6 -5
  98. package/corpus/core/src/client/app-providers.tsx +2 -2
  99. package/corpus/core/src/client/collab/index.ts +31 -0
  100. package/corpus/core/src/client/components/LiveCursorOverlay.tsx +16 -1
  101. package/corpus/core/src/client/components/PresenceBar.tsx +14 -1
  102. package/corpus/core/src/client/components/RecentEditHighlights.tsx +219 -0
  103. package/corpus/core/src/client/components/RemoteSelectionRings.tsx +40 -6
  104. package/corpus/core/src/client/db-admin/DbAdminPage.tsx +41 -13
  105. package/corpus/core/src/client/db-admin/SqlEditor.tsx +10 -3
  106. package/corpus/core/src/client/db-admin/TableEditor.tsx +12 -5
  107. package/corpus/core/src/client/db-admin/useAgentSync.ts +10 -3
  108. package/corpus/core/src/client/db-admin/useDbAdmin.ts +65 -16
  109. package/corpus/core/src/client/error-reporting.ts +100 -0
  110. package/corpus/core/src/client/index.ts +59 -0
  111. package/corpus/core/src/client/org/OrgSwitcher.tsx +0 -4
  112. package/corpus/core/src/client/org/RequireActiveOrg.tsx +12 -0
  113. package/corpus/core/src/client/rich-markdown-editor/SharedRichEditor.tsx +49 -32
  114. package/corpus/core/src/client/rich-markdown-editor/index.ts +6 -0
  115. package/corpus/core/src/client/rich-markdown-editor/surgical-apply.ts +192 -0
  116. package/corpus/core/src/client/rich-markdown-editor/useCollabReconcile.ts +59 -8
  117. package/corpus/core/src/client/session-replay.ts +181 -15
  118. package/corpus/core/src/client/sse-event-processor.ts +90 -1
  119. package/corpus/core/src/client/use-action.ts +123 -25
  120. package/corpus/core/src/client/use-agent-engine-configured.ts +7 -1
  121. package/corpus/core/src/client/use-chat-threads.ts +18 -7
  122. package/corpus/core/src/client/use-db-sync.ts +104 -19
  123. package/corpus/core/src/client/visual-style-controls.tsx +1088 -0
  124. package/corpus/core/src/collab/agent-presence.ts +191 -62
  125. package/corpus/core/src/collab/awareness.ts +83 -6
  126. package/corpus/core/src/collab/client.ts +89 -146
  127. package/corpus/core/src/collab/index.ts +34 -0
  128. package/corpus/core/src/collab/recent-edits.ts +171 -0
  129. package/corpus/core/src/collab/undo.ts +432 -0
  130. package/corpus/core/src/collab/ydoc-manager.ts +68 -0
  131. package/corpus/core/src/connections/catalog.ts +2 -3
  132. package/corpus/core/src/db/create-get-db.ts +86 -1
  133. package/corpus/core/src/db/ensure-additive-columns.ts +430 -0
  134. package/corpus/core/src/db/index.ts +6 -0
  135. package/corpus/core/src/db/migrations.ts +236 -35
  136. package/corpus/core/src/db-admin/index.ts +26 -0
  137. package/corpus/core/src/db-admin/operations.ts +87 -49
  138. package/corpus/core/src/jobs/scheduler.ts +17 -14
  139. package/corpus/core/src/localization/default-messages.ts +4 -0
  140. package/corpus/core/src/observability/traces.ts +182 -1
  141. package/corpus/core/src/org/context.ts +79 -2
  142. package/corpus/core/src/server/agent-chat-plugin.ts +10 -6
  143. package/corpus/core/src/server/auth-marketing.ts +0 -11
  144. package/corpus/core/src/server/auth.ts +11 -4
  145. package/corpus/core/src/server/builder-design-systems.ts +328 -9
  146. package/corpus/core/src/server/collab-plugin.ts +56 -13
  147. package/corpus/core/src/server/design-token-utils.ts +1 -1
  148. package/corpus/core/src/server/fusion-app.ts +447 -0
  149. package/corpus/core/src/server/index.ts +28 -0
  150. package/corpus/core/src/server/onboarding-html.ts +3 -4
  151. package/corpus/core/src/server/poll-events.ts +14 -2
  152. package/corpus/core/src/server/poll.ts +219 -12
  153. package/corpus/core/src/server/schema-prompt.ts +28 -9
  154. package/corpus/core/src/settings/store.ts +33 -2
  155. package/corpus/core/src/sharing/actions/set-resource-visibility.ts +2 -0
  156. package/corpus/core/src/sharing/actions/share-resource.ts +3 -0
  157. package/corpus/core/src/sharing/actions/unshare-resource.ts +2 -0
  158. package/corpus/core/src/styles/agent-native.css +0 -5
  159. package/corpus/core/src/templates/default/.agents/skills/real-time-collab/SKILL.md +82 -19
  160. package/corpus/core/src/templates/default/.agents/skills/real-time-sync/SKILL.md +15 -0
  161. package/corpus/core/src/templates/default/.agents/skills/storing-data/SKILL.md +8 -0
  162. package/corpus/core/src/templates/default/app/root.tsx +47 -0
  163. package/corpus/core/src/templates/default/package.json +3 -3
  164. package/corpus/core/src/templates/workspace-core/.agents/skills/client-methods/SKILL.md +8 -0
  165. package/corpus/core/src/templates/workspace-core/.agents/skills/observability/SKILL.md +22 -0
  166. package/corpus/core/src/templates/workspace-core/.agents/skills/real-time-collab/SKILL.md +82 -19
  167. package/corpus/core/src/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +15 -0
  168. package/corpus/core/src/templates/workspace-core/.agents/skills/storing-data/SKILL.md +8 -0
  169. package/corpus/core/src/templates/workspace-core/.agents/skills/tracking/SKILL.md +1 -0
  170. package/corpus/core/src/tracking/providers.ts +22 -1
  171. package/corpus/templates/analytics/.agents/skills/real-time-sync/SKILL.md +15 -0
  172. package/corpus/templates/analytics/.agents/skills/session-replay/SKILL.md +20 -5
  173. package/corpus/templates/analytics/.agents/skills/storing-data/SKILL.md +8 -0
  174. package/corpus/templates/analytics/AGENTS.md +35 -6
  175. package/corpus/templates/analytics/actions/delete-db-admin-connection.ts +19 -0
  176. package/corpus/templates/analytics/actions/list-db-admin-connections.ts +18 -0
  177. package/corpus/templates/analytics/actions/navigate.ts +28 -4
  178. package/corpus/templates/analytics/actions/query-agent-native-analytics.ts +1 -1
  179. package/corpus/templates/analytics/actions/save-db-admin-connection.ts +33 -0
  180. package/corpus/templates/analytics/actions/view-screen.ts +65 -0
  181. package/corpus/templates/analytics/app/components/layout/CommandPalette.tsx +23 -1
  182. package/corpus/templates/analytics/app/components/layout/Header.tsx +1 -0
  183. package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +21 -0
  184. package/corpus/templates/analytics/app/hooks/use-navigation-state.ts +16 -0
  185. package/corpus/templates/analytics/app/i18n/zh-TW.ts +36 -1
  186. package/corpus/templates/analytics/app/i18n-data.ts +361 -10
  187. package/corpus/templates/analytics/app/pages/Agents.tsx +512 -0
  188. package/corpus/templates/analytics/app/pages/DataSources.tsx +11 -1
  189. package/corpus/templates/analytics/app/pages/sessions/SessionDevToolsPanel.tsx +76 -40
  190. package/corpus/templates/analytics/app/pages/sessions/session-replay-devtools.ts +5 -0
  191. package/corpus/templates/analytics/app/routes/agents.tsx +10 -0
  192. package/corpus/templates/analytics/changelog/2026-07-03-agent-admin-tools-page.md +6 -0
  193. package/corpus/templates/analytics/changelog/2026-07-03-agent-llm-observability-dashboard.md +6 -0
  194. package/corpus/templates/analytics/changelog/2026-07-03-connect-other-app-databases-from-analytics.md +6 -0
  195. package/corpus/templates/analytics/changelog/2026-07-03-session-recordings-now-include-response-bodies-for-5xx-error.md +6 -0
  196. package/corpus/templates/analytics/docs/schemas/first-party-analytics.md +34 -0
  197. package/corpus/templates/analytics/docs/schemas/tracked-events.md +6 -0
  198. package/corpus/templates/analytics/package.json +3 -3
  199. package/corpus/templates/analytics/seeds/dashboards/agent-observability-llm.json +173 -0
  200. package/corpus/templates/analytics/server/db/schema.ts +27 -0
  201. package/corpus/templates/analytics/server/jobs/analytics-alerts.ts +23 -5
  202. package/corpus/templates/analytics/server/lib/analytics-alerts.ts +58 -13
  203. package/corpus/templates/analytics/server/lib/dashboard-catalog.ts +23 -0
  204. package/corpus/templates/analytics/server/lib/dashboard-seeds.ts +5 -0
  205. package/corpus/templates/analytics/server/lib/db-admin-connections.ts +458 -0
  206. package/corpus/templates/analytics/server/lib/session-replay-agent-context.ts +120 -8
  207. package/corpus/templates/analytics/server/lib/session-replay.ts +3 -2
  208. package/corpus/templates/analytics/server/plugins/db.ts +128 -2
  209. package/corpus/templates/analytics/server/routes/[base]/_agent-native/analytics-db-admin/[...path].ts +1 -0
  210. package/corpus/templates/analytics/server/routes/_agent-native/analytics-db-admin/[...path].ts +160 -0
  211. package/corpus/templates/analytics/server/routes/api/session-replay/agent-diagnostics.json.get.ts +45 -1
  212. package/corpus/templates/analytics/shared/session-replay-diagnostics.ts +10 -0
  213. package/corpus/templates/assets/.agents/skills/real-time-collab/SKILL.md +82 -19
  214. package/corpus/templates/assets/.agents/skills/real-time-sync/SKILL.md +15 -0
  215. package/corpus/templates/assets/.agents/skills/storing-data/SKILL.md +8 -0
  216. package/corpus/templates/assets/package.json +3 -3
  217. package/corpus/templates/assets/server/plugins/db.ts +63 -2
  218. package/corpus/templates/brain/.agents/skills/real-time-sync/SKILL.md +15 -0
  219. package/corpus/templates/brain/package.json +3 -3
  220. package/corpus/templates/brain/server/plugins/db.ts +75 -2
  221. package/corpus/templates/calendar/.agents/skills/real-time-sync/SKILL.md +15 -0
  222. package/corpus/templates/calendar/.agents/skills/storing-data/SKILL.md +8 -0
  223. package/corpus/templates/calendar/package.json +3 -3
  224. package/corpus/templates/calendar/server/plugins/db.ts +64 -2
  225. package/corpus/templates/chat/.agents/skills/real-time-sync/SKILL.md +15 -0
  226. package/corpus/templates/chat/package.json +3 -3
  227. package/corpus/templates/clips/actions/finalize-recording.ts +50 -40
  228. package/corpus/templates/clips/app/routes/r.$recordingId.tsx +8 -6
  229. package/corpus/templates/clips/app/routes/share.$shareId.tsx +3 -3
  230. package/corpus/templates/clips/changelog/2026-07-03-mobile-recording-pages-keep-videos-in-a-16-9-player-with-act.md +6 -0
  231. package/corpus/templates/clips/package.json +3 -3
  232. package/corpus/templates/clips/server/lib/recording-upload-state.ts +56 -0
  233. package/corpus/templates/clips/server/plugins/db.ts +68 -1
  234. package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/chunk.post.ts +27 -3
  235. package/corpus/templates/content/.agents/skills/real-time-sync/SKILL.md +15 -0
  236. package/corpus/templates/content/.agents/skills/storing-data/SKILL.md +8 -0
  237. package/corpus/templates/content/actions/edit-document.ts +48 -1
  238. package/corpus/templates/content/actions/list-documents.ts +101 -94
  239. package/corpus/templates/content/actions/search-documents.ts +19 -3
  240. package/corpus/templates/content/actions/update-document.ts +54 -1
  241. package/corpus/templates/content/app/components/editor/DocumentEditor.tsx +127 -7
  242. package/corpus/templates/content/app/components/editor/VisualEditor.tsx +97 -2
  243. package/corpus/templates/content/app/root.tsx +9 -0
  244. package/corpus/templates/content/changelog/2026-07-03-agent-document-edits-now-appear-as-a-live-collaborator-prese.md +6 -0
  245. package/corpus/templates/content/changelog/2026-07-03-document-search-and-list-views-load-faster-on-large-workspac.md +6 -0
  246. package/corpus/templates/content/changelog/2026-07-03-error-screens-now-include-a-feedback-button-with-debug-info.md +6 -0
  247. package/corpus/templates/content/package.json +3 -3
  248. package/corpus/templates/content/server/plugins/db.ts +57 -1
  249. package/corpus/templates/design/.agents/skills/full-app-build/SKILL.md +140 -0
  250. package/corpus/templates/design/.agents/skills/visual-edit/SKILL.md +20 -0
  251. package/corpus/templates/design/AGENTS.md +63 -19
  252. package/corpus/templates/design/actions/add-fusion-screens.ts +91 -0
  253. package/corpus/templates/design/actions/apply-a11y-fix.ts +5 -1
  254. package/corpus/templates/design/actions/apply-component-prop-edit.ts +10 -2
  255. package/corpus/templates/design/actions/apply-fusion-edits.ts +161 -0
  256. package/corpus/templates/design/actions/apply-visual-edit.ts +34 -1
  257. package/corpus/templates/design/actions/create-component.ts +5 -1
  258. package/corpus/templates/design/actions/create-fusion-app.ts +202 -0
  259. package/corpus/templates/design/actions/deploy-fusion-app.ts +123 -0
  260. package/corpus/templates/design/actions/edit-design.ts +13 -16
  261. package/corpus/templates/design/actions/get-design-system.ts +21 -0
  262. package/corpus/templates/design/actions/get-fusion-deploy-status.ts +86 -0
  263. package/corpus/templates/design/actions/index-design-system-with-builder.ts +14 -37
  264. package/corpus/templates/design/actions/list-fusion-edits.ts +96 -0
  265. package/corpus/templates/design/actions/list-local-files.ts +133 -0
  266. package/corpus/templates/design/actions/push-fusion-app.ts +62 -0
  267. package/corpus/templates/design/actions/queue-fusion-edit.ts +112 -0
  268. package/corpus/templates/design/actions/read-local-file.ts +139 -0
  269. package/corpus/templates/design/actions/send-fusion-message.ts +69 -0
  270. package/corpus/templates/design/actions/sync-fusion-app.ts +196 -0
  271. package/corpus/templates/design/actions/write-local-file.ts +115 -14
  272. package/corpus/templates/design/app/components/design/CanvasContextMenu.tsx +12 -0
  273. package/corpus/templates/design/app/components/design/DesignCanvas.tsx +379 -0
  274. package/corpus/templates/design/app/components/design/EditPanel.tsx +149 -73
  275. package/corpus/templates/design/app/components/design/FusionAppBanner.tsx +328 -0
  276. package/corpus/templates/design/app/components/design/LayersPanel.tsx +148 -30
  277. package/corpus/templates/design/app/components/design/LocalhostWriteConsentDialog.tsx +1 -1
  278. package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +567 -6
  279. package/corpus/templates/design/app/components/design/TweaksPanel.tsx +7 -98
  280. package/corpus/templates/design/app/components/design/code-workbench/ActivityBar.tsx +85 -0
  281. package/corpus/templates/design/app/components/design/code-workbench/CodeWorkbench.tsx +466 -0
  282. package/corpus/templates/design/app/components/design/code-workbench/SideBar.tsx +114 -0
  283. package/corpus/templates/design/app/components/design/code-workbench/commands.ts +339 -0
  284. package/corpus/templates/design/app/components/design/code-workbench/editor/Breadcrumbs.tsx +42 -0
  285. package/corpus/templates/design/app/components/design/code-workbench/editor/BufferSync.tsx +128 -0
  286. package/corpus/templates/design/app/components/design/code-workbench/editor/EditorTabs.tsx +372 -0
  287. package/corpus/templates/design/app/components/design/code-workbench/editor/MonacoHost.tsx +268 -0
  288. package/corpus/templates/design/app/components/design/code-workbench/editor/StatusBar.tsx +208 -0
  289. package/corpus/templates/design/app/components/design/code-workbench/editor/monaco-setup.ts +61 -0
  290. package/corpus/templates/design/app/components/design/code-workbench/editor/monaco-theme-palette.ts +191 -0
  291. package/corpus/templates/design/app/components/design/code-workbench/editor/monaco-theme.ts +29 -0
  292. package/corpus/templates/design/app/components/design/code-workbench/editor/status-bar-lang.ts +21 -0
  293. package/corpus/templates/design/app/components/design/code-workbench/editor/tab-drag.ts +27 -0
  294. package/corpus/templates/design/app/components/design/code-workbench/explorer/ExplorerView.tsx +161 -0
  295. package/corpus/templates/design/app/components/design/code-workbench/explorer/FileTree.tsx +555 -0
  296. package/corpus/templates/design/app/components/design/code-workbench/explorer/file-icons.tsx +115 -0
  297. package/corpus/templates/design/app/components/design/code-workbench/format/format-on-open.ts +65 -0
  298. package/corpus/templates/design/app/components/design/code-workbench/format/prettier-format.ts +182 -0
  299. package/corpus/templates/design/app/components/design/code-workbench/model-registry.ts +133 -0
  300. package/corpus/templates/design/app/components/design/code-workbench/quickinput/QuickInput.tsx +563 -0
  301. package/corpus/templates/design/app/components/design/code-workbench/quickinput/fuzzy.ts +170 -0
  302. package/corpus/templates/design/app/components/design/code-workbench/search/SearchView.tsx +508 -0
  303. package/corpus/templates/design/app/components/design/code-workbench/search/search-engine.ts +280 -0
  304. package/corpus/templates/design/app/components/design/code-workbench/store.tsx +782 -0
  305. package/corpus/templates/design/app/components/design/code-workbench/workspace/create-providers.ts +39 -0
  306. package/corpus/templates/design/app/components/design/code-workbench/workspace/inline-provider.ts +196 -0
  307. package/corpus/templates/design/app/components/design/code-workbench/workspace/localhost-provider.ts +177 -0
  308. package/corpus/templates/design/app/components/design/code-workbench/workspace/tree.ts +110 -0
  309. package/corpus/templates/design/app/components/design/code-workbench/workspace/types.ts +103 -0
  310. package/corpus/templates/design/app/components/design/code-workbench-theme.ts +68 -0
  311. package/corpus/templates/design/app/components/design/inspector/DesignColorPicker.tsx +127 -10
  312. package/corpus/templates/design/app/components/design/inspector/ScrubInput.tsx +52 -29
  313. package/corpus/templates/design/app/components/design/inspector/index.ts +9 -0
  314. package/corpus/templates/design/app/components/design/inspector/scrub-input-utils.ts +56 -0
  315. package/corpus/templates/design/app/components/editor/PromptDialog.tsx +80 -1
  316. package/corpus/templates/design/app/components/visual-editor/SaveStatusIndicator.tsx +6 -16
  317. package/corpus/templates/design/app/hooks/useDesignHotkeys.ts +6 -0
  318. package/corpus/templates/design/app/i18n/zh-TW.ts +17 -15
  319. package/corpus/templates/design/app/i18n-data.ts +185 -160
  320. package/corpus/templates/design/app/pages/DesignEditor.tsx +1474 -175
  321. package/corpus/templates/design/app/pages/DesignSystemSetup.tsx +32 -14
  322. package/corpus/templates/design/app/pages/Index.tsx +90 -17
  323. package/corpus/templates/design/changelog/2026-07-03-design-system-setup-now-indexes-figma-code-and-design-md-sou.md +6 -0
  324. package/corpus/templates/design/changelog/2026-07-03-the-ai-now-edits-like-a-collaborator-on-canvas-its-cursor-gl.md +6 -0
  325. package/corpus/templates/design/changelog/2026-07-03-the-code-editor-is-easier-to-use-with-top-sidebar-tabs-clear.md +6 -0
  326. 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
  327. package/corpus/templates/design/package.json +4 -3
  328. package/corpus/templates/design/server/db/schema.ts +31 -0
  329. package/corpus/templates/design/server/lib/builder-design-system-proxy.ts +16 -106
  330. package/corpus/templates/design/server/lib/fusion-screens.ts +246 -0
  331. package/corpus/templates/design/server/plugins/db.ts +89 -2
  332. package/corpus/templates/design/shared/collab-selection.ts +52 -0
  333. package/corpus/templates/design/shared/full-app.ts +126 -0
  334. package/corpus/templates/design/shared/pen-path.ts +296 -0
  335. package/corpus/templates/dispatch/package.json +3 -3
  336. package/corpus/templates/forms/.agents/skills/real-time-sync/SKILL.md +15 -0
  337. package/corpus/templates/forms/.agents/skills/storing-data/SKILL.md +8 -0
  338. package/corpus/templates/forms/package.json +3 -3
  339. package/corpus/templates/forms/server/plugins/db.ts +62 -2
  340. package/corpus/templates/macros/package.json +3 -3
  341. package/corpus/templates/macros/server/plugins/db.ts +63 -2
  342. package/corpus/templates/mail/.agents/skills/real-time-sync/SKILL.md +15 -0
  343. package/corpus/templates/mail/.agents/skills/storing-data/SKILL.md +8 -0
  344. package/corpus/templates/mail/app/root.tsx +60 -1
  345. package/corpus/templates/mail/changelog/2026-07-03-error-screens-now-include-a-feedback-button-with-debug-info.md +6 -0
  346. package/corpus/templates/mail/package.json +3 -3
  347. package/corpus/templates/mail/server/lib/contact-frequency.ts +42 -15
  348. package/corpus/templates/mail/server/plugins/db.ts +63 -2
  349. package/corpus/templates/plan/.agents/skills/real-time-sync/SKILL.md +15 -0
  350. package/corpus/templates/plan/.agents/skills/visual-plan/SKILL.md +9 -3
  351. package/corpus/templates/plan/.agents/skills/visualize-repo/SKILL.md +92 -0
  352. package/corpus/templates/plan/actions/export-visual-plan.ts +5 -0
  353. package/corpus/templates/plan/actions/get-local-plan-folder.ts +4 -22
  354. package/corpus/templates/plan/actions/get-plan-version.ts +6 -16
  355. package/corpus/templates/plan/actions/list-plan-versions.ts +48 -20
  356. package/corpus/templates/plan/actions/patch-visual-plan-source.ts +41 -1
  357. package/corpus/templates/plan/actions/promote-local-plan-folder.ts +4 -22
  358. package/corpus/templates/plan/actions/update-local-plan-comments.ts +4 -2
  359. package/corpus/templates/plan/actions/update-local-plan-folder.ts +4 -22
  360. package/corpus/templates/plan/actions/update-visual-plan.ts +60 -1
  361. package/corpus/templates/plan/agent-native.app-skill.json +10 -0
  362. package/corpus/templates/plan/app/components/editor/PlanDocumentEditor.tsx +138 -39
  363. package/corpus/templates/plan/app/components/editor/usePlanUndoStack.ts +165 -23
  364. package/corpus/templates/plan/app/components/plan/PlanContentRenderer.tsx +80 -4
  365. package/corpus/templates/plan/app/global.css +11 -9
  366. package/corpus/templates/plan/app/hooks/use-navigation-state.ts +10 -1
  367. package/corpus/templates/plan/app/hooks/use-plan-presence.ts +66 -0
  368. package/corpus/templates/plan/app/i18n/ar-SA.ts +3 -0
  369. package/corpus/templates/plan/app/i18n/de-DE.ts +4 -0
  370. package/corpus/templates/plan/app/i18n/en-US.ts +4 -0
  371. package/corpus/templates/plan/app/i18n/es-ES.ts +4 -0
  372. package/corpus/templates/plan/app/i18n/fr-FR.ts +4 -0
  373. package/corpus/templates/plan/app/i18n/hi-IN.ts +3 -0
  374. package/corpus/templates/plan/app/i18n/ja-JP.ts +4 -0
  375. package/corpus/templates/plan/app/i18n/ko-KR.ts +4 -0
  376. package/corpus/templates/plan/app/i18n/pt-BR.ts +4 -0
  377. package/corpus/templates/plan/app/i18n/zh-CN.ts +3 -0
  378. package/corpus/templates/plan/app/i18n/zh-TW.ts +3 -0
  379. package/corpus/templates/plan/app/pages/PlansPage.tsx +289 -66
  380. package/corpus/templates/plan/changelog/2026-07-03-error-screens-now-include-a-feedback-button-with-debug-info.md +6 -0
  381. package/corpus/templates/plan/changelog/2026-07-03-local-visual-plans-and-recaps-can-save-comments-without-sign.md +6 -0
  382. package/corpus/templates/plan/changelog/2026-07-03-plan-tabs-render-nested-text-instead-of-raw-json.md +6 -0
  383. package/corpus/templates/plan/changelog/2026-07-03-plans-are-now-fully-real-time-collaborative-multiple-people-.md +6 -0
  384. package/corpus/templates/plan/changelog/2026-07-03-plans-open-and-refresh-faster-especially-long-lived-plans-wi.md +6 -0
  385. package/corpus/templates/plan/changelog/2026-07-03-undo-now-survives-agent-edits-cmd-z-keeps-working-on-your-ow.md +6 -0
  386. package/corpus/templates/plan/package.json +5 -3
  387. package/corpus/templates/plan/server/db/schema.ts +12 -0
  388. package/corpus/templates/plan/server/lib/local-plan-kind.ts +25 -0
  389. package/corpus/templates/plan/server/lib/plan-versions.ts +83 -1
  390. package/corpus/templates/plan/server/lib/public-action-paths.ts +0 -2
  391. package/corpus/templates/plan/server/plans.ts +26 -3
  392. package/corpus/templates/plan/server/plugins/db.ts +105 -2
  393. package/corpus/templates/slides/.agents/skills/slide-editing/SKILL.md +8 -4
  394. package/corpus/templates/slides/AGENTS.md +11 -3
  395. package/corpus/templates/slides/actions/_agent-presence.ts +48 -0
  396. package/corpus/templates/slides/actions/add-slide.ts +16 -18
  397. package/corpus/templates/slides/actions/get-design-system.ts +21 -0
  398. package/corpus/templates/slides/actions/import-file.ts +15 -7
  399. package/corpus/templates/slides/actions/index-design-system-with-builder.ts +14 -37
  400. package/corpus/templates/slides/actions/patch-deck.ts +4 -2
  401. package/corpus/templates/slides/actions/update-slide.ts +114 -77
  402. package/corpus/templates/slides/actions/view-screen.ts +39 -0
  403. package/corpus/templates/slides/app/components/design-system/DesignSystemSetup.tsx +32 -8
  404. package/corpus/templates/slides/app/components/editor/EditorSidebar.tsx +47 -3
  405. package/corpus/templates/slides/app/components/editor/EditorToolbar.tsx +34 -39
  406. package/corpus/templates/slides/app/components/editor/SlideEditor.tsx +507 -72
  407. package/corpus/templates/slides/app/components/editor/SlideStyleInspector.tsx +346 -0
  408. package/corpus/templates/slides/app/components/editor/SpeakerNotesPanel.tsx +56 -6
  409. package/corpus/templates/slides/app/components/editor/TweaksPanel.tsx +46 -96
  410. package/corpus/templates/slides/app/components/layout/Layout.tsx +6 -1
  411. package/corpus/templates/slides/app/components/visual-editor/SaveStatusIndicator.tsx +8 -1
  412. package/corpus/templates/slides/app/context/DeckContext.tsx +589 -176
  413. package/corpus/templates/slides/app/hooks/use-deck-presence.ts +84 -42
  414. package/corpus/templates/slides/app/i18n/ar-SA.ts +54 -7
  415. package/corpus/templates/slides/app/i18n/de-DE.ts +53 -8
  416. package/corpus/templates/slides/app/i18n/en-US.ts +54 -7
  417. package/corpus/templates/slides/app/i18n/es-ES.ts +53 -8
  418. package/corpus/templates/slides/app/i18n/fr-FR.ts +53 -8
  419. package/corpus/templates/slides/app/i18n/hi-IN.ts +54 -7
  420. package/corpus/templates/slides/app/i18n/ja-JP.ts +53 -8
  421. package/corpus/templates/slides/app/i18n/ko-KR.ts +53 -7
  422. package/corpus/templates/slides/app/i18n/pt-BR.ts +53 -8
  423. package/corpus/templates/slides/app/i18n/zh-CN.ts +54 -7
  424. package/corpus/templates/slides/app/i18n/zh-TW.ts +54 -7
  425. package/corpus/templates/slides/app/lib/canvas-zoom.ts +16 -1
  426. package/corpus/templates/slides/app/pages/DeckEditor.tsx +28 -16
  427. package/corpus/templates/slides/changelog/2026-07-03-design-system-setup-now-indexes-figma-code-and-design-md-sou.md +6 -0
  428. package/corpus/templates/slides/changelog/2026-07-03-figma-style-slide-editing.md +6 -0
  429. package/corpus/templates/slides/changelog/2026-07-03-see-the-ai-working-with-you-when-the-agent-edits-a-slide-it-.md +6 -0
  430. package/corpus/templates/slides/changelog/2026-07-03-slide-editing-now-keeps-thumbnails-speaker-notes-styling-and.md +6 -0
  431. package/corpus/templates/slides/changelog/2026-07-03-undo-redo-is-now-precise-and-safe-with-collaborators-it-only.md +6 -0
  432. package/corpus/templates/slides/package.json +3 -3
  433. package/corpus/templates/slides/server/handlers/decks.ts +31 -3
  434. package/corpus/templates/slides/server/lib/builder-design-system-proxy.ts +16 -104
  435. package/corpus/templates/slides/server/plugins/db.ts +65 -2
  436. package/corpus/templates/videos/netlify.toml +1 -12
  437. package/dist/agent/run-store.js +1 -1
  438. package/dist/agent/run-store.js.map +1 -1
  439. package/dist/chat-threads/store.d.ts +9 -1
  440. package/dist/chat-threads/store.d.ts.map +1 -1
  441. package/dist/chat-threads/store.js +63 -11
  442. package/dist/chat-threads/store.js.map +1 -1
  443. package/dist/checkpoints/store.d.ts.map +1 -1
  444. package/dist/checkpoints/store.js +10 -2
  445. package/dist/checkpoints/store.js.map +1 -1
  446. package/dist/cli/create.d.ts.map +1 -1
  447. package/dist/cli/create.js +3 -5
  448. package/dist/cli/create.js.map +1 -1
  449. package/dist/cli/design-connect.d.ts +49 -1
  450. package/dist/cli/design-connect.d.ts.map +1 -1
  451. package/dist/cli/design-connect.js +414 -9
  452. package/dist/cli/design-connect.js.map +1 -1
  453. package/dist/cli/index.js +12 -0
  454. package/dist/cli/index.js.map +1 -1
  455. package/dist/cli/plan-local.d.ts +24 -0
  456. package/dist/cli/plan-local.d.ts.map +1 -1
  457. package/dist/cli/plan-local.js +188 -20
  458. package/dist/cli/plan-local.js.map +1 -1
  459. package/dist/cli/skills.d.ts +3 -1
  460. package/dist/cli/skills.d.ts.map +1 -1
  461. package/dist/cli/skills.js +173 -21
  462. package/dist/cli/skills.js.map +1 -1
  463. package/dist/cli/templates-meta.d.ts.map +1 -1
  464. package/dist/cli/templates-meta.js +0 -14
  465. package/dist/cli/templates-meta.js.map +1 -1
  466. package/dist/cli/visualize-repo.d.ts +49 -0
  467. package/dist/cli/visualize-repo.d.ts.map +1 -0
  468. package/dist/cli/visualize-repo.js +561 -0
  469. package/dist/cli/visualize-repo.js.map +1 -0
  470. package/dist/client/AgentPanel.d.ts.map +1 -1
  471. package/dist/client/AgentPanel.js +2 -1
  472. package/dist/client/AgentPanel.js.map +1 -1
  473. package/dist/client/AssistantChat.d.ts.map +1 -1
  474. package/dist/client/AssistantChat.js +175 -18
  475. package/dist/client/AssistantChat.js.map +1 -1
  476. package/dist/client/ErrorBoundary.d.ts.map +1 -1
  477. package/dist/client/ErrorBoundary.js +37 -2
  478. package/dist/client/ErrorBoundary.js.map +1 -1
  479. package/dist/client/ErrorReportActions.d.ts +13 -0
  480. package/dist/client/ErrorReportActions.d.ts.map +1 -0
  481. package/dist/client/ErrorReportActions.js +14 -0
  482. package/dist/client/ErrorReportActions.js.map +1 -0
  483. package/dist/client/FeedbackButton.d.ts +3 -1
  484. package/dist/client/FeedbackButton.d.ts.map +1 -1
  485. package/dist/client/FeedbackButton.js +6 -5
  486. package/dist/client/FeedbackButton.js.map +1 -1
  487. package/dist/client/agent-chat-adapter.d.ts.map +1 -1
  488. package/dist/client/agent-chat-adapter.js +6 -5
  489. package/dist/client/agent-chat-adapter.js.map +1 -1
  490. package/dist/client/app-providers.d.ts +2 -2
  491. package/dist/client/app-providers.js.map +1 -1
  492. package/dist/client/collab/index.d.ts +4 -1
  493. package/dist/client/collab/index.d.ts.map +1 -1
  494. package/dist/client/collab/index.js +3 -0
  495. package/dist/client/collab/index.js.map +1 -1
  496. package/dist/client/components/LiveCursorOverlay.d.ts.map +1 -1
  497. package/dist/client/components/LiveCursorOverlay.js +11 -3
  498. package/dist/client/components/LiveCursorOverlay.js.map +1 -1
  499. package/dist/client/components/PresenceBar.d.ts.map +1 -1
  500. package/dist/client/components/PresenceBar.js +6 -1
  501. package/dist/client/components/PresenceBar.js.map +1 -1
  502. package/dist/client/components/RecentEditHighlights.d.ts +43 -0
  503. package/dist/client/components/RecentEditHighlights.d.ts.map +1 -0
  504. package/dist/client/components/RecentEditHighlights.js +146 -0
  505. package/dist/client/components/RecentEditHighlights.js.map +1 -0
  506. package/dist/client/components/RemoteSelectionRings.d.ts +9 -0
  507. package/dist/client/components/RemoteSelectionRings.d.ts.map +1 -1
  508. package/dist/client/components/RemoteSelectionRings.js +22 -8
  509. package/dist/client/components/RemoteSelectionRings.js.map +1 -1
  510. package/dist/client/db-admin/DbAdminPage.d.ts +9 -1
  511. package/dist/client/db-admin/DbAdminPage.d.ts.map +1 -1
  512. package/dist/client/db-admin/DbAdminPage.js +17 -13
  513. package/dist/client/db-admin/DbAdminPage.js.map +1 -1
  514. package/dist/client/db-admin/SqlEditor.d.ts +3 -1
  515. package/dist/client/db-admin/SqlEditor.d.ts.map +1 -1
  516. package/dist/client/db-admin/SqlEditor.js +3 -3
  517. package/dist/client/db-admin/SqlEditor.js.map +1 -1
  518. package/dist/client/db-admin/TableEditor.d.ts +3 -1
  519. package/dist/client/db-admin/TableEditor.d.ts.map +1 -1
  520. package/dist/client/db-admin/TableEditor.js +6 -6
  521. package/dist/client/db-admin/TableEditor.js.map +1 -1
  522. package/dist/client/db-admin/useAgentSync.d.ts +3 -2
  523. package/dist/client/db-admin/useAgentSync.d.ts.map +1 -1
  524. package/dist/client/db-admin/useAgentSync.js +8 -4
  525. package/dist/client/db-admin/useAgentSync.js.map +1 -1
  526. package/dist/client/db-admin/useDbAdmin.d.ts +11 -7
  527. package/dist/client/db-admin/useDbAdmin.d.ts.map +1 -1
  528. package/dist/client/db-admin/useDbAdmin.js +45 -20
  529. package/dist/client/db-admin/useDbAdmin.js.map +1 -1
  530. package/dist/client/error-reporting.d.ts +19 -0
  531. package/dist/client/error-reporting.d.ts.map +1 -0
  532. package/dist/client/error-reporting.js +71 -0
  533. package/dist/client/error-reporting.js.map +1 -0
  534. package/dist/client/index.d.ts +8 -1
  535. package/dist/client/index.d.ts.map +1 -1
  536. package/dist/client/index.js +9 -0
  537. package/dist/client/index.js.map +1 -1
  538. package/dist/client/org/OrgSwitcher.d.ts.map +1 -1
  539. package/dist/client/org/OrgSwitcher.js +1 -3
  540. package/dist/client/org/OrgSwitcher.js.map +1 -1
  541. package/dist/client/org/RequireActiveOrg.d.ts.map +1 -1
  542. package/dist/client/org/RequireActiveOrg.js +2 -1
  543. package/dist/client/org/RequireActiveOrg.js.map +1 -1
  544. package/dist/client/rich-markdown-editor/SharedRichEditor.d.ts +8 -1
  545. package/dist/client/rich-markdown-editor/SharedRichEditor.d.ts.map +1 -1
  546. package/dist/client/rich-markdown-editor/SharedRichEditor.js +8 -2
  547. package/dist/client/rich-markdown-editor/SharedRichEditor.js.map +1 -1
  548. package/dist/client/rich-markdown-editor/index.d.ts +1 -0
  549. package/dist/client/rich-markdown-editor/index.d.ts.map +1 -1
  550. package/dist/client/rich-markdown-editor/index.js +1 -0
  551. package/dist/client/rich-markdown-editor/index.js.map +1 -1
  552. package/dist/client/rich-markdown-editor/surgical-apply.d.ts +66 -0
  553. package/dist/client/rich-markdown-editor/surgical-apply.d.ts.map +1 -0
  554. package/dist/client/rich-markdown-editor/surgical-apply.js +147 -0
  555. package/dist/client/rich-markdown-editor/surgical-apply.js.map +1 -0
  556. package/dist/client/rich-markdown-editor/useCollabReconcile.d.ts +18 -2
  557. package/dist/client/rich-markdown-editor/useCollabReconcile.d.ts.map +1 -1
  558. package/dist/client/rich-markdown-editor/useCollabReconcile.js +39 -8
  559. package/dist/client/rich-markdown-editor/useCollabReconcile.js.map +1 -1
  560. package/dist/client/session-replay.d.ts +10 -1
  561. package/dist/client/session-replay.d.ts.map +1 -1
  562. package/dist/client/session-replay.js +134 -7
  563. package/dist/client/session-replay.js.map +1 -1
  564. package/dist/client/sse-event-processor.d.ts.map +1 -1
  565. package/dist/client/sse-event-processor.js +81 -1
  566. package/dist/client/sse-event-processor.js.map +1 -1
  567. package/dist/client/use-action.d.ts +24 -0
  568. package/dist/client/use-action.d.ts.map +1 -1
  569. package/dist/client/use-action.js +109 -27
  570. package/dist/client/use-action.js.map +1 -1
  571. package/dist/client/use-agent-engine-configured.d.ts.map +1 -1
  572. package/dist/client/use-agent-engine-configured.js +7 -1
  573. package/dist/client/use-agent-engine-configured.js.map +1 -1
  574. package/dist/client/use-chat-threads.d.ts.map +1 -1
  575. package/dist/client/use-chat-threads.js +11 -3
  576. package/dist/client/use-chat-threads.js.map +1 -1
  577. package/dist/client/use-db-sync.d.ts +36 -0
  578. package/dist/client/use-db-sync.d.ts.map +1 -1
  579. package/dist/client/use-db-sync.js +68 -12
  580. package/dist/client/use-db-sync.js.map +1 -1
  581. package/dist/client/visual-style-controls.d.ts +90 -0
  582. package/dist/client/visual-style-controls.d.ts.map +1 -0
  583. package/dist/client/visual-style-controls.js +499 -0
  584. package/dist/client/visual-style-controls.js.map +1 -0
  585. package/dist/collab/agent-presence.d.ts +51 -5
  586. package/dist/collab/agent-presence.d.ts.map +1 -1
  587. package/dist/collab/agent-presence.js +144 -58
  588. package/dist/collab/agent-presence.js.map +1 -1
  589. package/dist/collab/awareness-store.d.ts +32 -0
  590. package/dist/collab/awareness-store.d.ts.map +1 -0
  591. package/dist/collab/awareness-store.js +0 -0
  592. package/dist/collab/awareness-store.js.map +1 -0
  593. package/dist/collab/awareness.d.ts +12 -1
  594. package/dist/collab/awareness.d.ts.map +1 -1
  595. package/dist/collab/awareness.js +53 -5
  596. package/dist/collab/awareness.js.map +1 -1
  597. package/dist/collab/client.d.ts +2 -0
  598. package/dist/collab/client.d.ts.map +1 -1
  599. package/dist/collab/client.js +79 -119
  600. package/dist/collab/client.js.map +1 -1
  601. package/dist/collab/index.d.ts +3 -1
  602. package/dist/collab/index.d.ts.map +1 -1
  603. package/dist/collab/index.js +5 -1
  604. package/dist/collab/index.js.map +1 -1
  605. package/dist/collab/recent-edits.d.ts +87 -0
  606. package/dist/collab/recent-edits.d.ts.map +1 -0
  607. package/dist/collab/recent-edits.js +116 -0
  608. package/dist/collab/recent-edits.js.map +1 -0
  609. package/dist/collab/routes.d.ts +1 -1
  610. package/dist/collab/undo.d.ts +121 -0
  611. package/dist/collab/undo.d.ts.map +1 -0
  612. package/dist/collab/undo.js +244 -0
  613. package/dist/collab/undo.js.map +1 -0
  614. package/dist/collab/ydoc-manager.d.ts +10 -0
  615. package/dist/collab/ydoc-manager.d.ts.map +1 -1
  616. package/dist/collab/ydoc-manager.js +57 -0
  617. package/dist/collab/ydoc-manager.js.map +1 -1
  618. package/dist/connections/catalog.d.ts +2 -2
  619. package/dist/connections/catalog.d.ts.map +1 -1
  620. package/dist/connections/catalog.js +1 -1
  621. package/dist/connections/catalog.js.map +1 -1
  622. package/dist/db/create-get-db.d.ts +22 -0
  623. package/dist/db/create-get-db.d.ts.map +1 -1
  624. package/dist/db/create-get-db.js +73 -1
  625. package/dist/db/create-get-db.js.map +1 -1
  626. package/dist/db/ensure-additive-columns.d.ts +93 -0
  627. package/dist/db/ensure-additive-columns.d.ts.map +1 -0
  628. package/dist/db/ensure-additive-columns.js +355 -0
  629. package/dist/db/ensure-additive-columns.js.map +1 -0
  630. package/dist/db/index.d.ts +1 -0
  631. package/dist/db/index.d.ts.map +1 -1
  632. package/dist/db/index.js +1 -0
  633. package/dist/db/index.js.map +1 -1
  634. package/dist/db/migrations.d.ts +70 -0
  635. package/dist/db/migrations.d.ts.map +1 -1
  636. package/dist/db/migrations.js +196 -33
  637. package/dist/db/migrations.js.map +1 -1
  638. package/dist/db-admin/index.d.ts +3 -0
  639. package/dist/db-admin/index.d.ts.map +1 -0
  640. package/dist/db-admin/index.js +2 -0
  641. package/dist/db-admin/index.js.map +1 -0
  642. package/dist/db-admin/operations.d.ts +26 -5
  643. package/dist/db-admin/operations.d.ts.map +1 -1
  644. package/dist/db-admin/operations.js +66 -55
  645. package/dist/db-admin/operations.js.map +1 -1
  646. package/dist/jobs/scheduler.js +17 -10
  647. package/dist/jobs/scheduler.js.map +1 -1
  648. package/dist/localization/default-messages.d.ts +3 -0
  649. package/dist/localization/default-messages.d.ts.map +1 -1
  650. package/dist/localization/default-messages.js +3 -0
  651. package/dist/localization/default-messages.js.map +1 -1
  652. package/dist/notifications/routes.d.ts +2 -2
  653. package/dist/observability/routes.d.ts +2 -2
  654. package/dist/observability/traces.d.ts.map +1 -1
  655. package/dist/observability/traces.js +155 -1
  656. package/dist/observability/traces.js.map +1 -1
  657. package/dist/org/context.d.ts +7 -0
  658. package/dist/org/context.d.ts.map +1 -1
  659. package/dist/org/context.js +54 -2
  660. package/dist/org/context.js.map +1 -1
  661. package/dist/provider-api/corpus-jobs.d.ts +2 -2
  662. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  663. package/dist/server/agent-chat-plugin.js +10 -6
  664. package/dist/server/agent-chat-plugin.js.map +1 -1
  665. package/dist/server/auth-marketing.d.ts.map +1 -1
  666. package/dist/server/auth-marketing.js +0 -10
  667. package/dist/server/auth-marketing.js.map +1 -1
  668. package/dist/server/auth.d.ts.map +1 -1
  669. package/dist/server/auth.js +6 -4
  670. package/dist/server/auth.js.map +1 -1
  671. package/dist/server/builder-design-systems.d.ts +61 -0
  672. package/dist/server/builder-design-systems.d.ts.map +1 -1
  673. package/dist/server/builder-design-systems.js +219 -14
  674. package/dist/server/builder-design-systems.js.map +1 -1
  675. package/dist/server/collab-plugin.d.ts.map +1 -1
  676. package/dist/server/collab-plugin.js +45 -13
  677. package/dist/server/collab-plugin.js.map +1 -1
  678. package/dist/server/design-token-utils.d.ts +1 -1
  679. package/dist/server/design-token-utils.js +1 -1
  680. package/dist/server/design-token-utils.js.map +1 -1
  681. package/dist/server/fusion-app.d.ts +107 -0
  682. package/dist/server/fusion-app.d.ts.map +1 -0
  683. package/dist/server/fusion-app.js +371 -0
  684. package/dist/server/fusion-app.js.map +1 -0
  685. package/dist/server/index.d.ts +2 -1
  686. package/dist/server/index.d.ts.map +1 -1
  687. package/dist/server/index.js +2 -1
  688. package/dist/server/index.js.map +1 -1
  689. package/dist/server/onboarding-html.d.ts.map +1 -1
  690. package/dist/server/onboarding-html.js +3 -4
  691. package/dist/server/onboarding-html.js.map +1 -1
  692. package/dist/server/poll-events.d.ts +2 -0
  693. package/dist/server/poll-events.d.ts.map +1 -1
  694. package/dist/server/poll-events.js +7 -2
  695. package/dist/server/poll-events.js.map +1 -1
  696. package/dist/server/poll.d.ts +47 -3
  697. package/dist/server/poll.d.ts.map +1 -1
  698. package/dist/server/poll.js +176 -10
  699. package/dist/server/poll.js.map +1 -1
  700. package/dist/server/schema-prompt.d.ts.map +1 -1
  701. package/dist/server/schema-prompt.js +24 -7
  702. package/dist/server/schema-prompt.js.map +1 -1
  703. package/dist/settings/store.d.ts.map +1 -1
  704. package/dist/settings/store.js +32 -3
  705. package/dist/settings/store.js.map +1 -1
  706. package/dist/sharing/actions/set-resource-visibility.js +2 -0
  707. package/dist/sharing/actions/set-resource-visibility.js.map +1 -1
  708. package/dist/sharing/actions/share-resource.d.ts.map +1 -1
  709. package/dist/sharing/actions/share-resource.js +3 -0
  710. package/dist/sharing/actions/share-resource.js.map +1 -1
  711. package/dist/sharing/actions/unshare-resource.js +2 -0
  712. package/dist/sharing/actions/unshare-resource.js.map +1 -1
  713. package/dist/styles/agent-native.css +0 -5
  714. package/dist/templates/default/.agents/skills/real-time-collab/SKILL.md +82 -19
  715. package/dist/templates/default/.agents/skills/real-time-sync/SKILL.md +15 -0
  716. package/dist/templates/default/.agents/skills/storing-data/SKILL.md +8 -0
  717. package/dist/templates/default/app/root.tsx +47 -0
  718. package/dist/templates/default/package.json +3 -3
  719. package/dist/templates/workspace-core/.agents/skills/client-methods/SKILL.md +8 -0
  720. package/dist/templates/workspace-core/.agents/skills/observability/SKILL.md +22 -0
  721. package/dist/templates/workspace-core/.agents/skills/real-time-collab/SKILL.md +82 -19
  722. package/dist/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +15 -0
  723. package/dist/templates/workspace-core/.agents/skills/storing-data/SKILL.md +8 -0
  724. package/dist/templates/workspace-core/.agents/skills/tracking/SKILL.md +1 -0
  725. package/dist/tracking/providers.d.ts.map +1 -1
  726. package/dist/tracking/providers.js +17 -1
  727. package/dist/tracking/providers.js.map +1 -1
  728. package/docs/content/cloneable-saas.mdx +0 -1
  729. package/docs/content/locales/ar-SA/cloneable-saas.mdx +0 -1
  730. package/docs/content/locales/ar-SA/plan-plugin.mdx +10 -9
  731. package/docs/content/locales/ar-SA/sharing.mdx +1 -2
  732. package/docs/content/locales/ar-SA/skills-guide.mdx +2 -3
  733. package/docs/content/locales/ar-SA/template-plan.mdx +23 -7
  734. package/docs/content/locales/ar-SA/tracking.mdx +1 -1
  735. package/docs/content/locales/ar-SA/workspace-connections.mdx +11 -11
  736. package/docs/content/locales/de-DE/cloneable-saas.mdx +0 -1
  737. package/docs/content/locales/de-DE/plan-plugin.mdx +10 -9
  738. package/docs/content/locales/de-DE/sharing.mdx +1 -2
  739. package/docs/content/locales/de-DE/skills-guide.mdx +2 -3
  740. package/docs/content/locales/de-DE/template-plan.mdx +23 -7
  741. package/docs/content/locales/de-DE/tracking.mdx +1 -1
  742. package/docs/content/locales/de-DE/workspace-connections.mdx +1 -1
  743. package/docs/content/locales/es-ES/cloneable-saas.mdx +0 -1
  744. package/docs/content/locales/es-ES/plan-plugin.mdx +10 -9
  745. package/docs/content/locales/es-ES/sharing.mdx +1 -2
  746. package/docs/content/locales/es-ES/skills-guide.mdx +2 -3
  747. package/docs/content/locales/es-ES/template-plan.mdx +23 -7
  748. package/docs/content/locales/es-ES/tracking.mdx +1 -1
  749. package/docs/content/locales/es-ES/workspace-connections.mdx +1 -1
  750. package/docs/content/locales/fr-FR/cloneable-saas.mdx +0 -1
  751. package/docs/content/locales/fr-FR/plan-plugin.mdx +10 -9
  752. package/docs/content/locales/fr-FR/sharing.mdx +1 -2
  753. package/docs/content/locales/fr-FR/skills-guide.mdx +2 -3
  754. package/docs/content/locales/fr-FR/template-plan.mdx +23 -7
  755. package/docs/content/locales/fr-FR/tracking.mdx +1 -1
  756. package/docs/content/locales/fr-FR/workspace-connections.mdx +1 -1
  757. package/docs/content/locales/hi-IN/cloneable-saas.mdx +0 -1
  758. package/docs/content/locales/hi-IN/plan-plugin.mdx +10 -9
  759. package/docs/content/locales/hi-IN/sharing.mdx +1 -2
  760. package/docs/content/locales/hi-IN/skills-guide.mdx +2 -3
  761. package/docs/content/locales/hi-IN/template-plan.mdx +23 -7
  762. package/docs/content/locales/hi-IN/tracking.mdx +1 -1
  763. package/docs/content/locales/hi-IN/workspace-connections.mdx +1 -1
  764. package/docs/content/locales/ja-JP/cloneable-saas.mdx +0 -1
  765. package/docs/content/locales/ja-JP/plan-plugin.mdx +10 -9
  766. package/docs/content/locales/ja-JP/sharing.mdx +1 -2
  767. package/docs/content/locales/ja-JP/skills-guide.mdx +2 -3
  768. package/docs/content/locales/ja-JP/template-plan.mdx +23 -7
  769. package/docs/content/locales/ja-JP/tracking.mdx +1 -1
  770. package/docs/content/locales/ja-JP/workspace-connections.mdx +1 -1
  771. package/docs/content/locales/ko-KR/cloneable-saas.mdx +0 -1
  772. package/docs/content/locales/ko-KR/plan-plugin.mdx +10 -9
  773. package/docs/content/locales/ko-KR/sharing.mdx +1 -2
  774. package/docs/content/locales/ko-KR/skills-guide.mdx +2 -3
  775. package/docs/content/locales/ko-KR/template-plan.mdx +23 -7
  776. package/docs/content/locales/ko-KR/tracking.mdx +1 -1
  777. package/docs/content/locales/ko-KR/workspace-connections.mdx +1 -1
  778. package/docs/content/locales/pt-BR/cloneable-saas.mdx +0 -1
  779. package/docs/content/locales/pt-BR/plan-plugin.mdx +10 -9
  780. package/docs/content/locales/pt-BR/sharing.mdx +1 -2
  781. package/docs/content/locales/pt-BR/skills-guide.mdx +2 -3
  782. package/docs/content/locales/pt-BR/template-plan.mdx +23 -7
  783. package/docs/content/locales/pt-BR/tracking.mdx +1 -1
  784. package/docs/content/locales/pt-BR/workspace-connections.mdx +1 -1
  785. package/docs/content/locales/zh-CN/cloneable-saas.mdx +0 -1
  786. package/docs/content/locales/zh-CN/plan-plugin.mdx +10 -9
  787. package/docs/content/locales/zh-CN/sharing.mdx +1 -2
  788. package/docs/content/locales/zh-CN/skills-guide.mdx +2 -3
  789. package/docs/content/locales/zh-CN/template-plan.mdx +23 -7
  790. package/docs/content/locales/zh-CN/tracking.mdx +1 -1
  791. package/docs/content/locales/zh-CN/workspace-connections.mdx +1 -1
  792. package/docs/content/locales/zh-TW/cloneable-saas.mdx +0 -1
  793. package/docs/content/locales/zh-TW/plan-plugin.mdx +10 -9
  794. package/docs/content/locales/zh-TW/sharing.mdx +1 -2
  795. package/docs/content/locales/zh-TW/skills-guide.mdx +2 -3
  796. package/docs/content/locales/zh-TW/template-plan.mdx +23 -7
  797. package/docs/content/locales/zh-TW/tracking.mdx +1 -1
  798. package/docs/content/locales/zh-TW/workspace-connections.mdx +1 -1
  799. package/docs/content/plan-plugin.mdx +12 -11
  800. package/docs/content/sharing.mdx +1 -2
  801. package/docs/content/skills-guide.mdx +4 -3
  802. package/docs/content/template-plan.mdx +37 -6
  803. package/docs/content/tracking.mdx +1 -1
  804. package/docs/content/workspace-connections.mdx +1 -1
  805. package/package.json +7 -6
  806. package/src/templates/default/.agents/skills/real-time-collab/SKILL.md +82 -19
  807. package/src/templates/default/.agents/skills/real-time-sync/SKILL.md +15 -0
  808. package/src/templates/default/.agents/skills/storing-data/SKILL.md +8 -0
  809. package/src/templates/default/app/root.tsx +47 -0
  810. package/src/templates/default/package.json +3 -3
  811. package/src/templates/workspace-core/.agents/skills/client-methods/SKILL.md +8 -0
  812. package/src/templates/workspace-core/.agents/skills/observability/SKILL.md +22 -0
  813. package/src/templates/workspace-core/.agents/skills/real-time-collab/SKILL.md +82 -19
  814. package/src/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +15 -0
  815. package/src/templates/workspace-core/.agents/skills/storing-data/SKILL.md +8 -0
  816. package/src/templates/workspace-core/.agents/skills/tracking/SKILL.md +1 -0
  817. package/corpus/core/docs/content/locales/ar-SA/template-videos.mdx +0 -336
  818. package/corpus/core/docs/content/locales/de-DE/template-videos.mdx +0 -336
  819. package/corpus/core/docs/content/locales/es-ES/template-videos.mdx +0 -336
  820. package/corpus/core/docs/content/locales/fr-FR/template-videos.mdx +0 -336
  821. package/corpus/core/docs/content/locales/hi-IN/template-videos.mdx +0 -336
  822. package/corpus/core/docs/content/locales/ja-JP/template-videos.mdx +0 -336
  823. package/corpus/core/docs/content/locales/ko-KR/template-videos.mdx +0 -336
  824. package/corpus/core/docs/content/locales/pt-BR/template-videos.mdx +0 -336
  825. package/corpus/core/docs/content/locales/zh-CN/template-videos.mdx +0 -334
  826. package/corpus/core/docs/content/locales/zh-TW/template-videos.mdx +0 -334
  827. package/corpus/core/docs/content/template-videos.mdx +0 -332
  828. package/corpus/templates/design/app/components/design/CodeWorkbenchHost.tsx +0 -697
  829. package/corpus/templates/slides/app/components/editor/CodeEditor.tsx +0 -49
  830. package/corpus/templates/videos/.agents/skills/actions/SKILL.md +0 -432
  831. package/corpus/templates/videos/.agents/skills/animation-tracks/SKILL.md +0 -99
  832. package/corpus/templates/videos/.agents/skills/capture-learnings/SKILL.md +0 -76
  833. package/corpus/templates/videos/.agents/skills/composition-management/SKILL.md +0 -106
  834. package/corpus/templates/videos/.agents/skills/create-skill/SKILL.md +0 -221
  835. package/corpus/templates/videos/.agents/skills/delegate-to-agent/SKILL.md +0 -263
  836. package/corpus/templates/videos/.agents/skills/frontend-design/SKILL.md +0 -112
  837. package/corpus/templates/videos/.agents/skills/security/SKILL.md +0 -263
  838. package/corpus/templates/videos/.agents/skills/self-modifying-code/SKILL.md +0 -88
  839. package/corpus/templates/videos/.agents/skills/shadcn-ui/SKILL.md +0 -95
  840. package/corpus/templates/videos/.builder/ANIMATED_PROPERTIES.md +0 -335
  841. package/corpus/templates/videos/.builder/KEYFRAME_SYNC.md +0 -166
  842. package/corpus/templates/videos/.builder/SEAMLESS_SYNC.md +0 -211
  843. package/corpus/templates/videos/.builder/rules/deploy-app.mdc +0 -22
  844. package/corpus/templates/videos/.builder/rules/organize-ui.mdc +0 -9
  845. package/corpus/templates/videos/.builder/skills/remotion/SKILL.md +0 -29
  846. package/corpus/templates/videos/.builder/skills/remotion/rules/animations.md +0 -27
  847. package/corpus/templates/videos/.builder/skills/remotion/rules/assets.md +0 -43
  848. package/corpus/templates/videos/.builder/skills/remotion/rules/audio.md +0 -58
  849. package/corpus/templates/videos/.builder/skills/remotion/rules/compositions.md +0 -129
  850. package/corpus/templates/videos/.builder/skills/remotion/rules/fonts.md +0 -47
  851. package/corpus/templates/videos/.builder/skills/remotion/rules/images.md +0 -41
  852. package/corpus/templates/videos/.builder/skills/remotion/rules/parameters.md +0 -59
  853. package/corpus/templates/videos/.builder/skills/remotion/rules/sequencing.md +0 -54
  854. package/corpus/templates/videos/.builder/skills/remotion/rules/tailwind.md +0 -11
  855. package/corpus/templates/videos/.builder/skills/remotion/rules/text-animations.md +0 -18
  856. package/corpus/templates/videos/.builder/skills/remotion/rules/timing.md +0 -103
  857. package/corpus/templates/videos/.builder/skills/remotion/rules/transparent-videos.md +0 -35
  858. package/corpus/templates/videos/.builder/skills/remotion/rules/trimming.md +0 -38
  859. package/corpus/templates/videos/.builder/skills/remotion/rules/videos.md +0 -54
  860. package/corpus/templates/videos/.dockerignore +0 -62
  861. package/corpus/templates/videos/.env.example +0 -4
  862. package/corpus/templates/videos/.oxfmtrc.json +0 -8
  863. package/corpus/templates/videos/AGENTS.md +0 -46
  864. package/corpus/templates/videos/CHANGELOG.md +0 -10
  865. package/corpus/templates/videos/DEVELOPING.md +0 -143
  866. package/corpus/templates/videos/README.md +0 -33
  867. package/corpus/templates/videos/actions/analyze-brand-assets.ts +0 -151
  868. package/corpus/templates/videos/actions/apply-design-system.ts +0 -35
  869. package/corpus/templates/videos/actions/create-design-system.ts +0 -84
  870. package/corpus/templates/videos/actions/create-folder.ts +0 -48
  871. package/corpus/templates/videos/actions/db-connect.ts +0 -45
  872. package/corpus/templates/videos/actions/db-health.ts +0 -24
  873. package/corpus/templates/videos/actions/db-status.ts +0 -28
  874. package/corpus/templates/videos/actions/delete-composition.ts +0 -272
  875. package/corpus/templates/videos/actions/delete-folder.ts +0 -27
  876. package/corpus/templates/videos/actions/generate-animated-component.ts +0 -470
  877. package/corpus/templates/videos/actions/get-composition.ts +0 -36
  878. package/corpus/templates/videos/actions/get-design-system.ts +0 -35
  879. package/corpus/templates/videos/actions/import-code.ts +0 -67
  880. package/corpus/templates/videos/actions/import-design-project.ts +0 -42
  881. package/corpus/templates/videos/actions/import-document.ts +0 -125
  882. package/corpus/templates/videos/actions/import-from-url.ts +0 -18
  883. package/corpus/templates/videos/actions/import-github.ts +0 -182
  884. package/corpus/templates/videos/actions/list-compositions.ts +0 -32
  885. package/corpus/templates/videos/actions/list-design-systems.ts +0 -66
  886. package/corpus/templates/videos/actions/list-folders.ts +0 -61
  887. package/corpus/templates/videos/actions/move-composition-to-folder.ts +0 -59
  888. package/corpus/templates/videos/actions/navigate.ts +0 -40
  889. package/corpus/templates/videos/actions/rename-folder.ts +0 -41
  890. package/corpus/templates/videos/actions/run.ts +0 -2
  891. package/corpus/templates/videos/actions/save-composition.ts +0 -114
  892. package/corpus/templates/videos/actions/set-default-design-system.ts +0 -40
  893. package/corpus/templates/videos/actions/update-composition.ts +0 -81
  894. package/corpus/templates/videos/actions/update-design-system.ts +0 -68
  895. package/corpus/templates/videos/actions/validate-compositions.ts +0 -502
  896. package/corpus/templates/videos/actions/view-screen.ts +0 -48
  897. package/corpus/templates/videos/app/components/CameraControls.tsx +0 -442
  898. package/corpus/templates/videos/app/components/CameraToolbar.tsx +0 -437
  899. package/corpus/templates/videos/app/components/CloudUpgrade.tsx +0 -287
  900. package/corpus/templates/videos/app/components/CollabPresenceBar.tsx +0 -81
  901. package/corpus/templates/videos/app/components/CompSettingsEditor.tsx +0 -107
  902. package/corpus/templates/videos/app/components/ComponentLibrarySidebar.tsx +0 -457
  903. package/corpus/templates/videos/app/components/ComponentPropsPanel.tsx +0 -227
  904. package/corpus/templates/videos/app/components/ComponentsSidebar.tsx +0 -70
  905. package/corpus/templates/videos/app/components/CompositionCard.tsx +0 -147
  906. package/corpus/templates/videos/app/components/CurrentElementPanel.tsx +0 -835
  907. package/corpus/templates/videos/app/components/CursorControls.tsx +0 -664
  908. package/corpus/templates/videos/app/components/CursorPositioningOverlay.tsx +0 -238
  909. package/corpus/templates/videos/app/components/LibraryFolderRow.tsx +0 -235
  910. package/corpus/templates/videos/app/components/MotionCurveSelect.tsx +0 -61
  911. package/corpus/templates/videos/app/components/NewCompositionPopover.tsx +0 -192
  912. package/corpus/templates/videos/app/components/PropsEditor.tsx +0 -210
  913. package/corpus/templates/videos/app/components/QuestionFlow.tsx +0 -40
  914. package/corpus/templates/videos/app/components/Sidebar.tsx +0 -609
  915. package/corpus/templates/videos/app/components/StudioHeader.tsx +0 -109
  916. package/corpus/templates/videos/app/components/Timeline.tsx +0 -2067
  917. package/corpus/templates/videos/app/components/TrackPropertiesPanel.tsx +0 -922
  918. package/corpus/templates/videos/app/components/TweaksPanel.tsx +0 -277
  919. package/corpus/templates/videos/app/components/VideoPlayer.tsx +0 -487
  920. package/corpus/templates/videos/app/components/design-system/DesignSystemCard.tsx +0 -134
  921. package/corpus/templates/videos/app/components/design-system/DesignSystemPreview.tsx +0 -176
  922. package/corpus/templates/videos/app/components/design-system/DesignSystemSetup.tsx +0 -707
  923. package/corpus/templates/videos/app/components/keyframes/KeyframeActionButtons.tsx +0 -78
  924. package/corpus/templates/videos/app/components/keyframes/KeyframeNavigation.tsx +0 -59
  925. package/corpus/templates/videos/app/components/keyframes/PropertyNumberInput.tsx +0 -56
  926. package/corpus/templates/videos/app/components/layout/Header.tsx +0 -64
  927. package/corpus/templates/videos/app/components/layout/HeaderActions.tsx +0 -84
  928. package/corpus/templates/videos/app/components/layout/Layout.tsx +0 -132
  929. package/corpus/templates/videos/app/components/layout/NavSidebar.tsx +0 -180
  930. package/corpus/templates/videos/app/components/ui/accordion.tsx +0 -56
  931. package/corpus/templates/videos/app/components/ui/alert-dialog.tsx +0 -139
  932. package/corpus/templates/videos/app/components/ui/alert.tsx +0 -59
  933. package/corpus/templates/videos/app/components/ui/aspect-ratio.tsx +0 -5
  934. package/corpus/templates/videos/app/components/ui/avatar.tsx +0 -48
  935. package/corpus/templates/videos/app/components/ui/badge.tsx +0 -37
  936. package/corpus/templates/videos/app/components/ui/breadcrumb.tsx +0 -115
  937. package/corpus/templates/videos/app/components/ui/button.tsx +0 -57
  938. package/corpus/templates/videos/app/components/ui/calendar.tsx +0 -68
  939. package/corpus/templates/videos/app/components/ui/card.tsx +0 -86
  940. package/corpus/templates/videos/app/components/ui/carousel.tsx +0 -260
  941. package/corpus/templates/videos/app/components/ui/chart.tsx +0 -375
  942. package/corpus/templates/videos/app/components/ui/checkbox.tsx +0 -28
  943. package/corpus/templates/videos/app/components/ui/collapsible.tsx +0 -9
  944. package/corpus/templates/videos/app/components/ui/command.tsx +0 -154
  945. package/corpus/templates/videos/app/components/ui/context-menu.tsx +0 -202
  946. package/corpus/templates/videos/app/components/ui/dialog.tsx +0 -130
  947. package/corpus/templates/videos/app/components/ui/drawer.tsx +0 -116
  948. package/corpus/templates/videos/app/components/ui/dropdown-menu.tsx +0 -212
  949. package/corpus/templates/videos/app/components/ui/form.tsx +0 -177
  950. package/corpus/templates/videos/app/components/ui/hover-card.tsx +0 -27
  951. package/corpus/templates/videos/app/components/ui/input-otp.tsx +0 -69
  952. package/corpus/templates/videos/app/components/ui/input.tsx +0 -22
  953. package/corpus/templates/videos/app/components/ui/label.tsx +0 -24
  954. package/corpus/templates/videos/app/components/ui/menubar.tsx +0 -234
  955. package/corpus/templates/videos/app/components/ui/navigation-menu.tsx +0 -128
  956. package/corpus/templates/videos/app/components/ui/pagination.tsx +0 -121
  957. package/corpus/templates/videos/app/components/ui/popover.tsx +0 -44
  958. package/corpus/templates/videos/app/components/ui/progress.tsx +0 -26
  959. package/corpus/templates/videos/app/components/ui/radio-group.tsx +0 -42
  960. package/corpus/templates/videos/app/components/ui/resizable.tsx +0 -43
  961. package/corpus/templates/videos/app/components/ui/scroll-area.tsx +0 -46
  962. package/corpus/templates/videos/app/components/ui/select.tsx +0 -158
  963. package/corpus/templates/videos/app/components/ui/separator.tsx +0 -29
  964. package/corpus/templates/videos/app/components/ui/sheet.tsx +0 -160
  965. package/corpus/templates/videos/app/components/ui/sidebar.tsx +0 -782
  966. package/corpus/templates/videos/app/components/ui/skeleton.tsx +0 -15
  967. package/corpus/templates/videos/app/components/ui/slider.tsx +0 -26
  968. package/corpus/templates/videos/app/components/ui/sonner.tsx +0 -58
  969. package/corpus/templates/videos/app/components/ui/spinner.tsx +0 -17
  970. package/corpus/templates/videos/app/components/ui/switch.tsx +0 -27
  971. package/corpus/templates/videos/app/components/ui/table.tsx +0 -117
  972. package/corpus/templates/videos/app/components/ui/tabs.tsx +0 -53
  973. package/corpus/templates/videos/app/components/ui/textarea.tsx +0 -23
  974. package/corpus/templates/videos/app/components/ui/toast.tsx +0 -127
  975. package/corpus/templates/videos/app/components/ui/toaster.tsx +0 -33
  976. package/corpus/templates/videos/app/components/ui/toggle-group.tsx +0 -59
  977. package/corpus/templates/videos/app/components/ui/toggle.tsx +0 -43
  978. package/corpus/templates/videos/app/components/ui/tooltip.tsx +0 -30
  979. package/corpus/templates/videos/app/components/ui/use-toast.ts +0 -3
  980. package/corpus/templates/videos/app/config/constants.ts +0 -204
  981. package/corpus/templates/videos/app/contexts/CompositionContext.tsx +0 -437
  982. package/corpus/templates/videos/app/contexts/CurrentElementContext.tsx +0 -247
  983. package/corpus/templates/videos/app/contexts/PlaybackContext.tsx +0 -65
  984. package/corpus/templates/videos/app/contexts/TimelineContext.tsx +0 -433
  985. package/corpus/templates/videos/app/entry.client.tsx +0 -19
  986. package/corpus/templates/videos/app/entry.server.tsx +0 -10
  987. package/corpus/templates/videos/app/global.css +0 -171
  988. package/corpus/templates/videos/app/hooks/use-composition-collab.ts +0 -269
  989. package/corpus/templates/videos/app/hooks/use-composition-design-system.ts +0 -47
  990. package/corpus/templates/videos/app/hooks/use-database-compositions.ts +0 -144
  991. package/corpus/templates/videos/app/hooks/use-db-status.ts +0 -30
  992. package/corpus/templates/videos/app/hooks/use-design-systems.ts +0 -21
  993. package/corpus/templates/videos/app/hooks/use-folders.ts +0 -199
  994. package/corpus/templates/videos/app/hooks/use-mobile.tsx +0 -21
  995. package/corpus/templates/videos/app/hooks/use-navigation-state.ts +0 -52
  996. package/corpus/templates/videos/app/hooks/use-question-flow.ts +0 -14
  997. package/corpus/templates/videos/app/hooks/use-toast.ts +0 -188
  998. package/corpus/templates/videos/app/hooks/useUnsavedChanges.ts +0 -48
  999. package/corpus/templates/videos/app/i18n/ar-SA.ts +0 -446
  1000. package/corpus/templates/videos/app/i18n/de-DE.ts +0 -470
  1001. package/corpus/templates/videos/app/i18n/en-US.ts +0 -452
  1002. package/corpus/templates/videos/app/i18n/es-ES.ts +0 -468
  1003. package/corpus/templates/videos/app/i18n/fr-FR.ts +0 -469
  1004. package/corpus/templates/videos/app/i18n/hi-IN.ts +0 -446
  1005. package/corpus/templates/videos/app/i18n/index.ts +0 -34
  1006. package/corpus/templates/videos/app/i18n/ja-JP.ts +0 -460
  1007. package/corpus/templates/videos/app/i18n/ko-KR.ts +0 -453
  1008. package/corpus/templates/videos/app/i18n/pt-BR.ts +0 -461
  1009. package/corpus/templates/videos/app/i18n/zh-CN.ts +0 -437
  1010. package/corpus/templates/videos/app/i18n/zh-TW.ts +0 -437
  1011. package/corpus/templates/videos/app/lib/database-compositions.ts +0 -67
  1012. package/corpus/templates/videos/app/lib/design-systems.ts +0 -234
  1013. package/corpus/templates/videos/app/lib/tab-id.ts +0 -1
  1014. package/corpus/templates/videos/app/lib/utils.ts +0 -1
  1015. package/corpus/templates/videos/app/pages/ComponentLibrary.tsx +0 -134
  1016. package/corpus/templates/videos/app/pages/ComponentLibraryView.tsx +0 -362
  1017. package/corpus/templates/videos/app/pages/CompositionView.tsx +0 -715
  1018. package/corpus/templates/videos/app/pages/DesignSystems.tsx +0 -180
  1019. package/corpus/templates/videos/app/pages/Index.tsx +0 -258
  1020. package/corpus/templates/videos/app/pages/NewComposition.tsx +0 -95
  1021. package/corpus/templates/videos/app/pages/NotFound.tsx +0 -36
  1022. package/corpus/templates/videos/app/remotion/CameraHost.tsx +0 -223
  1023. package/corpus/templates/videos/app/remotion/animations/useElementAnimations.ts +0 -231
  1024. package/corpus/templates/videos/app/remotion/componentRegistry.ts +0 -473
  1025. package/corpus/templates/videos/app/remotion/components/AnimatedElement.tsx +0 -436
  1026. package/corpus/templates/videos/app/remotion/components/InteractiveElement.tsx +0 -159
  1027. package/corpus/templates/videos/app/remotion/components/InteractiveZoneEditor.tsx +0 -273
  1028. package/corpus/templates/videos/app/remotion/compositions/BlankComposition.tsx +0 -204
  1029. package/corpus/templates/videos/app/remotion/compositions/index.ts +0 -2
  1030. package/corpus/templates/videos/app/remotion/createComponentCursorTrack.ts +0 -132
  1031. package/corpus/templates/videos/app/remotion/docs/CURSOR_TRACKS.md +0 -285
  1032. package/corpus/templates/videos/app/remotion/easingFunctions.ts +0 -255
  1033. package/corpus/templates/videos/app/remotion/hooks/createInteractiveComposition.tsx +0 -283
  1034. package/corpus/templates/videos/app/remotion/hooks/useCursorHistory.ts +0 -72
  1035. package/corpus/templates/videos/app/remotion/hooks/useCursorTypeFromHover.ts +0 -35
  1036. package/corpus/templates/videos/app/remotion/hooks/useEditableZones.tsx +0 -267
  1037. package/corpus/templates/videos/app/remotion/hooks/useHoverAnimation.ts +0 -90
  1038. package/corpus/templates/videos/app/remotion/hooks/useHoverAnimationSmooth.ts +0 -146
  1039. package/corpus/templates/videos/app/remotion/hooks/useInteractiveComponent.ts +0 -711
  1040. package/corpus/templates/videos/app/remotion/hooks/useRegisterInteractiveElement.ts +0 -56
  1041. package/corpus/templates/videos/app/remotion/library-components/Button.tsx +0 -252
  1042. package/corpus/templates/videos/app/remotion/library-components/Card.tsx +0 -241
  1043. package/corpus/templates/videos/app/remotion/library-components/CodePanel.tsx +0 -1005
  1044. package/corpus/templates/videos/app/remotion/library-components/FileItem.tsx +0 -196
  1045. package/corpus/templates/videos/app/remotion/library-components/FolderItem.tsx +0 -199
  1046. package/corpus/templates/videos/app/remotion/library-components/PrimaryButton.tsx +0 -177
  1047. package/corpus/templates/videos/app/remotion/library-components/SecondaryButton.tsx +0 -167
  1048. package/corpus/templates/videos/app/remotion/library-components/SectionHeader.tsx +0 -108
  1049. package/corpus/templates/videos/app/remotion/library-components/TEMPLATE.tsx +0 -211
  1050. package/corpus/templates/videos/app/remotion/library-components/index.ts +0 -10
  1051. package/corpus/templates/videos/app/remotion/registry.ts +0 -91
  1052. package/corpus/templates/videos/app/remotion/testing/animationTestUtils.ts +0 -366
  1053. package/corpus/templates/videos/app/remotion/trackAnimation.ts +0 -179
  1054. package/corpus/templates/videos/app/remotion/trackHelpers.ts +0 -110
  1055. package/corpus/templates/videos/app/remotion/ui-components/Cursor.tsx +0 -182
  1056. package/corpus/templates/videos/app/remotion/ui-components/InteractiveButton.tsx +0 -116
  1057. package/corpus/templates/videos/app/remotion/ui-components/InteractiveCard.tsx +0 -126
  1058. package/corpus/templates/videos/app/remotion/ui-components/index.ts +0 -16
  1059. package/corpus/templates/videos/app/remotion/utils/animationHelpers.ts +0 -444
  1060. package/corpus/templates/videos/app/remotion/utils/interactiveElements.ts +0 -235
  1061. package/corpus/templates/videos/app/remotion/utils/springAnimation.ts +0 -76
  1062. package/corpus/templates/videos/app/root.tsx +0 -165
  1063. package/corpus/templates/videos/app/routes/$.tsx +0 -10
  1064. package/corpus/templates/videos/app/routes/_index.tsx +0 -25
  1065. package/corpus/templates/videos/app/routes/c.$compositionId.tsx +0 -10
  1066. package/corpus/templates/videos/app/routes/components.tsx +0 -10
  1067. package/corpus/templates/videos/app/routes/design-systems.tsx +0 -10
  1068. package/corpus/templates/videos/app/routes/extensions.$id.$slug.tsx +0 -2
  1069. package/corpus/templates/videos/app/routes/extensions.$id.tsx +0 -5
  1070. package/corpus/templates/videos/app/routes/extensions._index.tsx +0 -5
  1071. package/corpus/templates/videos/app/routes/extensions.tsx +0 -5
  1072. package/corpus/templates/videos/app/routes/settings.tsx +0 -88
  1073. package/corpus/templates/videos/app/routes/team.tsx +0 -11
  1074. package/corpus/templates/videos/app/routes.ts +0 -4
  1075. package/corpus/templates/videos/app/state.ts +0 -77
  1076. package/corpus/templates/videos/app/types/elementAnimations.ts +0 -121
  1077. package/corpus/templates/videos/app/types.ts +0 -200
  1078. package/corpus/templates/videos/app/utils/compositionHelpers.ts +0 -445
  1079. package/corpus/templates/videos/app/utils/debug.ts +0 -63
  1080. package/corpus/templates/videos/app/utils/keyframeUtils.ts +0 -331
  1081. package/corpus/templates/videos/app/utils/timelineCoordinates.ts +0 -79
  1082. package/corpus/templates/videos/app/vite-env.d.ts +0 -6
  1083. package/corpus/templates/videos/changelog/2026-06-24-a-new-settings-page-gives-quick-access-to-language-workspace.md +0 -6
  1084. package/corpus/templates/videos/changelog/2026-06-24-added-a-language-picker-and-localized-app-chrome-for-support.md +0 -6
  1085. package/corpus/templates/videos/changelog/2026-06-27-traditional-chinese-copy-uses-taiwan-terminology.md +0 -6
  1086. package/corpus/templates/videos/changelog/2026-06-28-left-sidebar-collapses-into-an-animated-icon-rail.md +0 -6
  1087. package/corpus/templates/videos/changelog/2026-06-29-video-layouts-adapt-when-the-agent-sidebar-is-open.md +0 -6
  1088. package/corpus/templates/videos/components.json +0 -20
  1089. package/corpus/templates/videos/data/sync-config.json +0 -3
  1090. package/corpus/templates/videos/docs/examples/create-composition.example.ts +0 -128
  1091. package/corpus/templates/videos/drizzle.config.ts +0 -3
  1092. package/corpus/templates/videos/learnings.defaults.md +0 -5
  1093. package/corpus/templates/videos/package.json +0 -114
  1094. package/corpus/templates/videos/public/agent-native-icon-dark.svg +0 -10
  1095. package/corpus/templates/videos/public/agent-native-icon-light.svg +0 -10
  1096. package/corpus/templates/videos/public/agent-native-logo-dark.svg +0 -21
  1097. package/corpus/templates/videos/public/agent-native-logo-light.svg +0 -21
  1098. package/corpus/templates/videos/public/favicon.svg +0 -1
  1099. package/corpus/templates/videos/public/icon-180.svg +0 -1
  1100. package/corpus/templates/videos/public/icon-192.svg +0 -1
  1101. package/corpus/templates/videos/public/icon-512.svg +0 -1
  1102. package/corpus/templates/videos/public/manifest.json +0 -21
  1103. package/corpus/templates/videos/public/placeholder.svg +0 -1
  1104. package/corpus/templates/videos/public/robots.txt +0 -14
  1105. package/corpus/templates/videos/react-router.config.ts +0 -7
  1106. package/corpus/templates/videos/server/db/index.ts +0 -37
  1107. package/corpus/templates/videos/server/db/schema.ts +0 -55
  1108. package/corpus/templates/videos/server/middleware/auth.ts +0 -15
  1109. package/corpus/templates/videos/server/plugins/agent-chat.ts +0 -29
  1110. package/corpus/templates/videos/server/plugins/auth.ts +0 -14
  1111. package/corpus/templates/videos/server/plugins/collab.ts +0 -11
  1112. package/corpus/templates/videos/server/plugins/core-routes.ts +0 -22
  1113. package/corpus/templates/videos/server/plugins/db.ts +0 -160
  1114. package/corpus/templates/videos/server/routes/[...page].get.ts +0 -5
  1115. package/corpus/templates/videos/server/routes/[...page].head.ts +0 -1
  1116. package/corpus/templates/videos/server/routes/api/save-composition-defaults.post.ts +0 -274
  1117. package/corpus/templates/videos/shared/api.ts +0 -75
  1118. package/corpus/templates/videos/ssr-entry.ts +0 -15
  1119. package/corpus/templates/videos/tsconfig.json +0 -21
  1120. package/corpus/templates/videos/vite.config.ts +0 -19
  1121. package/corpus/templates/videos/vitest.config.ts +0 -16
  1122. package/docs/content/locales/ar-SA/template-videos.mdx +0 -336
  1123. package/docs/content/locales/de-DE/template-videos.mdx +0 -336
  1124. package/docs/content/locales/es-ES/template-videos.mdx +0 -336
  1125. package/docs/content/locales/fr-FR/template-videos.mdx +0 -336
  1126. package/docs/content/locales/hi-IN/template-videos.mdx +0 -336
  1127. package/docs/content/locales/ja-JP/template-videos.mdx +0 -336
  1128. package/docs/content/locales/ko-KR/template-videos.mdx +0 -336
  1129. package/docs/content/locales/pt-BR/template-videos.mdx +0 -336
  1130. package/docs/content/locales/zh-CN/template-videos.mdx +0 -334
  1131. package/docs/content/locales/zh-TW/template-videos.mdx +0 -334
  1132. package/docs/content/template-videos.mdx +0 -332
@@ -1,3 +1,5 @@
1
+ import { type AwarenessChangeEvent } from "../collab/awareness.js";
2
+ export declare function canSeeAwarenessChangeForUser(change: Pick<AwarenessChangeEvent, "owner" | "orgId" | "resourceType" | "resourceId">, userEmail: string, orgId: string | undefined): boolean;
1
3
  /**
2
4
  * Stream in-process poll events over SSE.
3
5
  *
@@ -1 +1 @@
1
- {"version":3,"file":"poll-events.d.ts","sourceRoot":"","sources":["../../src/server/poll-events.ts"],"names":[],"mappings":"AAeA;;;;;;;;;;;;GAYG;AACH,wBAAgB,uBAAuB;;IA+CtC"}
1
+ {"version":3,"file":"poll-events.d.ts","sourceRoot":"","sources":["../../src/server/poll-events.ts"],"names":[],"mappings":"AAEA,OAAO,EAGL,KAAK,oBAAoB,EAC1B,MAAM,wBAAwB,CAAC;AAShC,wBAAgB,4BAA4B,CAC1C,MAAM,EAAE,IAAI,CACV,oBAAoB,EACpB,OAAO,GAAG,OAAO,GAAG,cAAc,GAAG,YAAY,CAClD,EACD,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,GAAG,SAAS,GACxB,OAAO,CAGT;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,uBAAuB;;IA+CtC"}
@@ -2,6 +2,11 @@ import { createEventStream, defineEventHandler, setResponseStatus } from "h3";
2
2
  import { getAwarenessEmitter, AWARENESS_CHANGE_EVENT, } from "../collab/awareness.js";
3
3
  import { getSession } from "./auth.js";
4
4
  import { canSeeChangeForUser, getPollEmitter, POLL_CHANGE_EVENT, } from "./poll.js";
5
+ export function canSeeAwarenessChangeForUser(change, userEmail, orgId) {
6
+ if (!change.owner && !change.orgId && !change.resourceType)
7
+ return false;
8
+ return canSeeChangeForUser(change, userEmail, orgId);
9
+ }
5
10
  /**
6
11
  * Stream in-process poll events over SSE.
7
12
  *
@@ -46,9 +51,9 @@ export function createPollEventsHandler() {
46
51
  const pushAwareness = (change) => {
47
52
  if (closed)
48
53
  return;
49
- // Respect org scoping if present.
50
- if (change.orgId && session.orgId && change.orgId !== session.orgId)
54
+ if (!canSeeAwarenessChangeForUser(change, session.email, session.orgId)) {
51
55
  return;
56
+ }
52
57
  safePush(JSON.stringify(change));
53
58
  };
54
59
  getPollEmitter().on(POLL_CHANGE_EVENT, push);
@@ -1 +1 @@
1
- {"version":3,"file":"poll-events.js","sourceRoot":"","sources":["../../src/server/poll-events.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,IAAI,CAAC;AAE9E,OAAO,EACL,mBAAmB,EACnB,sBAAsB,GAEvB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,OAAO,EACL,mBAAmB,EACnB,cAAc,EACd,iBAAiB,GAElB,MAAM,WAAW,CAAC;AAEnB;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,uBAAuB;IACrC,OAAO,kBAAkB,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;QACxC,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;QAC1D,IAAI,CAAC,OAAO,EAAE,KAAK,EAAE,CAAC;YACpB,iBAAiB,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;YAC9B,OAAO,EAAE,KAAK,EAAE,iBAAiB,EAAE,CAAC;QACtC,CAAC;QAED,MAAM,MAAM,GAAG,iBAAiB,CAAC,KAAK,CAAC,CAAC;QACxC,IAAI,MAAM,GAAG,KAAK,CAAC;QAEnB,MAAM,QAAQ,GAAG,CAAC,IAAY,EAAE,EAAE;YAChC,IAAI,MAAM;gBAAE,OAAO;YACnB,IAAI,CAAC;gBACH,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACpB,CAAC;YAAC,MAAM,CAAC;gBACP,6DAA6D;YAC/D,CAAC;QACH,CAAC,CAAC;QAEF,MAAM,IAAI,GAAG,CAAC,MAAmB,EAAE,EAAE;YACnC,IAAI,MAAM;gBAAE,OAAO;YACnB,IAAI,CAAC,mBAAmB,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC;gBAAE,OAAO;YACvE,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;QACnC,CAAC,CAAC;QAEF,mEAAmE;QACnE,6EAA6E;QAC7E,MAAM,aAAa,GAAG,CAAC,MAA4B,EAAE,EAAE;YACrD,IAAI,MAAM;gBAAE,OAAO;YACnB,kCAAkC;YAClC,IAAI,MAAM,CAAC,KAAK,IAAI,OAAO,CAAC,KAAK,IAAI,MAAM,CAAC,KAAK,KAAK,OAAO,CAAC,KAAK;gBACjE,OAAO;YACT,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;QACnC,CAAC,CAAC;QAEF,cAAc,EAAE,CAAC,EAAE,CAAC,iBAAiB,EAAE,IAAI,CAAC,CAAC;QAC7C,mBAAmB,EAAE,CAAC,EAAE,CAAC,sBAAsB,EAAE,aAAa,CAAC,CAAC;QAEhE,MAAM,CAAC,QAAQ,CAAC,GAAG,EAAE;YACnB,MAAM,GAAG,IAAI,CAAC;YACd,cAAc,EAAE,CAAC,GAAG,CAAC,iBAAiB,EAAE,IAAI,CAAC,CAAC;YAC9C,mBAAmB,EAAE,CAAC,GAAG,CAAC,sBAAsB,EAAE,aAAa,CAAC,CAAC;QACnE,CAAC,CAAC,CAAC;QAEH,OAAO,MAAM,CAAC,IAAI,EAAE,CAAC;IACvB,CAAC,CAAC,CAAC;AACL,CAAC","sourcesContent":["import { createEventStream, defineEventHandler, setResponseStatus } from \"h3\";\n\nimport {\n getAwarenessEmitter,\n AWARENESS_CHANGE_EVENT,\n type AwarenessChangeEvent,\n} from \"../collab/awareness.js\";\nimport { getSession } from \"./auth.js\";\nimport {\n canSeeChangeForUser,\n getPollEmitter,\n POLL_CHANGE_EVENT,\n type ChangeEvent,\n} from \"./poll.js\";\n\n/**\n * Stream in-process poll events over SSE.\n *\n * This is the fast path for agent/tool/action writes that happen in the same\n * server process. The regular /poll endpoint remains the cross-process and\n * serverless cold-start fallback because it can detect DB timestamp changes\n * even when the write happened somewhere this EventEmitter could not see.\n *\n * Also forwards awareness change events (cursor/presence updates) so\n * connected peers receive cursor moves push-style instead of waiting for\n * the next poll cycle. Polling fallback keeps working — cursors degrade\n * gracefully to poll cadence without SSE.\n */\nexport function createPollEventsHandler() {\n return defineEventHandler(async (event) => {\n const session = await getSession(event).catch(() => null);\n if (!session?.email) {\n setResponseStatus(event, 401);\n return { error: \"Unauthenticated\" };\n }\n\n const stream = createEventStream(event);\n let closed = false;\n\n const safePush = (data: string) => {\n if (closed) return;\n try {\n stream.push(data);\n } catch {\n // EventSource will reconnect; /poll catches anything missed.\n }\n };\n\n const push = (change: ChangeEvent) => {\n if (closed) return;\n if (!canSeeChangeForUser(change, session.email, session.orgId)) return;\n safePush(JSON.stringify(change));\n };\n\n // Awareness fast-path: forward cursor/presence events immediately.\n // No ring-buffer needed — clients reconcile on the next poll if SSE is down.\n const pushAwareness = (change: AwarenessChangeEvent) => {\n if (closed) return;\n // Respect org scoping if present.\n if (change.orgId && session.orgId && change.orgId !== session.orgId)\n return;\n safePush(JSON.stringify(change));\n };\n\n getPollEmitter().on(POLL_CHANGE_EVENT, push);\n getAwarenessEmitter().on(AWARENESS_CHANGE_EVENT, pushAwareness);\n\n stream.onClosed(() => {\n closed = true;\n getPollEmitter().off(POLL_CHANGE_EVENT, push);\n getAwarenessEmitter().off(AWARENESS_CHANGE_EVENT, pushAwareness);\n });\n\n return stream.send();\n });\n}\n"]}
1
+ {"version":3,"file":"poll-events.js","sourceRoot":"","sources":["../../src/server/poll-events.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,IAAI,CAAC;AAE9E,OAAO,EACL,mBAAmB,EACnB,sBAAsB,GAEvB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,OAAO,EACL,mBAAmB,EACnB,cAAc,EACd,iBAAiB,GAElB,MAAM,WAAW,CAAC;AAEnB,MAAM,UAAU,4BAA4B,CAC1C,MAGC,EACD,SAAiB,EACjB,KAAyB;IAEzB,IAAI,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC,MAAM,CAAC,YAAY;QAAE,OAAO,KAAK,CAAC;IACzE,OAAO,mBAAmB,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC;AACvD,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,uBAAuB;IACrC,OAAO,kBAAkB,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;QACxC,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;QAC1D,IAAI,CAAC,OAAO,EAAE,KAAK,EAAE,CAAC;YACpB,iBAAiB,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;YAC9B,OAAO,EAAE,KAAK,EAAE,iBAAiB,EAAE,CAAC;QACtC,CAAC;QAED,MAAM,MAAM,GAAG,iBAAiB,CAAC,KAAK,CAAC,CAAC;QACxC,IAAI,MAAM,GAAG,KAAK,CAAC;QAEnB,MAAM,QAAQ,GAAG,CAAC,IAAY,EAAE,EAAE;YAChC,IAAI,MAAM;gBAAE,OAAO;YACnB,IAAI,CAAC;gBACH,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACpB,CAAC;YAAC,MAAM,CAAC;gBACP,6DAA6D;YAC/D,CAAC;QACH,CAAC,CAAC;QAEF,MAAM,IAAI,GAAG,CAAC,MAAmB,EAAE,EAAE;YACnC,IAAI,MAAM;gBAAE,OAAO;YACnB,IAAI,CAAC,mBAAmB,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC;gBAAE,OAAO;YACvE,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;QACnC,CAAC,CAAC;QAEF,mEAAmE;QACnE,6EAA6E;QAC7E,MAAM,aAAa,GAAG,CAAC,MAA4B,EAAE,EAAE;YACrD,IAAI,MAAM;gBAAE,OAAO;YACnB,IAAI,CAAC,4BAA4B,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;gBACxE,OAAO;YACT,CAAC;YACD,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;QACnC,CAAC,CAAC;QAEF,cAAc,EAAE,CAAC,EAAE,CAAC,iBAAiB,EAAE,IAAI,CAAC,CAAC;QAC7C,mBAAmB,EAAE,CAAC,EAAE,CAAC,sBAAsB,EAAE,aAAa,CAAC,CAAC;QAEhE,MAAM,CAAC,QAAQ,CAAC,GAAG,EAAE;YACnB,MAAM,GAAG,IAAI,CAAC;YACd,cAAc,EAAE,CAAC,GAAG,CAAC,iBAAiB,EAAE,IAAI,CAAC,CAAC;YAC9C,mBAAmB,EAAE,CAAC,GAAG,CAAC,sBAAsB,EAAE,aAAa,CAAC,CAAC;QACnE,CAAC,CAAC,CAAC;QAEH,OAAO,MAAM,CAAC,IAAI,EAAE,CAAC;IACvB,CAAC,CAAC,CAAC;AACL,CAAC","sourcesContent":["import { createEventStream, defineEventHandler, setResponseStatus } from \"h3\";\n\nimport {\n getAwarenessEmitter,\n AWARENESS_CHANGE_EVENT,\n type AwarenessChangeEvent,\n} from \"../collab/awareness.js\";\nimport { getSession } from \"./auth.js\";\nimport {\n canSeeChangeForUser,\n getPollEmitter,\n POLL_CHANGE_EVENT,\n type ChangeEvent,\n} from \"./poll.js\";\n\nexport function canSeeAwarenessChangeForUser(\n change: Pick<\n AwarenessChangeEvent,\n \"owner\" | \"orgId\" | \"resourceType\" | \"resourceId\"\n >,\n userEmail: string,\n orgId: string | undefined,\n): boolean {\n if (!change.owner && !change.orgId && !change.resourceType) return false;\n return canSeeChangeForUser(change, userEmail, orgId);\n}\n\n/**\n * Stream in-process poll events over SSE.\n *\n * This is the fast path for agent/tool/action writes that happen in the same\n * server process. The regular /poll endpoint remains the cross-process and\n * serverless cold-start fallback because it can detect DB timestamp changes\n * even when the write happened somewhere this EventEmitter could not see.\n *\n * Also forwards awareness change events (cursor/presence updates) so\n * connected peers receive cursor moves push-style instead of waiting for\n * the next poll cycle. Polling fallback keeps working — cursors degrade\n * gracefully to poll cadence without SSE.\n */\nexport function createPollEventsHandler() {\n return defineEventHandler(async (event) => {\n const session = await getSession(event).catch(() => null);\n if (!session?.email) {\n setResponseStatus(event, 401);\n return { error: \"Unauthenticated\" };\n }\n\n const stream = createEventStream(event);\n let closed = false;\n\n const safePush = (data: string) => {\n if (closed) return;\n try {\n stream.push(data);\n } catch {\n // EventSource will reconnect; /poll catches anything missed.\n }\n };\n\n const push = (change: ChangeEvent) => {\n if (closed) return;\n if (!canSeeChangeForUser(change, session.email, session.orgId)) return;\n safePush(JSON.stringify(change));\n };\n\n // Awareness fast-path: forward cursor/presence events immediately.\n // No ring-buffer needed — clients reconcile on the next poll if SSE is down.\n const pushAwareness = (change: AwarenessChangeEvent) => {\n if (closed) return;\n if (!canSeeAwarenessChangeForUser(change, session.email, session.orgId)) {\n return;\n }\n safePush(JSON.stringify(change));\n };\n\n getPollEmitter().on(POLL_CHANGE_EVENT, push);\n getAwarenessEmitter().on(AWARENESS_CHANGE_EVENT, pushAwareness);\n\n stream.onClosed(() => {\n closed = true;\n getPollEmitter().off(POLL_CHANGE_EVENT, push);\n getAwarenessEmitter().off(AWARENESS_CHANGE_EVENT, pushAwareness);\n });\n\n return stream.send();\n });\n}\n"]}
@@ -28,13 +28,54 @@ export interface ChangeEvent {
28
28
  owner?: string;
29
29
  /** Optional org ID for org-scoped events. */
30
30
  orgId?: string;
31
+ /**
32
+ * Shareable resource type this event belongs to (e.g. "document"). When
33
+ * present together with `resourceId`, the per-user delivery filter
34
+ * (`canSeeChangeForUser`) can run an access-aware check so non-owner sharees
35
+ * with explicit viewer+ access receive the push instead of only the poll
36
+ * fallback. See the SYNC-CACHE note above `canSeeChangeForUser`.
37
+ */
38
+ resourceType?: string;
39
+ /**
40
+ * Shareable resource id this event belongs to. Paired with `resourceType`
41
+ * to drive the access-aware delivery check in `canSeeChangeForUser`.
42
+ */
43
+ resourceId?: string;
31
44
  [k: string]: unknown;
32
45
  }
33
46
  export declare const POLL_CHANGE_EVENT = "poll-change";
34
47
  /** Get the current global version counter. */
35
48
  export declare function getVersion(): number;
36
49
  export declare function getPollEmitter(): EventEmitter;
37
- export declare function canSeeChangeForUser(event: ChangeEvent, userEmail: string, orgId: string | undefined): boolean;
50
+ export declare function invalidateCollabAccessCache(resourceType: string, resourceId: string): void;
51
+ /**
52
+ * Test-only: clear the access cache and in-flight set so cases don't bleed
53
+ * into each other. Underscore-prefixed and intentionally NOT part of the
54
+ * public API — do not rely on it outside tests.
55
+ */
56
+ export declare function __resetCollabAccessCacheForTests(): void;
57
+ /**
58
+ * Decide whether a poll/SSE change event should be delivered to a user.
59
+ *
60
+ * SYNC-CACHE VARIANT — WHY THIS IS SYNCHRONOUS:
61
+ * This function is called on hot, synchronous paths: the SSE emitter callback
62
+ * `push(change)` in poll-events.ts (fires per event) and the
63
+ * `getChangesSinceForUser` loop in this file. Making it async would be
64
+ * invasive (it would ripple through both call sites and their emitters).
65
+ * Instead, for the access-aware branch we consult an in-memory cache and, on a
66
+ * miss, fire a NON-BLOCKING background access check and return `false` for the
67
+ * current event. Because the poll fallback (`getChangesSinceForUser` on the
68
+ * next `/poll` cycle) re-evaluates with the now-populated cache, delivery is
69
+ * eventually guaranteed — the only cost is that the very first event for a
70
+ * fresh (user, resource) pair goes over poll instead of push, and every
71
+ * subsequent event within the TTL is pushed.
72
+ *
73
+ * Security: a cache MISS returns `false`, so we NEVER deliver to a user before
74
+ * their access has been affirmatively confirmed by `resolveAccess` — the same
75
+ * authority that gates the HTTP routes. Errors fail closed (cached deny). The
76
+ * owner/org fast paths below are unchanged and evaluated first.
77
+ */
78
+ export declare function canSeeChangeForUser(event: Pick<ChangeEvent, "owner" | "orgId" | "resourceType" | "resourceId">, userEmail: string, orgId: string | undefined): boolean;
38
79
  /** Record a change event. Called by emitter listeners. */
39
80
  export declare function recordChange(event: {
40
81
  source: string;
@@ -52,10 +93,13 @@ export declare function getChangesSince(since: number): {
52
93
  * allowed to see.
53
94
  *
54
95
  * Filtering rules:
55
- * - Events without an `owner` are deployment-global (table-level pings,
56
- * screen-refresh, etc.) and visible to every authenticated user.
96
+ * - Events without an `owner`/`orgId`/`resourceType` are deployment-global
97
+ * (table-level pings, screen-refresh, etc.) and visible to every
98
+ * authenticated user.
57
99
  * - Events with `owner === userEmail` go to that user.
58
100
  * - Events with `orgId === orgId` go to anyone in that org.
101
+ * - Events carrying `resourceType` + `resourceId` additionally reach explicit
102
+ * viewer+ sharees via the access-aware cache in `canSeeChangeForUser`.
59
103
  * - All other owned events are filtered out.
60
104
  */
61
105
  export declare function getChangesSinceForUser(since: number, userEmail: string, orgId: string | undefined): {
@@ -1 +1 @@
1
- {"version":3,"file":"poll.d.ts","sourceRoot":"","sources":["../../src/server/poll.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAmB3C,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,6CAA6C;IAC7C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CACtB;AAOD,eAAO,MAAM,iBAAiB,gBAAgB,CAAC;AA0I/C,8CAA8C;AAC9C,wBAAgB,UAAU,IAAI,MAAM,CAEnC;AAED,wBAAgB,cAAc,IAAI,YAAY,CAE7C;AAED,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,WAAW,EAClB,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,GAAG,SAAS,GACxB,OAAO,CAMT;AAED,0DAA0D;AAC1D,wBAAgB,YAAY,CAAC,KAAK,EAAE;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CACtB,GAAG,IAAI,CAWP;AA+GD,6CAA6C;AAC7C,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG;IAC9C,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,WAAW,EAAE,CAAC;CACvB,CAMA;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,GAAG,SAAS,GACxB;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,WAAW,EAAE,CAAA;CAAE,CAQ5C;AA6SD;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB;aAhUnB,MAAM;YAAU,WAAW,EAAE;;;IAiV1C"}
1
+ {"version":3,"file":"poll.d.ts","sourceRoot":"","sources":["../../src/server/poll.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAmB3C,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,6CAA6C;IAC7C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;;OAMG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CACtB;AAOD,eAAO,MAAM,iBAAiB,gBAAgB,CAAC;AA0I/C,8CAA8C;AAC9C,wBAAgB,UAAU,IAAI,MAAM,CAEnC;AAED,wBAAgB,cAAc,IAAI,YAAY,CAE7C;AAyCD,wBAAgB,2BAA2B,CACzC,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,GACjB,IAAI,CAaN;AA0DD;;;;GAIG;AACH,wBAAgB,gCAAgC,IAAI,IAAI,CAIvD;AAID;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,IAAI,CAAC,WAAW,EAAE,OAAO,GAAG,OAAO,GAAG,cAAc,GAAG,YAAY,CAAC,EAC3E,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,GAAG,SAAS,GACxB,OAAO,CAET;AAuCD,0DAA0D;AAC1D,wBAAgB,YAAY,CAAC,KAAK,EAAE;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CACtB,GAAG,IAAI,CAWP;AA+GD,6CAA6C;AAC7C,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG;IAC9C,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,WAAW,EAAE,CAAC;CACvB,CAMA;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,GAAG,SAAS,GACxB;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,WAAW,EAAE,CAAA;CAAE,CAmB5C;AA6SD;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB;aA3UnB,MAAM;YAAU,WAAW,EAAE;;;IA4V1C"}
@@ -142,15 +142,164 @@ export function getVersion() {
142
142
  export function getPollEmitter() {
143
143
  return _pollEmitter;
144
144
  }
145
+ /**
146
+ * In-memory, TTL'd access cache for the access-aware branch of
147
+ * `canSeeChangeForUser`. Keyed by `${userEmail}|${resourceType}|${resourceId}`.
148
+ *
149
+ * Insertion order doubles as FIFO for eviction (JS Maps preserve insertion
150
+ * order), so we can evict the oldest entries when we exceed the cap.
151
+ */
152
+ const _accessCache = new Map();
153
+ /** In-flight background access checks, keyed identically, to dedupe bursts. */
154
+ const _accessInFlight = new Set();
155
+ /** Per-resource generation bumped when shares/visibility change. */
156
+ const _accessInvalidationEpoch = new Map();
157
+ /** TTL for an allowed (true) cache entry. */
158
+ const ACCESS_CACHE_TTL_MS = 30_000;
159
+ /**
160
+ * Shorter TTL for a denied (false) entry so a transient DB error (which we
161
+ * fail-closed on) doesn't lock a legitimate user out of the push path for the
162
+ * full 30s — they recover on their next event after this window.
163
+ */
164
+ const ACCESS_CACHE_DENY_TTL_MS = 5_000;
165
+ /** Max cache entries before FIFO eviction kicks in. */
166
+ const ACCESS_CACHE_MAX = 500;
167
+ function accessCacheKey(userEmail, resourceType, resourceId) {
168
+ return `${userEmail}|${resourceType}|${resourceId}`;
169
+ }
170
+ function accessResourceKey(resourceType, resourceId) {
171
+ return `${resourceType}|${resourceId}`;
172
+ }
173
+ function accessCacheTtl(allowed) {
174
+ return allowed ? ACCESS_CACHE_TTL_MS : ACCESS_CACHE_DENY_TTL_MS;
175
+ }
176
+ export function invalidateCollabAccessCache(resourceType, resourceId) {
177
+ const resourceKey = accessResourceKey(resourceType, resourceId);
178
+ _accessInvalidationEpoch.set(resourceKey, (_accessInvalidationEpoch.get(resourceKey) ?? 0) + 1);
179
+ const suffix = `|${resourceKey}`;
180
+ for (const key of Array.from(_accessCache.keys())) {
181
+ if (key.endsWith(suffix))
182
+ _accessCache.delete(key);
183
+ }
184
+ for (const key of Array.from(_accessInFlight)) {
185
+ if (key.endsWith(suffix))
186
+ _accessInFlight.delete(key);
187
+ }
188
+ }
189
+ function setAccessCache(key, allowed, now) {
190
+ // Re-insert so the key moves to the end (most-recent) for FIFO ordering.
191
+ _accessCache.delete(key);
192
+ _accessCache.set(key, { allowed, checkedAt: now });
193
+ if (_accessCache.size > ACCESS_CACHE_MAX) {
194
+ // Evict the oldest entries (front of insertion order) back under the cap.
195
+ const overflow = _accessCache.size - ACCESS_CACHE_MAX;
196
+ let removed = 0;
197
+ for (const oldestKey of _accessCache.keys()) {
198
+ _accessCache.delete(oldestKey);
199
+ if (++removed >= overflow)
200
+ break;
201
+ }
202
+ }
203
+ }
204
+ /**
205
+ * Fire a background access check for a cache-miss key. Never awaited by the
206
+ * caller — the current event is NOT delivered (we returned false), but the
207
+ * result is cached so the user's NEXT event within the TTL is pushed. Dedupes
208
+ * concurrent checks for the same key via `_accessInFlight`.
209
+ */
210
+ function scheduleAccessCheck(key, resourceType, resourceId, userEmail, orgId) {
211
+ if (_accessInFlight.has(key))
212
+ return;
213
+ _accessInFlight.add(key);
214
+ const resourceKey = accessResourceKey(resourceType, resourceId);
215
+ const epoch = _accessInvalidationEpoch.get(resourceKey) ?? 0;
216
+ void (async () => {
217
+ try {
218
+ // Dynamic import to avoid a load-order/circular-import hazard: poll.ts is
219
+ // imported very widely, and the sharing/access module pulls in the
220
+ // resource registry. Importing it lazily inside this background function
221
+ // keeps the module graph acyclic at load time.
222
+ const { resolveAccess } = await import("../sharing/access.js");
223
+ const access = await resolveAccess(resourceType, resourceId, {
224
+ userEmail,
225
+ orgId,
226
+ });
227
+ if ((_accessInvalidationEpoch.get(resourceKey) ?? 0) !== epoch)
228
+ return;
229
+ setAccessCache(key, access != null, Date.now());
230
+ }
231
+ catch {
232
+ // Fail closed on any error (DB not ready, missing registration, etc.),
233
+ // but with the short deny TTL so a transient failure self-heals quickly.
234
+ if ((_accessInvalidationEpoch.get(resourceKey) ?? 0) !== epoch)
235
+ return;
236
+ setAccessCache(key, false, Date.now());
237
+ }
238
+ finally {
239
+ _accessInFlight.delete(key);
240
+ }
241
+ })();
242
+ }
243
+ /**
244
+ * Test-only: clear the access cache and in-flight set so cases don't bleed
245
+ * into each other. Underscore-prefixed and intentionally NOT part of the
246
+ * public API — do not rely on it outside tests.
247
+ */
248
+ export function __resetCollabAccessCacheForTests() {
249
+ _accessCache.clear();
250
+ _accessInFlight.clear();
251
+ _accessInvalidationEpoch.clear();
252
+ }
253
+ /**
254
+ * Decide whether a poll/SSE change event should be delivered to a user.
255
+ *
256
+ * SYNC-CACHE VARIANT — WHY THIS IS SYNCHRONOUS:
257
+ * This function is called on hot, synchronous paths: the SSE emitter callback
258
+ * `push(change)` in poll-events.ts (fires per event) and the
259
+ * `getChangesSinceForUser` loop in this file. Making it async would be
260
+ * invasive (it would ripple through both call sites and their emitters).
261
+ * Instead, for the access-aware branch we consult an in-memory cache and, on a
262
+ * miss, fire a NON-BLOCKING background access check and return `false` for the
263
+ * current event. Because the poll fallback (`getChangesSinceForUser` on the
264
+ * next `/poll` cycle) re-evaluates with the now-populated cache, delivery is
265
+ * eventually guaranteed — the only cost is that the very first event for a
266
+ * fresh (user, resource) pair goes over poll instead of push, and every
267
+ * subsequent event within the TTL is pushed.
268
+ *
269
+ * Security: a cache MISS returns `false`, so we NEVER deliver to a user before
270
+ * their access has been affirmatively confirmed by `resolveAccess` — the same
271
+ * authority that gates the HTTP routes. Errors fail closed (cached deny). The
272
+ * owner/org fast paths below are unchanged and evaluated first.
273
+ */
145
274
  export function canSeeChangeForUser(event, userEmail, orgId) {
146
- // Global / unowned events: every authenticated user gets them.
147
- if (!event.owner && !event.orgId)
148
- return true;
275
+ return getChangeVisibilityForUser(event, userEmail, orgId) === "visible";
276
+ }
277
+ function getChangeVisibilityForUser(event, userEmail, orgId) {
278
+ // Global / unowned events: every authenticated user gets them. Events that
279
+ // predate resource tagging (owner/org only, no resourceType) keep the exact
280
+ // conservative contract they had before.
281
+ if (!event.owner && !event.orgId && !event.resourceType)
282
+ return "visible";
149
283
  if (event.owner && event.owner === userEmail)
150
- return true;
284
+ return "visible";
151
285
  if (event.orgId && orgId && event.orgId === orgId)
152
- return true;
153
- return false;
286
+ return "visible";
287
+ // Access-aware branch: only when the event carries BOTH resourceType and
288
+ // resourceId and the owner/org fast paths above did not already grant.
289
+ if (event.resourceType && event.resourceId) {
290
+ const key = accessCacheKey(userEmail, event.resourceType, event.resourceId);
291
+ const cached = _accessCache.get(key);
292
+ const now = Date.now();
293
+ if (cached && now - cached.checkedAt < accessCacheTtl(cached.allowed)) {
294
+ // Fresh, non-expired cache hit → trust the cached decision.
295
+ return cached.allowed ? "visible" : "hidden";
296
+ }
297
+ // Miss or expired: do NOT deliver this event, but schedule the async check
298
+ // so the user's next event (or poll cycle) resolves correctly.
299
+ scheduleAccessCheck(key, event.resourceType, event.resourceId, userEmail, orgId);
300
+ return "pending";
301
+ }
302
+ return "hidden";
154
303
  }
155
304
  /** Record a change event. Called by emitter listeners. */
156
305
  export function recordChange(event) {
@@ -263,18 +412,35 @@ export function getChangesSince(since) {
263
412
  * allowed to see.
264
413
  *
265
414
  * Filtering rules:
266
- * - Events without an `owner` are deployment-global (table-level pings,
267
- * screen-refresh, etc.) and visible to every authenticated user.
415
+ * - Events without an `owner`/`orgId`/`resourceType` are deployment-global
416
+ * (table-level pings, screen-refresh, etc.) and visible to every
417
+ * authenticated user.
268
418
  * - Events with `owner === userEmail` go to that user.
269
419
  * - Events with `orgId === orgId` go to anyone in that org.
420
+ * - Events carrying `resourceType` + `resourceId` additionally reach explicit
421
+ * viewer+ sharees via the access-aware cache in `canSeeChangeForUser`.
270
422
  * - All other owned events are filtered out.
271
423
  */
272
424
  export function getChangesSinceForUser(since, userEmail, orgId) {
273
425
  if (since >= _version) {
274
426
  return { version: _version, events: [] };
275
427
  }
276
- const events = _buffer.filter((e) => e.version > since && canSeeChangeForUser(e, userEmail, orgId));
277
- return { version: _version, events };
428
+ const events = [];
429
+ let version = _version;
430
+ for (const event of _buffer) {
431
+ if (event.version <= since)
432
+ continue;
433
+ const visibility = getChangeVisibilityForUser(event, userEmail, orgId);
434
+ if (visibility === "visible") {
435
+ events.push(event);
436
+ continue;
437
+ }
438
+ if (visibility === "pending") {
439
+ version = Math.max(since, event.version - 1);
440
+ break;
441
+ }
442
+ }
443
+ return { version, events };
278
444
  }
279
445
  /**
280
446
  * Seed _version from DB timestamps on the first call so serverless
@@ -1 +1 @@
1
- {"version":3,"file":"poll.js","sourceRoot":"","sources":["../../src/server/poll.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Polling-based change notification.\n *\n * Replaces SSE with a simple version counter. Each DB mutation (app-state,\n * settings, resources) increments the version. Clients poll `/_agent-native/poll?since=N`\n * and receive any events that occurred after version N.\n *\n * Works in all deployment environments (serverless, edge, long-lived).\n *\n * Also detects cross-process DB writes by periodically checking the\n * application_state and settings tables' updated_at timestamps. This ensures\n * that changes made by external processes (e.g., CLI actions, cron jobs)\n * are picked up even though they don't call recordChange() in this process.\n */\n\nimport { EventEmitter } from \"node:events\";\n\nimport { defineEventHandler, getQuery, setResponseStatus } from \"h3\";\n\nimport {\n ACTION_CHANGE_MARKER_KEY,\n parseActionChangeMarker,\n type ActionChangeTarget,\n} from \"../action-change-marker.js\";\nimport { getAppStateEmitter } from \"../application-state/emitter.js\";\nimport { getDbExec } from \"../db/client.js\";\nimport {\n EXTENSION_CHANGE_MARKER_KEY,\n parseExtensionChangeMarker,\n type ExtensionChangeTarget,\n} from \"../extensions/change-marker.js\";\nimport { getSettingsEmitter } from \"../settings/store.js\";\nimport { getSession } from \"./auth.js\";\n\nexport interface ChangeEvent {\n version: number;\n source: string;\n type: string;\n key?: string;\n /**\n * Owner email for tenant-scoped events. When absent, the event is treated\n * as deployment-global (e.g. table-level \"something changed\" pings) and\n * delivered to every authenticated poller. Specific events that should\n * only fan out to one user MUST set this — otherwise polling clients\n * across tenants see each other's signals.\n */\n owner?: string;\n /** Optional org ID for org-scoped events. */\n orgId?: string;\n [k: string]: unknown;\n}\n\n// In-memory ring buffer of recent changes. Kept small since clients\n// poll frequently (every 2-3s) and only need events since their last poll.\nconst MAX_BUFFER = 200;\nlet _version = 0;\nconst _buffer: ChangeEvent[] = [];\nexport const POLL_CHANGE_EVENT = \"poll-change\";\nconst _pollEmitter = new EventEmitter();\n_pollEmitter.setMaxListeners(0);\n\n/**\n * Whether we've seeded _version from the DB. In serverless (Netlify,\n * Vercel, etc.) each invocation starts fresh — without seeding, _version\n * resets to 0 and polling clients see the version jump backwards, causing\n * duplicate events and stuck UI.\n */\nlet _versionSeeded = false;\n\n/** Tracks the latest updated_at we've seen from the DB, per table. */\nlet _lastDbCheck = 0;\n// Coalesces concurrent checkExternalDbChanges runs. The 1s throttle alone does\n// not prevent overlap when a single check takes longer than 1s — two overlapping\n// runs would each read+advance the shared watermarks and double-emit events.\nlet _checkPromise: Promise<void> | null = null;\nlet _lastAppStateTs = 0;\nlet _lastSettingsTs = 0;\nlet _lastExtensionsTs = 0;\nlet _lastExtensionsUpdatedAt: string | number | undefined;\nlet _lastExtensionMarkerTs = 0;\nlet _lastActionMarkerTs = 0;\n\n/**\n * Tracks the latest updated_at seen on the `__screen_refresh__` key in\n * application_state. Bumped when the agent calls the `refresh-screen` tool,\n * and surfaced as a distinct `screen-refresh` event so clients can remount\n * the main content subtree via React key.\n *\n * `_screenRefreshInitialized` guards against spurious emits on the first\n * poll after a restart (where an existing row would look like a fresh bump).\n * Once we've taken a baseline reading, any subsequent increase emits.\n */\nlet _lastScreenRefreshTs = 0;\nlet _screenRefreshInitialized = false;\n// Per-session high-water marks for `__screen_refresh__`. Each user's row is\n// tracked independently so a refresh triggered by one user only remounts that\n// user's screen (owner-scoped), never every authenticated poller.\nconst _lastScreenRefreshTsBySession = new Map<string, number>();\nconst SCREEN_REFRESH_KEY = \"__screen_refresh__\";\nlet _localEmittersWired = false;\n\nfunction wireLocalEmitters(): void {\n if (_localEmittersWired) return;\n _localEmittersWired = true;\n getAppStateEmitter().on(\"app-state\", (event) => {\n if (\n event.key === EXTENSION_CHANGE_MARKER_KEY ||\n event.key === ACTION_CHANGE_MARKER_KEY\n ) {\n return;\n }\n recordChange(event);\n });\n getSettingsEmitter().on(\"settings\", (event) => {\n recordChange(event);\n });\n}\n\nfunction timestampValue(value: unknown): number {\n if (typeof value === \"number\" && Number.isFinite(value)) return value;\n if (typeof value !== \"string\") return 0;\n const numeric = Number(value);\n if (Number.isFinite(numeric)) return numeric;\n const parsed = Date.parse(value);\n return Number.isFinite(parsed) ? parsed : 0;\n}\n\nfunction sqlWatermarkValue(value: unknown): string | number | undefined {\n if (typeof value === \"string\" && value.length > 0) return value;\n if (typeof value === \"number\" && Number.isFinite(value)) return value;\n return undefined;\n}\n\nasync function readMaxUpdatedAtRaw(\n db: {\n execute: (\n query: string | { sql: string; args?: unknown[] },\n ) => Promise<{ rows: Array<Record<string, unknown>> }>;\n },\n table: \"application_state\" | \"settings\" | \"tools\",\n): Promise<unknown> {\n try {\n const result = await db.execute(\n `SELECT MAX(updated_at) as max_ts FROM ${table}`,\n );\n return result.rows[0]?.max_ts;\n } catch {\n // Optional framework tables may not exist in every app yet.\n return undefined;\n }\n}\n\nasync function readMaxUpdatedAt(\n db: {\n execute: (\n query: string | { sql: string; args?: unknown[] },\n ) => Promise<{ rows: Array<Record<string, unknown>> }>;\n },\n table: \"application_state\" | \"settings\" | \"tools\",\n): Promise<number> {\n return timestampValue(await readMaxUpdatedAtRaw(db, table));\n}\n\nasync function readExtensionMarkerMaxUpdatedAt(db: {\n execute: (\n query: string | { sql: string; args?: unknown[] },\n ) => Promise<{ rows: Array<Record<string, unknown>> }>;\n}): Promise<number> {\n try {\n const result = await db.execute({\n sql: \"SELECT MAX(updated_at) as max_ts FROM application_state WHERE key = ?\",\n args: [EXTENSION_CHANGE_MARKER_KEY],\n });\n return timestampValue(result.rows[0]?.max_ts);\n } catch {\n return 0;\n }\n}\n\nasync function readActionMarkerMaxUpdatedAt(db: {\n execute: (\n query: string | { sql: string; args?: unknown[] },\n ) => Promise<{ rows: Array<Record<string, unknown>> }>;\n}): Promise<number> {\n try {\n const result = await db.execute({\n sql: \"SELECT MAX(updated_at) as max_ts FROM application_state WHERE key = ?\",\n args: [ACTION_CHANGE_MARKER_KEY],\n });\n return timestampValue(result.rows[0]?.max_ts);\n } catch {\n return 0;\n }\n}\n\n/** Get the current global version counter. */\nexport function getVersion(): number {\n return _version;\n}\n\nexport function getPollEmitter(): EventEmitter {\n return _pollEmitter;\n}\n\nexport function canSeeChangeForUser(\n event: ChangeEvent,\n userEmail: string,\n orgId: string | undefined,\n): boolean {\n // Global / unowned events: every authenticated user gets them.\n if (!event.owner && !event.orgId) return true;\n if (event.owner && event.owner === userEmail) return true;\n if (event.orgId && orgId && event.orgId === orgId) return true;\n return false;\n}\n\n/** Record a change event. Called by emitter listeners. */\nexport function recordChange(event: {\n source: string;\n type: string;\n key?: string;\n [k: string]: unknown;\n}): void {\n // Use timestamp-aligned versions so all serverless instances produce\n // values in the same range (seeded from DB, then incremented via\n // Date.now). Plain ++counter diverges across cold starts.\n _version = Math.max(_version + 1, Date.now());\n const entry: ChangeEvent = { ...event, version: _version };\n _buffer.push(entry);\n if (_buffer.length > MAX_BUFFER) {\n _buffer.splice(0, _buffer.length - MAX_BUFFER);\n }\n _pollEmitter.emit(POLL_CHANGE_EVENT, entry);\n}\n\nfunction extensionTargetKey(target: ExtensionChangeTarget): string | null {\n if (target.owner) return `owner:${target.owner}`;\n if (target.orgId) return `org:${target.orgId}`;\n return null;\n}\n\nfunction addExtensionTarget(\n targets: Map<string, ExtensionChangeTarget>,\n target: ExtensionChangeTarget,\n): void {\n const key = extensionTargetKey(target);\n if (key) targets.set(key, target);\n}\n\nfunction recordExtensionChanges(targets: ExtensionChangeTarget[]): void {\n const uniqueTargets = new Map<string, ExtensionChangeTarget>();\n for (const target of targets) addExtensionTarget(uniqueTargets, target);\n for (const target of uniqueTargets.values()) {\n recordChange({\n source: \"extensions\",\n type: \"change\",\n key: \"*\",\n ...(target.owner ? { owner: target.owner } : {}),\n ...(target.orgId ? { orgId: target.orgId } : {}),\n });\n }\n}\n\nfunction recordActionChanges(targets: ActionChangeTarget[]): void {\n for (const target of targets) {\n recordChange({\n source: \"action\",\n type: \"change\",\n key: target.actionName ?? \"*\",\n ...(target.owner ? { owner: target.owner } : {}),\n ...(target.orgId ? { orgId: target.orgId } : {}),\n });\n }\n}\n\nfunction extensionTargetsForRow(\n row: Record<string, unknown>,\n shareRows: Array<Record<string, unknown>>,\n): ExtensionChangeTarget[] {\n const targets = new Map<string, ExtensionChangeTarget>();\n const owner = typeof row.owner_email === \"string\" ? row.owner_email : \"\";\n const orgId = typeof row.org_id === \"string\" ? row.org_id : \"\";\n const visibility =\n typeof row.visibility === \"string\" ? row.visibility : \"private\";\n\n if (owner) addExtensionTarget(targets, { owner });\n if (visibility === \"org\" && orgId) addExtensionTarget(targets, { orgId });\n\n for (const share of shareRows) {\n const principalType =\n typeof share.principal_type === \"string\" ? share.principal_type : \"\";\n const principalId =\n typeof share.principal_id === \"string\" ? share.principal_id : \"\";\n if (principalType === \"user\" && principalId) {\n addExtensionTarget(targets, { owner: principalId });\n } else if (principalType === \"org\" && principalId) {\n addExtensionTarget(targets, { orgId: principalId });\n }\n }\n\n return Array.from(targets.values());\n}\n\nasync function readExtensionTargetsForRows(\n db: {\n execute: (\n query: string | { sql: string; args?: unknown[] },\n ) => Promise<{ rows: Array<Record<string, unknown>> }>;\n },\n rows: Array<Record<string, unknown>>,\n): Promise<ExtensionChangeTarget[][]> {\n const ids = rows\n .map((row) => (typeof row.id === \"string\" ? row.id : \"\"))\n .filter(Boolean);\n const sharesByResourceId = new Map<string, Array<Record<string, unknown>>>();\n\n if (ids.length > 0) {\n try {\n const placeholders = ids.map(() => \"?\").join(\", \");\n const shareResult = await db.execute({\n sql: `SELECT resource_id, principal_type, principal_id FROM tool_shares WHERE resource_id IN (${placeholders})`,\n args: ids,\n });\n for (const share of shareResult.rows) {\n const resourceId =\n typeof share.resource_id === \"string\" ? share.resource_id : \"\";\n if (!resourceId) continue;\n const bucket = sharesByResourceId.get(resourceId) ?? [];\n bucket.push(share);\n sharesByResourceId.set(resourceId, bucket);\n }\n } catch {\n // Sharing tables are optional during early app initialization.\n }\n }\n\n return rows.map((row) =>\n extensionTargetsForRow(\n row,\n sharesByResourceId.get(typeof row.id === \"string\" ? row.id : \"\") ?? [],\n ),\n );\n}\n\n/** Get all changes after a given version. */\nexport function getChangesSince(since: number): {\n version: number;\n events: ChangeEvent[];\n} {\n if (since >= _version) {\n return { version: _version, events: [] };\n }\n const events = _buffer.filter((e) => e.version > since);\n return { version: _version, events };\n}\n\n/**\n * Get changes after a given version, filtered to events the caller is\n * allowed to see.\n *\n * Filtering rules:\n * - Events without an `owner` are deployment-global (table-level pings,\n * screen-refresh, etc.) and visible to every authenticated user.\n * - Events with `owner === userEmail` go to that user.\n * - Events with `orgId === orgId` go to anyone in that org.\n * - All other owned events are filtered out.\n */\nexport function getChangesSinceForUser(\n since: number,\n userEmail: string,\n orgId: string | undefined,\n): { version: number; events: ChangeEvent[] } {\n if (since >= _version) {\n return { version: _version, events: [] };\n }\n const events = _buffer.filter(\n (e) => e.version > since && canSeeChangeForUser(e, userEmail, orgId),\n );\n return { version: _version, events };\n}\n\n/**\n * Seed _version from DB timestamps on the first call so serverless\n * cold starts don't return version 0 and confuse polling clients.\n */\nasync function seedVersionFromDb(): Promise<void> {\n if (_versionSeeded) return;\n _versionSeeded = true;\n\n try {\n const db = getDbExec();\n\n const [\n appTs,\n settingsTs,\n extensionsMaxUpdatedAt,\n extensionMarkerTs,\n actionMarkerTs,\n refreshResult,\n ] = await Promise.all([\n readMaxUpdatedAt(db, \"application_state\"),\n readMaxUpdatedAt(db, \"settings\"),\n readMaxUpdatedAtRaw(db, \"tools\"),\n readExtensionMarkerMaxUpdatedAt(db),\n readActionMarkerMaxUpdatedAt(db),\n db\n .execute({\n sql: \"SELECT session_id, updated_at FROM application_state WHERE key = ?\",\n args: [SCREEN_REFRESH_KEY],\n })\n .catch(() => ({ rows: [] as Record<string, unknown>[] })),\n ]);\n\n const extensionsTs = timestampValue(extensionsMaxUpdatedAt);\n let refreshTs = 0;\n for (const row of refreshResult.rows) {\n refreshTs = Math.max(refreshTs, timestampValue(row.updated_at));\n }\n\n // Seed version — never decrease an already-set value\n _version = Math.max(\n _version,\n appTs,\n settingsTs,\n extensionsTs,\n extensionMarkerTs,\n actionMarkerTs,\n );\n\n // Set baselines so checkExternalDbChanges detects future writes\n _lastAppStateTs = appTs;\n _lastSettingsTs = settingsTs;\n _lastExtensionsTs = extensionsTs;\n _lastExtensionsUpdatedAt = sqlWatermarkValue(extensionsMaxUpdatedAt);\n _lastExtensionMarkerTs = extensionMarkerTs;\n // Action markers are durable specifically so a web server can observe work\n // performed by a separate action process. Do not baseline past an existing\n // marker on cold start, or the first poll after the action will miss it.\n _lastActionMarkerTs = 0;\n _lastScreenRefreshTs = refreshTs;\n _lastScreenRefreshTsBySession.clear();\n for (const row of refreshResult.rows) {\n if (typeof row.session_id === \"string\") {\n _lastScreenRefreshTsBySession.set(\n row.session_id,\n timestampValue(row.updated_at),\n );\n }\n }\n _screenRefreshInitialized = true;\n // Skip the redundant cold-start recheck unless there is an existing durable\n // action marker that the first poll still needs to emit.\n _lastDbCheck = actionMarkerTs > 0 ? 0 : Date.now();\n } catch {\n // Tables may not exist yet — ignore\n }\n}\n\n/**\n * Check for cross-process DB writes by comparing updated_at timestamps.\n * Runs at most once per second to avoid excessive queries.\n */\nasync function checkExternalDbChanges(): Promise<void> {\n const now = Date.now();\n if (now - _lastDbCheck < 1000) return;\n // Coalesce: if a check is already running, await it instead of starting a\n // second overlapping run that would double-advance the shared watermarks\n // (and double-emit change events).\n if (_checkPromise) return _checkPromise;\n _lastDbCheck = now;\n _checkPromise = doCheckExternalDbChanges().finally(() => {\n _checkPromise = null;\n });\n return _checkPromise;\n}\n\nasync function doCheckExternalDbChanges(): Promise<void> {\n try {\n const db = getDbExec();\n\n // These reads are independent — each compares the DB against module-level\n // high-water marks (`_lastAppStateTs`, etc.) rather than another query's\n // result, and none of them mutate state before processing below. On a\n // serverless SQL backend every `await` is a network round-trip, so running\n // them concurrently shaves stacked latency off every poll cycle. Results\n // are still processed in the original sequential order, and conditional\n // follow-up queries (action/extension marker detail rows, tool-shares) stay\n // sequential within their branch where they depend on these results.\n const [\n appResult,\n actionMarkerTs,\n refreshResult,\n extensionMarkerTs,\n settingsTs,\n extensionsMaxUpdatedAt,\n ] = await Promise.all([\n db.execute({\n sql: \"SELECT session_id, key, updated_at FROM application_state WHERE updated_at > ? ORDER BY updated_at ASC\",\n args: [_lastAppStateTs],\n }),\n readActionMarkerMaxUpdatedAt(db),\n db.execute({\n sql: \"SELECT session_id, updated_at, value FROM application_state WHERE key = ?\",\n args: [SCREEN_REFRESH_KEY],\n }),\n readExtensionMarkerMaxUpdatedAt(db),\n readMaxUpdatedAt(db, \"settings\"),\n readMaxUpdatedAtRaw(db, \"tools\"),\n ]);\n\n // Check application_state for external writes. Preserve the changed key so\n // clients can invalidate one-shot command queries (`navigate`, `__set_url__`)\n // only when those command rows actually change; noisy keys such as\n // `slide-fit-check` should not wake navigation readers.\n if (appResult.rows.length > 0) {\n const appTs = appResult.rows.reduce(\n (max, row) => Math.max(max, timestampValue(row.updated_at)),\n _lastAppStateTs,\n );\n if (_lastAppStateTs > 0) {\n for (const row of appResult.rows) {\n const key = typeof row.key === \"string\" ? row.key : \"*\";\n if (\n key === EXTENSION_CHANGE_MARKER_KEY ||\n key === ACTION_CHANGE_MARKER_KEY\n ) {\n continue;\n }\n const owner =\n typeof row.session_id === \"string\" ? row.session_id : undefined;\n recordChange({\n source: \"app-state\",\n type: \"change\",\n key,\n ...(owner ? { owner } : {}),\n });\n }\n }\n _lastAppStateTs = appTs;\n }\n\n // Mutating actions write a durable marker in addition to the in-process\n // event. This lets dev-mode `pnpm action ...` child processes and\n // serverless action invocations wake the web server's SSE/poll loop as a\n // first-class source:\"action\" event rather than a generic app-state bump.\n // `actionMarkerTs` was read above; the detail-row query below is conditional\n // on it and depends on its result, so it stays sequential.\n if (actionMarkerTs > _lastActionMarkerTs) {\n const actionMarkerResult = await db.execute({\n sql: \"SELECT session_id, value, updated_at FROM application_state WHERE key = ? ORDER BY updated_at ASC\",\n args: [ACTION_CHANGE_MARKER_KEY],\n });\n const changedActionMarkers = actionMarkerResult.rows.filter(\n (row) => timestampValue(row.updated_at) > _lastActionMarkerTs,\n );\n recordActionChanges(\n changedActionMarkers\n .map((row) => parseActionChangeMarker(row.session_id, row.value))\n .filter((target): target is ActionChangeTarget => !!target),\n );\n _lastActionMarkerTs = actionMarkerTs;\n }\n\n // Check for screen-refresh requests from the agent. The `refresh-screen`\n // tool writes to application_state under a well-known key; when its\n // updated_at bumps, emit a distinct event so the client invalidates\n // all queries (not just the ones matching its default queryKey prefix).\n // `refreshResult` was read above.\n const refreshTs = refreshResult.rows.reduce(\n (max, row) => Math.max(max, timestampValue(row.updated_at)),\n 0,\n );\n if (!_screenRefreshInitialized) {\n _lastScreenRefreshTs = refreshTs;\n for (const row of refreshResult.rows) {\n if (typeof row.session_id === \"string\") {\n _lastScreenRefreshTsBySession.set(\n row.session_id,\n timestampValue(row.updated_at),\n );\n }\n }\n _screenRefreshInitialized = true;\n } else if (refreshTs > _lastScreenRefreshTs) {\n // Emit a per-user event only for the session(s) whose row actually\n // advanced, scoped with `owner` so canSeeChangeForUser delivers it only\n // to that user — not every authenticated poller.\n for (const row of refreshResult.rows) {\n const owner =\n typeof row.session_id === \"string\" ? row.session_id : undefined;\n if (!owner) continue;\n const rowTs = timestampValue(row.updated_at);\n if (rowTs <= (_lastScreenRefreshTsBySession.get(owner) ?? 0)) continue;\n let scope: string | undefined;\n try {\n const raw = row.value;\n if (typeof raw === \"string\") {\n const parsed = JSON.parse(raw);\n if (typeof parsed?.scope === \"string\") scope = parsed.scope;\n }\n } catch {}\n recordChange({\n source: \"screen-refresh\",\n type: \"change\",\n key: SCREEN_REFRESH_KEY,\n owner,\n ...(scope ? { scope } : {}),\n });\n _lastScreenRefreshTsBySession.set(owner, rowTs);\n }\n _lastScreenRefreshTs = refreshTs;\n }\n\n // Extension mutations write a durable marker row so delete and hide/unhide\n // operations are visible across serverless invocations. Translate those\n // marker rows back into extension-source events for targeted client\n // invalidation while preserving user/org scope. `extensionMarkerTs` was read\n // above; the detail-row query below depends on it and stays sequential.\n if (extensionMarkerTs > _lastExtensionMarkerTs) {\n const extensionMarkerResult = await db.execute({\n sql: \"SELECT session_id, value, updated_at FROM application_state WHERE key = ? ORDER BY updated_at ASC\",\n args: [EXTENSION_CHANGE_MARKER_KEY],\n });\n const changedExtensionMarkers = extensionMarkerResult.rows.filter(\n (row) => timestampValue(row.updated_at) > _lastExtensionMarkerTs,\n );\n if (_lastExtensionMarkerTs > 0) {\n recordExtensionChanges(\n changedExtensionMarkers\n .map((row) => parseExtensionChangeMarker(row.session_id, row.value))\n .filter((target): target is ExtensionChangeTarget => !!target),\n );\n }\n _lastExtensionMarkerTs = extensionMarkerTs;\n }\n\n // Check settings for external writes. `settingsTs` was read above.\n if (settingsTs > _lastSettingsTs) {\n if (_lastSettingsTs > 0) {\n recordChange({ source: \"settings\", type: \"change\", key: \"*\" });\n }\n _lastSettingsTs = settingsTs;\n }\n\n // Extension rows live in the legacy physical `tools` table. Keep this as a\n // compatibility fallback for direct table writes, but scope events to the\n // resource owner/share targets instead of broadcasting deployment-wide.\n // `extensionsMaxUpdatedAt` was read above; the per-row query below is\n // conditional on `extensionsTs` and stays sequential.\n const extensionsTs = timestampValue(extensionsMaxUpdatedAt);\n if (extensionsTs > _lastExtensionsTs) {\n const since = _lastExtensionsUpdatedAt;\n const extensionResult =\n since === undefined\n ? await db.execute({\n sql: \"SELECT id, owner_email, org_id, visibility, updated_at FROM tools ORDER BY updated_at ASC\",\n args: [],\n })\n : await db.execute({\n sql: \"SELECT id, owner_email, org_id, visibility, updated_at FROM tools WHERE updated_at > ? ORDER BY updated_at ASC\",\n args: [since],\n });\n const changedExtensionRows = extensionResult.rows.filter(\n (row) => timestampValue(row.updated_at) > _lastExtensionsTs,\n );\n if (_lastExtensionsTs > 0) {\n const targetsByRow = await readExtensionTargetsForRows(\n db,\n changedExtensionRows,\n );\n for (const targets of targetsByRow) recordExtensionChanges(targets);\n }\n _lastExtensionsTs = extensionsTs;\n _lastExtensionsUpdatedAt = sqlWatermarkValue(extensionsMaxUpdatedAt);\n }\n } catch {\n // Tables may not exist yet — ignore\n }\n}\n\n/**\n * Create an H3 handler for the poll endpoint.\n *\n * GET /_agent-native/poll?since=N → { version, events[] }\n *\n * Requires an authenticated session. Events are filtered to the caller's\n * tenant — global events (owner-less, table-level pings) reach every\n * authenticated caller; owned events reach only the matching user/org.\n * Without auth + filtering, an anonymous attacker could poll the deployment\n * and infer cross-tenant activity from the global event stream.\n */\nexport function createPollHandler() {\n wireLocalEmitters();\n return defineEventHandler(async (event) => {\n const session = await getSession(event).catch(() => null);\n if (!session?.email) {\n setResponseStatus(event, 401);\n return { error: \"Unauthenticated\" };\n }\n // On cold start, seed _version from DB so we don't return version: 0\n await seedVersionFromDb();\n // Check for cross-process writes before responding\n await checkExternalDbChanges();\n\n const query = getQuery(event);\n const since = parseInt(String(query.since ?? \"0\"), 10) || 0;\n return getChangesSinceForUser(since, session.email, session.orgId);\n });\n}\n"]}
1
+ {"version":3,"file":"poll.js","sourceRoot":"","sources":["../../src/server/poll.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Polling-based change notification.\n *\n * Replaces SSE with a simple version counter. Each DB mutation (app-state,\n * settings, resources) increments the version. Clients poll `/_agent-native/poll?since=N`\n * and receive any events that occurred after version N.\n *\n * Works in all deployment environments (serverless, edge, long-lived).\n *\n * Also detects cross-process DB writes by periodically checking the\n * application_state and settings tables' updated_at timestamps. This ensures\n * that changes made by external processes (e.g., CLI actions, cron jobs)\n * are picked up even though they don't call recordChange() in this process.\n */\n\nimport { EventEmitter } from \"node:events\";\n\nimport { defineEventHandler, getQuery, setResponseStatus } from \"h3\";\n\nimport {\n ACTION_CHANGE_MARKER_KEY,\n parseActionChangeMarker,\n type ActionChangeTarget,\n} from \"../action-change-marker.js\";\nimport { getAppStateEmitter } from \"../application-state/emitter.js\";\nimport { getDbExec } from \"../db/client.js\";\nimport {\n EXTENSION_CHANGE_MARKER_KEY,\n parseExtensionChangeMarker,\n type ExtensionChangeTarget,\n} from \"../extensions/change-marker.js\";\nimport { getSettingsEmitter } from \"../settings/store.js\";\nimport { getSession } from \"./auth.js\";\n\nexport interface ChangeEvent {\n version: number;\n source: string;\n type: string;\n key?: string;\n /**\n * Owner email for tenant-scoped events. When absent, the event is treated\n * as deployment-global (e.g. table-level \"something changed\" pings) and\n * delivered to every authenticated poller. Specific events that should\n * only fan out to one user MUST set this — otherwise polling clients\n * across tenants see each other's signals.\n */\n owner?: string;\n /** Optional org ID for org-scoped events. */\n orgId?: string;\n /**\n * Shareable resource type this event belongs to (e.g. \"document\"). When\n * present together with `resourceId`, the per-user delivery filter\n * (`canSeeChangeForUser`) can run an access-aware check so non-owner sharees\n * with explicit viewer+ access receive the push instead of only the poll\n * fallback. See the SYNC-CACHE note above `canSeeChangeForUser`.\n */\n resourceType?: string;\n /**\n * Shareable resource id this event belongs to. Paired with `resourceType`\n * to drive the access-aware delivery check in `canSeeChangeForUser`.\n */\n resourceId?: string;\n [k: string]: unknown;\n}\n\n// In-memory ring buffer of recent changes. Kept small since clients\n// poll frequently (every 2-3s) and only need events since their last poll.\nconst MAX_BUFFER = 200;\nlet _version = 0;\nconst _buffer: ChangeEvent[] = [];\nexport const POLL_CHANGE_EVENT = \"poll-change\";\nconst _pollEmitter = new EventEmitter();\n_pollEmitter.setMaxListeners(0);\n\n/**\n * Whether we've seeded _version from the DB. In serverless (Netlify,\n * Vercel, etc.) each invocation starts fresh — without seeding, _version\n * resets to 0 and polling clients see the version jump backwards, causing\n * duplicate events and stuck UI.\n */\nlet _versionSeeded = false;\n\n/** Tracks the latest updated_at we've seen from the DB, per table. */\nlet _lastDbCheck = 0;\n// Coalesces concurrent checkExternalDbChanges runs. The 1s throttle alone does\n// not prevent overlap when a single check takes longer than 1s — two overlapping\n// runs would each read+advance the shared watermarks and double-emit events.\nlet _checkPromise: Promise<void> | null = null;\nlet _lastAppStateTs = 0;\nlet _lastSettingsTs = 0;\nlet _lastExtensionsTs = 0;\nlet _lastExtensionsUpdatedAt: string | number | undefined;\nlet _lastExtensionMarkerTs = 0;\nlet _lastActionMarkerTs = 0;\n\n/**\n * Tracks the latest updated_at seen on the `__screen_refresh__` key in\n * application_state. Bumped when the agent calls the `refresh-screen` tool,\n * and surfaced as a distinct `screen-refresh` event so clients can remount\n * the main content subtree via React key.\n *\n * `_screenRefreshInitialized` guards against spurious emits on the first\n * poll after a restart (where an existing row would look like a fresh bump).\n * Once we've taken a baseline reading, any subsequent increase emits.\n */\nlet _lastScreenRefreshTs = 0;\nlet _screenRefreshInitialized = false;\n// Per-session high-water marks for `__screen_refresh__`. Each user's row is\n// tracked independently so a refresh triggered by one user only remounts that\n// user's screen (owner-scoped), never every authenticated poller.\nconst _lastScreenRefreshTsBySession = new Map<string, number>();\nconst SCREEN_REFRESH_KEY = \"__screen_refresh__\";\nlet _localEmittersWired = false;\n\nfunction wireLocalEmitters(): void {\n if (_localEmittersWired) return;\n _localEmittersWired = true;\n getAppStateEmitter().on(\"app-state\", (event) => {\n if (\n event.key === EXTENSION_CHANGE_MARKER_KEY ||\n event.key === ACTION_CHANGE_MARKER_KEY\n ) {\n return;\n }\n recordChange(event);\n });\n getSettingsEmitter().on(\"settings\", (event) => {\n recordChange(event);\n });\n}\n\nfunction timestampValue(value: unknown): number {\n if (typeof value === \"number\" && Number.isFinite(value)) return value;\n if (typeof value !== \"string\") return 0;\n const numeric = Number(value);\n if (Number.isFinite(numeric)) return numeric;\n const parsed = Date.parse(value);\n return Number.isFinite(parsed) ? parsed : 0;\n}\n\nfunction sqlWatermarkValue(value: unknown): string | number | undefined {\n if (typeof value === \"string\" && value.length > 0) return value;\n if (typeof value === \"number\" && Number.isFinite(value)) return value;\n return undefined;\n}\n\nasync function readMaxUpdatedAtRaw(\n db: {\n execute: (\n query: string | { sql: string; args?: unknown[] },\n ) => Promise<{ rows: Array<Record<string, unknown>> }>;\n },\n table: \"application_state\" | \"settings\" | \"tools\",\n): Promise<unknown> {\n try {\n const result = await db.execute(\n `SELECT MAX(updated_at) as max_ts FROM ${table}`,\n );\n return result.rows[0]?.max_ts;\n } catch {\n // Optional framework tables may not exist in every app yet.\n return undefined;\n }\n}\n\nasync function readMaxUpdatedAt(\n db: {\n execute: (\n query: string | { sql: string; args?: unknown[] },\n ) => Promise<{ rows: Array<Record<string, unknown>> }>;\n },\n table: \"application_state\" | \"settings\" | \"tools\",\n): Promise<number> {\n return timestampValue(await readMaxUpdatedAtRaw(db, table));\n}\n\nasync function readExtensionMarkerMaxUpdatedAt(db: {\n execute: (\n query: string | { sql: string; args?: unknown[] },\n ) => Promise<{ rows: Array<Record<string, unknown>> }>;\n}): Promise<number> {\n try {\n const result = await db.execute({\n sql: \"SELECT MAX(updated_at) as max_ts FROM application_state WHERE key = ?\",\n args: [EXTENSION_CHANGE_MARKER_KEY],\n });\n return timestampValue(result.rows[0]?.max_ts);\n } catch {\n return 0;\n }\n}\n\nasync function readActionMarkerMaxUpdatedAt(db: {\n execute: (\n query: string | { sql: string; args?: unknown[] },\n ) => Promise<{ rows: Array<Record<string, unknown>> }>;\n}): Promise<number> {\n try {\n const result = await db.execute({\n sql: \"SELECT MAX(updated_at) as max_ts FROM application_state WHERE key = ?\",\n args: [ACTION_CHANGE_MARKER_KEY],\n });\n return timestampValue(result.rows[0]?.max_ts);\n } catch {\n return 0;\n }\n}\n\n/** Get the current global version counter. */\nexport function getVersion(): number {\n return _version;\n}\n\nexport function getPollEmitter(): EventEmitter {\n return _pollEmitter;\n}\n\n/**\n * In-memory, TTL'd access cache for the access-aware branch of\n * `canSeeChangeForUser`. Keyed by `${userEmail}|${resourceType}|${resourceId}`.\n *\n * Insertion order doubles as FIFO for eviction (JS Maps preserve insertion\n * order), so we can evict the oldest entries when we exceed the cap.\n */\nconst _accessCache = new Map<string, { allowed: boolean; checkedAt: number }>();\n/** In-flight background access checks, keyed identically, to dedupe bursts. */\nconst _accessInFlight = new Set<string>();\n/** Per-resource generation bumped when shares/visibility change. */\nconst _accessInvalidationEpoch = new Map<string, number>();\n/** TTL for an allowed (true) cache entry. */\nconst ACCESS_CACHE_TTL_MS = 30_000;\n/**\n * Shorter TTL for a denied (false) entry so a transient DB error (which we\n * fail-closed on) doesn't lock a legitimate user out of the push path for the\n * full 30s — they recover on their next event after this window.\n */\nconst ACCESS_CACHE_DENY_TTL_MS = 5_000;\n/** Max cache entries before FIFO eviction kicks in. */\nconst ACCESS_CACHE_MAX = 500;\n\nfunction accessCacheKey(\n userEmail: string,\n resourceType: string,\n resourceId: string,\n): string {\n return `${userEmail}|${resourceType}|${resourceId}`;\n}\n\nfunction accessResourceKey(resourceType: string, resourceId: string): string {\n return `${resourceType}|${resourceId}`;\n}\n\nfunction accessCacheTtl(allowed: boolean): number {\n return allowed ? ACCESS_CACHE_TTL_MS : ACCESS_CACHE_DENY_TTL_MS;\n}\n\nexport function invalidateCollabAccessCache(\n resourceType: string,\n resourceId: string,\n): void {\n const resourceKey = accessResourceKey(resourceType, resourceId);\n _accessInvalidationEpoch.set(\n resourceKey,\n (_accessInvalidationEpoch.get(resourceKey) ?? 0) + 1,\n );\n const suffix = `|${resourceKey}`;\n for (const key of Array.from(_accessCache.keys())) {\n if (key.endsWith(suffix)) _accessCache.delete(key);\n }\n for (const key of Array.from(_accessInFlight)) {\n if (key.endsWith(suffix)) _accessInFlight.delete(key);\n }\n}\n\nfunction setAccessCache(key: string, allowed: boolean, now: number): void {\n // Re-insert so the key moves to the end (most-recent) for FIFO ordering.\n _accessCache.delete(key);\n _accessCache.set(key, { allowed, checkedAt: now });\n if (_accessCache.size > ACCESS_CACHE_MAX) {\n // Evict the oldest entries (front of insertion order) back under the cap.\n const overflow = _accessCache.size - ACCESS_CACHE_MAX;\n let removed = 0;\n for (const oldestKey of _accessCache.keys()) {\n _accessCache.delete(oldestKey);\n if (++removed >= overflow) break;\n }\n }\n}\n\n/**\n * Fire a background access check for a cache-miss key. Never awaited by the\n * caller — the current event is NOT delivered (we returned false), but the\n * result is cached so the user's NEXT event within the TTL is pushed. Dedupes\n * concurrent checks for the same key via `_accessInFlight`.\n */\nfunction scheduleAccessCheck(\n key: string,\n resourceType: string,\n resourceId: string,\n userEmail: string,\n orgId: string | undefined,\n): void {\n if (_accessInFlight.has(key)) return;\n _accessInFlight.add(key);\n const resourceKey = accessResourceKey(resourceType, resourceId);\n const epoch = _accessInvalidationEpoch.get(resourceKey) ?? 0;\n void (async () => {\n try {\n // Dynamic import to avoid a load-order/circular-import hazard: poll.ts is\n // imported very widely, and the sharing/access module pulls in the\n // resource registry. Importing it lazily inside this background function\n // keeps the module graph acyclic at load time.\n const { resolveAccess } = await import(\"../sharing/access.js\");\n const access = await resolveAccess(resourceType, resourceId, {\n userEmail,\n orgId,\n });\n if ((_accessInvalidationEpoch.get(resourceKey) ?? 0) !== epoch) return;\n setAccessCache(key, access != null, Date.now());\n } catch {\n // Fail closed on any error (DB not ready, missing registration, etc.),\n // but with the short deny TTL so a transient failure self-heals quickly.\n if ((_accessInvalidationEpoch.get(resourceKey) ?? 0) !== epoch) return;\n setAccessCache(key, false, Date.now());\n } finally {\n _accessInFlight.delete(key);\n }\n })();\n}\n\n/**\n * Test-only: clear the access cache and in-flight set so cases don't bleed\n * into each other. Underscore-prefixed and intentionally NOT part of the\n * public API — do not rely on it outside tests.\n */\nexport function __resetCollabAccessCacheForTests(): void {\n _accessCache.clear();\n _accessInFlight.clear();\n _accessInvalidationEpoch.clear();\n}\n\ntype ChangeVisibility = \"visible\" | \"hidden\" | \"pending\";\n\n/**\n * Decide whether a poll/SSE change event should be delivered to a user.\n *\n * SYNC-CACHE VARIANT — WHY THIS IS SYNCHRONOUS:\n * This function is called on hot, synchronous paths: the SSE emitter callback\n * `push(change)` in poll-events.ts (fires per event) and the\n * `getChangesSinceForUser` loop in this file. Making it async would be\n * invasive (it would ripple through both call sites and their emitters).\n * Instead, for the access-aware branch we consult an in-memory cache and, on a\n * miss, fire a NON-BLOCKING background access check and return `false` for the\n * current event. Because the poll fallback (`getChangesSinceForUser` on the\n * next `/poll` cycle) re-evaluates with the now-populated cache, delivery is\n * eventually guaranteed — the only cost is that the very first event for a\n * fresh (user, resource) pair goes over poll instead of push, and every\n * subsequent event within the TTL is pushed.\n *\n * Security: a cache MISS returns `false`, so we NEVER deliver to a user before\n * their access has been affirmatively confirmed by `resolveAccess` — the same\n * authority that gates the HTTP routes. Errors fail closed (cached deny). The\n * owner/org fast paths below are unchanged and evaluated first.\n */\nexport function canSeeChangeForUser(\n event: Pick<ChangeEvent, \"owner\" | \"orgId\" | \"resourceType\" | \"resourceId\">,\n userEmail: string,\n orgId: string | undefined,\n): boolean {\n return getChangeVisibilityForUser(event, userEmail, orgId) === \"visible\";\n}\n\nfunction getChangeVisibilityForUser(\n event: Pick<ChangeEvent, \"owner\" | \"orgId\" | \"resourceType\" | \"resourceId\">,\n userEmail: string,\n orgId: string | undefined,\n): ChangeVisibility {\n // Global / unowned events: every authenticated user gets them. Events that\n // predate resource tagging (owner/org only, no resourceType) keep the exact\n // conservative contract they had before.\n if (!event.owner && !event.orgId && !event.resourceType) return \"visible\";\n if (event.owner && event.owner === userEmail) return \"visible\";\n if (event.orgId && orgId && event.orgId === orgId) return \"visible\";\n\n // Access-aware branch: only when the event carries BOTH resourceType and\n // resourceId and the owner/org fast paths above did not already grant.\n if (event.resourceType && event.resourceId) {\n const key = accessCacheKey(userEmail, event.resourceType, event.resourceId);\n const cached = _accessCache.get(key);\n const now = Date.now();\n if (cached && now - cached.checkedAt < accessCacheTtl(cached.allowed)) {\n // Fresh, non-expired cache hit → trust the cached decision.\n return cached.allowed ? \"visible\" : \"hidden\";\n }\n // Miss or expired: do NOT deliver this event, but schedule the async check\n // so the user's next event (or poll cycle) resolves correctly.\n scheduleAccessCheck(\n key,\n event.resourceType,\n event.resourceId,\n userEmail,\n orgId,\n );\n return \"pending\";\n }\n\n return \"hidden\";\n}\n\n/** Record a change event. Called by emitter listeners. */\nexport function recordChange(event: {\n source: string;\n type: string;\n key?: string;\n [k: string]: unknown;\n}): void {\n // Use timestamp-aligned versions so all serverless instances produce\n // values in the same range (seeded from DB, then incremented via\n // Date.now). Plain ++counter diverges across cold starts.\n _version = Math.max(_version + 1, Date.now());\n const entry: ChangeEvent = { ...event, version: _version };\n _buffer.push(entry);\n if (_buffer.length > MAX_BUFFER) {\n _buffer.splice(0, _buffer.length - MAX_BUFFER);\n }\n _pollEmitter.emit(POLL_CHANGE_EVENT, entry);\n}\n\nfunction extensionTargetKey(target: ExtensionChangeTarget): string | null {\n if (target.owner) return `owner:${target.owner}`;\n if (target.orgId) return `org:${target.orgId}`;\n return null;\n}\n\nfunction addExtensionTarget(\n targets: Map<string, ExtensionChangeTarget>,\n target: ExtensionChangeTarget,\n): void {\n const key = extensionTargetKey(target);\n if (key) targets.set(key, target);\n}\n\nfunction recordExtensionChanges(targets: ExtensionChangeTarget[]): void {\n const uniqueTargets = new Map<string, ExtensionChangeTarget>();\n for (const target of targets) addExtensionTarget(uniqueTargets, target);\n for (const target of uniqueTargets.values()) {\n recordChange({\n source: \"extensions\",\n type: \"change\",\n key: \"*\",\n ...(target.owner ? { owner: target.owner } : {}),\n ...(target.orgId ? { orgId: target.orgId } : {}),\n });\n }\n}\n\nfunction recordActionChanges(targets: ActionChangeTarget[]): void {\n for (const target of targets) {\n recordChange({\n source: \"action\",\n type: \"change\",\n key: target.actionName ?? \"*\",\n ...(target.owner ? { owner: target.owner } : {}),\n ...(target.orgId ? { orgId: target.orgId } : {}),\n });\n }\n}\n\nfunction extensionTargetsForRow(\n row: Record<string, unknown>,\n shareRows: Array<Record<string, unknown>>,\n): ExtensionChangeTarget[] {\n const targets = new Map<string, ExtensionChangeTarget>();\n const owner = typeof row.owner_email === \"string\" ? row.owner_email : \"\";\n const orgId = typeof row.org_id === \"string\" ? row.org_id : \"\";\n const visibility =\n typeof row.visibility === \"string\" ? row.visibility : \"private\";\n\n if (owner) addExtensionTarget(targets, { owner });\n if (visibility === \"org\" && orgId) addExtensionTarget(targets, { orgId });\n\n for (const share of shareRows) {\n const principalType =\n typeof share.principal_type === \"string\" ? share.principal_type : \"\";\n const principalId =\n typeof share.principal_id === \"string\" ? share.principal_id : \"\";\n if (principalType === \"user\" && principalId) {\n addExtensionTarget(targets, { owner: principalId });\n } else if (principalType === \"org\" && principalId) {\n addExtensionTarget(targets, { orgId: principalId });\n }\n }\n\n return Array.from(targets.values());\n}\n\nasync function readExtensionTargetsForRows(\n db: {\n execute: (\n query: string | { sql: string; args?: unknown[] },\n ) => Promise<{ rows: Array<Record<string, unknown>> }>;\n },\n rows: Array<Record<string, unknown>>,\n): Promise<ExtensionChangeTarget[][]> {\n const ids = rows\n .map((row) => (typeof row.id === \"string\" ? row.id : \"\"))\n .filter(Boolean);\n const sharesByResourceId = new Map<string, Array<Record<string, unknown>>>();\n\n if (ids.length > 0) {\n try {\n const placeholders = ids.map(() => \"?\").join(\", \");\n const shareResult = await db.execute({\n sql: `SELECT resource_id, principal_type, principal_id FROM tool_shares WHERE resource_id IN (${placeholders})`,\n args: ids,\n });\n for (const share of shareResult.rows) {\n const resourceId =\n typeof share.resource_id === \"string\" ? share.resource_id : \"\";\n if (!resourceId) continue;\n const bucket = sharesByResourceId.get(resourceId) ?? [];\n bucket.push(share);\n sharesByResourceId.set(resourceId, bucket);\n }\n } catch {\n // Sharing tables are optional during early app initialization.\n }\n }\n\n return rows.map((row) =>\n extensionTargetsForRow(\n row,\n sharesByResourceId.get(typeof row.id === \"string\" ? row.id : \"\") ?? [],\n ),\n );\n}\n\n/** Get all changes after a given version. */\nexport function getChangesSince(since: number): {\n version: number;\n events: ChangeEvent[];\n} {\n if (since >= _version) {\n return { version: _version, events: [] };\n }\n const events = _buffer.filter((e) => e.version > since);\n return { version: _version, events };\n}\n\n/**\n * Get changes after a given version, filtered to events the caller is\n * allowed to see.\n *\n * Filtering rules:\n * - Events without an `owner`/`orgId`/`resourceType` are deployment-global\n * (table-level pings, screen-refresh, etc.) and visible to every\n * authenticated user.\n * - Events with `owner === userEmail` go to that user.\n * - Events with `orgId === orgId` go to anyone in that org.\n * - Events carrying `resourceType` + `resourceId` additionally reach explicit\n * viewer+ sharees via the access-aware cache in `canSeeChangeForUser`.\n * - All other owned events are filtered out.\n */\nexport function getChangesSinceForUser(\n since: number,\n userEmail: string,\n orgId: string | undefined,\n): { version: number; events: ChangeEvent[] } {\n if (since >= _version) {\n return { version: _version, events: [] };\n }\n const events: ChangeEvent[] = [];\n let version = _version;\n for (const event of _buffer) {\n if (event.version <= since) continue;\n const visibility = getChangeVisibilityForUser(event, userEmail, orgId);\n if (visibility === \"visible\") {\n events.push(event);\n continue;\n }\n if (visibility === \"pending\") {\n version = Math.max(since, event.version - 1);\n break;\n }\n }\n return { version, events };\n}\n\n/**\n * Seed _version from DB timestamps on the first call so serverless\n * cold starts don't return version 0 and confuse polling clients.\n */\nasync function seedVersionFromDb(): Promise<void> {\n if (_versionSeeded) return;\n _versionSeeded = true;\n\n try {\n const db = getDbExec();\n\n const [\n appTs,\n settingsTs,\n extensionsMaxUpdatedAt,\n extensionMarkerTs,\n actionMarkerTs,\n refreshResult,\n ] = await Promise.all([\n readMaxUpdatedAt(db, \"application_state\"),\n readMaxUpdatedAt(db, \"settings\"),\n readMaxUpdatedAtRaw(db, \"tools\"),\n readExtensionMarkerMaxUpdatedAt(db),\n readActionMarkerMaxUpdatedAt(db),\n db\n .execute({\n sql: \"SELECT session_id, updated_at FROM application_state WHERE key = ?\",\n args: [SCREEN_REFRESH_KEY],\n })\n .catch(() => ({ rows: [] as Record<string, unknown>[] })),\n ]);\n\n const extensionsTs = timestampValue(extensionsMaxUpdatedAt);\n let refreshTs = 0;\n for (const row of refreshResult.rows) {\n refreshTs = Math.max(refreshTs, timestampValue(row.updated_at));\n }\n\n // Seed version — never decrease an already-set value\n _version = Math.max(\n _version,\n appTs,\n settingsTs,\n extensionsTs,\n extensionMarkerTs,\n actionMarkerTs,\n );\n\n // Set baselines so checkExternalDbChanges detects future writes\n _lastAppStateTs = appTs;\n _lastSettingsTs = settingsTs;\n _lastExtensionsTs = extensionsTs;\n _lastExtensionsUpdatedAt = sqlWatermarkValue(extensionsMaxUpdatedAt);\n _lastExtensionMarkerTs = extensionMarkerTs;\n // Action markers are durable specifically so a web server can observe work\n // performed by a separate action process. Do not baseline past an existing\n // marker on cold start, or the first poll after the action will miss it.\n _lastActionMarkerTs = 0;\n _lastScreenRefreshTs = refreshTs;\n _lastScreenRefreshTsBySession.clear();\n for (const row of refreshResult.rows) {\n if (typeof row.session_id === \"string\") {\n _lastScreenRefreshTsBySession.set(\n row.session_id,\n timestampValue(row.updated_at),\n );\n }\n }\n _screenRefreshInitialized = true;\n // Skip the redundant cold-start recheck unless there is an existing durable\n // action marker that the first poll still needs to emit.\n _lastDbCheck = actionMarkerTs > 0 ? 0 : Date.now();\n } catch {\n // Tables may not exist yet — ignore\n }\n}\n\n/**\n * Check for cross-process DB writes by comparing updated_at timestamps.\n * Runs at most once per second to avoid excessive queries.\n */\nasync function checkExternalDbChanges(): Promise<void> {\n const now = Date.now();\n if (now - _lastDbCheck < 1000) return;\n // Coalesce: if a check is already running, await it instead of starting a\n // second overlapping run that would double-advance the shared watermarks\n // (and double-emit change events).\n if (_checkPromise) return _checkPromise;\n _lastDbCheck = now;\n _checkPromise = doCheckExternalDbChanges().finally(() => {\n _checkPromise = null;\n });\n return _checkPromise;\n}\n\nasync function doCheckExternalDbChanges(): Promise<void> {\n try {\n const db = getDbExec();\n\n // These reads are independent — each compares the DB against module-level\n // high-water marks (`_lastAppStateTs`, etc.) rather than another query's\n // result, and none of them mutate state before processing below. On a\n // serverless SQL backend every `await` is a network round-trip, so running\n // them concurrently shaves stacked latency off every poll cycle. Results\n // are still processed in the original sequential order, and conditional\n // follow-up queries (action/extension marker detail rows, tool-shares) stay\n // sequential within their branch where they depend on these results.\n const [\n appResult,\n actionMarkerTs,\n refreshResult,\n extensionMarkerTs,\n settingsTs,\n extensionsMaxUpdatedAt,\n ] = await Promise.all([\n db.execute({\n sql: \"SELECT session_id, key, updated_at FROM application_state WHERE updated_at > ? ORDER BY updated_at ASC\",\n args: [_lastAppStateTs],\n }),\n readActionMarkerMaxUpdatedAt(db),\n db.execute({\n sql: \"SELECT session_id, updated_at, value FROM application_state WHERE key = ?\",\n args: [SCREEN_REFRESH_KEY],\n }),\n readExtensionMarkerMaxUpdatedAt(db),\n readMaxUpdatedAt(db, \"settings\"),\n readMaxUpdatedAtRaw(db, \"tools\"),\n ]);\n\n // Check application_state for external writes. Preserve the changed key so\n // clients can invalidate one-shot command queries (`navigate`, `__set_url__`)\n // only when those command rows actually change; noisy keys such as\n // `slide-fit-check` should not wake navigation readers.\n if (appResult.rows.length > 0) {\n const appTs = appResult.rows.reduce(\n (max, row) => Math.max(max, timestampValue(row.updated_at)),\n _lastAppStateTs,\n );\n if (_lastAppStateTs > 0) {\n for (const row of appResult.rows) {\n const key = typeof row.key === \"string\" ? row.key : \"*\";\n if (\n key === EXTENSION_CHANGE_MARKER_KEY ||\n key === ACTION_CHANGE_MARKER_KEY\n ) {\n continue;\n }\n const owner =\n typeof row.session_id === \"string\" ? row.session_id : undefined;\n recordChange({\n source: \"app-state\",\n type: \"change\",\n key,\n ...(owner ? { owner } : {}),\n });\n }\n }\n _lastAppStateTs = appTs;\n }\n\n // Mutating actions write a durable marker in addition to the in-process\n // event. This lets dev-mode `pnpm action ...` child processes and\n // serverless action invocations wake the web server's SSE/poll loop as a\n // first-class source:\"action\" event rather than a generic app-state bump.\n // `actionMarkerTs` was read above; the detail-row query below is conditional\n // on it and depends on its result, so it stays sequential.\n if (actionMarkerTs > _lastActionMarkerTs) {\n const actionMarkerResult = await db.execute({\n sql: \"SELECT session_id, value, updated_at FROM application_state WHERE key = ? ORDER BY updated_at ASC\",\n args: [ACTION_CHANGE_MARKER_KEY],\n });\n const changedActionMarkers = actionMarkerResult.rows.filter(\n (row) => timestampValue(row.updated_at) > _lastActionMarkerTs,\n );\n recordActionChanges(\n changedActionMarkers\n .map((row) => parseActionChangeMarker(row.session_id, row.value))\n .filter((target): target is ActionChangeTarget => !!target),\n );\n _lastActionMarkerTs = actionMarkerTs;\n }\n\n // Check for screen-refresh requests from the agent. The `refresh-screen`\n // tool writes to application_state under a well-known key; when its\n // updated_at bumps, emit a distinct event so the client invalidates\n // all queries (not just the ones matching its default queryKey prefix).\n // `refreshResult` was read above.\n const refreshTs = refreshResult.rows.reduce(\n (max, row) => Math.max(max, timestampValue(row.updated_at)),\n 0,\n );\n if (!_screenRefreshInitialized) {\n _lastScreenRefreshTs = refreshTs;\n for (const row of refreshResult.rows) {\n if (typeof row.session_id === \"string\") {\n _lastScreenRefreshTsBySession.set(\n row.session_id,\n timestampValue(row.updated_at),\n );\n }\n }\n _screenRefreshInitialized = true;\n } else if (refreshTs > _lastScreenRefreshTs) {\n // Emit a per-user event only for the session(s) whose row actually\n // advanced, scoped with `owner` so canSeeChangeForUser delivers it only\n // to that user — not every authenticated poller.\n for (const row of refreshResult.rows) {\n const owner =\n typeof row.session_id === \"string\" ? row.session_id : undefined;\n if (!owner) continue;\n const rowTs = timestampValue(row.updated_at);\n if (rowTs <= (_lastScreenRefreshTsBySession.get(owner) ?? 0)) continue;\n let scope: string | undefined;\n try {\n const raw = row.value;\n if (typeof raw === \"string\") {\n const parsed = JSON.parse(raw);\n if (typeof parsed?.scope === \"string\") scope = parsed.scope;\n }\n } catch {}\n recordChange({\n source: \"screen-refresh\",\n type: \"change\",\n key: SCREEN_REFRESH_KEY,\n owner,\n ...(scope ? { scope } : {}),\n });\n _lastScreenRefreshTsBySession.set(owner, rowTs);\n }\n _lastScreenRefreshTs = refreshTs;\n }\n\n // Extension mutations write a durable marker row so delete and hide/unhide\n // operations are visible across serverless invocations. Translate those\n // marker rows back into extension-source events for targeted client\n // invalidation while preserving user/org scope. `extensionMarkerTs` was read\n // above; the detail-row query below depends on it and stays sequential.\n if (extensionMarkerTs > _lastExtensionMarkerTs) {\n const extensionMarkerResult = await db.execute({\n sql: \"SELECT session_id, value, updated_at FROM application_state WHERE key = ? ORDER BY updated_at ASC\",\n args: [EXTENSION_CHANGE_MARKER_KEY],\n });\n const changedExtensionMarkers = extensionMarkerResult.rows.filter(\n (row) => timestampValue(row.updated_at) > _lastExtensionMarkerTs,\n );\n if (_lastExtensionMarkerTs > 0) {\n recordExtensionChanges(\n changedExtensionMarkers\n .map((row) => parseExtensionChangeMarker(row.session_id, row.value))\n .filter((target): target is ExtensionChangeTarget => !!target),\n );\n }\n _lastExtensionMarkerTs = extensionMarkerTs;\n }\n\n // Check settings for external writes. `settingsTs` was read above.\n if (settingsTs > _lastSettingsTs) {\n if (_lastSettingsTs > 0) {\n recordChange({ source: \"settings\", type: \"change\", key: \"*\" });\n }\n _lastSettingsTs = settingsTs;\n }\n\n // Extension rows live in the legacy physical `tools` table. Keep this as a\n // compatibility fallback for direct table writes, but scope events to the\n // resource owner/share targets instead of broadcasting deployment-wide.\n // `extensionsMaxUpdatedAt` was read above; the per-row query below is\n // conditional on `extensionsTs` and stays sequential.\n const extensionsTs = timestampValue(extensionsMaxUpdatedAt);\n if (extensionsTs > _lastExtensionsTs) {\n const since = _lastExtensionsUpdatedAt;\n const extensionResult =\n since === undefined\n ? await db.execute({\n sql: \"SELECT id, owner_email, org_id, visibility, updated_at FROM tools ORDER BY updated_at ASC\",\n args: [],\n })\n : await db.execute({\n sql: \"SELECT id, owner_email, org_id, visibility, updated_at FROM tools WHERE updated_at > ? ORDER BY updated_at ASC\",\n args: [since],\n });\n const changedExtensionRows = extensionResult.rows.filter(\n (row) => timestampValue(row.updated_at) > _lastExtensionsTs,\n );\n if (_lastExtensionsTs > 0) {\n const targetsByRow = await readExtensionTargetsForRows(\n db,\n changedExtensionRows,\n );\n for (const targets of targetsByRow) recordExtensionChanges(targets);\n }\n _lastExtensionsTs = extensionsTs;\n _lastExtensionsUpdatedAt = sqlWatermarkValue(extensionsMaxUpdatedAt);\n }\n } catch {\n // Tables may not exist yet — ignore\n }\n}\n\n/**\n * Create an H3 handler for the poll endpoint.\n *\n * GET /_agent-native/poll?since=N → { version, events[] }\n *\n * Requires an authenticated session. Events are filtered to the caller's\n * tenant — global events (owner-less, table-level pings) reach every\n * authenticated caller; owned events reach only the matching user/org.\n * Without auth + filtering, an anonymous attacker could poll the deployment\n * and infer cross-tenant activity from the global event stream.\n */\nexport function createPollHandler() {\n wireLocalEmitters();\n return defineEventHandler(async (event) => {\n const session = await getSession(event).catch(() => null);\n if (!session?.email) {\n setResponseStatus(event, 401);\n return { error: \"Unauthenticated\" };\n }\n // On cold start, seed _version from DB so we don't return version: 0\n await seedVersionFromDb();\n // Check for cross-process writes before responding\n await checkExternalDbChanges();\n\n const query = getQuery(event);\n const since = parseInt(String(query.since ?? \"0\"), 10) || 0;\n return getChangesSinceForUser(since, session.email, session.orgId);\n });\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"schema-prompt.d.ts","sourceRoot":"","sources":["../../src/server/schema-prompt.ts"],"names":[],"mappings":"AAqBA,OAAO,EAEL,KAAK,mBAAmB,EACzB,MAAM,4BAA4B,CAAC;AA4KpC,gFAAgF;AAChF,wBAAgB,2BAA2B,IAAI,IAAI,CAElD;AA6CD;;;;;;GAMG;AACH,wBAAsB,qBAAqB,CAAC,IAAI,EAAE;IAChD,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,gEAAgE;IAChE,aAAa,CAAC,EAAE,mBAAmB,CAAC;IACpC,6CAA6C;IAC7C,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB,GAAG,OAAO,CAAC,MAAM,CAAC,CAuJlB"}
1
+ {"version":3,"file":"schema-prompt.d.ts","sourceRoot":"","sources":["../../src/server/schema-prompt.ts"],"names":[],"mappings":"AAqBA,OAAO,EAEL,KAAK,mBAAmB,EACzB,MAAM,4BAA4B,CAAC;AA+LpC,gFAAgF;AAChF,wBAAgB,2BAA2B,IAAI,IAAI,CAElD;AA6CD;;;;;;GAMG;AACH,wBAAsB,qBAAqB,CAAC,IAAI,EAAE;IAChD,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,gEAAgE;IAChE,aAAa,CAAC,EAAE,mBAAmB,CAAC;IACpC,6CAA6C;IAC7C,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB,GAAG,OAAO,CAAC,MAAM,CAAC,CAuJlB"}