@agent-native/core 0.88.0 → 0.90.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/corpus/README.md +2 -2
- package/corpus/core/CHANGELOG.md +96 -2
- package/corpus/core/docs/content/agent-native-toolkit.mdx +87 -146
- package/corpus/core/docs/content/cloneable-saas.mdx +19 -19
- package/corpus/core/docs/content/components.mdx +16 -4
- package/corpus/core/docs/content/data-programs.mdx +329 -0
- package/corpus/core/docs/content/deployment.mdx +9 -9
- package/corpus/core/docs/content/extensions.mdx +8 -7
- package/corpus/core/docs/content/generative-ui.mdx +5 -3
- package/corpus/core/docs/content/key-concepts.mdx +6 -9
- package/corpus/core/docs/content/locales/ar-SA/agent-native-toolkit.mdx +100 -70
- package/corpus/core/docs/content/locales/ar-SA/cloneable-saas.mdx +19 -19
- package/corpus/core/docs/content/locales/ar-SA/components.mdx +12 -2
- package/corpus/core/docs/content/locales/ar-SA/data-programs.mdx +329 -0
- package/corpus/core/docs/content/locales/ar-SA/deployment.mdx +8 -9
- package/corpus/core/docs/content/locales/ar-SA/extensions.mdx +6 -4
- package/corpus/core/docs/content/locales/ar-SA/key-concepts.mdx +7 -9
- package/corpus/core/docs/content/locales/ar-SA/real-time-collaboration.mdx +9 -10
- package/corpus/core/docs/content/locales/de-DE/agent-native-toolkit.mdx +100 -74
- package/corpus/core/docs/content/locales/de-DE/cloneable-saas.mdx +19 -19
- package/corpus/core/docs/content/locales/de-DE/components.mdx +12 -2
- package/corpus/core/docs/content/locales/de-DE/data-programs.mdx +329 -0
- package/corpus/core/docs/content/locales/de-DE/deployment.mdx +8 -9
- package/corpus/core/docs/content/locales/de-DE/extensions.mdx +6 -4
- package/corpus/core/docs/content/locales/de-DE/key-concepts.mdx +8 -10
- package/corpus/core/docs/content/locales/de-DE/real-time-collaboration.mdx +9 -10
- package/corpus/core/docs/content/locales/es-ES/agent-native-toolkit.mdx +100 -74
- package/corpus/core/docs/content/locales/es-ES/cloneable-saas.mdx +19 -19
- package/corpus/core/docs/content/locales/es-ES/components.mdx +12 -2
- package/corpus/core/docs/content/locales/es-ES/data-programs.mdx +329 -0
- package/corpus/core/docs/content/locales/es-ES/deployment.mdx +8 -9
- package/corpus/core/docs/content/locales/es-ES/extensions.mdx +6 -4
- package/corpus/core/docs/content/locales/es-ES/key-concepts.mdx +8 -10
- package/corpus/core/docs/content/locales/es-ES/real-time-collaboration.mdx +9 -10
- package/corpus/core/docs/content/locales/fr-FR/agent-native-toolkit.mdx +100 -76
- package/corpus/core/docs/content/locales/fr-FR/cloneable-saas.mdx +19 -19
- package/corpus/core/docs/content/locales/fr-FR/components.mdx +12 -2
- package/corpus/core/docs/content/locales/fr-FR/data-programs.mdx +329 -0
- package/corpus/core/docs/content/locales/fr-FR/deployment.mdx +8 -9
- package/corpus/core/docs/content/locales/fr-FR/extensions.mdx +6 -4
- package/corpus/core/docs/content/locales/fr-FR/key-concepts.mdx +8 -10
- package/corpus/core/docs/content/locales/fr-FR/real-time-collaboration.mdx +9 -10
- package/corpus/core/docs/content/locales/hi-IN/agent-native-toolkit.mdx +100 -71
- package/corpus/core/docs/content/locales/hi-IN/cloneable-saas.mdx +19 -19
- package/corpus/core/docs/content/locales/hi-IN/components.mdx +20 -10
- package/corpus/core/docs/content/locales/hi-IN/data-programs.mdx +329 -0
- package/corpus/core/docs/content/locales/hi-IN/deployment.mdx +8 -9
- package/corpus/core/docs/content/locales/hi-IN/extensions.mdx +6 -4
- package/corpus/core/docs/content/locales/hi-IN/key-concepts.mdx +8 -10
- package/corpus/core/docs/content/locales/hi-IN/real-time-collaboration.mdx +9 -10
- package/corpus/core/docs/content/locales/ja-JP/agent-native-toolkit.mdx +100 -64
- package/corpus/core/docs/content/locales/ja-JP/cloneable-saas.mdx +19 -19
- package/corpus/core/docs/content/locales/ja-JP/components.mdx +12 -2
- package/corpus/core/docs/content/locales/ja-JP/data-programs.mdx +329 -0
- package/corpus/core/docs/content/locales/ja-JP/deployment.mdx +8 -9
- package/corpus/core/docs/content/locales/ja-JP/extensions.mdx +6 -4
- package/corpus/core/docs/content/locales/ja-JP/key-concepts.mdx +9 -11
- package/corpus/core/docs/content/locales/ja-JP/real-time-collaboration.mdx +9 -10
- package/corpus/core/docs/content/locales/ko-KR/agent-native-toolkit.mdx +100 -60
- package/corpus/core/docs/content/locales/ko-KR/cloneable-saas.mdx +19 -19
- package/corpus/core/docs/content/locales/ko-KR/components.mdx +20 -10
- package/corpus/core/docs/content/locales/ko-KR/data-programs.mdx +329 -0
- package/corpus/core/docs/content/locales/ko-KR/deployment.mdx +8 -9
- package/corpus/core/docs/content/locales/ko-KR/extensions.mdx +16 -14
- package/corpus/core/docs/content/locales/ko-KR/key-concepts.mdx +9 -11
- package/corpus/core/docs/content/locales/ko-KR/real-time-collaboration.mdx +9 -10
- package/corpus/core/docs/content/locales/pt-BR/agent-native-toolkit.mdx +100 -74
- package/corpus/core/docs/content/locales/pt-BR/cloneable-saas.mdx +19 -19
- package/corpus/core/docs/content/locales/pt-BR/components.mdx +12 -2
- package/corpus/core/docs/content/locales/pt-BR/data-programs.mdx +329 -0
- package/corpus/core/docs/content/locales/pt-BR/deployment.mdx +8 -9
- package/corpus/core/docs/content/locales/pt-BR/extensions.mdx +6 -4
- package/corpus/core/docs/content/locales/pt-BR/key-concepts.mdx +8 -11
- package/corpus/core/docs/content/locales/pt-BR/real-time-collaboration.mdx +9 -10
- package/corpus/core/docs/content/locales/zh-CN/agent-native-toolkit.mdx +100 -58
- package/corpus/core/docs/content/locales/zh-CN/cloneable-saas.mdx +19 -19
- package/corpus/core/docs/content/locales/zh-CN/components.mdx +20 -10
- package/corpus/core/docs/content/locales/zh-CN/data-programs.mdx +329 -0
- package/corpus/core/docs/content/locales/zh-CN/deployment.mdx +7 -9
- package/corpus/core/docs/content/locales/zh-CN/extensions.mdx +16 -14
- package/corpus/core/docs/content/locales/zh-CN/key-concepts.mdx +7 -11
- package/corpus/core/docs/content/locales/zh-CN/real-time-collaboration.mdx +10 -11
- package/corpus/core/docs/content/locales/zh-TW/agent-native-toolkit.mdx +100 -58
- package/corpus/core/docs/content/locales/zh-TW/cloneable-saas.mdx +19 -19
- package/corpus/core/docs/content/locales/zh-TW/components.mdx +20 -10
- package/corpus/core/docs/content/locales/zh-TW/data-programs.mdx +329 -0
- package/corpus/core/docs/content/locales/zh-TW/deployment.mdx +7 -9
- package/corpus/core/docs/content/locales/zh-TW/extensions.mdx +16 -14
- package/corpus/core/docs/content/locales/zh-TW/key-concepts.mdx +7 -11
- package/corpus/core/docs/content/locales/zh-TW/real-time-collaboration.mdx +10 -11
- package/corpus/core/docs/content/real-time-collaboration.mdx +10 -11
- package/corpus/core/docs/content/toolkit-app-adapters.mdx +46 -0
- package/corpus/core/docs/content/toolkit-collaboration-ui.mdx +48 -0
- package/corpus/core/docs/content/toolkit-sharing-ui.mdx +33 -0
- package/corpus/core/docs/content/toolkit-shell-hooks.mdx +27 -0
- package/corpus/core/docs/content/toolkit-ui.mdx +69 -0
- package/corpus/core/package.json +5 -1
- package/corpus/core/src/agent/durable-background.ts +53 -0
- package/corpus/core/src/agent/engine/ai-sdk-engine.ts +7 -1
- package/corpus/core/src/agent/engine/anthropic-engine.ts +29 -1
- package/corpus/core/src/agent/engine/builder-engine.ts +1 -0
- package/corpus/core/src/agent/engine/output-tokens.ts +26 -13
- package/corpus/core/src/agent/engine/registry.ts +45 -26
- package/corpus/core/src/agent/engine/translate-ai-sdk.ts +56 -7
- package/corpus/core/src/agent/engine/translate-anthropic.ts +43 -1
- package/corpus/core/src/agent/engine/types.ts +16 -0
- package/corpus/core/src/agent/model-config.ts +100 -0
- package/corpus/core/src/agent/production-agent.ts +492 -241
- package/corpus/core/src/agent/runtime-context.ts +50 -12
- package/corpus/core/src/agent/tool-result-images.ts +178 -0
- package/corpus/core/src/brand-kit/fig/index.ts +8 -4
- package/corpus/core/src/client/AgentPanel.tsx +89 -32
- package/corpus/core/src/client/AssistantChat.tsx +95 -46
- package/corpus/core/src/client/KeepTabOpenNotice.tsx +176 -0
- package/corpus/core/src/client/MultiTabAssistantChat.tsx +7 -0
- package/corpus/core/src/client/RunStuckBanner.tsx +13 -1
- package/corpus/core/src/client/chat/run-recovery.tsx +7 -1
- package/corpus/core/src/client/clipboard.ts +17 -13
- package/corpus/core/src/client/components/AgentPresenceChip.tsx +4 -69
- package/corpus/core/src/client/components/LiveCursorOverlay.tsx +5 -240
- package/corpus/core/src/client/components/PresenceBar.tsx +4 -346
- package/corpus/core/src/client/components/RecentEditHighlights.tsx +4 -219
- package/corpus/core/src/client/components/RemoteSelectionRings.tsx +5 -220
- package/corpus/core/src/client/composer/TiptapComposer.tsx +94 -38
- package/corpus/core/src/client/db-admin/SqlEditor.tsx +13 -3
- package/corpus/core/src/client/dynamic-suggestions.ts +6 -1
- package/corpus/core/src/client/extensions/ExtensionViewer.tsx +0 -14
- package/corpus/core/src/client/extensions/ExtensionsListPage.tsx +29 -30
- package/corpus/core/src/client/extensions/ExtensionsSidebarSection.tsx +2 -1
- package/corpus/core/src/client/host-bridge.ts +29 -8
- package/corpus/core/src/client/i18n.tsx +7 -1
- package/corpus/core/src/client/index.ts +5 -0
- package/corpus/core/src/client/resources/McpIntegrationDialog.tsx +34 -69
- package/corpus/core/src/client/rich-markdown-editor/SharedRichEditor.tsx +4 -0
- package/corpus/core/src/client/rich-markdown-editor/useCollabReconcile.ts +18 -7
- package/corpus/core/src/client/settings/SettingsPanel.tsx +409 -230
- package/corpus/core/src/client/settings/SettingsTabsPage.tsx +5 -7
- package/corpus/core/src/client/settings/index.ts +5 -1
- package/corpus/core/src/client/sharing/VisibilityBadge.tsx +4 -37
- package/corpus/core/src/client/use-action.ts +39 -2
- package/corpus/core/src/client/use-db-sync.ts +44 -18
- package/corpus/core/src/client/use-run-stuck-detection.ts +10 -1
- package/corpus/core/src/coding-tools/run-code.ts +473 -74
- package/corpus/core/src/coding-tools/sandbox/background.ts +406 -0
- package/corpus/core/src/coding-tools/sandbox/executions-store.ts +517 -0
- package/corpus/core/src/coding-tools/sandbox/index.ts +53 -13
- package/corpus/core/src/coding-tools/sandbox/local-child-process-adapter.ts +61 -4
- package/corpus/core/src/collab/client.ts +870 -562
- package/corpus/core/src/collab/presence.ts +12 -23
- package/corpus/core/src/collab/recent-edits.ts +13 -32
- package/corpus/core/src/data-programs/actions.ts +335 -0
- package/corpus/core/src/data-programs/contract.ts +284 -0
- package/corpus/core/src/data-programs/execute.ts +693 -0
- package/corpus/core/src/data-programs/index.ts +72 -0
- package/corpus/core/src/data-programs/schema.ts +148 -0
- package/corpus/core/src/data-programs/store.ts +755 -0
- package/corpus/core/src/db/create-get-db.ts +32 -2
- package/corpus/core/src/deploy/build.ts +34 -0
- package/corpus/core/src/extensions/actions.ts +2 -2
- package/corpus/core/src/file-upload/builder.ts +11 -0
- package/corpus/core/src/integrations/webhook-handler.ts +27 -8
- package/corpus/core/src/local-artifacts/index.ts +1 -1
- package/corpus/core/src/localization/default-messages.ts +1 -2
- package/corpus/core/src/mcp-client/index.ts +29 -0
- package/corpus/core/src/onboarding/default-steps.ts +5 -2
- package/corpus/core/src/resources/store.ts +34 -3
- package/corpus/core/src/scripts/agent-engines/list-agent-engines.ts +4 -8
- package/corpus/core/src/scripts/agent-engines/test-agent-engine.ts +9 -2
- package/corpus/core/src/scripts/db/tool-mode.ts +2 -2
- package/corpus/core/src/scripts/resources/migrate-learnings.ts +9 -13
- package/corpus/core/src/server/agent-chat-plugin.ts +154 -62
- package/corpus/core/src/server/agent-discovery.ts +67 -7
- package/corpus/core/src/server/auth.ts +90 -3
- package/corpus/core/src/server/builder-design-systems.ts +2 -2
- package/corpus/core/src/server/core-routes-plugin.ts +119 -22
- package/corpus/core/src/server/credential-provider.ts +28 -8
- package/corpus/core/src/server/csrf.ts +3 -0
- package/corpus/core/src/server/framework-request-handler.ts +52 -4
- package/corpus/core/src/server/oauth-helpers.ts +11 -1
- package/corpus/core/src/server/onboarding-html.ts +80 -48
- package/corpus/core/src/server/prompts/shared-rules.ts +2 -2
- package/corpus/core/src/server/transcribe-voice.ts +93 -9
- package/corpus/core/src/styles/agent-native.css +57 -45
- package/corpus/core/src/templates/default/.agents/skills/actions/SKILL.md +55 -0
- package/corpus/core/src/templates/default/AGENTS.md +11 -14
- package/corpus/core/src/templates/default/actions/navigate.ts +1 -1
- package/corpus/core/src/templates/default/app/i18n/ar-SA.ts +0 -1
- package/corpus/core/src/templates/default/app/i18n/de-DE.ts +0 -1
- package/corpus/core/src/templates/default/app/i18n/en-US.ts +0 -1
- package/corpus/core/src/templates/default/app/i18n/es-ES.ts +0 -1
- package/corpus/core/src/templates/default/app/i18n/fr-FR.ts +0 -1
- package/corpus/core/src/templates/default/app/i18n/hi-IN.ts +0 -1
- package/corpus/core/src/templates/default/app/i18n/ja-JP.ts +0 -1
- package/corpus/core/src/templates/default/app/i18n/ko-KR.ts +0 -1
- package/corpus/core/src/templates/default/app/i18n/pt-BR.ts +0 -1
- package/corpus/core/src/templates/default/app/i18n/zh-CN.ts +0 -1
- package/corpus/core/src/templates/default/app/i18n/zh-TW.ts +0 -1
- package/corpus/core/src/templates/default/app/routes/settings.tsx +22 -33
- package/corpus/core/src/templates/headless/.agents/skills/agent-native-docs/SKILL.md +20 -7
- package/corpus/core/src/templates/headless/AGENTS.md +9 -6
- package/corpus/core/src/templates/workspace-core/.agents/skills/actions/SKILL.md +55 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/data-programs/SKILL.md +128 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/harness-agents/SKILL.md +10 -4
- package/corpus/core/src/vite/agents-bundle-plugin.ts +26 -1
- package/corpus/core/src/vite/client.ts +12 -0
- package/corpus/templates/analytics/.agents/skills/actions/SKILL.md +55 -0
- package/corpus/templates/analytics/.agents/skills/analysis-workspace/SKILL.md +8 -0
- package/corpus/templates/analytics/.agents/skills/data-programs/SKILL.md +348 -0
- package/corpus/templates/analytics/.agents/skills/provider-api/SKILL.md +10 -0
- package/corpus/templates/analytics/AGENTS.md +31 -32
- package/corpus/templates/analytics/actions/dashboard-mutation-api.ts +1 -1
- package/corpus/templates/analytics/actions/delete-data-source-credentials.ts +32 -0
- package/corpus/templates/analytics/actions/ensure-risk-meeting-dashboard.ts +247 -0
- package/corpus/templates/analytics/actions/update-data-source-credentials.ts +123 -0
- package/corpus/templates/analytics/app/components/InlineMetric.tsx +2 -2
- package/corpus/templates/analytics/app/components/dashboard/CumulativeNetChart.tsx +2 -7
- package/corpus/templates/analytics/app/components/dashboard/DataTable.tsx +11 -16
- package/corpus/templates/analytics/app/components/dashboard/DateRangePicker.tsx +1 -2
- package/corpus/templates/analytics/app/components/dashboard/MetricCard.tsx +2 -7
- package/corpus/templates/analytics/app/components/dashboard/RecentActivity.tsx +3 -6
- package/corpus/templates/analytics/app/components/dashboard/RevenueChart.tsx +1 -6
- package/corpus/templates/analytics/app/components/dashboard/RevenueComparisonChart.tsx +2 -7
- package/corpus/templates/analytics/app/components/dashboard/SqlChart.tsx +11 -15
- package/corpus/templates/analytics/app/components/dashboard/StatsCard.tsx +1 -7
- package/corpus/templates/analytics/app/components/dashboard/TimeSeriesChart.tsx +2 -7
- package/corpus/templates/analytics/app/components/layout/CommandPalette.tsx +16 -16
- package/corpus/templates/analytics/app/components/layout/Header.tsx +2 -2
- package/corpus/templates/analytics/app/components/layout/HeaderActions.tsx +2 -1
- package/corpus/templates/analytics/app/components/layout/Layout.tsx +2 -2
- package/corpus/templates/analytics/app/components/layout/MobileNav.tsx +33 -17
- package/corpus/templates/analytics/app/components/layout/NewAnalysisDialog.tsx +6 -6
- package/corpus/templates/analytics/app/components/layout/NewDashboardDialog.tsx +4 -3
- package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +119 -68
- package/corpus/templates/analytics/app/components/ui/alert-dialog.tsx +1 -0
- package/corpus/templates/analytics/app/components/ui/alert.tsx +1 -0
- package/corpus/templates/analytics/app/components/ui/avatar.tsx +1 -0
- package/corpus/templates/analytics/app/components/ui/badge.tsx +1 -0
- package/corpus/templates/analytics/app/components/ui/button.tsx +1 -0
- package/corpus/templates/analytics/app/components/ui/calendar.tsx +1 -1
- package/corpus/templates/analytics/app/components/ui/card.tsx +1 -0
- package/corpus/templates/analytics/app/components/ui/checkbox.tsx +1 -0
- package/corpus/templates/analytics/app/components/ui/collapsible.tsx +1 -0
- package/corpus/templates/analytics/app/components/ui/command.tsx +1 -0
- package/corpus/templates/analytics/app/components/ui/date-picker.tsx +1 -0
- package/corpus/templates/analytics/app/components/ui/dialog.tsx +1 -0
- package/corpus/templates/analytics/app/components/ui/dropdown-menu.tsx +1 -0
- package/corpus/templates/analytics/app/components/ui/input.tsx +1 -0
- package/corpus/templates/analytics/app/components/ui/label.tsx +1 -0
- package/corpus/templates/analytics/app/components/ui/popover.tsx +1 -0
- package/corpus/templates/analytics/app/components/ui/progress.tsx +1 -0
- package/corpus/templates/analytics/app/components/ui/select.tsx +1 -0
- package/corpus/templates/analytics/app/components/ui/sheet.tsx +1 -0
- package/corpus/templates/analytics/app/components/ui/skeleton.tsx +1 -0
- package/corpus/templates/analytics/app/components/ui/sonner.tsx +1 -0
- package/corpus/templates/analytics/app/components/ui/spinner.tsx +1 -0
- package/corpus/templates/analytics/app/components/ui/switch.tsx +1 -0
- package/corpus/templates/analytics/app/components/ui/table.tsx +1 -0
- package/corpus/templates/analytics/app/components/ui/tabs.tsx +1 -0
- package/corpus/templates/analytics/app/components/ui/textarea.tsx +1 -0
- package/corpus/templates/analytics/app/components/ui/toaster.tsx +1 -0
- package/corpus/templates/analytics/app/components/ui/toggle-group.tsx +1 -0
- package/corpus/templates/analytics/app/components/ui/toolkit-provider.tsx +12 -0
- package/corpus/templates/analytics/app/components/ui/tooltip.tsx +1 -0
- package/corpus/templates/analytics/app/global.css +26 -3
- package/corpus/templates/analytics/app/i18n/zh-TW.ts +27 -4
- package/corpus/templates/analytics/app/i18n-data.ts +277 -42
- package/corpus/templates/analytics/app/pages/Agents.tsx +19 -19
- package/corpus/templates/analytics/app/pages/DataDictionary.tsx +21 -21
- package/corpus/templates/analytics/app/pages/DataSources.tsx +31 -54
- package/corpus/templates/analytics/app/pages/NotFound.tsx +2 -1
- package/corpus/templates/analytics/app/pages/Placeholder.tsx +2 -1
- package/corpus/templates/analytics/app/pages/Settings.tsx +19 -37
- package/corpus/templates/analytics/app/pages/adhoc/DashboardSkeleton.tsx +3 -2
- package/corpus/templates/analytics/app/pages/adhoc/_shared/KpiChart.tsx +8 -13
- package/corpus/templates/analytics/app/pages/adhoc/_shared/components/DateRangeInput.tsx +1 -2
- package/corpus/templates/analytics/app/pages/adhoc/explorer/components/ChartTypePicker.tsx +2 -4
- package/corpus/templates/analytics/app/pages/adhoc/explorer/components/DateRangePicker.tsx +1 -2
- package/corpus/templates/analytics/app/pages/adhoc/explorer/components/EventCombobox.tsx +7 -7
- package/corpus/templates/analytics/app/pages/adhoc/explorer/components/EventPanel.tsx +2 -1
- package/corpus/templates/analytics/app/pages/adhoc/explorer/components/EventRow.tsx +2 -1
- package/corpus/templates/analytics/app/pages/adhoc/explorer/components/ExplorerChart.tsx +3 -8
- package/corpus/templates/analytics/app/pages/adhoc/explorer/components/FilterBuilder.tsx +5 -4
- package/corpus/templates/analytics/app/pages/adhoc/explorer/components/GroupByPicker.tsx +2 -1
- package/corpus/templates/analytics/app/pages/adhoc/explorer/components/PropertyCombobox.tsx +7 -7
- package/corpus/templates/analytics/app/pages/adhoc/explorer/components/PropertyValueCombobox.tsx +7 -7
- package/corpus/templates/analytics/app/pages/adhoc/explorer/components/SqlPreview.tsx +1 -1
- package/corpus/templates/analytics/app/pages/adhoc/explorer/index.tsx +16 -16
- package/corpus/templates/analytics/app/pages/adhoc/explorer-dashboard/ChartCard.tsx +16 -21
- package/corpus/templates/analytics/app/pages/adhoc/explorer-dashboard/index.tsx +32 -32
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/DashboardFilterBar.tsx +14 -14
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/EmailReportDialog.tsx +14 -13
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/PanelEditorDialog.tsx +200 -52
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/SqlChartCard.tsx +23 -28
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/ViewSqlPopover.tsx +13 -12
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/ViewsMenu.tsx +15 -15
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +32 -36
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/types.ts +2 -1
- package/corpus/templates/analytics/app/pages/analyses/AnalysesList.tsx +8 -7
- package/corpus/templates/analytics/app/pages/analyses/AnalysisDetail.tsx +19 -19
- package/corpus/templates/analytics/app/pages/analyses/LegacyFusionAnalysis.tsx +11 -15
- package/corpus/templates/analytics/app/pages/sessions/SessionDetailPage.tsx +14 -14
- package/corpus/templates/analytics/app/pages/sessions/SessionDevToolsPanel.tsx +7 -12
- package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +12 -12
- package/corpus/templates/analytics/app/pages/settings/AlertRulesSettingsCard.tsx +25 -25
- package/corpus/templates/analytics/app/root.tsx +22 -19
- package/corpus/templates/analytics/app/routes/catalog.tsx +8 -8
- package/corpus/templates/analytics/changelog/2026-07-06-dashboard-lists-and-headers-stay-compact.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-06-dashboards-can-now-chart-data-programs-saved-server-side-scr.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-06-extension-pages-and-mobile-headers-now-share-one-background-shade.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-06-mobile-chat-header-is-more-compact-and-the-menu-button-opens-navigation.md +5 -0
- package/corpus/templates/analytics/learnings.defaults.md +36 -0
- package/corpus/templates/analytics/seeds/data-programs/risk-meeting-cohort.js +254 -0
- package/corpus/templates/analytics/seeds/data-programs/risk-meeting-pylon-early-warning.js +184 -0
- package/corpus/templates/analytics/server/handlers/sql-query.ts +1 -1
- package/corpus/templates/analytics/server/lib/dashboard-panel-query.ts +109 -1
- package/corpus/templates/assets/.agents/skills/actions/SKILL.md +55 -0
- package/corpus/templates/assets/.agents/skills/asset-generation/SKILL.md +5 -0
- package/corpus/templates/assets/.agents/skills/logo-composite/SKILL.md +34 -6
- package/corpus/templates/assets/AGENTS.md +23 -4
- package/corpus/templates/assets/actions/_generation-preset-settings.ts +48 -0
- package/corpus/templates/assets/actions/_helpers.ts +8 -1
- package/corpus/templates/assets/actions/_preset-skeleton-validation.ts +64 -0
- package/corpus/templates/assets/actions/create-generation-preset.ts +11 -3
- package/corpus/templates/assets/actions/generate-image-batch.ts +7 -2
- package/corpus/templates/assets/actions/generate-image.ts +342 -25
- package/corpus/templates/assets/actions/get-library.ts +4 -3
- package/corpus/templates/assets/actions/navigate.ts +2 -1
- package/corpus/templates/assets/actions/refresh-generation-run.ts +5 -1
- package/corpus/templates/assets/actions/update-asset.ts +1 -0
- package/corpus/templates/assets/actions/update-generation-preset.ts +8 -1
- package/corpus/templates/assets/actions/view-screen.ts +8 -1
- package/corpus/templates/assets/app/components/create/RecentDraftsSection.tsx +3 -2
- package/corpus/templates/assets/app/components/generation/GenerationResults.tsx +25 -11
- package/corpus/templates/assets/app/components/layout/Header.tsx +1 -1
- package/corpus/templates/assets/app/components/layout/PageShell.tsx +4 -4
- package/corpus/templates/assets/app/components/layout/Sidebar.tsx +12 -12
- package/corpus/templates/assets/app/components/library/CreateLibraryDialog.tsx +8 -8
- package/corpus/templates/assets/app/components/library/EditLibraryDialog.tsx +7 -7
- package/corpus/templates/assets/app/components/library/LibraryCard.tsx +8 -8
- package/corpus/templates/assets/app/components/library/LibraryPresetGrid.tsx +3 -2
- package/corpus/templates/assets/app/components/ui/alert-dialog.tsx +1 -0
- package/corpus/templates/assets/app/components/ui/badge.tsx +1 -0
- package/corpus/templates/assets/app/components/ui/button.tsx +1 -0
- package/corpus/templates/assets/app/components/ui/card.tsx +1 -0
- package/corpus/templates/assets/app/components/ui/checkbox.tsx +1 -0
- package/corpus/templates/assets/app/components/ui/dialog.tsx +1 -0
- package/corpus/templates/assets/app/components/ui/dropdown-menu.tsx +1 -0
- package/corpus/templates/assets/app/components/ui/input.tsx +1 -0
- package/corpus/templates/assets/app/components/ui/label.tsx +1 -0
- package/corpus/templates/assets/app/components/ui/popover.tsx +1 -0
- package/corpus/templates/assets/app/components/ui/select.tsx +1 -0
- package/corpus/templates/assets/app/components/ui/separator.tsx +1 -0
- package/corpus/templates/assets/app/components/ui/sheet.tsx +1 -0
- package/corpus/templates/assets/app/components/ui/skeleton.tsx +1 -0
- package/corpus/templates/assets/app/components/ui/sonner.tsx +1 -0
- package/corpus/templates/assets/app/components/ui/spinner.tsx +1 -0
- package/corpus/templates/assets/app/components/ui/tabs.tsx +1 -0
- package/corpus/templates/assets/app/components/ui/toolkit-provider.tsx +12 -0
- package/corpus/templates/assets/app/components/ui/tooltip.tsx +1 -0
- package/corpus/templates/assets/app/global.css +1 -0
- package/corpus/templates/assets/app/hooks/use-image-model-menu.ts +1 -0
- package/corpus/templates/assets/app/hooks/use-navigation-state.ts +11 -0
- package/corpus/templates/assets/app/i18n/zh-TW.ts +64 -0
- package/corpus/templates/assets/app/i18n-data.ts +650 -0
- package/corpus/templates/assets/app/root.tsx +12 -9
- package/corpus/templates/assets/app/routes/asset.$id.tsx +21 -20
- package/corpus/templates/assets/app/routes/audit.tsx +15 -14
- package/corpus/templates/assets/app/routes/brand-kits.$id.tsx +93 -87
- package/corpus/templates/assets/app/routes/brand-kits.$id_.presets.$presetId.tsx +1474 -0
- package/corpus/templates/assets/app/routes/library.tsx +74 -32
- package/corpus/templates/assets/app/routes/settings.tsx +21 -35
- package/corpus/templates/assets/changelog/2026-07-06-mobile-layouts-no-longer-stack-two-top-headers.md +5 -0
- package/corpus/templates/assets/server/lib/generation.ts +366 -44
- package/corpus/templates/assets/server/lib/image-processing.ts +252 -0
- package/corpus/templates/assets/server/lib/preset-skeleton.ts +137 -0
- package/corpus/templates/assets/shared/api.ts +47 -0
- package/corpus/templates/brain/.agents/skills/actions/SKILL.md +55 -0
- package/corpus/templates/brain/.agents/skills/ask-across-everything/SKILL.md +6 -1
- package/corpus/templates/brain/.agents/skills/brain/SKILL.md +63 -5
- package/corpus/templates/brain/.agents/skills/ingestion-and-connectors/SKILL.md +112 -0
- package/corpus/templates/brain/AGENTS.md +93 -8
- package/corpus/templates/brain/app/components/brain/CanonicalPreviewSheet.tsx +6 -5
- package/corpus/templates/brain/app/components/brain/Surface.tsx +3 -8
- package/corpus/templates/brain/app/components/layout/Layout.tsx +7 -7
- package/corpus/templates/brain/app/components/layout/Sidebar.tsx +6 -6
- package/corpus/templates/brain/app/components/ui/badge.tsx +1 -0
- package/corpus/templates/brain/app/components/ui/button.tsx +1 -0
- package/corpus/templates/brain/app/components/ui/card.tsx +1 -0
- package/corpus/templates/brain/app/components/ui/input.tsx +1 -0
- package/corpus/templates/brain/app/components/ui/label.tsx +1 -0
- package/corpus/templates/brain/app/components/ui/progress.tsx +1 -0
- package/corpus/templates/brain/app/components/ui/select.tsx +1 -0
- package/corpus/templates/brain/app/components/ui/separator.tsx +1 -0
- package/corpus/templates/brain/app/components/ui/sheet.tsx +1 -0
- package/corpus/templates/brain/app/components/ui/skeleton.tsx +1 -0
- package/corpus/templates/brain/app/components/ui/switch.tsx +1 -0
- package/corpus/templates/brain/app/components/ui/table.tsx +1 -0
- package/corpus/templates/brain/app/components/ui/textarea.tsx +1 -0
- package/corpus/templates/brain/app/components/ui/toolkit-provider.tsx +12 -0
- package/corpus/templates/brain/app/components/ui/tooltip.tsx +1 -0
- package/corpus/templates/brain/app/global.css +1 -0
- package/corpus/templates/brain/app/hooks/use-distillation-bridge.ts +9 -4
- package/corpus/templates/brain/app/root.tsx +11 -8
- package/corpus/templates/brain/app/routes/knowledge.tsx +19 -19
- package/corpus/templates/brain/app/routes/ops.tsx +18 -18
- package/corpus/templates/brain/app/routes/review.tsx +22 -27
- package/corpus/templates/brain/app/routes/search.tsx +20 -20
- package/corpus/templates/brain/app/routes/settings.tsx +25 -40
- package/corpus/templates/brain/app/routes/sources.tsx +23 -23
- package/corpus/templates/calendar/.agents/skills/actions/SKILL.md +55 -0
- package/corpus/templates/calendar/actions/find-a-time.ts +29 -16
- package/corpus/templates/calendar/actions/list-bookings.ts +33 -2
- package/corpus/templates/calendar/actions/list-events.ts +34 -8
- package/corpus/templates/calendar/actions/update-calendar-visual-preferences.ts +105 -34
- package/corpus/templates/calendar/app/components/ThemeToggle.tsx +5 -5
- package/corpus/templates/calendar/app/components/TimezoneCombobox.tsx +6 -6
- package/corpus/templates/calendar/app/components/booking/BookingConfirmation.tsx +2 -1
- package/corpus/templates/calendar/app/components/booking/BookingForm.tsx +9 -8
- package/corpus/templates/calendar/app/components/booking/DatePicker.tsx +2 -2
- package/corpus/templates/calendar/app/components/booking/TimeSlotPicker.tsx +3 -2
- package/corpus/templates/calendar/app/components/calendar/AddCalendarDialog.tsx +10 -15
- package/corpus/templates/calendar/app/components/calendar/AttendeeAutocomplete.tsx +6 -6
- package/corpus/templates/calendar/app/components/calendar/CommandPalette.tsx +73 -3
- package/corpus/templates/calendar/app/components/calendar/CreateEventDialog.tsx +27 -27
- package/corpus/templates/calendar/app/components/calendar/DayView.tsx +553 -267
- package/corpus/templates/calendar/app/components/calendar/DeleteEventDialog.tsx +9 -12
- package/corpus/templates/calendar/app/components/calendar/EventAttendeesSection.tsx +10 -13
- package/corpus/templates/calendar/app/components/calendar/EventDetailPanel.tsx +7 -7
- package/corpus/templates/calendar/app/components/calendar/EventDetailPopover.tsx +21 -21
- package/corpus/templates/calendar/app/components/calendar/EventDialog.tsx +11 -11
- package/corpus/templates/calendar/app/components/calendar/EventOptionControls.tsx +9 -9
- package/corpus/templates/calendar/app/components/calendar/FindTimePanel.tsx +9 -9
- package/corpus/templates/calendar/app/components/calendar/GoogleConnectBanner.tsx +6 -6
- package/corpus/templates/calendar/app/components/calendar/GoogleSetupWizard.tsx +3 -3
- package/corpus/templates/calendar/app/components/calendar/GoogleSyncButton.tsx +1 -1
- package/corpus/templates/calendar/app/components/calendar/GuestNotificationDialog.tsx +8 -10
- package/corpus/templates/calendar/app/components/calendar/IntegrationsSidebar.tsx +12 -12
- package/corpus/templates/calendar/app/components/calendar/KeyboardShortcutsHelp.tsx +2 -2
- package/corpus/templates/calendar/app/components/calendar/MonthView.tsx +93 -41
- package/corpus/templates/calendar/app/components/calendar/PeopleSearchDialog.tsx +6 -6
- package/corpus/templates/calendar/app/components/calendar/WeekView.tsx +530 -299
- package/corpus/templates/calendar/app/components/layout/AppLayout.tsx +229 -134
- package/corpus/templates/calendar/app/components/layout/Sidebar.tsx +135 -108
- package/corpus/templates/calendar/app/components/ui/alert-dialog.tsx +1 -0
- package/corpus/templates/calendar/app/components/ui/badge.tsx +1 -0
- package/corpus/templates/calendar/app/components/ui/button.tsx +1 -0
- package/corpus/templates/calendar/app/components/ui/card.tsx +1 -0
- package/corpus/templates/calendar/app/components/ui/checkbox.tsx +1 -0
- package/corpus/templates/calendar/app/components/ui/collapsible.tsx +1 -0
- package/corpus/templates/calendar/app/components/ui/command.tsx +1 -0
- package/corpus/templates/calendar/app/components/ui/dialog.tsx +1 -0
- package/corpus/templates/calendar/app/components/ui/dropdown-menu.tsx +1 -0
- package/corpus/templates/calendar/app/components/ui/input.tsx +1 -0
- package/corpus/templates/calendar/app/components/ui/label.tsx +1 -0
- package/corpus/templates/calendar/app/components/ui/popover.tsx +1 -0
- package/corpus/templates/calendar/app/components/ui/radio-group.tsx +1 -0
- package/corpus/templates/calendar/app/components/ui/select.tsx +1 -0
- package/corpus/templates/calendar/app/components/ui/separator.tsx +1 -0
- package/corpus/templates/calendar/app/components/ui/skeleton.tsx +1 -0
- package/corpus/templates/calendar/app/components/ui/spinner.tsx +1 -0
- package/corpus/templates/calendar/app/components/ui/switch.tsx +1 -0
- package/corpus/templates/calendar/app/components/ui/table.tsx +1 -0
- package/corpus/templates/calendar/app/components/ui/tabs.tsx +1 -0
- package/corpus/templates/calendar/app/components/ui/textarea.tsx +1 -0
- package/corpus/templates/calendar/app/components/ui/toolkit-provider.tsx +12 -0
- package/corpus/templates/calendar/app/components/ui/tooltip.tsx +1 -0
- package/corpus/templates/calendar/app/global.css +1 -0
- package/corpus/templates/calendar/app/hooks/use-event-drag.ts +63 -9
- package/corpus/templates/calendar/app/hooks/use-google-auth.ts +15 -27
- package/corpus/templates/calendar/app/hooks/use-grid-create-drag.ts +254 -0
- package/corpus/templates/calendar/app/hooks/use-mobile.ts +1 -0
- package/corpus/templates/calendar/app/hooks/use-view-preferences.ts +287 -21
- package/corpus/templates/calendar/app/hooks/use-zoom-auth.ts +56 -19
- package/corpus/templates/calendar/app/i18n/zh-TW.ts +3 -0
- package/corpus/templates/calendar/app/i18n-data.ts +31 -0
- package/corpus/templates/calendar/app/lib/event-colors.ts +29 -8
- package/corpus/templates/calendar/app/pages/AvailabilitySettings.tsx +11 -11
- package/corpus/templates/calendar/app/pages/BookingLinksPage.tsx +45 -50
- package/corpus/templates/calendar/app/pages/BookingPage.tsx +2 -2
- package/corpus/templates/calendar/app/pages/BookingsList.tsx +12 -12
- package/corpus/templates/calendar/app/pages/CalendarView.tsx +438 -271
- package/corpus/templates/calendar/app/pages/ManageBookingPage.tsx +13 -13
- package/corpus/templates/calendar/app/pages/Settings.tsx +15 -29
- package/corpus/templates/calendar/app/root.tsx +19 -15
- package/corpus/templates/calendar/app/routes/event.tsx +2 -2
- package/corpus/templates/calendar/changelog/2026-07-06-calendar-now-loads-view-preferences-much-more-efficiently.md +6 -0
- package/corpus/templates/calendar/changelog/2026-07-06-connected-calendars-keep-their-own-color-when-you-customize-.md +6 -0
- package/corpus/templates/calendar/changelog/2026-07-06-create-events-from-the-command-menu-with-natural-phrases-lik.md +6 -0
- package/corpus/templates/calendar/changelog/2026-07-06-drag-across-empty-week-or-day-slots-to-create-an-event-with-.md +6 -0
- package/corpus/templates/calendar/changelog/2026-07-06-dragging-and-resizing-events-is-much-smoother-especially-on-.md +6 -0
- package/corpus/templates/calendar/changelog/2026-07-06-each-connected-google-account-can-now-have-its-own-calendar-.md +6 -0
- package/corpus/templates/calendar/changelog/2026-07-06-events-spanning-multiple-days-now-show-on-every-day-they-cov.md +6 -0
- package/corpus/templates/calendar/changelog/2026-07-06-google-calendar-now-finishes-connecting-correctly-after-sign.md +6 -0
- package/corpus/templates/calendar/changelog/2026-07-06-public-booking-pages-respond-faster.md +6 -0
- package/corpus/templates/calendar/changelog/2026-07-06-the-app-header-no-longer-shows-the-global-notifications-bell.md +6 -0
- package/corpus/templates/calendar/package.json +1 -0
- package/corpus/templates/calendar/server/handlers/bookings.ts +46 -52
- package/corpus/templates/calendar/server/handlers/google-auth.ts +21 -5
- package/corpus/templates/calendar/server/lib/google-calendar.ts +32 -3
- package/corpus/templates/calendar/shared/calendar-view-preferences.ts +66 -2
- package/corpus/templates/chat/.agents/skills/actions/SKILL.md +55 -0
- package/corpus/templates/chat/app/components/layout/Layout.tsx +6 -6
- package/corpus/templates/chat/app/components/layout/Sidebar.tsx +12 -12
- package/corpus/templates/chat/app/components/ui/button.tsx +1 -0
- package/corpus/templates/chat/app/components/ui/card.tsx +1 -0
- package/corpus/templates/chat/app/components/ui/dropdown-menu.tsx +1 -0
- package/corpus/templates/chat/app/components/ui/input.tsx +1 -0
- package/corpus/templates/chat/app/components/ui/label.tsx +1 -0
- package/corpus/templates/chat/app/components/ui/sheet.tsx +1 -0
- package/corpus/templates/chat/app/components/ui/toolkit-provider.tsx +12 -0
- package/corpus/templates/chat/app/components/ui/tooltip.tsx +1 -0
- package/corpus/templates/chat/app/global.css +1 -0
- package/corpus/templates/chat/app/root.tsx +7 -4
- package/corpus/templates/chat/app/routes/settings.tsx +6 -21
- package/corpus/templates/clips/.agents/skills/actions/SKILL.md +55 -0
- package/corpus/templates/clips/.agents/skills/video-sharing/SKILL.md +18 -4
- package/corpus/templates/clips/.env.example +8 -0
- package/corpus/templates/clips/actions/accept-invite.ts +3 -0
- package/corpus/templates/clips/actions/add-recording-to-space.ts +55 -27
- package/corpus/templates/clips/actions/add-vocabulary-term.ts +3 -1
- package/corpus/templates/clips/actions/archive-recording.ts +5 -12
- package/corpus/templates/clips/actions/cleanup-transcript.ts +5 -4
- package/corpus/templates/clips/actions/clear-edits.ts +42 -29
- package/corpus/templates/clips/actions/create-meeting.ts +87 -40
- package/corpus/templates/clips/actions/create-recording.ts +6 -3
- package/corpus/templates/clips/actions/delete-meeting.ts +25 -0
- package/corpus/templates/clips/actions/delete-recording-permanent.ts +3 -0
- package/corpus/templates/clips/actions/disconnect-calendar.ts +10 -4
- package/corpus/templates/clips/actions/export-insights-csv.ts +28 -8
- package/corpus/templates/clips/actions/finalize-meeting.ts +106 -33
- package/corpus/templates/clips/actions/finalize-recording.ts +201 -3
- package/corpus/templates/clips/actions/get-organization-insights.ts +51 -7
- package/corpus/templates/clips/actions/import-loom-recording.ts +17 -0
- package/corpus/templates/clips/actions/lib/audio-only-transcription.ts +18 -1
- package/corpus/templates/clips/actions/lib/create-recording-schema.ts +7 -1
- package/corpus/templates/clips/actions/lib/ensure-seekable-video.ts +16 -0
- package/corpus/templates/clips/actions/list-clip-views.ts +60 -0
- package/corpus/templates/clips/actions/regenerate-summary.ts +10 -0
- package/corpus/templates/clips/actions/remove-vocabulary-term.ts +59 -0
- package/corpus/templates/clips/actions/request-transcript.ts +170 -25
- package/corpus/templates/clips/actions/restore-recording.ts +5 -12
- package/corpus/templates/clips/actions/save-browser-transcript.ts +13 -2
- package/corpus/templates/clips/actions/set-chapters.ts +6 -15
- package/corpus/templates/clips/actions/set-thumbnail.ts +77 -36
- package/corpus/templates/clips/actions/split-recording.ts +49 -35
- package/corpus/templates/clips/actions/stitch-recordings.ts +7 -4
- package/corpus/templates/clips/actions/stop-meeting-recording.ts +15 -1
- package/corpus/templates/clips/actions/sync-calendars.ts +10 -108
- package/corpus/templates/clips/actions/trash-recording.ts +43 -14
- package/corpus/templates/clips/actions/trim-recording.ts +48 -27
- package/corpus/templates/clips/actions/undo-edit.ts +49 -37
- package/corpus/templates/clips/app/components/capture-install-options.tsx +6 -6
- package/corpus/templates/clips/app/components/dictate/vocabulary-section.tsx +208 -0
- package/corpus/templates/clips/app/components/editable-recording-title.tsx +2 -2
- package/corpus/templates/clips/app/components/editor/chapters-editor.tsx +7 -7
- package/corpus/templates/clips/app/components/editor/editor-toolbar.tsx +26 -26
- package/corpus/templates/clips/app/components/editor/split-button.tsx +5 -4
- package/corpus/templates/clips/app/components/editor/stitch-manager.tsx +9 -9
- package/corpus/templates/clips/app/components/editor/thumbnail-picker.tsx +11 -16
- package/corpus/templates/clips/app/components/editor/timeline.tsx +3 -3
- package/corpus/templates/clips/app/components/editor/transcript-editor.tsx +5 -5
- package/corpus/templates/clips/app/components/library/bulk-action-toolbar.tsx +4 -4
- package/corpus/templates/clips/app/components/library/create-space-dialog.tsx +8 -8
- package/corpus/templates/clips/app/components/library/empty-state.tsx +2 -1
- package/corpus/templates/clips/app/components/library/folder-tree.tsx +14 -14
- package/corpus/templates/clips/app/components/library/library-grid.tsx +24 -98
- package/corpus/templates/clips/app/components/library/library-layout.tsx +25 -21
- package/corpus/templates/clips/app/components/library/organization-switcher.tsx +11 -11
- package/corpus/templates/clips/app/components/library/recording-card.tsx +44 -50
- package/corpus/templates/clips/app/components/library/search-bar.tsx +5 -5
- package/corpus/templates/clips/app/components/library/sort-menu.tsx +5 -4
- package/corpus/templates/clips/app/components/library/tag-input.tsx +4 -4
- package/corpus/templates/clips/app/components/meetings/attendee-stack.tsx +2 -6
- package/corpus/templates/clips/app/components/meetings/auto-record-prompt.tsx +1 -1
- package/corpus/templates/clips/app/components/meetings/bullet-link.tsx +4 -4
- package/corpus/templates/clips/app/components/meetings/canvas-editor.tsx +5 -5
- package/corpus/templates/clips/app/components/meetings/meeting-card.tsx +3 -3
- package/corpus/templates/clips/app/components/meetings/quick-ask-sidebar.tsx +17 -9
- package/corpus/templates/clips/app/components/meetings/share-meeting-dialog.tsx +6 -11
- package/corpus/templates/clips/app/components/meetings/transcript-bubbles.tsx +215 -21
- package/corpus/templates/clips/app/components/player/access-password-prompt.tsx +3 -2
- package/corpus/templates/clips/app/components/player/comments-panel.tsx +14 -14
- package/corpus/templates/clips/app/components/player/delete-recording-menu.tsx +7 -6
- package/corpus/templates/clips/app/components/player/insights-panel.tsx +18 -6
- package/corpus/templates/clips/app/components/player/player-controls.tsx +42 -36
- package/corpus/templates/clips/app/components/player/reactions-tray.tsx +4 -4
- package/corpus/templates/clips/app/components/player/settings-panel.tsx +13 -12
- package/corpus/templates/clips/app/components/player/share-dialog.tsx +80 -49
- package/corpus/templates/clips/app/components/player/sign-in-prompt-dialog.tsx +3 -2
- package/corpus/templates/clips/app/components/player/timestamped-comment-button.tsx +2 -2
- package/corpus/templates/clips/app/components/player/transcript-panel.tsx +7 -7
- package/corpus/templates/clips/app/components/player/video-player.tsx +182 -15
- package/corpus/templates/clips/app/components/recorder/camera-visualizer.tsx +1 -1
- package/corpus/templates/clips/app/components/recorder/microphone-visualizer.tsx +1 -1
- package/corpus/templates/clips/app/components/recorder/pre-record-panel.tsx +49 -36
- package/corpus/templates/clips/app/components/recorder/recorder-engine.ts +399 -57
- package/corpus/templates/clips/app/components/recorder/recording-toolbar.tsx +6 -5
- package/corpus/templates/clips/app/components/recorder/storage-setup-card.tsx +7 -6
- package/corpus/templates/clips/app/components/sharing/share-ui.tsx +10 -10
- package/corpus/templates/clips/app/components/sharing/viewed-by-popover.tsx +132 -0
- package/corpus/templates/clips/app/components/ui/alert-dialog.tsx +1 -0
- package/corpus/templates/clips/app/components/ui/avatar.tsx +1 -0
- package/corpus/templates/clips/app/components/ui/badge.tsx +1 -0
- package/corpus/templates/clips/app/components/ui/button.tsx +1 -0
- package/corpus/templates/clips/app/components/ui/card.tsx +1 -0
- package/corpus/templates/clips/app/components/ui/checkbox.tsx +1 -0
- package/corpus/templates/clips/app/components/ui/collapsible.tsx +1 -0
- package/corpus/templates/clips/app/components/ui/context-menu.tsx +1 -0
- package/corpus/templates/clips/app/components/ui/dialog.tsx +1 -0
- package/corpus/templates/clips/app/components/ui/dropdown-menu.tsx +1 -0
- package/corpus/templates/clips/app/components/ui/input.tsx +1 -0
- package/corpus/templates/clips/app/components/ui/label.tsx +1 -0
- package/corpus/templates/clips/app/components/ui/popover.tsx +1 -0
- package/corpus/templates/clips/app/components/ui/scroll-area.tsx +1 -0
- package/corpus/templates/clips/app/components/ui/select.tsx +1 -0
- package/corpus/templates/clips/app/components/ui/separator.tsx +1 -0
- package/corpus/templates/clips/app/components/ui/sheet.tsx +1 -0
- package/corpus/templates/clips/app/components/ui/skeleton.tsx +1 -0
- package/corpus/templates/clips/app/components/ui/slider.tsx +1 -0
- package/corpus/templates/clips/app/components/ui/sonner.tsx +1 -0
- package/corpus/templates/clips/app/components/ui/spinner.tsx +1 -0
- package/corpus/templates/clips/app/components/ui/switch.tsx +1 -0
- package/corpus/templates/clips/app/components/ui/table.tsx +1 -0
- package/corpus/templates/clips/app/components/ui/tabs.tsx +1 -0
- package/corpus/templates/clips/app/components/ui/textarea.tsx +1 -0
- package/corpus/templates/clips/app/components/ui/toolkit-provider.tsx +12 -0
- package/corpus/templates/clips/app/components/ui/tooltip.tsx +1 -0
- package/corpus/templates/clips/app/components/workspace/branding-editor.tsx +5 -9
- package/corpus/templates/clips/app/components/workspace/insights-hub.tsx +9 -19
- package/corpus/templates/clips/app/components/workspace/invite-dialog.tsx +10 -9
- package/corpus/templates/clips/app/components/workspace/members-list.tsx +11 -10
- package/corpus/templates/clips/app/components/workspace/notifications-list.tsx +2 -1
- package/corpus/templates/clips/app/components/workspace/top-creators-table.tsx +3 -2
- package/corpus/templates/clips/app/components/workspace/top-videos-table.tsx +3 -2
- package/corpus/templates/clips/app/global.css +1 -0
- package/corpus/templates/clips/app/hooks/use-desktop-promo.ts +2 -1
- package/corpus/templates/clips/app/hooks/use-mobile.ts +1 -0
- package/corpus/templates/clips/app/hooks/use-player-shortcuts.ts +14 -10
- package/corpus/templates/clips/app/hooks/use-view-tracking.ts +14 -0
- package/corpus/templates/clips/app/i18n/ar-SA.ts +56 -0
- package/corpus/templates/clips/app/i18n/de-DE.ts +53 -0
- package/corpus/templates/clips/app/i18n/en-US.ts +52 -0
- package/corpus/templates/clips/app/i18n/es-ES.ts +53 -0
- package/corpus/templates/clips/app/i18n/fr-FR.ts +53 -0
- package/corpus/templates/clips/app/i18n/hi-IN.ts +52 -0
- package/corpus/templates/clips/app/i18n/ja-JP.ts +53 -0
- package/corpus/templates/clips/app/i18n/ko-KR.ts +52 -0
- package/corpus/templates/clips/app/i18n/pt-BR.ts +53 -0
- package/corpus/templates/clips/app/i18n/zh-CN.ts +51 -0
- package/corpus/templates/clips/app/i18n/zh-TW.ts +51 -0
- package/corpus/templates/clips/app/lib/recorder-preferences.ts +4 -0
- package/corpus/templates/clips/app/lib/timestamp-mapping.ts +5 -0
- package/corpus/templates/clips/app/root.tsx +26 -23
- package/corpus/templates/clips/app/routes/_app.dictate.tsx +39 -23
- package/corpus/templates/clips/app/routes/_app.library._index.tsx +27 -1
- package/corpus/templates/clips/app/routes/_app.meetings.$meetingId.tsx +134 -39
- package/corpus/templates/clips/app/routes/_app.meetings._index.tsx +20 -20
- package/corpus/templates/clips/app/routes/_app.notifications.tsx +3 -3
- package/corpus/templates/clips/app/routes/_app.settings._index.tsx +92 -60
- package/corpus/templates/clips/app/routes/_app.settings.organization.tsx +8 -13
- package/corpus/templates/clips/app/routes/_app.spaces._index.tsx +1 -1
- package/corpus/templates/clips/app/routes/_app.trash.tsx +96 -31
- package/corpus/templates/clips/app/routes/bug-report.done.tsx +1 -1
- package/corpus/templates/clips/app/routes/bug-report.tsx +11 -11
- package/corpus/templates/clips/app/routes/download.tsx +2 -2
- package/corpus/templates/clips/app/routes/embed.$shareId.tsx +2 -1
- package/corpus/templates/clips/app/routes/invite.$token.tsx +8 -13
- package/corpus/templates/clips/app/routes/r.$recordingId.tsx +263 -251
- package/corpus/templates/clips/app/routes/record.tsx +185 -78
- package/corpus/templates/clips/app/routes/share.$shareId.tsx +51 -29
- package/corpus/templates/clips/app/routes/share.meeting.$meetingId.tsx +71 -16
- package/corpus/templates/clips/changelog/2026-07-05-mobile-clip-pages-use-a-tighter-viewer-layout-with-inline-ac.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-06-ai-setup-now-switches-to-your-saved-provider-key-and-uses-fa.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-06-browsers-that-can-t-play-a-clip-s-video-format-now-see-a-cle.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-06-calendar-connections-no-longer-ask-you-to-reconnect-after-te.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-06-chrome-extension-recordings-keep-your-selected-microphone.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-06-clip-recordings-now-use-streaming-uploads-by-default.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-06-clip-titles-in-the-library-grid-now-open-the-clip-instead-of.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-06-desktop-countdown-now-dims-the-screen-before-recording.md +5 -0
- package/corpus/templates/clips/changelog/2026-07-06-desktop-popover-no-longer-drops-bluetooth-headphones-into-call-quality-mode.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-06-desktop-recorder-now-refreshes-cameras-and-mics-when-the-pop.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-06-desktop-recordings-keep-microphone-volume-clear-while-recor.md +5 -0
- package/corpus/templates/clips/changelog/2026-07-06-desktop-recordings-no-longer-get-stuck-optimizing-when-scree.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-06-dictation-history-from-the-desktop-app-now-appears-in-the-di.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-06-dictation-no-longer-overwrites-your-clipboard-and-messaging-.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-06-double-tap-your-dictation-key-for-hands-free-dictation-tap-a.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-06-fixed-desktop-recordings-sometimes-uploading-without-audio-a.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-06-fixed-desktop-recordings-that-could-get-stuck-uploading-and-.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-06-fixed-recordings-sometimes-capturing-from-the-wrong-micropho.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-06-hands-free-dictation-and-meeting-cleanup-recover-more-reliab.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-06-live-meetings-show-time-remaining-and-you-can-end-a-meeting-.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-06-manage-your-personal-dictation-dictionary-from-the-dictate-t.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-06-meetings-interrupted-by-quitting-or-crashing-now-close-out-c.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-06-mic-only-desktop-recordings-now-use-the-selected-microphone-.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-06-paste-your-last-dictation-anytime-with-cmd-ctrl-v-or-from-th.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-06-press-esc-to-cancel-a-dictation-in-progress.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-06-recordings-whose-video-file-contains-no-audio-track-no-longe.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-06-search-inside-meeting-transcripts.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-06-see-who-viewed-your-shared-clips-and-when-click-the-view-cou.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-06-share-links-for-agents-now-appear-as-soon-as-the-share-menu-.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-06-share-popovers-now-stay-above-video-playback-controls.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-06-shared-clip-pages-now-recover-automatically-from-transient-v.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-06-the-desktop-app-now-walks-you-through-permissions-on-first-l.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-06-transcript-cleanup-preferences-now-save-per-user.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-06-transcripts-now-retry-automatically-after-transient-failures.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-06-video-compression-now-runs-in-the-background-without-blocking.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-07-native-microphone-recordings-now-reduce-steady-background-noise.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-07-recording-transcripts-now-line-up-with-the-video-start-afte.md +6 -0
- package/corpus/templates/clips/chrome-extension/public/manifest.json +1 -1
- package/corpus/templates/clips/chrome-extension/src/background.ts +141 -48
- package/corpus/templates/clips/chrome-extension/src/offscreen.ts +383 -59
- package/corpus/templates/clips/chrome-extension/src/overlay.ts +51 -10
- package/corpus/templates/clips/chrome-extension/src/popup.ts +57 -6
- package/corpus/templates/clips/desktop/package.json +1 -1
- package/corpus/templates/clips/desktop/scripts/sign-macos-local.ts +67 -0
- package/corpus/templates/clips/desktop/src/app.tsx +38 -13
- package/corpus/templates/clips/desktop/src/components/SourceRow.tsx +1 -0
- package/corpus/templates/clips/desktop/src/hooks/useMediaDevices.ts +88 -28
- package/corpus/templates/clips/desktop/src/hooks/useMeetingTranscription.ts +165 -55
- package/corpus/templates/clips/desktop/src/hooks/useMicMeter.ts +35 -10
- package/corpus/templates/clips/desktop/src/lib/backtrack.ts +12 -0
- package/corpus/templates/clips/desktop/src/lib/media-capture-constraints.ts +129 -34
- package/corpus/templates/clips/desktop/src/lib/media-device-selection.ts +157 -0
- package/corpus/templates/clips/desktop/src/lib/permissions.ts +2 -0
- package/corpus/templates/clips/desktop/src/lib/recorder.ts +109 -47
- package/corpus/templates/clips/desktop/src/lib/transcription-capture.ts +22 -2
- package/corpus/templates/clips/desktop/src/lib/transcription-engine.ts +29 -1
- package/corpus/templates/clips/desktop/src/lib/updater.ts +6 -0
- package/corpus/templates/clips/desktop/src/lib/voice-dictation.ts +372 -31
- package/corpus/templates/clips/desktop/src/overlays/finalizing.tsx +90 -0
- package/corpus/templates/clips/desktop/src/overlays/flow-bar.tsx +4 -6
- package/corpus/templates/clips/desktop/src/overlays/onboarding.tsx +214 -9
- package/corpus/templates/clips/desktop/src/overlays/recording-pill.tsx +37 -52
- package/corpus/templates/clips/desktop/src/styles.css +1 -1
- package/corpus/templates/clips/desktop/src-tauri/Cargo.toml +7 -0
- package/corpus/templates/clips/desktop/src-tauri/src/clips/mod.rs +371 -43
- package/corpus/templates/clips/desktop/src-tauri/src/lib.rs +79 -0
- package/corpus/templates/clips/desktop/src-tauri/src/native_screen.rs +1418 -260
- package/corpus/templates/clips/desktop/src-tauri/src/native_speech.rs +188 -44
- package/corpus/templates/clips/desktop/src-tauri/src/shortcuts.rs +197 -8
- package/corpus/templates/clips/desktop/src-tauri/src/silence_detector.rs +64 -8
- package/corpus/templates/clips/desktop/src-tauri/src/state.rs +3 -2
- package/corpus/templates/clips/desktop/src-tauri/src/system_audio.rs +10 -0
- package/corpus/templates/clips/desktop/src-tauri/src/tray.rs +29 -8
- package/corpus/templates/clips/desktop/src-tauri/src/whisper_speech.rs +136 -13
- package/corpus/templates/clips/desktop/vite.config.ts +3 -0
- package/corpus/templates/clips/package.json +1 -1
- package/corpus/templates/clips/server/db/schema.ts +26 -0
- package/corpus/templates/clips/server/jobs/builder-media-compression.ts +41 -0
- package/corpus/templates/clips/server/jobs/stale-meeting-sweeper.ts +294 -0
- package/corpus/templates/clips/server/lib/builder-media-compression.ts +976 -0
- package/corpus/templates/clips/server/lib/calendar-event-meetings.ts +107 -56
- package/corpus/templates/clips/server/lib/env-flags.ts +4 -0
- package/corpus/templates/clips/server/lib/google-calendar-client.ts +8 -1
- package/corpus/templates/clips/server/lib/media-worker.ts +153 -0
- package/corpus/templates/clips/server/lib/s3-upload-provider.ts +58 -17
- package/corpus/templates/clips/server/lib/streaming-upload-mode.ts +17 -5
- package/corpus/templates/clips/server/lib/video-remux.ts +90 -0
- package/corpus/templates/clips/server/plugins/calendar-jobs.ts +4 -0
- package/corpus/templates/clips/server/plugins/db.ts +196 -0
- package/corpus/templates/clips/server/register-secrets.ts +78 -0
- package/corpus/templates/clips/server/routes/_agent-native/clips/user-prefs.get.ts +15 -0
- package/corpus/templates/clips/server/routes/_agent-native/clips/user-prefs.put.ts +27 -0
- package/corpus/templates/clips/server/routes/api/media-worker/callback.post.ts +88 -0
- package/corpus/templates/clips/server/routes/api/public-recording.get.ts +87 -7
- package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/abort.post.ts +11 -4
- package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/chunk.post.ts +55 -13
- package/corpus/templates/clips/server/routes/api/video/[recordingId].get.ts +24 -42
- package/corpus/templates/clips/server/routes/api/view-event.post.ts +29 -1
- package/corpus/templates/clips/shared/finalize-recovery.ts +23 -3
- package/corpus/templates/clips/shared/media-device-selection.ts +157 -0
- package/corpus/templates/clips/shared/media-worker-contract.ts +146 -0
- package/corpus/templates/content/.agents/skills/actions/SKILL.md +55 -0
- package/corpus/templates/content/.agents/skills/notion-integration/SKILL.md +67 -2
- package/corpus/templates/content/AGENTS.md +73 -65
- package/corpus/templates/content/actions/_builder-cms-read-client.ts +188 -8
- package/corpus/templates/content/actions/_builder-docs-client.ts +41 -3
- package/corpus/templates/content/actions/_database-source-utils.ts +998 -160
- package/corpus/templates/content/actions/_database-utils.ts +44 -4
- package/corpus/templates/content/actions/_local-file-documents.ts +90 -1
- package/corpus/templates/content/actions/_notion-action-utils.ts +12 -4
- package/corpus/templates/content/actions/add-content-database-source-field-property.ts +23 -1
- package/corpus/templates/content/actions/attach-content-database-source.ts +85 -12
- package/corpus/templates/content/actions/change-content-database-source-role.ts +9 -1
- package/corpus/templates/content/actions/delete-content-database.ts +1 -0
- package/corpus/templates/content/actions/delete-document.ts +8 -0
- package/corpus/templates/content/actions/get-document.ts +11 -2
- package/corpus/templates/content/actions/list-content-databases.ts +57 -9
- package/corpus/templates/content/actions/prepare-builder-source-review.ts +23 -6
- package/corpus/templates/content/actions/refresh-content-database-source.ts +26 -3
- package/corpus/templates/content/actions/remove-local-file-source.ts +100 -0
- package/corpus/templates/content/actions/restore-content-database.ts +1 -0
- package/corpus/templates/content/actions/sync-notion-comments.ts +174 -20
- package/corpus/templates/content/actions/update-document.ts +134 -5
- package/corpus/templates/content/app/blocks/SourceComponentBlock.tsx +31 -3
- package/corpus/templates/content/app/blocks/contentBlockRegistry.tsx +4 -4
- package/corpus/templates/content/app/components/EmptyState.tsx +1 -1
- package/corpus/templates/content/app/components/ThemeToggle.tsx +6 -6
- package/corpus/templates/content/app/components/editor/BubbleToolbar.tsx +5 -5
- package/corpus/templates/content/app/components/editor/BuilderBodySyncingNotice.tsx +21 -0
- package/corpus/templates/content/app/components/editor/CommentsSidebar.tsx +5 -5
- package/corpus/templates/content/app/components/editor/ContentReferencePreview.tsx +1 -1
- package/corpus/templates/content/app/components/editor/DocumentDatabase.tsx +9 -14630
- package/corpus/templates/content/app/components/editor/DocumentEditor.tsx +142 -79
- package/corpus/templates/content/app/components/editor/DocumentEditorSkeleton.tsx +36 -0
- package/corpus/templates/content/app/components/editor/DocumentProperties.tsx +98 -46
- package/corpus/templates/content/app/components/editor/DocumentToolbar.tsx +29 -44
- package/corpus/templates/content/app/components/editor/EmojiPicker.tsx +5 -4
- package/corpus/templates/content/app/components/editor/LinkHoverPreview.tsx +5 -4
- package/corpus/templates/content/app/components/editor/NotionConflictBanner.tsx +1 -1
- package/corpus/templates/content/app/components/editor/NotionSyncBar.tsx +2 -2
- package/corpus/templates/content/app/components/editor/SlashCommandMenu.tsx +5 -5
- package/corpus/templates/content/app/components/editor/TableHoverControls.tsx +13 -13
- package/corpus/templates/content/app/components/editor/VersionHistoryPanel.tsx +10 -10
- package/corpus/templates/content/app/components/editor/VisualEditor.tsx +28 -11
- package/corpus/templates/content/app/components/editor/body-hydration.ts +112 -0
- package/corpus/templates/content/app/components/editor/builder-body-hydration-pump.ts +52 -0
- package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +736 -69
- package/corpus/templates/content/app/components/editor/database/navigation-state.ts +36 -1
- package/corpus/templates/content/app/components/editor/database/settings.tsx +3224 -0
- package/corpus/templates/content/app/components/editor/database/shared.tsx +19 -19
- package/corpus/templates/content/app/components/editor/database/text.ts +23 -0
- package/corpus/templates/content/app/components/editor/database-sources/BuilderSourceReviewDialog.tsx +50 -9
- package/corpus/templates/content/app/components/editor/extensions/AudioBlock.tsx +19 -18
- package/corpus/templates/content/app/components/editor/extensions/ImageBlock.tsx +57 -31
- package/corpus/templates/content/app/components/editor/extensions/LocalMdxComponentNode.tsx +8 -8
- package/corpus/templates/content/app/components/editor/extensions/NotionExtensions.tsx +9 -0
- package/corpus/templates/content/app/components/editor/extensions/VideoBlock.tsx +19 -18
- package/corpus/templates/content/app/components/editor/previewDocumentSaveController.ts +21 -1
- package/corpus/templates/content/app/components/layout/Header.tsx +1 -5
- package/corpus/templates/content/app/components/layout/Layout.tsx +25 -8
- package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +214 -56
- package/corpus/templates/content/app/components/sidebar/DocumentTreeItem.tsx +33 -30
- package/corpus/templates/content/app/components/sidebar/NotionButton.tsx +11 -11
- package/corpus/templates/content/app/components/sidebar/document-sidebar-sections.ts +109 -1
- package/corpus/templates/content/app/components/ui/alert-dialog.tsx +1 -0
- package/corpus/templates/content/app/components/ui/button.tsx +1 -0
- package/corpus/templates/content/app/components/ui/dialog.tsx +1 -0
- package/corpus/templates/content/app/components/ui/dropdown-menu.tsx +1 -0
- package/corpus/templates/content/app/components/ui/input.tsx +1 -0
- package/corpus/templates/content/app/components/ui/label.tsx +1 -0
- package/corpus/templates/content/app/components/ui/popover.tsx +1 -0
- package/corpus/templates/content/app/components/ui/separator.tsx +1 -0
- package/corpus/templates/content/app/components/ui/sheet.tsx +1 -0
- package/corpus/templates/content/app/components/ui/skeleton.tsx +1 -0
- package/corpus/templates/content/app/components/ui/sonner.tsx +1 -0
- package/corpus/templates/content/app/components/ui/spinner.tsx +1 -0
- package/corpus/templates/content/app/components/ui/table.tsx +1 -0
- package/corpus/templates/content/app/components/ui/toaster.tsx +1 -0
- package/corpus/templates/content/app/components/ui/toolkit-provider.tsx +12 -0
- package/corpus/templates/content/app/components/ui/tooltip.tsx +1 -0
- package/corpus/templates/content/app/global.css +42 -0
- package/corpus/templates/content/app/hooks/use-content-database.ts +346 -42
- package/corpus/templates/content/app/hooks/use-db-sync.ts +9 -0
- package/corpus/templates/content/app/hooks/use-documents.ts +136 -37
- package/corpus/templates/content/app/hooks/use-mobile.ts +1 -0
- package/corpus/templates/content/app/hooks/use-notion.ts +85 -15
- package/corpus/templates/content/app/i18n/zh-TW.ts +49 -0
- package/corpus/templates/content/app/i18n-data.ts +508 -0
- package/corpus/templates/content/app/root.tsx +57 -29
- package/corpus/templates/content/app/routes/_app._index.tsx +1 -1
- package/corpus/templates/content/app/routes/_app.local-files.tsx +268 -81
- package/corpus/templates/content/app/routes/_app.settings.tsx +4 -21
- package/corpus/templates/content/changelog/2026-07-01-builder-database-sources-keep-loading-rows-in-the-background.md +6 -0
- package/corpus/templates/content/changelog/2026-07-01-builder-source-attach-starts-with-usable-rows.md +6 -0
- package/corpus/templates/content/changelog/2026-07-01-builder-source-attachment-now-stays-connected-after-large.md +6 -0
- package/corpus/templates/content/changelog/2026-07-01-builder-source-components-show-preservation-and-review-states.md +6 -0
- package/corpus/templates/content/changelog/2026-07-01-builder-source-refreshes-now-show-progress-for-large-docs-blog.md +6 -0
- package/corpus/templates/content/changelog/2026-07-01-database-pages-now-delete-to-trash-without-route-errors.md +6 -0
- package/corpus/templates/content/changelog/2026-07-02-builder-source-refreshes-recover-from-stalled-background-row.md +6 -0
- package/corpus/templates/content/changelog/2026-07-02-builder-sourced-rows-open-with-sync-protection.md +6 -0
- package/corpus/templates/content/changelog/2026-07-02-database-rows-and-pages-open-faster-from-recently-loaded-dat.md +6 -0
- package/corpus/templates/content/changelog/2026-07-02-preview-panels-close-reliably-narrow-sidebar-row-actions-sta.md +6 -0
- package/corpus/templates/content/changelog/2026-07-06-builder-sync-progress-no-longer-shows-continue.md +6 -0
- package/corpus/templates/content/changelog/2026-07-06-document-headers-and-page-bodies-now-share-one-background-shade.md +6 -0
- package/corpus/templates/content/changelog/2026-07-06-export-submenus-stay-visible-outside-the-page-actions-menu.md +6 -0
- package/corpus/templates/content/changelog/2026-07-06-fixed-collaborative-documents-reapplying-content-before-save.md +6 -0
- package/corpus/templates/content/changelog/2026-07-06-local-files-now-remember-sidebar-collapse-state-and-include-.md +6 -0
- package/corpus/templates/content/changelog/2026-07-06-notion-comment-sync-now-preserves-threads-replies-stay-attac.md +6 -0
- package/corpus/templates/content/changelog/2026-07-06-notion-sync-is-far-more-reliable-auto-sync-no-longer-overwri.md +6 -0
- package/corpus/templates/content/changelog/2026-07-06-opening-pages-now-highlights-the-sidebar-item-and-shows-the-.md +6 -0
- package/corpus/templates/content/changelog/2026-07-06-presence-markers-in-the-editor-are-now-compact-instead-of-co.md +6 -0
- package/corpus/templates/content/changelog/2026-07-06-sidebar-collapse-now-keeps-the-same-background-shade-as-the-.md +6 -0
- package/corpus/templates/content/changelog/2026-07-06-the-content-header-no-longer-shows-the-global-notifications-.md +6 -0
- package/corpus/templates/content/parity/matrix.md +24 -24
- package/corpus/templates/content/parity/matrix.ts +7 -3
- package/corpus/templates/content/server/db/schema.ts +15 -0
- package/corpus/templates/content/server/lib/notion-sync.ts +481 -39
- package/corpus/templates/content/server/lib/notion.ts +212 -48
- package/corpus/templates/content/server/plugins/db.ts +20 -0
- package/corpus/templates/content/server/routes/api/documents/[id]/notion/resolve.post.ts +14 -2
- package/corpus/templates/content/server/routes/api/notion/callback.get.ts +54 -6
- package/corpus/templates/content/shared/api.ts +13 -0
- package/corpus/templates/content/shared/builder-mdx.ts +84 -15
- package/corpus/templates/content/shared/builder-source-component-registry.ts +177 -0
- package/corpus/templates/content/shared/nfm.ts +459 -66
- package/corpus/templates/content/shared/source-component-block.ts +72 -6
- package/corpus/templates/content/vite.config.ts +17 -1
- package/corpus/templates/design/.agents/skills/actions/SKILL.md +55 -0
- package/corpus/templates/design/.agents/skills/design-generation/SKILL.md +44 -25
- package/corpus/templates/design/.agents/skills/responsive-breakpoints/SKILL.md +98 -0
- package/corpus/templates/design/.agents/skills/shader-fills/SKILL.md +162 -0
- package/corpus/templates/design/AGENTS.md +12 -4
- package/corpus/templates/design/actions/add-breakpoint.ts +6 -3
- package/corpus/templates/design/actions/apply-a11y-fix.ts +57 -37
- package/corpus/templates/design/actions/apply-component-prop-edit.ts +41 -20
- package/corpus/templates/design/actions/apply-motion-edit.ts +251 -38
- package/corpus/templates/design/actions/apply-shader-fill.ts +90 -66
- package/corpus/templates/design/actions/apply-visual-edit.ts +282 -55
- package/corpus/templates/design/actions/create-component.ts +29 -60
- package/corpus/templates/design/actions/create-file.ts +9 -2
- package/corpus/templates/design/actions/duplicate-design.ts +31 -2
- package/corpus/templates/design/actions/edit-design.ts +36 -38
- package/corpus/templates/design/actions/generate-design-title.ts +87 -0
- package/corpus/templates/design/actions/generate-design.ts +53 -18
- package/corpus/templates/design/actions/generate-screens.ts +108 -4
- package/corpus/templates/design/actions/get-motion-timeline.ts +35 -7
- package/corpus/templates/design/actions/import-design-source.ts +8 -58
- package/corpus/templates/design/actions/insert-asset.ts +34 -29
- package/corpus/templates/design/actions/insert-design-native-asset.ts +129 -32
- package/corpus/templates/design/actions/insert-figma-library-asset.ts +35 -30
- package/corpus/templates/design/actions/present-design-variants.ts +7 -2
- package/corpus/templates/design/actions/remove-motion-timeline.ts +31 -36
- package/corpus/templates/design/actions/run-design-audit.ts +127 -1
- package/corpus/templates/design/actions/take-design-screenshot.ts +673 -0
- package/corpus/templates/design/actions/update-file.ts +190 -75
- package/corpus/templates/design/app/components/ThemeToggle.tsx +6 -6
- package/corpus/templates/design/app/components/design/BreakpointBar.tsx +403 -0
- package/corpus/templates/design/app/components/design/CanvasContextMenu.tsx +480 -233
- package/corpus/templates/design/app/components/design/DesignCanvas.tsx +708 -53
- package/corpus/templates/design/app/components/design/DesignEditorSkeleton.tsx +2 -2
- package/corpus/templates/design/app/components/design/DesignExtensionsPanel.tsx +99 -24
- package/corpus/templates/design/app/components/design/DesignImportPanel.tsx +6 -97
- package/corpus/templates/design/app/components/design/DrawOverlay.tsx +7 -7
- package/corpus/templates/design/app/components/design/EditPanel.tsx +1120 -6977
- package/corpus/templates/design/app/components/design/FusionAppBanner.tsx +9 -8
- package/corpus/templates/design/app/components/design/LayersPanel.tsx +433 -99
- package/corpus/templates/design/app/components/design/LocalhostWriteConsentDialog.tsx +6 -5
- package/corpus/templates/design/app/components/design/MotionDock.tsx +1138 -117
- package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +2610 -1398
- package/corpus/templates/design/app/components/design/QuestionFlow.tsx +3 -3
- package/corpus/templates/design/app/components/design/ReadOnlyDesignBanner.tsx +22 -0
- package/corpus/templates/design/app/components/design/ReviewPanel.tsx +3 -3
- package/corpus/templates/design/app/components/design/StatesPanel.tsx +13 -13
- package/corpus/templates/design/app/components/design/TokensPanel.tsx +14 -14
- package/corpus/templates/design/app/components/design/TweaksPanel.tsx +6 -6
- package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +2221 -244
- package/corpus/templates/design/app/components/design/bridge/motion-preview.bridge.ts +187 -11
- package/corpus/templates/design/app/components/design/bridge/shader-fill-preview.bridge.ts +376 -1
- package/corpus/templates/design/app/components/design/bridge/shader-runtime.bridge.ts +746 -0
- package/corpus/templates/design/app/components/design/canvas-primitive-style.ts +17 -0
- package/corpus/templates/design/app/components/design/code-workbench/ActivityBar.tsx +3 -3
- package/corpus/templates/design/app/components/design/code-workbench/SideBar.tsx +5 -8
- package/corpus/templates/design/app/components/design/code-workbench/editor/EditorTabs.tsx +6 -6
- package/corpus/templates/design/app/components/design/code-workbench/editor/MonacoHost.tsx +2 -1
- package/corpus/templates/design/app/components/design/code-workbench/explorer/FileTree.tsx +18 -20
- package/corpus/templates/design/app/components/design/code-workbench/quickinput/QuickInput.tsx +1 -1
- package/corpus/templates/design/app/components/design/code-workbench/search/SearchView.tsx +6 -6
- package/corpus/templates/design/app/components/design/edit-panel/appearance-properties.tsx +518 -0
- package/corpus/templates/design/app/components/design/edit-panel/code-inspect-helpers.tsx +562 -0
- package/corpus/templates/design/app/components/design/edit-panel/component-section.tsx +763 -0
- package/corpus/templates/design/app/components/design/edit-panel/document-colors.ts +94 -0
- package/corpus/templates/design/app/components/design/edit-panel/effects-properties.tsx +780 -0
- package/corpus/templates/design/app/components/design/edit-panel/element-classification.ts +446 -0
- package/corpus/templates/design/app/components/design/edit-panel/element-identity.ts +79 -0
- package/corpus/templates/design/app/components/design/edit-panel/field-primitives.tsx +315 -0
- package/corpus/templates/design/app/components/design/edit-panel/fill-gradient-helpers.ts +344 -0
- package/corpus/templates/design/app/components/design/edit-panel/fill-properties.tsx +594 -0
- package/corpus/templates/design/app/components/design/edit-panel/frame-presets-panel.tsx +119 -0
- package/corpus/templates/design/app/components/design/edit-panel/inspector-controls.tsx +248 -0
- package/corpus/templates/design/app/components/design/edit-panel/interaction-state-helpers.ts +45 -0
- package/corpus/templates/design/app/components/design/edit-panel/layout-properties.tsx +693 -0
- package/corpus/templates/design/app/components/design/edit-panel/panel-primitives.tsx +724 -0
- package/corpus/templates/design/app/components/design/edit-panel/position-helpers.ts +207 -0
- package/corpus/templates/design/app/components/design/edit-panel/position-layout-properties.tsx +628 -0
- package/corpus/templates/design/app/components/design/edit-panel/selection-helpers.ts +91 -0
- package/corpus/templates/design/app/components/design/edit-panel/stroke-properties.tsx +649 -0
- package/corpus/templates/design/app/components/design/edit-panel/style-change-types.ts +118 -0
- package/corpus/templates/design/app/components/design/edit-panel/style-options.ts +88 -0
- package/corpus/templates/design/app/components/design/edit-panel/transform-helpers.ts +100 -0
- package/corpus/templates/design/app/components/design/edit-panel/typography-helpers.ts +117 -0
- package/corpus/templates/design/app/components/design/edit-panel/typography-properties.tsx +501 -0
- package/corpus/templates/design/app/components/design/inspector/AlignmentMatrix.tsx +3 -3
- package/corpus/templates/design/app/components/design/inspector/AutoLayoutMatrix.tsx +98 -47
- package/corpus/templates/design/app/components/design/inspector/BreakpointOverrideIndicator.tsx +82 -0
- package/corpus/templates/design/app/components/design/inspector/ConstraintsWidget.tsx +3 -3
- package/corpus/templates/design/app/components/design/inspector/DesignColorPicker.tsx +207 -105
- package/corpus/templates/design/app/components/design/inspector/ExportSettingsPanel.tsx +6 -6
- package/corpus/templates/design/app/components/design/inspector/GlslShaderPanel.tsx +1097 -0
- package/corpus/templates/design/app/components/design/inspector/GradientEditor.tsx +44 -0
- package/corpus/templates/design/app/components/design/inspector/ImageFillControls.tsx +6 -6
- package/corpus/templates/design/app/components/design/inspector/InteractionStatePanel.tsx +258 -0
- package/corpus/templates/design/app/components/design/inspector/MotionKeyframeDiamond.tsx +144 -0
- package/corpus/templates/design/app/components/design/inspector/ScrubInput.tsx +106 -16
- package/corpus/templates/design/app/components/design/inspector/ShaderControls.tsx +14 -14
- package/corpus/templates/design/app/components/design/inspector/ShaderEffectRow.tsx +9 -9
- package/corpus/templates/design/app/components/design/inspector/ShaderFillsPanel.tsx +6 -6
- package/corpus/templates/design/app/components/design/inspector/frame-size-presets.ts +116 -0
- package/corpus/templates/design/app/components/design/inspector/index.ts +26 -0
- package/corpus/templates/design/app/components/design/inspector/scrub-input-utils.ts +29 -0
- package/corpus/templates/design/app/components/design/multi-screen/alt-hover-measurement.ts +171 -0
- package/corpus/templates/design/app/components/design/multi-screen/board-surface-html.ts +220 -0
- package/corpus/templates/design/app/components/design/multi-screen/chrome-transitions.ts +35 -0
- package/corpus/templates/design/app/components/design/multi-screen/cross-screen-drop.ts +134 -0
- package/corpus/templates/design/app/components/design/multi-screen/culling.ts +185 -0
- package/corpus/templates/design/app/components/design/multi-screen/gradient-overlay-geometry.ts +120 -0
- package/corpus/templates/design/app/components/design/multi-screen/types.ts +892 -0
- package/corpus/templates/design/app/components/design/multi-screen/vector-edit-geometry.ts +21 -0
- package/corpus/templates/design/app/components/design/types.ts +15 -0
- package/corpus/templates/design/app/components/design-system/DesignSystemCard.tsx +3 -2
- package/corpus/templates/design/app/components/editor/PromptDialog.tsx +124 -23
- package/corpus/templates/design/app/components/layout/Header.tsx +2 -2
- package/corpus/templates/design/app/components/layout/Sidebar.tsx +5 -5
- package/corpus/templates/design/app/components/ui/alert-dialog.tsx +1 -0
- package/corpus/templates/design/app/components/ui/avatar.tsx +1 -0
- package/corpus/templates/design/app/components/ui/badge.tsx +1 -0
- package/corpus/templates/design/app/components/ui/button.tsx +1 -0
- package/corpus/templates/design/app/components/ui/card.tsx +1 -0
- package/corpus/templates/design/app/components/ui/checkbox.tsx +1 -0
- package/corpus/templates/design/app/components/ui/collapsible.tsx +1 -0
- package/corpus/templates/design/app/components/ui/context-menu.tsx +1 -0
- package/corpus/templates/design/app/components/ui/dialog.tsx +1 -0
- package/corpus/templates/design/app/components/ui/dropdown-menu.tsx +1 -0
- package/corpus/templates/design/app/components/ui/input.tsx +1 -0
- package/corpus/templates/design/app/components/ui/label.tsx +1 -0
- package/corpus/templates/design/app/components/ui/popover.tsx +1 -0
- package/corpus/templates/design/app/components/ui/select.tsx +1 -0
- package/corpus/templates/design/app/components/ui/separator.tsx +1 -0
- package/corpus/templates/design/app/components/ui/sheet.tsx +1 -0
- package/corpus/templates/design/app/components/ui/skeleton.tsx +1 -0
- package/corpus/templates/design/app/components/ui/slider.tsx +1 -0
- package/corpus/templates/design/app/components/ui/sonner.tsx +1 -0
- package/corpus/templates/design/app/components/ui/spinner.tsx +1 -0
- package/corpus/templates/design/app/components/ui/switch.tsx +1 -0
- package/corpus/templates/design/app/components/ui/tabs.tsx +1 -0
- package/corpus/templates/design/app/components/ui/textarea.tsx +1 -0
- package/corpus/templates/design/app/components/ui/toolkit-provider.tsx +12 -0
- package/corpus/templates/design/app/components/ui/tooltip.tsx +1 -0
- package/corpus/templates/design/app/components/visual-editor/CanvasCommentPins.tsx +7 -7
- package/corpus/templates/design/app/components/visual-editor/DrawOverlay.tsx +7 -7
- package/corpus/templates/design/app/components/visual-editor/SaveStatusIndicator.tsx +3 -3
- package/corpus/templates/design/app/global.css +9 -8
- package/corpus/templates/design/app/hooks/useDesignHotkeys.ts +259 -2
- package/corpus/templates/design/app/i18n/zh-TW.ts +166 -13
- package/corpus/templates/design/app/i18n-breakpoints.ts +205 -0
- package/corpus/templates/design/app/i18n-data.ts +1702 -187
- package/corpus/templates/design/app/i18n-motion.ts +563 -0
- package/corpus/templates/design/app/lib/design-import.ts +73 -0
- package/corpus/templates/design/app/pages/DesignSystemSetup.tsx +6 -6
- package/corpus/templates/design/app/pages/DesignSystems.tsx +31 -31
- package/corpus/templates/design/app/pages/Index.tsx +66 -51
- package/corpus/templates/design/app/pages/NotFound.tsx +2 -1
- package/corpus/templates/design/app/pages/Present.tsx +2 -1
- package/corpus/templates/design/app/pages/VisualEdit.tsx +2 -1
- package/corpus/templates/design/app/root.tsx +7 -4
- package/corpus/templates/design/app/routes/settings.tsx +22 -49
- package/corpus/templates/design/changelog/2026-06-29-design-inspector-controls-now-match-figmas-softer-dark-chrome.md +1 -1
- package/corpus/templates/design/changelog/2026-06-30-design-now-has-a-figma-style-left-rail-for-file-agent-assets.md +1 -1
- package/corpus/templates/design/changelog/2026-06-30-design-tools-now-use-a-quieter-figma-style-list-layout.md +1 -1
- package/corpus/templates/design/changelog/2026-06-30-multi-select-outlines-now-stay-consistent-across-all-screens.md +1 -1
- package/corpus/templates/design/changelog/2026-07-03-canvas-interactions-now-match-figma-rotation-aware-resizing-.md +1 -1
- package/corpus/templates/design/changelog/2026-07-03-layers-panel-matches-figma-top-layer-on-top-drag-with-auto-s.md +1 -1
- package/corpus/templates/design/changelog/2026-07-05-code-sidebar-tabs-now-use-a-quieter-active-highlight-that-ma.md +6 -0
- package/corpus/templates/design/changelog/2026-07-05-designs-get-ai-generated-names-from-your-prompt.md +6 -0
- package/corpus/templates/design/changelog/2026-07-05-local-code-screens-keep-their-connection-when-duplicated-and.md +6 -0
- package/corpus/templates/design/changelog/2026-07-05-press-a-to-draw-screens-on-the-canvas-inside-a-screen-it-dr.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-3d-rotation-and-perspective-controls-on-every-element.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-ai-generated-and-duplicated-screens-now-get-their-editor-sel.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-applying-shaders-and-fills-in-quick-succession-can-no-longer.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-breakpoint-frames-in-the-overview-now-support-click-to-selec.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-breakpoint-segments-in-the-inspector-now-show-a-device-icon-.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-breakpoint-targeting-now-lives-in-one-compact-control-in-the.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-canvas-edits-can-no-longer-be-overwritten-by-stale-collabora.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-canvas-edits-inside-screens-save-reliably-again.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-cleaner-inspector-removed-the-ask-ai-box-from-the-design-tab.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-clicking-empty-canvas-space-now-deselects-an-element-inside-.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-dragging-an-element-onto-a-rectangle-now-nests-it-inside-wit.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-dragging-screens-and-objects-on-the-canvas-is-now-much-smoot.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-drawing-a-shape-or-text-on-the-canvas-no-longer-flashes-away.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-dropping-an-element-between-two-others-inside-a-screen-now-s.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-duplicating-a-screen-now-places-the-copy-exactly-where-you-d.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-edit-gradients-directly-on-elements-inside-screens-scale-str.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-edits-from-collaborators-and-the-agent-now-update-the-canvas.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-fig-files-now-stay-on-the-builder-indexing-path-through-desi.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-fixed-a-bug-where-most-style-position-and-text-edits-briefly.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-fixed-a-confusing-raw-error-message-when-a-file-upload-fails.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-fixed-a-rare-case-where-an-edit-could-be-silently-overwritte.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-fixed-inserted-assets-sometimes-disappearing-reappearing-or-.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-fixed-inspector-value-scrubbing-producing-erratic-numbers-an.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-fixed-padding-gap-and-min-max-size-scrubbing-not-updating-th.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-fixed-text-stroke-color-turning-black-and-glyphs-disappearin.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-fixed-the-collapsed-effects-and-stroke-inspector-sections-sh.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-fixed-the-new-design-dialog-closing-unexpectedly-when-using-.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-fixed-the-typography-section-missing-when-selecting-text-nes.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-full-view-no-longer-flashes-back-to-the-overview-on-entry-no.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-keyframe-animation-timeline-per-property-keyframes-easing-cu.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-mobile-layouts-no-longer-stack-two-top-headers.md +5 -0
- package/corpus/templates/design/changelog/2026-07-06-moving-restyling-and-scrubbing-values-on-elements-in-ai-gene.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-padding-and-corner-radius-value-scrubbing-now-snaps-to-whole.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-padding-handles-now-only-resize-on-the-handle-line-itself-sh.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-preview-and-edit-hover-focus-and-pressed-states-with-real-cs.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-promoting-an-element-to-a-component-now-works-correctly-for-.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-reduced-url-history-churn-and-selection-overlay-flicker-whil.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-removed-the-decorative-dot-before-screen-names-in-the-overvi.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-responsive-breakpoints-edit-at-any-width-with-cascading-over.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-screen-labels-no-longer-turn-blue-when-you-hover-inside-the-.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-scrolling-a-screen-with-an-element-selected-stays-smooth-on-.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-selecting-multiple-elements-and-dragging-now-moves-the-whole.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-selection-borders-handles-and-value-readouts-now-stay-the-sa.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-selection-handles-and-editing-chrome-now-stay-a-constant-siz.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-shader-fills-and-effects-ai-authored-or-preset-glsl-shaders-.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-text-drawn-on-the-canvas-now-defaults-to-white-and-inter-in-.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-text-dropped-into-a-shape-now-stays-readable-instead-of-disa.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-the-add-tweak-controls-prompt-no-longer-jumps-to-the-corner-.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-the-design-agent-now-visually-reviews-rendered-screenshots-o.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-the-padding-value-readout-now-stays-visible-while-you-hover-.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-the-selected-element-attachment-now-clears-from-the-chat-com.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-the-zoom-menu-is-more-compact-with-tight-rows-and-right-alig.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-undo-and-redo-no-longer-flash-the-screen-changes-now-apply-i.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-zoom-presets-like-zoom-to-50-now-stay-on-the-focused-screen-.md +6 -0
- package/corpus/templates/design/server/handlers/import-design-file.ts +4 -43
- package/corpus/templates/design/server/handlers/index-design-system-with-builder.ts +2 -2
- package/corpus/templates/design/server/lib/import-design-files.ts +11 -2
- package/corpus/templates/design/server/lib/visible-clipboard-html.ts +32 -0
- package/corpus/templates/design/server/source-workspace.ts +139 -59
- package/corpus/templates/design/shared/board-file.ts +11 -2
- package/corpus/templates/design/shared/breakpoint-media.ts +543 -0
- package/corpus/templates/design/shared/canvas-math.ts +354 -35
- package/corpus/templates/design/shared/code-layer.ts +277 -8
- package/corpus/templates/design/shared/design-review.ts +1 -0
- package/corpus/templates/design/shared/design-state.ts +11 -4
- package/corpus/templates/design/shared/interaction-states.ts +548 -0
- package/corpus/templates/design/shared/motion-compiler.ts +186 -23
- package/corpus/templates/design/shared/motion-easing.ts +294 -0
- package/corpus/templates/design/shared/motion-timeline.ts +400 -34
- package/corpus/templates/design/shared/prompt-title.ts +95 -0
- package/corpus/templates/design/shared/responsive-classes.ts +448 -10
- package/corpus/templates/design/shared/screen-annotation.ts +46 -0
- package/corpus/templates/design/shared/shader-fills.ts +1009 -0
- package/corpus/templates/design/shared/shader-presets.ts +852 -4
- package/corpus/templates/dispatch/.agents/skills/actions/SKILL.md +55 -0
- package/corpus/templates/dispatch/actions/list-staged-datasets.ts +3 -0
- package/corpus/templates/dispatch/app/routes/settings.tsx +3 -17
- package/corpus/templates/forms/.agents/skills/actions/SKILL.md +55 -0
- package/corpus/templates/forms/app/components/CloudUpgrade.tsx +10 -10
- package/corpus/templates/forms/app/components/ThemeToggle.tsx +5 -5
- package/corpus/templates/forms/app/components/builder/FieldPropertiesPanel.tsx +11 -10
- package/corpus/templates/forms/app/components/builder/FieldRenderer.tsx +10 -13
- package/corpus/templates/forms/app/components/layout/Sidebar.tsx +17 -17
- package/corpus/templates/forms/app/components/ui/alert-dialog.tsx +1 -0
- package/corpus/templates/forms/app/components/ui/badge.tsx +1 -0
- package/corpus/templates/forms/app/components/ui/button.tsx +1 -0
- package/corpus/templates/forms/app/components/ui/calendar.tsx +1 -1
- package/corpus/templates/forms/app/components/ui/card.tsx +1 -0
- package/corpus/templates/forms/app/components/ui/checkbox.tsx +1 -0
- package/corpus/templates/forms/app/components/ui/command.tsx +1 -1
- package/corpus/templates/forms/app/components/ui/dialog.tsx +1 -0
- package/corpus/templates/forms/app/components/ui/dropdown-menu.tsx +1 -0
- package/corpus/templates/forms/app/components/ui/input.tsx +1 -0
- package/corpus/templates/forms/app/components/ui/label.tsx +1 -0
- package/corpus/templates/forms/app/components/ui/popover.tsx +1 -0
- package/corpus/templates/forms/app/components/ui/radio-group.tsx +1 -0
- package/corpus/templates/forms/app/components/ui/scroll-area.tsx +1 -0
- package/corpus/templates/forms/app/components/ui/select.tsx +1 -0
- package/corpus/templates/forms/app/components/ui/separator.tsx +1 -0
- package/corpus/templates/forms/app/components/ui/skeleton.tsx +1 -0
- package/corpus/templates/forms/app/components/ui/slider.tsx +1 -0
- package/corpus/templates/forms/app/components/ui/switch.tsx +1 -0
- package/corpus/templates/forms/app/components/ui/table.tsx +1 -0
- package/corpus/templates/forms/app/components/ui/tabs.tsx +1 -0
- package/corpus/templates/forms/app/components/ui/textarea.tsx +1 -0
- package/corpus/templates/forms/app/components/ui/toolkit-provider.tsx +12 -0
- package/corpus/templates/forms/app/components/ui/tooltip.tsx +1 -0
- package/corpus/templates/forms/app/global.css +1 -0
- package/corpus/templates/forms/app/hooks/use-mobile.ts +1 -0
- package/corpus/templates/forms/app/hooks/use-navigation-state.ts +0 -1
- package/corpus/templates/forms/app/pages/FormBuilderPage.tsx +24 -26
- package/corpus/templates/forms/app/pages/FormFillPage.tsx +2 -2
- package/corpus/templates/forms/app/pages/FormsListPage.tsx +21 -21
- package/corpus/templates/forms/app/pages/ResponseInsightsPage.tsx +11 -11
- package/corpus/templates/forms/app/pages/ResponsesPage.tsx +4 -4
- package/corpus/templates/forms/app/root.tsx +11 -8
- package/corpus/templates/forms/app/routes/_app.settings.tsx +6 -21
- package/corpus/templates/forms/app/routes/form-preview.tsx +3 -3
- package/corpus/templates/forms/changelog/2026-07-06-the-form-builder-header-no-longer-shows-the-global-notificat.md +6 -0
- package/corpus/templates/macros/app/components/AddExerciseDialog.tsx +1 -1
- package/corpus/templates/macros/app/components/AddMealDialog.tsx +1 -1
- package/corpus/templates/macros/app/components/AddWeightDialog.tsx +1 -1
- package/corpus/templates/macros/app/components/DailyProgress.tsx +7 -7
- package/corpus/templates/macros/app/components/WeeklyCaloriesChart.tsx +2 -1
- package/corpus/templates/macros/app/components/WeightCard.tsx +10 -10
- package/corpus/templates/macros/app/components/WeightTracker.tsx +1 -1
- package/corpus/templates/macros/app/components/layout/AppLayout.tsx +6 -10
- package/corpus/templates/macros/app/components/ui/alert-dialog.tsx +1 -0
- package/corpus/templates/macros/app/components/ui/label.tsx +1 -0
- package/corpus/templates/macros/app/components/ui/select.tsx +1 -0
- package/corpus/templates/macros/app/components/ui/sheet.tsx +1 -0
- package/corpus/templates/macros/app/components/ui/skeleton.tsx +1 -0
- package/corpus/templates/macros/app/components/ui/sonner.tsx +1 -0
- package/corpus/templates/macros/app/components/ui/toolkit-provider.tsx +12 -0
- package/corpus/templates/macros/app/components/ui/tooltip.tsx +1 -0
- package/corpus/templates/macros/app/global.css +1 -0
- package/corpus/templates/macros/app/root.tsx +17 -14
- package/corpus/templates/macros/app/routes/_index.tsx +1 -1
- package/corpus/templates/macros/app/routes/analytics.tsx +8 -8
- package/corpus/templates/macros/app/routes/settings.tsx +4 -19
- package/corpus/templates/mail/.agents/skills/actions/SKILL.md +55 -0
- package/corpus/templates/mail/.agents/skills/contacts-and-crm/SKILL.md +67 -0
- package/corpus/templates/mail/.agents/skills/draft-queue/SKILL.md +35 -1
- package/corpus/templates/mail/.agents/skills/email-drafts/SKILL.md +74 -33
- package/corpus/templates/mail/AGENTS.md +102 -16
- package/corpus/templates/mail/actions/archive-email.ts +67 -11
- package/corpus/templates/mail/actions/manage-snippets.ts +106 -0
- package/corpus/templates/mail/actions/mark-read.ts +45 -11
- package/corpus/templates/mail/actions/send-queued-drafts.ts +77 -42
- package/corpus/templates/mail/actions/star-email.ts +55 -10
- package/corpus/templates/mail/actions/trash-email.ts +48 -9
- package/corpus/templates/mail/app/components/GoogleConnectBanner.tsx +1 -1
- package/corpus/templates/mail/app/components/ThemeToggle.tsx +6 -6
- package/corpus/templates/mail/app/components/agent-engine-picker.tsx +10 -10
- package/corpus/templates/mail/app/components/email/CodeBlockLangPicker.tsx +4 -3
- package/corpus/templates/mail/app/components/email/ComposeBubbleToolbar.tsx +5 -5
- package/corpus/templates/mail/app/components/email/ComposeEditor.tsx +109 -10
- package/corpus/templates/mail/app/components/email/ComposeModal.tsx +44 -19
- package/corpus/templates/mail/app/components/email/ComposeSlashMenu.tsx +139 -17
- package/corpus/templates/mail/app/components/email/EmailList.tsx +522 -314
- package/corpus/templates/mail/app/components/email/EmailListItem.tsx +130 -45
- package/corpus/templates/mail/app/components/email/EmailThread.tsx +9 -9
- package/corpus/templates/mail/app/components/email/InlineReplyComposer.tsx +35 -13
- package/corpus/templates/mail/app/components/email/IntegrationsSidebar.tsx +13 -13
- package/corpus/templates/mail/app/components/email/MobileActionBar.tsx +13 -13
- package/corpus/templates/mail/app/components/email/RecipientInput.tsx +53 -42
- package/corpus/templates/mail/app/components/email/SendLaterButton.tsx +5 -4
- package/corpus/templates/mail/app/components/email/SnoozeModal.tsx +1 -1
- package/corpus/templates/mail/app/components/email/SnoozePopover.tsx +6 -6
- package/corpus/templates/mail/app/components/layout/AppLayout.tsx +19 -23
- package/corpus/templates/mail/app/components/layout/HeaderActions.tsx +12 -4
- package/corpus/templates/mail/app/components/layout/SearchBar.tsx +138 -18
- package/corpus/templates/mail/app/components/settings/GmailFiltersSection.tsx +23 -23
- package/corpus/templates/mail/app/components/settings/SnippetsSection.tsx +303 -0
- package/corpus/templates/mail/app/components/ui/alert-dialog.tsx +1 -0
- package/corpus/templates/mail/app/components/ui/badge.tsx +1 -0
- package/corpus/templates/mail/app/components/ui/button.tsx +1 -0
- package/corpus/templates/mail/app/components/ui/calendar.tsx +1 -1
- package/corpus/templates/mail/app/components/ui/command.tsx +1 -1
- package/corpus/templates/mail/app/components/ui/dialog.tsx +1 -0
- package/corpus/templates/mail/app/components/ui/drawer.tsx +1 -0
- package/corpus/templates/mail/app/components/ui/dropdown-menu.tsx +1 -0
- package/corpus/templates/mail/app/components/ui/popover.tsx +1 -0
- package/corpus/templates/mail/app/components/ui/select.tsx +1 -0
- package/corpus/templates/mail/app/components/ui/skeleton.tsx +1 -0
- package/corpus/templates/mail/app/components/ui/spinner.tsx +1 -0
- package/corpus/templates/mail/app/components/ui/switch.tsx +1 -0
- package/corpus/templates/mail/app/components/ui/toolkit-provider.tsx +12 -0
- package/corpus/templates/mail/app/components/ui/tooltip.tsx +1 -0
- package/corpus/templates/mail/app/global.css +20 -3
- package/corpus/templates/mail/app/hooks/use-emails.ts +187 -0
- package/corpus/templates/mail/app/hooks/use-snippets.ts +103 -0
- package/corpus/templates/mail/app/i18n/ar-SA.ts +17 -0
- package/corpus/templates/mail/app/i18n/de-DE.ts +18 -0
- package/corpus/templates/mail/app/i18n/en-US.ts +17 -0
- package/corpus/templates/mail/app/i18n/es-ES.ts +17 -0
- package/corpus/templates/mail/app/i18n/fr-FR.ts +18 -0
- package/corpus/templates/mail/app/i18n/hi-IN.ts +17 -0
- package/corpus/templates/mail/app/i18n/ja-JP.ts +18 -0
- package/corpus/templates/mail/app/i18n/ko-KR.ts +17 -0
- package/corpus/templates/mail/app/i18n/pt-BR.ts +17 -0
- package/corpus/templates/mail/app/i18n/zh-CN.ts +16 -0
- package/corpus/templates/mail/app/i18n/zh-TW.ts +16 -0
- package/corpus/templates/mail/app/pages/DraftQueuePage.tsx +14 -14
- package/corpus/templates/mail/app/pages/InboxPage.tsx +3 -3
- package/corpus/templates/mail/app/pages/NotFound.tsx +2 -1
- package/corpus/templates/mail/app/pages/SettingsPage.tsx +64 -66
- package/corpus/templates/mail/app/root.tsx +21 -18
- package/corpus/templates/mail/app/routes/_index.tsx +2 -1
- package/corpus/templates/mail/app/routes/email.tsx +2 -2
- package/corpus/templates/mail/changelog/2026-07-06-a-queued-draft-can-no-longer-be-sent-twice-by-simultaneous-s.md +6 -0
- package/corpus/templates/mail/changelog/2026-07-06-bulk-archive-trash-star-and-mark-read-now-complete-in-one-fa.md +6 -0
- package/corpus/templates/mail/changelog/2026-07-06-dark-mode-sidebars-and-notifications-now-use-the-softer-gray.md +6 -0
- package/corpus/templates/mail/changelog/2026-07-06-inbox-automations-pick-up-new-mail-faster.md +6 -0
- package/corpus/templates/mail/changelog/2026-07-06-inbox-lists-stay-fast-as-scheduled-and-snoozed-mail-accumula.md +6 -0
- package/corpus/templates/mail/changelog/2026-07-06-long-inboxes-scroll-smoothly-and-stay-fast-as-more-mail-load.md +6 -0
- package/corpus/templates/mail/changelog/2026-07-06-paste-or-drop-images-straight-into-the-composer-to-send-them.md +6 -0
- package/corpus/templates/mail/changelog/2026-07-06-save-reusable-snippets-and-insert-them-from-the-compose-slas.md +6 -0
- package/corpus/templates/mail/changelog/2026-07-06-scrolling-older-mail-keeps-loading-correctly-when-no-gmail-a.md +6 -0
- package/corpus/templates/mail/changelog/2026-07-06-search-shows-instant-matches-from-already-loaded-mail-while-.md +6 -0
- package/corpus/templates/mail/changelog/2026-07-06-sends-now-fail-with-a-clear-error-instead-of-quietly-missing.md +6 -0
- package/corpus/templates/mail/changelog/2026-07-06-the-mail-header-no-longer-shows-the-global-notifications-bel.md +6 -0
- package/corpus/templates/mail/package.json +1 -0
- package/corpus/templates/mail/server/db/schema.ts +11 -0
- package/corpus/templates/mail/server/handlers/emails.ts +20 -1
- package/corpus/templates/mail/server/lib/automation-engine.ts +53 -25
- package/corpus/templates/mail/server/lib/google-auth.ts +140 -9
- package/corpus/templates/mail/server/lib/jobs.ts +22 -6
- package/corpus/templates/mail/server/lib/outgoing-email.ts +11 -2
- package/corpus/templates/mail/server/lib/queued-drafts.ts +145 -4
- package/corpus/templates/mail/server/plugins/db.ts +29 -0
- package/corpus/templates/plan/.agents/skills/actions/SKILL.md +55 -0
- package/corpus/templates/plan/app/components/editor/PlanDocumentEditor.tsx +42 -3
- package/corpus/templates/plan/app/components/layout/Layout.tsx +5 -4
- package/corpus/templates/plan/app/components/layout/Sidebar.tsx +20 -20
- package/corpus/templates/plan/app/components/plan/CanvasArea.tsx +3 -2
- package/corpus/templates/plan/app/components/plan/DocumentArea.tsx +2 -2
- package/corpus/templates/plan/app/components/plan/GuestModeBanner.tsx +2 -1
- package/corpus/templates/plan/app/components/plan/LocalCodebasePicker.tsx +8 -8
- package/corpus/templates/plan/app/components/plan/PlanContentRenderer.tsx +6 -1
- package/corpus/templates/plan/app/components/plan/PlanImageViewer.tsx +8 -12
- package/corpus/templates/plan/app/components/plan/PlanMarkdownEditor.tsx +6 -1
- package/corpus/templates/plan/app/components/plan/PlanVisualSurface.tsx +3 -3
- package/corpus/templates/plan/app/components/plan/planBlocks.tsx +4 -4
- package/corpus/templates/plan/app/components/plan/wireframe/kit/rough.tsx +61 -27
- package/corpus/templates/plan/app/components/ui/alert-dialog.tsx +1 -0
- package/corpus/templates/plan/app/components/ui/avatar.tsx +1 -0
- package/corpus/templates/plan/app/components/ui/badge.tsx +1 -0
- package/corpus/templates/plan/app/components/ui/button.tsx +1 -0
- package/corpus/templates/plan/app/components/ui/card.tsx +1 -0
- package/corpus/templates/plan/app/components/ui/checkbox.tsx +1 -0
- package/corpus/templates/plan/app/components/ui/collapsible.tsx +1 -0
- package/corpus/templates/plan/app/components/ui/dialog.tsx +1 -0
- package/corpus/templates/plan/app/components/ui/dropdown-menu.tsx +1 -0
- package/corpus/templates/plan/app/components/ui/input.tsx +1 -0
- package/corpus/templates/plan/app/components/ui/label.tsx +1 -0
- package/corpus/templates/plan/app/components/ui/popover.tsx +1 -0
- package/corpus/templates/plan/app/components/ui/scroll-area.tsx +1 -0
- package/corpus/templates/plan/app/components/ui/select.tsx +1 -0
- package/corpus/templates/plan/app/components/ui/separator.tsx +1 -0
- package/corpus/templates/plan/app/components/ui/sheet.tsx +1 -0
- package/corpus/templates/plan/app/components/ui/skeleton.tsx +1 -0
- package/corpus/templates/plan/app/components/ui/sonner.tsx +1 -0
- package/corpus/templates/plan/app/components/ui/spinner.tsx +1 -0
- package/corpus/templates/plan/app/components/ui/textarea.tsx +1 -0
- package/corpus/templates/plan/app/components/ui/toggle-group.tsx +1 -0
- package/corpus/templates/plan/app/components/ui/toolkit-provider.tsx +12 -0
- package/corpus/templates/plan/app/components/ui/tooltip.tsx +1 -0
- package/corpus/templates/plan/app/global.css +13 -0
- package/corpus/templates/plan/app/hooks/use-plan-presence.ts +11 -1
- package/corpus/templates/plan/app/lib/plan-access-prompt.ts +74 -0
- package/corpus/templates/plan/app/lib/plan-annotation-runtime.ts +1435 -0
- package/corpus/templates/plan/app/lib/plan-comment-editor-helpers.ts +142 -0
- package/corpus/templates/plan/app/lib/plan-local-bridge.ts +376 -0
- package/corpus/templates/plan/app/lib/plan-native-anchors.ts +682 -0
- package/corpus/templates/plan/app/pages/PlansPage.tsx +216 -2747
- package/corpus/templates/plan/app/root.tsx +13 -10
- package/corpus/templates/plan/app/routes/_index.tsx +1 -2
- package/corpus/templates/plan/app/routes/local-plans.$slug.tsx +1 -1
- package/corpus/templates/plan/app/routes/plans.$id.tsx +1 -2
- package/corpus/templates/plan/app/routes/plans.tsx +1 -2
- package/corpus/templates/plan/app/routes/recaps.$id.tsx +1 -2
- package/corpus/templates/plan/app/routes/recaps.tsx +1 -2
- package/corpus/templates/plan/app/routes/settings.tsx +7 -21
- package/corpus/templates/plan/changelog/2026-07-05-plan-pages-open-at-the-top-unless-a-shared-link-targets-a-sp.md +6 -0
- package/corpus/templates/plan/changelog/2026-07-06-fixed-collaborative-plan-editing-so-content-no-longer-duplic.md +6 -0
- package/corpus/templates/plan/changelog/2026-07-06-fixed-visual-reports-using-excessive-cpu-while-rendering-ske.md +6 -0
- package/corpus/templates/slides/.agents/skills/actions/SKILL.md +55 -0
- package/corpus/templates/slides/app/components/ThemeToggle.tsx +6 -6
- package/corpus/templates/slides/app/components/comments/SlideCommentsPanel.tsx +5 -5
- package/corpus/templates/slides/app/components/deck/DeckCard.tsx +7 -7
- package/corpus/templates/slides/app/components/deck/ExcalidrawSlide.tsx +2 -1
- package/corpus/templates/slides/app/components/deck/SlideRenderer.tsx +1 -1
- package/corpus/templates/slides/app/components/design-system/DesignSystemCard.tsx +3 -2
- package/corpus/templates/slides/app/components/design-system/DesignSystemSetup.tsx +15 -14
- package/corpus/templates/slides/app/components/editor/AnimationsPanel.tsx +7 -7
- package/corpus/templates/slides/app/components/editor/BlockBubbleMenu.tsx +5 -5
- package/corpus/templates/slides/app/components/editor/EditorSidebar.tsx +6 -6
- package/corpus/templates/slides/app/components/editor/EditorToolbar.tsx +29 -16
- package/corpus/templates/slides/app/components/editor/ExportMenu.tsx +10 -9
- package/corpus/templates/slides/app/components/editor/GenerateSlidesDialog.tsx +6 -5
- package/corpus/templates/slides/app/components/editor/HistoryPanel.tsx +12 -12
- package/corpus/templates/slides/app/components/editor/ImageDropPromptPopover.tsx +4 -3
- package/corpus/templates/slides/app/components/editor/ImageSearchPanel.tsx +5 -4
- package/corpus/templates/slides/app/components/editor/ImportButton.tsx +14 -4
- package/corpus/templates/slides/app/components/editor/PromptDialog.tsx +2 -1
- package/corpus/templates/slides/app/components/editor/ShareDialog.tsx +10 -10
- package/corpus/templates/slides/app/components/editor/SlideBubbleMenu.tsx +10 -10
- package/corpus/templates/slides/app/components/editor/SlideEditor.tsx +6 -6
- package/corpus/templates/slides/app/components/editor/SlideStyleInspector.tsx +2 -1
- package/corpus/templates/slides/app/components/editor/TweaksPanel.tsx +1 -1
- package/corpus/templates/slides/app/components/layout/Header.tsx +2 -2
- package/corpus/templates/slides/app/components/layout/Sidebar.tsx +5 -5
- package/corpus/templates/slides/app/components/ui/alert-dialog.tsx +1 -0
- package/corpus/templates/slides/app/components/ui/button.tsx +1 -0
- package/corpus/templates/slides/app/components/ui/card.tsx +1 -0
- package/corpus/templates/slides/app/components/ui/dialog.tsx +1 -0
- package/corpus/templates/slides/app/components/ui/dropdown-menu.tsx +1 -0
- package/corpus/templates/slides/app/components/ui/input.tsx +1 -0
- package/corpus/templates/slides/app/components/ui/label.tsx +1 -0
- package/corpus/templates/slides/app/components/ui/popover.tsx +1 -0
- package/corpus/templates/slides/app/components/ui/scroll-area.tsx +1 -0
- package/corpus/templates/slides/app/components/ui/select.tsx +1 -0
- package/corpus/templates/slides/app/components/ui/separator.tsx +1 -0
- package/corpus/templates/slides/app/components/ui/sheet.tsx +1 -0
- package/corpus/templates/slides/app/components/ui/skeleton.tsx +1 -0
- package/corpus/templates/slides/app/components/ui/spinner.tsx +1 -0
- package/corpus/templates/slides/app/components/ui/textarea.tsx +1 -0
- package/corpus/templates/slides/app/components/ui/toast.tsx +1 -0
- package/corpus/templates/slides/app/components/ui/toaster.tsx +1 -0
- package/corpus/templates/slides/app/components/ui/toggle-group.tsx +1 -0
- package/corpus/templates/slides/app/components/ui/toolkit-provider.tsx +12 -0
- package/corpus/templates/slides/app/components/ui/tooltip.tsx +1 -0
- package/corpus/templates/slides/app/components/visual-editor/CanvasCommentPins.tsx +6 -6
- package/corpus/templates/slides/app/components/visual-editor/DrawOverlay.tsx +7 -7
- package/corpus/templates/slides/app/global.css +1 -0
- package/corpus/templates/slides/app/hooks/use-toast.ts +1 -0
- package/corpus/templates/slides/app/lib/upload-response.ts +71 -0
- package/corpus/templates/slides/app/pages/DeckEditor.tsx +3 -3
- package/corpus/templates/slides/app/pages/DesignSystems.tsx +1 -1
- package/corpus/templates/slides/app/pages/Index.tsx +14 -17
- package/corpus/templates/slides/app/root.tsx +13 -10
- package/corpus/templates/slides/app/routes/settings.tsx +6 -21
- package/corpus/templates/slides/changelog/2026-07-06-mobile-layouts-no-longer-stack-two-top-headers.md +5 -0
- package/corpus/templates/slides/server/handlers/uploads.ts +7 -2
- package/corpus/templates/slides/server/lib/chat-attachments.ts +1 -1
- package/dist/agent/durable-background.d.ts +29 -0
- package/dist/agent/durable-background.d.ts.map +1 -1
- package/dist/agent/durable-background.js +46 -0
- package/dist/agent/durable-background.js.map +1 -1
- package/dist/agent/engine/ai-sdk-engine.d.ts.map +1 -1
- package/dist/agent/engine/ai-sdk-engine.js +7 -2
- package/dist/agent/engine/ai-sdk-engine.js.map +1 -1
- package/dist/agent/engine/anthropic-engine.d.ts.map +1 -1
- package/dist/agent/engine/anthropic-engine.js +28 -2
- package/dist/agent/engine/anthropic-engine.js.map +1 -1
- package/dist/agent/engine/builder-engine.d.ts.map +1 -1
- package/dist/agent/engine/builder-engine.js +1 -1
- package/dist/agent/engine/builder-engine.js.map +1 -1
- package/dist/agent/engine/output-tokens.d.ts +3 -3
- package/dist/agent/engine/output-tokens.d.ts.map +1 -1
- package/dist/agent/engine/output-tokens.js +16 -14
- package/dist/agent/engine/output-tokens.js.map +1 -1
- package/dist/agent/engine/registry.d.ts +3 -3
- package/dist/agent/engine/registry.d.ts.map +1 -1
- package/dist/agent/engine/registry.js +28 -25
- package/dist/agent/engine/registry.js.map +1 -1
- package/dist/agent/engine/translate-ai-sdk.d.ts +14 -2
- package/dist/agent/engine/translate-ai-sdk.d.ts.map +1 -1
- package/dist/agent/engine/translate-ai-sdk.js +33 -18
- package/dist/agent/engine/translate-ai-sdk.js.map +1 -1
- package/dist/agent/engine/translate-anthropic.d.ts.map +1 -1
- package/dist/agent/engine/translate-anthropic.js +42 -1
- package/dist/agent/engine/translate-anthropic.js.map +1 -1
- package/dist/agent/engine/types.d.ts +15 -0
- package/dist/agent/engine/types.d.ts.map +1 -1
- package/dist/agent/engine/types.js.map +1 -1
- package/dist/agent/model-config.d.ts +8 -0
- package/dist/agent/model-config.d.ts.map +1 -1
- package/dist/agent/model-config.js +86 -0
- package/dist/agent/model-config.js.map +1 -1
- package/dist/agent/production-agent.d.ts +91 -5
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +389 -180
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/agent/runtime-context.d.ts +29 -0
- package/dist/agent/runtime-context.d.ts.map +1 -1
- package/dist/agent/runtime-context.js +40 -11
- package/dist/agent/runtime-context.js.map +1 -1
- package/dist/agent/tool-result-images.d.ts +49 -0
- package/dist/agent/tool-result-images.d.ts.map +1 -0
- package/dist/agent/tool-result-images.js +141 -0
- package/dist/agent/tool-result-images.js.map +1 -0
- package/dist/brand-kit/fig/index.d.ts.map +1 -1
- package/dist/brand-kit/fig/index.js +6 -3
- package/dist/brand-kit/fig/index.js.map +1 -1
- package/dist/client/AgentPanel.d.ts.map +1 -1
- package/dist/client/AgentPanel.js +67 -18
- package/dist/client/AgentPanel.js.map +1 -1
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +72 -40
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/KeepTabOpenNotice.d.ts +55 -0
- package/dist/client/KeepTabOpenNotice.d.ts.map +1 -0
- package/dist/client/KeepTabOpenNotice.js +85 -0
- package/dist/client/KeepTabOpenNotice.js.map +1 -0
- package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
- package/dist/client/MultiTabAssistantChat.js +2 -1
- package/dist/client/MultiTabAssistantChat.js.map +1 -1
- package/dist/client/RunStuckBanner.d.ts +7 -1
- package/dist/client/RunStuckBanner.d.ts.map +1 -1
- package/dist/client/RunStuckBanner.js +7 -2
- package/dist/client/RunStuckBanner.js.map +1 -1
- package/dist/client/chat/run-recovery.d.ts.map +1 -1
- package/dist/client/chat/run-recovery.js +7 -1
- package/dist/client/chat/run-recovery.js.map +1 -1
- package/dist/client/clipboard.d.ts.map +1 -1
- package/dist/client/clipboard.js +5 -6
- package/dist/client/clipboard.js.map +1 -1
- package/dist/client/components/AgentPresenceChip.d.ts +1 -11
- package/dist/client/components/AgentPresenceChip.d.ts.map +1 -1
- package/dist/client/components/AgentPresenceChip.js +1 -41
- package/dist/client/components/AgentPresenceChip.js.map +1 -1
- package/dist/client/components/LiveCursorOverlay.d.ts +1 -44
- package/dist/client/components/LiveCursorOverlay.d.ts.map +1 -1
- package/dist/client/components/LiveCursorOverlay.js +1 -123
- package/dist/client/components/LiveCursorOverlay.js.map +1 -1
- package/dist/client/components/PresenceBar.d.ts +1 -26
- package/dist/client/components/PresenceBar.d.ts.map +1 -1
- package/dist/client/components/PresenceBar.js +1 -164
- package/dist/client/components/PresenceBar.js.map +1 -1
- package/dist/client/components/RecentEditHighlights.d.ts +1 -42
- package/dist/client/components/RecentEditHighlights.d.ts.map +1 -1
- package/dist/client/components/RecentEditHighlights.js +1 -145
- package/dist/client/components/RecentEditHighlights.js.map +1 -1
- package/dist/client/components/RemoteSelectionRings.d.ts +1 -51
- package/dist/client/components/RemoteSelectionRings.d.ts.map +1 -1
- package/dist/client/components/RemoteSelectionRings.js +1 -129
- package/dist/client/components/RemoteSelectionRings.js.map +1 -1
- package/dist/client/composer/TiptapComposer.d.ts +4 -0
- package/dist/client/composer/TiptapComposer.d.ts.map +1 -1
- package/dist/client/composer/TiptapComposer.js +74 -26
- package/dist/client/composer/TiptapComposer.js.map +1 -1
- package/dist/client/db-admin/SqlEditor.d.ts.map +1 -1
- package/dist/client/db-admin/SqlEditor.js +13 -3
- package/dist/client/db-admin/SqlEditor.js.map +1 -1
- package/dist/client/dynamic-suggestions.d.ts.map +1 -1
- package/dist/client/dynamic-suggestions.js +7 -1
- package/dist/client/dynamic-suggestions.js.map +1 -1
- package/dist/client/extensions/ExtensionViewer.d.ts.map +1 -1
- package/dist/client/extensions/ExtensionViewer.js +7 -7
- package/dist/client/extensions/ExtensionViewer.js.map +1 -1
- package/dist/client/extensions/ExtensionsListPage.d.ts.map +1 -1
- package/dist/client/extensions/ExtensionsListPage.js +5 -7
- package/dist/client/extensions/ExtensionsListPage.js.map +1 -1
- package/dist/client/extensions/ExtensionsSidebarSection.d.ts.map +1 -1
- package/dist/client/extensions/ExtensionsSidebarSection.js +1 -1
- package/dist/client/extensions/ExtensionsSidebarSection.js.map +1 -1
- package/dist/client/host-bridge.d.ts +2 -0
- package/dist/client/host-bridge.d.ts.map +1 -1
- package/dist/client/host-bridge.js +26 -10
- package/dist/client/host-bridge.js.map +1 -1
- package/dist/client/i18n.d.ts +1 -0
- package/dist/client/i18n.d.ts.map +1 -1
- package/dist/client/i18n.js +3 -1
- package/dist/client/i18n.js.map +1 -1
- package/dist/client/index.d.ts +2 -1
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +2 -1
- package/dist/client/index.js.map +1 -1
- package/dist/client/resources/McpIntegrationDialog.d.ts.map +1 -1
- package/dist/client/resources/McpIntegrationDialog.js +12 -31
- package/dist/client/resources/McpIntegrationDialog.js.map +1 -1
- package/dist/client/rich-markdown-editor/SharedRichEditor.d.ts +3 -1
- package/dist/client/rich-markdown-editor/SharedRichEditor.d.ts.map +1 -1
- package/dist/client/rich-markdown-editor/SharedRichEditor.js +2 -1
- package/dist/client/rich-markdown-editor/SharedRichEditor.js.map +1 -1
- package/dist/client/rich-markdown-editor/useCollabReconcile.d.ts +3 -1
- package/dist/client/rich-markdown-editor/useCollabReconcile.d.ts.map +1 -1
- package/dist/client/rich-markdown-editor/useCollabReconcile.js +17 -8
- package/dist/client/rich-markdown-editor/useCollabReconcile.js.map +1 -1
- package/dist/client/settings/SettingsPanel.d.ts +3 -1
- package/dist/client/settings/SettingsPanel.d.ts.map +1 -1
- package/dist/client/settings/SettingsPanel.js +103 -9
- package/dist/client/settings/SettingsPanel.js.map +1 -1
- package/dist/client/settings/SettingsTabsPage.d.ts.map +1 -1
- package/dist/client/settings/SettingsTabsPage.js +5 -5
- package/dist/client/settings/SettingsTabsPage.js.map +1 -1
- package/dist/client/settings/index.d.ts +1 -1
- package/dist/client/settings/index.d.ts.map +1 -1
- package/dist/client/settings/index.js +1 -1
- package/dist/client/settings/index.js.map +1 -1
- package/dist/client/sharing/VisibilityBadge.d.ts +1 -10
- package/dist/client/sharing/VisibilityBadge.d.ts.map +1 -1
- package/dist/client/sharing/VisibilityBadge.js +1 -18
- package/dist/client/sharing/VisibilityBadge.js.map +1 -1
- package/dist/client/use-action.d.ts +3 -0
- package/dist/client/use-action.d.ts.map +1 -1
- package/dist/client/use-action.js +34 -3
- package/dist/client/use-action.js.map +1 -1
- package/dist/client/use-db-sync.d.ts +4 -0
- package/dist/client/use-db-sync.d.ts.map +1 -1
- package/dist/client/use-db-sync.js +37 -18
- package/dist/client/use-db-sync.js.map +1 -1
- package/dist/client/use-run-stuck-detection.d.ts +8 -1
- package/dist/client/use-run-stuck-detection.d.ts.map +1 -1
- package/dist/client/use-run-stuck-detection.js +3 -2
- package/dist/client/use-run-stuck-detection.js.map +1 -1
- package/dist/coding-tools/run-code.d.ts +36 -0
- package/dist/coding-tools/run-code.d.ts.map +1 -1
- package/dist/coding-tools/run-code.js +333 -62
- package/dist/coding-tools/run-code.js.map +1 -1
- package/dist/coding-tools/sandbox/background.d.ts +141 -0
- package/dist/coding-tools/sandbox/background.d.ts.map +1 -0
- package/dist/coding-tools/sandbox/background.js +279 -0
- package/dist/coding-tools/sandbox/background.js.map +1 -0
- package/dist/coding-tools/sandbox/executions-store.d.ts +138 -0
- package/dist/coding-tools/sandbox/executions-store.d.ts.map +1 -0
- package/dist/coding-tools/sandbox/executions-store.js +380 -0
- package/dist/coding-tools/sandbox/executions-store.js.map +1 -0
- package/dist/coding-tools/sandbox/index.d.ts +22 -13
- package/dist/coding-tools/sandbox/index.d.ts.map +1 -1
- package/dist/coding-tools/sandbox/index.js +31 -13
- package/dist/coding-tools/sandbox/index.js.map +1 -1
- package/dist/coding-tools/sandbox/local-child-process-adapter.d.ts.map +1 -1
- package/dist/coding-tools/sandbox/local-child-process-adapter.js +61 -4
- package/dist/coding-tools/sandbox/local-child-process-adapter.js.map +1 -1
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/awareness.d.ts.map +1 -1
- package/dist/collab/client.d.ts +16 -12
- package/dist/collab/client.d.ts.map +1 -1
- package/dist/collab/client.js +744 -496
- package/dist/collab/client.js.map +1 -1
- package/dist/collab/presence.d.ts +2 -20
- package/dist/collab/presence.d.ts.map +1 -1
- package/dist/collab/presence.js +3 -0
- package/dist/collab/presence.js.map +1 -1
- package/dist/collab/recent-edits.d.ts +2 -37
- package/dist/collab/recent-edits.d.ts.map +1 -1
- package/dist/collab/recent-edits.js +2 -9
- package/dist/collab/recent-edits.js.map +1 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/data-programs/actions.d.ts +19 -0
- package/dist/data-programs/actions.d.ts.map +1 -0
- package/dist/data-programs/actions.js +279 -0
- package/dist/data-programs/actions.js.map +1 -0
- package/dist/data-programs/contract.d.ts +70 -0
- package/dist/data-programs/contract.d.ts.map +1 -0
- package/dist/data-programs/contract.js +225 -0
- package/dist/data-programs/contract.js.map +1 -0
- package/dist/data-programs/execute.d.ts +96 -0
- package/dist/data-programs/execute.d.ts.map +1 -0
- package/dist/data-programs/execute.js +454 -0
- package/dist/data-programs/execute.js.map +1 -0
- package/dist/data-programs/index.d.ts +11 -0
- package/dist/data-programs/index.d.ts.map +1 -0
- package/dist/data-programs/index.js +11 -0
- package/dist/data-programs/index.js.map +1 -0
- package/dist/data-programs/schema.d.ts +517 -0
- package/dist/data-programs/schema.d.ts.map +1 -0
- package/dist/data-programs/schema.js +138 -0
- package/dist/data-programs/schema.js.map +1 -0
- package/dist/data-programs/store.d.ts +158 -0
- package/dist/data-programs/store.d.ts.map +1 -0
- package/dist/data-programs/store.js +493 -0
- package/dist/data-programs/store.js.map +1 -0
- package/dist/db/create-get-db.d.ts +25 -0
- package/dist/db/create-get-db.d.ts.map +1 -1
- package/dist/db/create-get-db.js +25 -2
- package/dist/db/create-get-db.js.map +1 -1
- package/dist/deploy/build.d.ts.map +1 -1
- package/dist/deploy/build.js +34 -0
- package/dist/deploy/build.js.map +1 -1
- package/dist/extensions/actions.js +2 -2
- package/dist/extensions/actions.js.map +1 -1
- package/dist/file-upload/builder.d.ts.map +1 -1
- package/dist/file-upload/builder.js +9 -0
- package/dist/file-upload/builder.js.map +1 -1
- package/dist/integrations/webhook-handler.d.ts.map +1 -1
- package/dist/integrations/webhook-handler.js +21 -10
- package/dist/integrations/webhook-handler.js.map +1 -1
- package/dist/local-artifacts/index.js +1 -1
- package/dist/local-artifacts/index.js.map +1 -1
- package/dist/localization/default-messages.d.ts +0 -1
- package/dist/localization/default-messages.d.ts.map +1 -1
- package/dist/localization/default-messages.js +1 -2
- package/dist/localization/default-messages.js.map +1 -1
- package/dist/mcp-client/index.d.ts +9 -0
- package/dist/mcp-client/index.d.ts.map +1 -1
- package/dist/mcp-client/index.js +23 -0
- package/dist/mcp-client/index.js.map +1 -1
- package/dist/observability/routes.d.ts +3 -3
- package/dist/onboarding/default-steps.d.ts.map +1 -1
- package/dist/onboarding/default-steps.js +2 -2
- package/dist/onboarding/default-steps.js.map +1 -1
- package/dist/progress/routes.d.ts +1 -1
- package/dist/provider-api/corpus-jobs.d.ts +2 -2
- package/dist/resources/store.d.ts.map +1 -1
- package/dist/resources/store.js +35 -3
- package/dist/resources/store.js.map +1 -1
- package/dist/scripts/agent-engines/list-agent-engines.d.ts.map +1 -1
- package/dist/scripts/agent-engines/list-agent-engines.js +4 -8
- package/dist/scripts/agent-engines/list-agent-engines.js.map +1 -1
- package/dist/scripts/agent-engines/test-agent-engine.d.ts.map +1 -1
- package/dist/scripts/agent-engines/test-agent-engine.js +7 -2
- package/dist/scripts/agent-engines/test-agent-engine.js.map +1 -1
- package/dist/scripts/db/tool-mode.js +3 -3
- package/dist/scripts/db/tool-mode.js.map +1 -1
- package/dist/scripts/resources/migrate-learnings.d.ts +5 -1
- package/dist/scripts/resources/migrate-learnings.d.ts.map +1 -1
- package/dist/scripts/resources/migrate-learnings.js +8 -10
- package/dist/scripts/resources/migrate-learnings.js.map +1 -1
- package/dist/server/agent-chat-plugin.d.ts +20 -6
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +138 -59
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/agent-discovery.d.ts.map +1 -1
- package/dist/server/agent-discovery.js +62 -8
- package/dist/server/agent-discovery.js.map +1 -1
- package/dist/server/auth.d.ts.map +1 -1
- package/dist/server/auth.js +75 -3
- package/dist/server/auth.js.map +1 -1
- package/dist/server/builder-design-systems.js +2 -2
- package/dist/server/builder-design-systems.js.map +1 -1
- package/dist/server/core-routes-plugin.d.ts.map +1 -1
- package/dist/server/core-routes-plugin.js +100 -20
- package/dist/server/core-routes-plugin.js.map +1 -1
- package/dist/server/credential-provider.d.ts +6 -3
- package/dist/server/credential-provider.d.ts.map +1 -1
- package/dist/server/credential-provider.js +25 -8
- package/dist/server/credential-provider.js.map +1 -1
- package/dist/server/csrf.d.ts.map +1 -1
- package/dist/server/csrf.js +3 -0
- package/dist/server/csrf.js.map +1 -1
- package/dist/server/framework-request-handler.d.ts.map +1 -1
- package/dist/server/framework-request-handler.js +37 -1
- package/dist/server/framework-request-handler.js.map +1 -1
- package/dist/server/oauth-helpers.d.ts.map +1 -1
- package/dist/server/oauth-helpers.js +9 -1
- package/dist/server/oauth-helpers.js.map +1 -1
- package/dist/server/onboarding-html.d.ts.map +1 -1
- package/dist/server/onboarding-html.js +80 -48
- package/dist/server/onboarding-html.js.map +1 -1
- package/dist/server/prompts/shared-rules.js +2 -2
- package/dist/server/prompts/shared-rules.js.map +1 -1
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/dist/server/transcribe-voice.d.ts.map +1 -1
- package/dist/server/transcribe-voice.js +77 -15
- package/dist/server/transcribe-voice.js.map +1 -1
- package/dist/styles/agent-native.css +57 -45
- package/dist/templates/default/.agents/skills/actions/SKILL.md +55 -0
- package/dist/templates/default/AGENTS.md +11 -14
- package/dist/templates/default/actions/navigate.ts +1 -1
- package/dist/templates/default/app/i18n/ar-SA.ts +0 -1
- package/dist/templates/default/app/i18n/de-DE.ts +0 -1
- package/dist/templates/default/app/i18n/en-US.ts +0 -1
- package/dist/templates/default/app/i18n/es-ES.ts +0 -1
- package/dist/templates/default/app/i18n/fr-FR.ts +0 -1
- package/dist/templates/default/app/i18n/hi-IN.ts +0 -1
- package/dist/templates/default/app/i18n/ja-JP.ts +0 -1
- package/dist/templates/default/app/i18n/ko-KR.ts +0 -1
- package/dist/templates/default/app/i18n/pt-BR.ts +0 -1
- package/dist/templates/default/app/i18n/zh-CN.ts +0 -1
- package/dist/templates/default/app/i18n/zh-TW.ts +0 -1
- package/dist/templates/default/app/routes/settings.tsx +22 -33
- package/dist/templates/headless/.agents/skills/agent-native-docs/SKILL.md +20 -7
- package/dist/templates/headless/AGENTS.md +9 -6
- package/dist/templates/workspace-core/.agents/skills/actions/SKILL.md +55 -0
- package/dist/templates/workspace-core/.agents/skills/data-programs/SKILL.md +128 -0
- package/dist/templates/workspace-core/.agents/skills/harness-agents/SKILL.md +10 -4
- package/dist/vite/agents-bundle-plugin.d.ts.map +1 -1
- package/dist/vite/agents-bundle-plugin.js +26 -1
- package/dist/vite/agents-bundle-plugin.js.map +1 -1
- package/dist/vite/client.d.ts.map +1 -1
- package/dist/vite/client.js +11 -0
- package/dist/vite/client.js.map +1 -1
- package/docs/content/agent-native-toolkit.mdx +87 -146
- package/docs/content/cloneable-saas.mdx +19 -19
- package/docs/content/components.mdx +16 -4
- package/docs/content/data-programs.mdx +329 -0
- package/docs/content/deployment.mdx +9 -9
- package/docs/content/extensions.mdx +8 -7
- package/docs/content/generative-ui.mdx +5 -3
- package/docs/content/key-concepts.mdx +6 -9
- package/docs/content/locales/ar-SA/agent-native-toolkit.mdx +100 -70
- package/docs/content/locales/ar-SA/cloneable-saas.mdx +19 -19
- package/docs/content/locales/ar-SA/components.mdx +12 -2
- package/docs/content/locales/ar-SA/data-programs.mdx +329 -0
- package/docs/content/locales/ar-SA/deployment.mdx +8 -9
- package/docs/content/locales/ar-SA/extensions.mdx +6 -4
- package/docs/content/locales/ar-SA/key-concepts.mdx +7 -9
- package/docs/content/locales/ar-SA/real-time-collaboration.mdx +9 -10
- package/docs/content/locales/de-DE/agent-native-toolkit.mdx +100 -74
- package/docs/content/locales/de-DE/cloneable-saas.mdx +19 -19
- package/docs/content/locales/de-DE/components.mdx +12 -2
- package/docs/content/locales/de-DE/data-programs.mdx +329 -0
- package/docs/content/locales/de-DE/deployment.mdx +8 -9
- package/docs/content/locales/de-DE/extensions.mdx +6 -4
- package/docs/content/locales/de-DE/key-concepts.mdx +8 -10
- package/docs/content/locales/de-DE/real-time-collaboration.mdx +9 -10
- package/docs/content/locales/es-ES/agent-native-toolkit.mdx +100 -74
- package/docs/content/locales/es-ES/cloneable-saas.mdx +19 -19
- package/docs/content/locales/es-ES/components.mdx +12 -2
- package/docs/content/locales/es-ES/data-programs.mdx +329 -0
- package/docs/content/locales/es-ES/deployment.mdx +8 -9
- package/docs/content/locales/es-ES/extensions.mdx +6 -4
- package/docs/content/locales/es-ES/key-concepts.mdx +8 -10
- package/docs/content/locales/es-ES/real-time-collaboration.mdx +9 -10
- package/docs/content/locales/fr-FR/agent-native-toolkit.mdx +100 -76
- package/docs/content/locales/fr-FR/cloneable-saas.mdx +19 -19
- package/docs/content/locales/fr-FR/components.mdx +12 -2
- package/docs/content/locales/fr-FR/data-programs.mdx +329 -0
- package/docs/content/locales/fr-FR/deployment.mdx +8 -9
- package/docs/content/locales/fr-FR/extensions.mdx +6 -4
- package/docs/content/locales/fr-FR/key-concepts.mdx +8 -10
- package/docs/content/locales/fr-FR/real-time-collaboration.mdx +9 -10
- package/docs/content/locales/hi-IN/agent-native-toolkit.mdx +100 -71
- package/docs/content/locales/hi-IN/cloneable-saas.mdx +19 -19
- package/docs/content/locales/hi-IN/components.mdx +20 -10
- package/docs/content/locales/hi-IN/data-programs.mdx +329 -0
- package/docs/content/locales/hi-IN/deployment.mdx +8 -9
- package/docs/content/locales/hi-IN/extensions.mdx +6 -4
- package/docs/content/locales/hi-IN/key-concepts.mdx +8 -10
- package/docs/content/locales/hi-IN/real-time-collaboration.mdx +9 -10
- package/docs/content/locales/ja-JP/agent-native-toolkit.mdx +100 -64
- package/docs/content/locales/ja-JP/cloneable-saas.mdx +19 -19
- package/docs/content/locales/ja-JP/components.mdx +12 -2
- package/docs/content/locales/ja-JP/data-programs.mdx +329 -0
- package/docs/content/locales/ja-JP/deployment.mdx +8 -9
- package/docs/content/locales/ja-JP/extensions.mdx +6 -4
- package/docs/content/locales/ja-JP/key-concepts.mdx +9 -11
- package/docs/content/locales/ja-JP/real-time-collaboration.mdx +9 -10
- package/docs/content/locales/ko-KR/agent-native-toolkit.mdx +100 -60
- package/docs/content/locales/ko-KR/cloneable-saas.mdx +19 -19
- package/docs/content/locales/ko-KR/components.mdx +20 -10
- package/docs/content/locales/ko-KR/data-programs.mdx +329 -0
- package/docs/content/locales/ko-KR/deployment.mdx +8 -9
- package/docs/content/locales/ko-KR/extensions.mdx +16 -14
- package/docs/content/locales/ko-KR/key-concepts.mdx +9 -11
- package/docs/content/locales/ko-KR/real-time-collaboration.mdx +9 -10
- package/docs/content/locales/pt-BR/agent-native-toolkit.mdx +100 -74
- package/docs/content/locales/pt-BR/cloneable-saas.mdx +19 -19
- package/docs/content/locales/pt-BR/components.mdx +12 -2
- package/docs/content/locales/pt-BR/data-programs.mdx +329 -0
- package/docs/content/locales/pt-BR/deployment.mdx +8 -9
- package/docs/content/locales/pt-BR/extensions.mdx +6 -4
- package/docs/content/locales/pt-BR/key-concepts.mdx +8 -11
- package/docs/content/locales/pt-BR/real-time-collaboration.mdx +9 -10
- package/docs/content/locales/zh-CN/agent-native-toolkit.mdx +100 -58
- package/docs/content/locales/zh-CN/cloneable-saas.mdx +19 -19
- package/docs/content/locales/zh-CN/components.mdx +20 -10
- package/docs/content/locales/zh-CN/data-programs.mdx +329 -0
- package/docs/content/locales/zh-CN/deployment.mdx +7 -9
- package/docs/content/locales/zh-CN/extensions.mdx +16 -14
- package/docs/content/locales/zh-CN/key-concepts.mdx +7 -11
- package/docs/content/locales/zh-CN/real-time-collaboration.mdx +10 -11
- package/docs/content/locales/zh-TW/agent-native-toolkit.mdx +100 -58
- package/docs/content/locales/zh-TW/cloneable-saas.mdx +19 -19
- package/docs/content/locales/zh-TW/components.mdx +20 -10
- package/docs/content/locales/zh-TW/data-programs.mdx +329 -0
- package/docs/content/locales/zh-TW/deployment.mdx +7 -9
- package/docs/content/locales/zh-TW/extensions.mdx +16 -14
- package/docs/content/locales/zh-TW/key-concepts.mdx +7 -11
- package/docs/content/locales/zh-TW/real-time-collaboration.mdx +10 -11
- package/docs/content/real-time-collaboration.mdx +10 -11
- package/docs/content/toolkit-app-adapters.mdx +46 -0
- package/docs/content/toolkit-collaboration-ui.mdx +48 -0
- package/docs/content/toolkit-sharing-ui.mdx +33 -0
- package/docs/content/toolkit-shell-hooks.mdx +27 -0
- package/docs/content/toolkit-ui.mdx +69 -0
- package/package.json +6 -2
- package/src/templates/default/.agents/skills/actions/SKILL.md +55 -0
- package/src/templates/default/AGENTS.md +11 -14
- package/src/templates/default/actions/navigate.spec.ts +53 -0
- package/src/templates/default/actions/navigate.ts +1 -1
- package/src/templates/default/app/i18n/ar-SA.ts +0 -1
- package/src/templates/default/app/i18n/de-DE.ts +0 -1
- package/src/templates/default/app/i18n/en-US.ts +0 -1
- package/src/templates/default/app/i18n/es-ES.ts +0 -1
- package/src/templates/default/app/i18n/fr-FR.ts +0 -1
- package/src/templates/default/app/i18n/hi-IN.ts +0 -1
- package/src/templates/default/app/i18n/ja-JP.ts +0 -1
- package/src/templates/default/app/i18n/ko-KR.ts +0 -1
- package/src/templates/default/app/i18n/pt-BR.ts +0 -1
- package/src/templates/default/app/i18n/zh-CN.ts +0 -1
- package/src/templates/default/app/i18n/zh-TW.ts +0 -1
- package/src/templates/default/app/routes/settings.tsx +22 -33
- package/src/templates/headless/.agents/skills/agent-native-docs/SKILL.md +20 -7
- package/src/templates/headless/AGENTS.md +9 -6
- package/src/templates/workspace-core/.agents/skills/actions/SKILL.md +55 -0
- package/src/templates/workspace-core/.agents/skills/data-programs/SKILL.md +128 -0
- package/src/templates/workspace-core/.agents/skills/harness-agents/SKILL.md +10 -4
- package/corpus/templates/design/app/components/design/inspector/InspectorAiActions.tsx +0 -153
- package/corpus/templates/design/app/hooks/useAgentEditRequest.ts +0 -133
- package/corpus/templates/design/app/pages/DesignEditor.tsx +0 -22928
- package/corpus/templates/design/server/lib/figma-import/clipboard.ts +0 -122
- package/corpus/templates/design/server/lib/figma-import/decode.ts +0 -455
- package/corpus/templates/design/server/lib/figma-import/processor.ts +0 -116
- package/corpus/templates/design/server/lib/figma-import/render-html.ts +0 -397
- package/corpus/templates/design/server/lib/figma-import/types.ts +0 -60
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/collab/client.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Client-side hook for collaborative document editing via Yjs.\n *\n * Creates a STABLE Y.Doc per docId that never changes identity. This allows\n * TipTap's Collaboration extension to bind once without editor recreation.\n * Server state is applied to the existing doc when it arrives.\n *\n * Also manages Yjs Awareness for cursor positions and user presence,\n * synced via polling to the server's awareness endpoint.\n *\n * Transport improvements (vs previous version):\n * - Local update POSTs are debounced and coalesced with Y.mergeUpdates (~80ms)\n * to avoid per-keystroke requests. The batch is flushed immediately on\n * visibilitychange/pagehide and before each poll/awareness cycle.\n * - GET state?stateVector= is NOT fetched on every poll cycle. It is fetched:\n * (a) on (re)connect / initial load, (b) when a poll response indicates a\n * gap (version jump > ring-buffer size), (c) after applying an update fails,\n * and (d) as a low-frequency safety net every STATE_VECTOR_FETCH_INTERVAL\n * poll cycles (~15×).\n * - Network errors use exponential backoff with jitter (cap ~15s), reset on\n * success.\n * - SSE fast-path: collab events are received push-style from\n * /_agent-native/events (the framework SSE stream). While SSE is\n * healthy the poll loop relaxes to a slow cadence (10–15s). If SSE is\n * unavailable the 2s poll resumes automatically.\n */\n\nimport { useEffect, useRef, useState, useMemo } from \"react\";\nimport { Awareness } from \"y-protocols/awareness\";\nimport * as Y from \"yjs\";\n\nimport { agentNativePath } from \"../client/api-path.js\";\nimport { subscribeSyncEvents, type SyncEvent } from \"../client/use-db-sync.js\";\nimport { AGENT_CLIENT_ID } from \"./agent-identity.js\";\n\nexport interface CollabUser {\n name: string;\n email: string;\n color: string;\n /** Profile image shown in presence avatars, cursor flags, and edit tags. */\n avatarUrl?: string;\n}\n\nexport interface UseCollaborativeDocOptions {\n /** Document ID to collaborate on. Pass null to disable. */\n docId: string | null;\n /** Poll interval in ms when SSE is unavailable. Default: 2000 */\n pollInterval?: number;\n /** Poll interval in ms while SSE is healthy. Default: 12000 */\n pollIntervalWithSse?: number;\n /** Pause remote update/presence polling while the tab is hidden. Default: true */\n pauseWhenHidden?: boolean;\n /** Base URL for collab endpoints. Default: \"/_agent-native/collab\" */\n baseUrl?: string;\n /** Request source ID for jitter prevention (e.g., tab ID). */\n requestSource?: string;\n /** Current user info for cursor labels. */\n user?: CollabUser;\n}\n\nexport interface UseCollaborativeDocResult {\n /** The Yjs document instance. Stable per docId — never changes identity. */\n ydoc: Y.Doc | null;\n /** Yjs Awareness instance for cursor/presence sync. */\n awareness: Awareness | null;\n /** Whether the initial state is still loading from the server. */\n isLoading: boolean;\n /** Whether the doc is synced with the server. */\n isSynced: boolean;\n /** Active users on this document (from awareness). */\n activeUsers: CollabUser[];\n /** True briefly when the AI agent makes an edit (for presence indicator). */\n agentActive: boolean;\n /** True when the AI agent has an active awareness entry (durable presence). */\n agentPresent: boolean;\n}\n\n// Consistent color palette for user cursors\nconst CURSOR_COLORS = [\n \"#f87171\",\n \"#fb923c\",\n \"#fbbf24\",\n \"#a3e635\",\n \"#34d399\",\n \"#22d3ee\",\n \"#60a5fa\",\n \"#14b8a6\",\n \"#f472b6\",\n \"#e879f9\",\n];\n\n/** Hash a string to a consistent color from the palette. */\nexport function emailToColor(email: string): string {\n let hash = 0;\n for (let i = 0; i < email.length; i++) {\n hash = ((hash << 5) - hash + email.charCodeAt(i)) | 0;\n }\n return CURSOR_COLORS[Math.abs(hash) % CURSOR_COLORS.length];\n}\n\n/** Derive a display name from an email address. */\nexport function emailToName(email: string): string {\n const local = email.split(\"@\")[0] || email;\n return local.charAt(0).toUpperCase() + local.slice(1);\n}\n\nfunction normalizeCollabEmail(email: string): string {\n return email.trim().toLowerCase();\n}\n\nfunction isDocumentHidden(): boolean {\n return (\n typeof document !== \"undefined\" && document.visibilityState === \"hidden\"\n );\n}\n\nexport function dedupeCollabUsersByEmail(users: CollabUser[]): CollabUser[] {\n const byEmail = new Map<string, CollabUser>();\n for (const user of users) {\n const email = normalizeCollabEmail(user.email);\n if (!email || byEmail.has(email)) continue;\n byEmail.set(email, {\n name: user.name || emailToName(email),\n email,\n color: user.color || emailToColor(email),\n });\n }\n return Array.from(byEmail.values());\n}\n\n/**\n * Leader election for applying authoritative external snapshots into a shared\n * collaborative document.\n *\n * When the agent (or a Notion pull, or any full-document rewrite) writes new\n * content to SQL, the open editor reconciles it into the live Y.Doc with\n * `setContent`. If EVERY connected client did that independently, each would\n * diff the same snapshot into the CRDT and the changed region would be inserted\n * N times (concurrent inserts at the same position → duplicated text). So only\n * ONE client — the \"lead\" — applies the snapshot; every other client receives\n * the result through normal Yjs sync.\n *\n * The lead is the present client with the lowest Yjs `clientID`. The agent's\n * awareness entry uses `AGENT_CLIENT_ID` (max int) so it can never be the lead,\n * and a client editing alone is always the lead. This is deterministic across\n * clients with no coordination round-trip.\n */\nexport function isReconcileLeadClient(\n awareness: Awareness | null | undefined,\n localClientId: number | null | undefined,\n): boolean {\n if (localClientId == null) return false;\n if (!awareness) return true; // standalone / tests — act alone\n\n let hasPeer = false;\n let minVisible = localClientId;\n awareness.getStates().forEach((state, clientId) => {\n if (clientId === AGENT_CLIENT_ID) return; // agent never leads\n if (clientId === localClientId) return;\n const s = state as { user?: unknown; visible?: boolean };\n if (!s || !s.user) return; // skip empty/stale entries\n hasPeer = true;\n // Only VISIBLE peers can act; a peer published `visible: false` (backgrounded)\n // is skipped. A peer that hasn't published the field is treated as visible.\n if (s.visible !== false && clientId < minVisible) minVisible = clientId;\n });\n\n // Sole client: always the applier — no other client can duplicate the edit,\n // so single-user agent edits apply even if this tab reports hidden.\n if (!hasPeer) return true;\n\n // With peers present, exactly one VISIBLE client applies (the lowest clientId\n // among visible ones). A backgrounded tab pauses its poll and can't reliably\n // act, so it yields — otherwise an agent edit would never reach the tab the\n // user is actually looking at. The caller re-elects on visibility change.\n const localHidden =\n typeof document !== \"undefined\" && document.visibilityState === \"hidden\";\n if (localHidden) return false;\n return localClientId <= minVisible;\n}\n\nexport interface RemoteAwarenessSnapshot {\n clientId: number;\n state: unknown;\n}\n\nexport function reconcileRemoteAwarenessStates(\n states: Map<number, unknown>,\n localClientId: number,\n remoteStates: RemoteAwarenessSnapshot[],\n): { added: number[]; updated: number[]; removed: number[] } {\n const incoming = new Set<number>();\n const added: number[] = [];\n const updated: number[] = [];\n const removed: number[] = [];\n\n for (const remote of remoteStates) {\n if (\n !Number.isFinite(remote.clientId) ||\n remote.clientId === localClientId\n ) {\n continue;\n }\n incoming.add(remote.clientId);\n const hadState = states.has(remote.clientId);\n states.set(remote.clientId, remote.state);\n (hadState ? updated : added).push(remote.clientId);\n }\n\n for (const clientId of Array.from(states.keys())) {\n if (clientId === localClientId) continue;\n if (incoming.has(clientId)) continue;\n states.delete(clientId);\n removed.push(clientId);\n }\n\n return { added, updated, removed };\n}\n\n// Base64 helpers\nfunction uint8ArrayToBase64(arr: Uint8Array): string {\n let binary = \"\";\n for (let i = 0; i < arr.length; i++) {\n binary += String.fromCharCode(arr[i]);\n }\n return btoa(binary);\n}\n\nfunction base64ToUint8Array(b64: string): Uint8Array {\n const binary = atob(b64);\n const arr = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n arr[i] = binary.charCodeAt(i);\n }\n return arr;\n}\n\n/** Debounce delay for coalescing local Yjs update POSTs (ms). */\nconst UPDATE_DEBOUNCE_MS = 80;\n\n/** Fetch state-vector every N poll cycles as a low-frequency safety net. */\nconst STATE_VECTOR_FETCH_INTERVAL = 15;\n\n/** Poll ring-buffer size on the server (MAX_BUFFER in poll.ts). */\nconst POLL_RING_BUFFER_SIZE = 200;\n\n/** Exponential backoff: base delay (ms), multiplier, cap (ms). */\nconst BACKOFF_BASE_MS = 500;\nconst BACKOFF_MAX_MS = 15_000;\n\nfunction calcBackoff(consecutiveErrors: number): number {\n const exp = Math.min(consecutiveErrors, 10);\n const delay = BACKOFF_BASE_MS * Math.pow(2, exp);\n // Add jitter: ±25%\n const jitter = delay * 0.25 * (Math.random() * 2 - 1);\n return Math.min(delay + jitter, BACKOFF_MAX_MS);\n}\n\n// ---------------------------------------------------------------------------\n// Fast awareness helper — throttled per (docId, ydocId) pair so multiple\n// setLocalStateField calls within a 150ms window are coalesced into one POST.\n// ---------------------------------------------------------------------------\n\nconst _awarenessThrottleTimers = new Map<\n string,\n ReturnType<typeof setTimeout>\n>();\n\nfunction scheduleAwarenessPush(\n baseUrl: string,\n docId: string,\n clientId: number,\n getState: () => Record<string, unknown> | null,\n): void {\n if (typeof window === \"undefined\") return;\n const key = `${docId}::${clientId}`;\n if (_awarenessThrottleTimers.has(key)) return; // already scheduled\n\n const timer = setTimeout(() => {\n _awarenessThrottleTimers.delete(key);\n const state = getState();\n fetch(`${baseUrl}/${docId}/awareness`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n clientId,\n state: state ? JSON.stringify(state) : null,\n }),\n }).catch(() => {}); // best-effort; poll cycle is the baseline fallback\n }, 150);\n\n _awarenessThrottleTimers.set(key, timer);\n}\n\nexport function useCollaborativeDoc(\n options: UseCollaborativeDocOptions,\n): UseCollaborativeDocResult {\n const {\n docId,\n pollInterval = 2000,\n pollIntervalWithSse = 12000,\n pauseWhenHidden = true,\n baseUrl = agentNativePath(\"/_agent-native/collab\"),\n requestSource,\n user,\n } = options;\n\n // Stable Y.Doc per docId\n const ydoc = useMemo(() => {\n if (!docId) return null;\n return new Y.Doc();\n }, [docId]);\n\n // Stable Awareness per ydoc\n const awareness = useMemo(() => {\n if (!ydoc) return null;\n return new Awareness(ydoc);\n }, [ydoc]);\n\n const [isLoading, setIsLoading] = useState(!!docId);\n const [isSynced, setIsSynced] = useState(false);\n const [activeUsers, setActiveUsers] = useState<CollabUser[]>([]);\n const [agentActive, setAgentActive] = useState(false);\n const [agentPresent, setAgentPresent] = useState(false);\n // Set when the initial state fetch returns 404/403 — stops the awareness\n // poll so we don't spam the console with errors against a doc that doesn't\n // exist or isn't accessible.\n const [docMissing, setDocMissing] = useState(false);\n const agentTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const pollVersionRef = useRef(0);\n\n // Set local awareness state (user info for cursor labels). Also publish this\n // tab's visibility so peers can elect a VISIBLE client to apply external\n // snapshots (see isReconcileLeadClient) — a backgrounded tab pauses its poll\n // and must not hold that role.\n useEffect(() => {\n if (!awareness || !user) return;\n awareness.setLocalStateField(\"user\", {\n name: user.name,\n email: user.email,\n color: user.color,\n });\n awareness.setLocalStateField(\"visible\", !isDocumentHidden());\n }, [awareness, user?.name, user?.email, user?.color]);\n\n // Fast awareness push: whenever local state changes (e.g. cursor moves,\n // setPresence() calls), schedule a throttled POST so peers receive updates\n // at ~150ms instead of waiting for the next 2s poll cycle. The poll cycle\n // remains the authoritative baseline (cursors degrade gracefully without SSE).\n useEffect(() => {\n if (!awareness || !ydoc || !docId || !user) return;\n const clientId = ydoc.clientID;\n\n const onLocalStateChange = () => {\n scheduleAwarenessPush(\n baseUrl,\n docId,\n clientId,\n () => awareness.getLocalState() as Record<string, unknown> | null,\n );\n };\n\n // awareness emits \"change\" for local state changes too (when origin is \"local\").\n awareness.on(\"change\", onLocalStateChange);\n return () => {\n awareness.off(\"change\", onLocalStateChange);\n };\n }, [awareness, ydoc, docId, baseUrl, user]);\n\n // Track active users from awareness changes\n useEffect(() => {\n if (!awareness) return;\n\n const updateUsers = () => {\n const users: CollabUser[] = [];\n let hasAgent = false;\n awareness.getStates().forEach((state, clientId) => {\n if (clientId === ydoc?.clientID) return; // Skip self\n if (state.user) {\n users.push(state.user as CollabUser);\n if ((state.user as CollabUser).email === \"agent@system\") {\n hasAgent = true;\n }\n }\n });\n setActiveUsers(dedupeCollabUsersByEmail(users));\n setAgentPresent(hasAgent);\n };\n\n awareness.on(\"change\", updateUsers);\n return () => {\n awareness.off(\"change\", updateUsers);\n };\n }, [awareness, ydoc]);\n\n // Clean up on unmount or docId change\n useEffect(() => {\n return () => {\n awareness?.destroy();\n ydoc?.destroy();\n };\n }, [ydoc, awareness]);\n\n // Fetch server state and apply to existing doc\n useEffect(() => {\n if (!ydoc || !docId) {\n setIsLoading(false);\n return;\n }\n\n let cancelled = false;\n setIsLoading(true);\n setIsSynced(false);\n setDocMissing(false);\n\n fetch(`${baseUrl}/${docId}/state`)\n .then(async (res) => {\n if (cancelled) return;\n if (res.status === 404 || res.status === 403) {\n setDocMissing(true);\n setIsLoading(false);\n setIsSynced(true);\n return;\n }\n const data = (await res.json().catch(() => null)) as {\n state?: string;\n } | null;\n if (data?.state) {\n const binary = base64ToUint8Array(data.state);\n if (binary.length > 4) {\n Y.applyUpdate(ydoc, binary, \"remote\");\n }\n }\n setIsLoading(false);\n setIsSynced(true);\n })\n .catch(() => {\n if (cancelled) return;\n setIsLoading(false);\n setIsSynced(true);\n });\n\n return () => {\n cancelled = true;\n };\n }, [ydoc, docId, baseUrl]);\n\n // Send local updates to server — debounced and coalesced with Y.mergeUpdates.\n //\n // Instead of firing one POST per Yjs update (one per keystroke), we accumulate\n // updates in a buffer for UPDATE_DEBOUNCE_MS then merge them into a single\n // request. The buffer is also flushed immediately on visibilitychange/pagehide\n // and before each poll/awareness cycle so we don't hold stale local state.\n useEffect(() => {\n if (!ydoc || !docId || docMissing) return;\n\n let pendingUpdates: Uint8Array[] = [];\n let flushTimer: ReturnType<typeof setTimeout> | null = null;\n\n const flushPendingUpdates = (keepalive = false) => {\n if (flushTimer) {\n clearTimeout(flushTimer);\n flushTimer = null;\n }\n if (pendingUpdates.length === 0) return;\n const toSend = pendingUpdates;\n pendingUpdates = [];\n\n const merged = toSend.length === 1 ? toSend[0] : Y.mergeUpdates(toSend);\n fetch(`${baseUrl}/${docId}/update`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n update: uint8ArrayToBase64(merged),\n requestSource,\n }),\n ...(keepalive ? { keepalive: true } : {}),\n }).catch(() => {});\n };\n\n // Expose flush to the poll loop via a ref so it can flush before each cycle.\n // We store the flusher in a closure-captured variable; the poll effect\n // below reads it through the shared `pendingFlushRef`.\n (ydoc as any).__collabFlush = flushPendingUpdates;\n\n const handler = (update: Uint8Array, origin: unknown) => {\n if (origin === \"remote\") return;\n pendingUpdates.push(update);\n if (flushTimer) clearTimeout(flushTimer);\n flushTimer = setTimeout(flushPendingUpdates, UPDATE_DEBOUNCE_MS);\n };\n\n const handlePageHide = () => {\n flushPendingUpdates(true /* keepalive */);\n };\n\n ydoc.on(\"update\", handler);\n if (typeof window !== \"undefined\") {\n window.addEventListener(\"pagehide\", handlePageHide);\n }\n\n return () => {\n ydoc.off(\"update\", handler);\n delete (ydoc as any).__collabFlush;\n if (typeof window !== \"undefined\") {\n window.removeEventListener(\"pagehide\", handlePageHide);\n }\n // Flush any remaining updates on teardown\n flushPendingUpdates(true);\n };\n }, [ydoc, docId, baseUrl, requestSource, docMissing]);\n\n // Poll for remote doc updates + awareness sync, with SSE fast-path.\n useEffect(() => {\n if (!ydoc || !docId || docMissing) return;\n // Non-null capture: null branch returned early above; async closures lose\n // the narrowing on the outer ydoc variable.\n const doc: Y.Doc = ydoc;\n\n let stopped = false;\n let timer: ReturnType<typeof setTimeout> | null = null;\n let consecutiveErrors = 0;\n let pollCycleCount = 0;\n // Track the last version we successfully polled. Used to detect ring-buffer\n // overflow (version gap larger than the ring buffer).\n let lastPolledVersion = pollVersionRef.current;\n\n // SSE connection state. When SSE is healthy, poll interval is relaxed.\n let sseActive = false;\n\n // ── SSE fast-path ────────────────────────────────────────────────\n // Subscribe to the SHARED framework transport for /_agent-native/events\n // instead of opening a dedicated EventSource per collab doc. A tab holds\n // exactly one SSE connection regardless of how many docs are mounted —\n // extra streams eat the browser's per-origin connection budget and can\n // starve regular data fetches (worst on HTTP/1.1 dev servers).\n // Collab update events arrive push-style; we apply them immediately,\n // avoiding ~2s polling latency for peer edits.\n //\n // NOTE: SSE events are subject to the same server-side access scoping as\n // polling — the server only pushes events that canSeeChangeForUser allows.\n // The server tags collab events with owner/orgId (security commit).\n const handleSharedEvent = (change: SyncEvent) => {\n if (\n change.source === \"collab\" &&\n change.docId === docId &&\n typeof change.update === \"string\"\n ) {\n if (requestSource && change.requestSource === requestSource) return;\n try {\n Y.applyUpdate(doc, base64ToUint8Array(change.update), \"remote\");\n } catch {\n // Malformed update — trigger state-vector fetch on next poll\n }\n\n if (change.requestSource === \"agent\") {\n setAgentActive(true);\n if (agentTimerRef.current) clearTimeout(agentTimerRef.current);\n agentTimerRef.current = setTimeout(() => setAgentActive(false), 3000);\n }\n }\n\n // Keep pollVersionRef updated from shared-transport events so the poll\n // loop starts from the right version when SSE drops.\n if (typeof change.version === \"number\") {\n pollVersionRef.current = Math.max(\n pollVersionRef.current,\n change.version,\n );\n }\n };\n\n const unsubscribeSharedEvents = subscribeSyncEvents({\n onEvents: (events) => {\n if (stopped) return;\n for (const change of events) handleSharedEvent(change);\n },\n onSseStateChange: (connected) => {\n sseActive = connected;\n if (connected) consecutiveErrors = 0;\n },\n pauseWhenHidden,\n });\n\n // ── Poll loop ───────────────────────────────────────────────────\n function getActivePollInterval(): number {\n return sseActive ? pollIntervalWithSse : pollInterval;\n }\n\n function schedulePoll() {\n if (stopped) return;\n if (pauseWhenHidden && isDocumentHidden()) return;\n timer = setTimeout(poll, getActivePollInterval());\n }\n\n async function fetchStateVector(): Promise<void> {\n try {\n const stateVector = uint8ArrayToBase64(Y.encodeStateVector(doc));\n const stateRes = await fetch(\n `${baseUrl}/${docId}/state?stateVector=${encodeURIComponent(stateVector)}`,\n );\n if (stateRes.ok) {\n const stateData = (await stateRes.json().catch(() => null)) as {\n state?: string;\n } | null;\n if (stateData?.state) {\n const binary = base64ToUint8Array(stateData.state);\n if (binary.length > 2) {\n Y.applyUpdate(doc, binary, \"remote\");\n }\n }\n }\n } catch {\n // Non-fatal; the next poll cycle will retry\n }\n }\n\n async function poll() {\n if (stopped) return;\n\n // Flush any pending local updates before polling so the server has the\n // latest state before we read remote changes.\n const flush = (ydoc as any).__collabFlush as\n | ((keepalive?: boolean) => void)\n | undefined;\n flush?.();\n\n try {\n const res = await fetch(\n agentNativePath(\n `/_agent-native/poll?since=${pollVersionRef.current}`,\n ),\n );\n if (!res.ok) throw new Error(\"HTTP \" + res.status);\n\n const data = await res.json();\n const { version, events } = data as {\n version: number;\n events: Array<{\n source: string;\n docId?: string;\n update?: string;\n requestSource?: string;\n }>;\n };\n\n // Detect ring-buffer overflow: if the version jumped by more than the\n // ring buffer size, some events were evicted and we need a state-vector\n // fetch to reconcile the gap.\n const versionGap = version - lastPolledVersion;\n const hadGap = versionGap > POLL_RING_BUFFER_SIZE;\n\n for (const evt of events) {\n if (evt.source === \"collab\" && evt.docId === docId && evt.update) {\n if (requestSource && evt.requestSource === requestSource) continue;\n try {\n Y.applyUpdate(doc, base64ToUint8Array(evt.update), \"remote\");\n } catch {\n // Failed to apply — fetch full state-vector below\n await fetchStateVector();\n }\n\n if (evt.requestSource === \"agent\") {\n setAgentActive(true);\n if (agentTimerRef.current) clearTimeout(agentTimerRef.current);\n agentTimerRef.current = setTimeout(\n () => setAgentActive(false),\n 3000,\n );\n }\n }\n }\n\n pollVersionRef.current = version;\n lastPolledVersion = version;\n pollCycleCount++;\n consecutiveErrors = 0;\n\n // Fetch state-vector only when needed:\n // 1. Ring-buffer overflow detected (missed events).\n // 2. Low-frequency safety net every STATE_VECTOR_FETCH_INTERVAL cycles.\n // 3. NOT on every cycle (the previous behavior causing 3 requests/cycle).\n const shouldFetchStateVector =\n hadGap || pollCycleCount % STATE_VECTOR_FETCH_INTERVAL === 0;\n\n if (shouldFetchStateVector) {\n await fetchStateVector();\n }\n\n // Sync awareness (cursor positions)\n if (awareness) {\n const localState = awareness.getLocalState();\n if (localState) {\n try {\n const awarenessRes = await fetch(\n `${baseUrl}/${docId}/awareness`,\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n clientId: doc.clientID,\n state: JSON.stringify(localState),\n }),\n },\n );\n if (awarenessRes.ok) {\n const awarenessData = await awarenessRes.json();\n const remoteStates: RemoteAwarenessSnapshot[] = [];\n for (const remote of awarenessData.states || []) {\n try {\n const remoteState = JSON.parse(remote.state);\n remoteStates.push({\n clientId: Number(remote.clientId),\n state: remoteState,\n });\n } catch {\n // Invalid state — skip\n }\n }\n const changes = reconcileRemoteAwarenessStates(\n awareness.getStates() as Map<number, unknown>,\n doc.clientID,\n remoteStates,\n );\n if (\n changes.added.length ||\n changes.updated.length ||\n changes.removed.length\n ) {\n awareness.emit(\"change\", [changes, \"remote\"]);\n }\n }\n } catch {\n // Awareness sync failure is non-fatal\n }\n }\n }\n } catch {\n // Network error — exponential backoff\n consecutiveErrors++;\n const backoff = calcBackoff(consecutiveErrors);\n if (!stopped) {\n timer = setTimeout(poll, backoff);\n return;\n }\n }\n\n schedulePoll();\n }\n\n function pollNow() {\n if (pauseWhenHidden && isDocumentHidden()) return;\n if (timer) {\n clearTimeout(timer);\n timer = null;\n }\n void poll();\n }\n\n // Publish this tab's visibility to peers. A hidden tab pauses its poll, so\n // we push the state immediately (keepalive) instead of waiting for the next\n // cycle — otherwise peers keep treating a backgrounded tab as the visible\n // lead and an agent edit never lands on the tab the user is actually viewing.\n function publishVisibility(visible: boolean) {\n if (!awareness) return;\n awareness.setLocalStateField(\"visible\", visible);\n const localState = awareness.getLocalState();\n if (!localState) return;\n fetch(`${baseUrl}/${docId}/awareness`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n clientId: doc.clientID,\n state: JSON.stringify(localState),\n }),\n keepalive: true,\n }).catch(() => {});\n }\n\n function handleVisibilityChange() {\n const visible = document.visibilityState === \"visible\";\n publishVisibility(visible);\n if (visible) {\n // Also flush any pending updates when coming back into view\n const flush = (ydoc as any).__collabFlush as\n | ((keepalive?: boolean) => void)\n | undefined;\n flush?.();\n pollNow();\n } else if (pauseWhenHidden && timer) {\n clearTimeout(timer);\n timer = null;\n }\n }\n\n if (!pauseWhenHidden || !isDocumentHidden()) {\n void poll();\n }\n window.addEventListener(\"focus\", pollNow);\n document.addEventListener(\"visibilitychange\", handleVisibilityChange);\n\n return () => {\n stopped = true;\n if (timer) clearTimeout(timer);\n unsubscribeSharedEvents();\n window.removeEventListener(\"focus\", pollNow);\n document.removeEventListener(\"visibilitychange\", handleVisibilityChange);\n };\n }, [\n ydoc,\n awareness,\n docId,\n pollInterval,\n pollIntervalWithSse,\n pauseWhenHidden,\n requestSource,\n baseUrl,\n docMissing,\n ]);\n\n // SSE fast-path for awareness: listen on the SHARED framework transport and\n // apply any awareness-change events immediately so peers receive cursor\n // moves push-style without waiting for the next poll cycle.\n // Polling fallback keeps working when SSE is unavailable. Reconnection and\n // focus/visibility handling live inside the shared transport.\n useEffect(() => {\n if (!ydoc || !docId || !awareness) {\n return;\n }\n // Non-null captures for closures: null branches returned early above.\n const capturedYdoc = ydoc;\n const capturedAwareness = awareness;\n let stopped = false;\n\n const applyAwarenessEvent = (data: SyncEvent) => {\n if (\n data.source !== \"awareness\" ||\n data.type !== \"awareness-change\" ||\n data.docId !== docId\n ) {\n return;\n }\n const states = Array.isArray(data.states)\n ? (data.states as Array<{ clientId: number; state: string }>)\n : [];\n const remoteStates: RemoteAwarenessSnapshot[] = [];\n for (const remote of states) {\n try {\n remoteStates.push({\n clientId: Number(remote.clientId),\n state: JSON.parse(remote.state),\n });\n } catch {\n // Invalid state entry — skip\n }\n }\n const changes = reconcileRemoteAwarenessStates(\n capturedAwareness.getStates() as Map<number, unknown>,\n capturedYdoc.clientID,\n remoteStates,\n );\n if (\n changes.added.length ||\n changes.updated.length ||\n changes.removed.length\n ) {\n capturedAwareness.emit(\"change\", [changes, \"remote\"]);\n }\n };\n\n const unsubscribe = subscribeSyncEvents({\n onEvents: (events) => {\n if (stopped) return;\n for (const data of events) applyAwarenessEvent(data);\n },\n });\n\n return () => {\n stopped = true;\n unsubscribe();\n };\n }, [ydoc, docId, awareness]);\n\n return {\n ydoc,\n awareness,\n isLoading,\n isSynced,\n activeUsers,\n agentActive,\n agentPresent,\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/collab/client.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Client-side hook for collaborative document editing via Yjs.\n *\n * Creates a STABLE Y.Doc per docId that never changes identity. This allows\n * TipTap's Collaboration extension to bind once without editor recreation.\n * Server state is applied to the existing doc when it arrives.\n *\n * Also manages Yjs Awareness for cursor positions and user presence,\n * synced via polling to the server's awareness endpoint.\n *\n * Connection sharing: connections live in a module-level, ref-counted registry\n * keyed by docId (mirroring the SyncTransport registry in use-db-sync.ts).\n * Every `useCollaborativeDoc` mount for the same docId attaches to ONE shared\n * connection — one Y.Doc, one Awareness, one state fetch, one poll loop, one\n * awareness POST cycle — instead of each hook instance opening an independent\n * connection and doubling all collab traffic (e.g. a presence bar and the\n * editor mounting the hook for the same doc). The first subscriber starts the\n * connection; the last one leaving tears it down after a short linger so\n * StrictMode double-mounts and rapid unmount/remounts don't thrash the doc.\n *\n * Transport improvements (vs previous version):\n * - Local update POSTs are debounced and coalesced with Y.mergeUpdates (~80ms)\n * to avoid per-keystroke requests. The batch is flushed immediately on\n * visibilitychange/pagehide and before each poll/awareness cycle.\n * - GET state?stateVector= is NOT fetched on every poll cycle. It is fetched:\n * (a) on (re)connect / initial load, (b) when a poll response indicates a\n * gap (version jump > ring-buffer size), (c) after applying an update fails,\n * and (d) as a low-frequency safety net every STATE_VECTOR_FETCH_INTERVAL\n * poll cycles (~15×).\n * - Network errors use exponential backoff with jitter (cap ~15s), reset on\n * success.\n * - SSE fast-path: collab events are received push-style from\n * /_agent-native/events (the framework SSE stream). While SSE is\n * healthy the poll loop relaxes to a slow cadence (10–15s). If SSE is\n * unavailable the 2s poll resumes automatically.\n */\n\nimport {\n dedupeCollabUsersByEmail,\n type CollabUser,\n} from \"@agent-native/toolkit/collab-ui\";\nimport { useEffect, useMemo, useState } from \"react\";\nimport { Awareness } from \"y-protocols/awareness\";\nimport * as Y from \"yjs\";\n\nimport { agentNativePath } from \"../client/api-path.js\";\nimport { subscribeSyncEvents, type SyncEvent } from \"../client/use-db-sync.js\";\nimport { AGENT_CLIENT_ID } from \"./agent-identity.js\";\n\nexport {\n dedupeCollabUsersByEmail,\n emailToColor,\n emailToName,\n type CollabUser,\n} from \"@agent-native/toolkit/collab-ui\";\n\nexport interface UseCollaborativeDocOptions {\n /** Document ID to collaborate on. Pass null to disable. */\n docId: string | null;\n /** Poll interval in ms when SSE is unavailable. Default: 2000 */\n pollInterval?: number;\n /** Poll interval in ms while SSE is healthy. Default: 12000 */\n pollIntervalWithSse?: number;\n /** Pause remote update/presence polling while the tab is hidden. Default: true */\n pauseWhenHidden?: boolean;\n /** Base URL for collab endpoints. Default: \"/_agent-native/collab\" */\n baseUrl?: string;\n /** Request source ID for jitter prevention (e.g., tab ID). */\n requestSource?: string;\n /** Current user info for cursor labels. */\n user?: CollabUser;\n}\n\nexport interface UseCollaborativeDocResult {\n /** The Yjs document instance. Stable per docId — never changes identity. */\n ydoc: Y.Doc | null;\n /** Yjs Awareness instance for cursor/presence sync. */\n awareness: Awareness | null;\n /** Whether the initial state is still loading from the server. */\n isLoading: boolean;\n /** Whether the doc is synced with the server. */\n isSynced: boolean;\n /** Active users on this document (from awareness). */\n activeUsers: CollabUser[];\n /** True briefly when the AI agent makes an edit (for presence indicator). */\n agentActive: boolean;\n /** True when the AI agent has an active awareness entry (durable presence). */\n agentPresent: boolean;\n}\n\nfunction isDocumentHidden(): boolean {\n return (\n typeof document !== \"undefined\" && document.visibilityState === \"hidden\"\n );\n}\n\n/**\n * Leader election for applying authoritative external snapshots into a shared\n * collaborative document.\n *\n * When the agent (or a Notion pull, or any full-document rewrite) writes new\n * content to SQL, the open editor reconciles it into the live Y.Doc with\n * `setContent`. If EVERY connected client did that independently, each would\n * diff the same snapshot into the CRDT and the changed region would be inserted\n * N times (concurrent inserts at the same position → duplicated text). So only\n * ONE client — the \"lead\" — applies the snapshot; every other client receives\n * the result through normal Yjs sync.\n *\n * The lead is the present client with the lowest Yjs `clientID`. The agent's\n * awareness entry uses `AGENT_CLIENT_ID` (max int) so it can never be the lead,\n * and a client editing alone is always the lead. This is deterministic across\n * clients with no coordination round-trip.\n */\nexport function isReconcileLeadClient(\n awareness: Awareness | null | undefined,\n localClientId: number | null | undefined,\n): boolean {\n if (localClientId == null) return false;\n if (!awareness) return true; // standalone / tests — act alone\n\n let hasPeer = false;\n let minVisible = localClientId;\n awareness.getStates().forEach((state, clientId) => {\n if (clientId === AGENT_CLIENT_ID) return; // agent never leads\n if (clientId === localClientId) return;\n const s = state as { user?: unknown; visible?: boolean };\n if (!s || !s.user) return; // skip empty/stale entries\n hasPeer = true;\n // Only VISIBLE peers can act; a peer published `visible: false` (backgrounded)\n // is skipped. A peer that hasn't published the field is treated as visible.\n if (s.visible !== false && clientId < minVisible) minVisible = clientId;\n });\n\n // Sole client: always the applier — no other client can duplicate the edit,\n // so single-user agent edits apply even if this tab reports hidden.\n if (!hasPeer) return true;\n\n // With peers present, exactly one VISIBLE client applies (the lowest clientId\n // among visible ones). A backgrounded tab pauses its poll and can't reliably\n // act, so it yields — otherwise an agent edit would never reach the tab the\n // user is actually looking at. The caller re-elects on visibility change.\n const localHidden =\n typeof document !== \"undefined\" && document.visibilityState === \"hidden\";\n if (localHidden) return false;\n return localClientId <= minVisible;\n}\n\nexport interface RemoteAwarenessSnapshot {\n clientId: number;\n state: unknown;\n}\n\nexport function reconcileRemoteAwarenessStates(\n states: Map<number, unknown>,\n localClientId: number,\n remoteStates: RemoteAwarenessSnapshot[],\n): { added: number[]; updated: number[]; removed: number[] } {\n const incoming = new Set<number>();\n const added: number[] = [];\n const updated: number[] = [];\n const removed: number[] = [];\n\n for (const remote of remoteStates) {\n if (\n !Number.isFinite(remote.clientId) ||\n remote.clientId === localClientId\n ) {\n continue;\n }\n incoming.add(remote.clientId);\n const hadState = states.has(remote.clientId);\n states.set(remote.clientId, remote.state);\n (hadState ? updated : added).push(remote.clientId);\n }\n\n for (const clientId of Array.from(states.keys())) {\n if (clientId === localClientId) continue;\n if (incoming.has(clientId)) continue;\n states.delete(clientId);\n removed.push(clientId);\n }\n\n return { added, updated, removed };\n}\n\n// Base64 helpers\nfunction uint8ArrayToBase64(arr: Uint8Array): string {\n let binary = \"\";\n for (let i = 0; i < arr.length; i++) {\n binary += String.fromCharCode(arr[i]);\n }\n return btoa(binary);\n}\n\nfunction base64ToUint8Array(b64: string): Uint8Array {\n const binary = atob(b64);\n const arr = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n arr[i] = binary.charCodeAt(i);\n }\n return arr;\n}\n\n/** Debounce delay for coalescing local Yjs update POSTs (ms). */\nconst UPDATE_DEBOUNCE_MS = 80;\n\n/** Fetch state-vector every N poll cycles as a low-frequency safety net. */\nconst STATE_VECTOR_FETCH_INTERVAL = 15;\n\n/** Poll ring-buffer size on the server (MAX_BUFFER in poll.ts). */\nconst POLL_RING_BUFFER_SIZE = 200;\n\n/** Exponential backoff: base delay (ms), multiplier, cap (ms). */\nconst BACKOFF_BASE_MS = 500;\nconst BACKOFF_MAX_MS = 15_000;\n\nfunction calcBackoff(consecutiveErrors: number): number {\n const exp = Math.min(consecutiveErrors, 10);\n const delay = BACKOFF_BASE_MS * Math.pow(2, exp);\n // Add jitter: ±25%\n const jitter = delay * 0.25 * (Math.random() * 2 - 1);\n return Math.min(delay + jitter, BACKOFF_MAX_MS);\n}\n\n// ---------------------------------------------------------------------------\n// Fast awareness helper — throttled per (docId, ydocId) pair so multiple\n// setLocalStateField calls within a 150ms window are coalesced into one POST.\n// ---------------------------------------------------------------------------\n\nconst _awarenessThrottleTimers = new Map<\n string,\n ReturnType<typeof setTimeout>\n>();\n\nfunction scheduleAwarenessPush(\n baseUrl: string,\n docId: string,\n clientId: number,\n getState: () => Record<string, unknown> | null,\n): void {\n if (typeof window === \"undefined\") return;\n const key = `${docId}::${clientId}`;\n if (_awarenessThrottleTimers.has(key)) return; // already scheduled\n\n const timer = setTimeout(() => {\n _awarenessThrottleTimers.delete(key);\n const state = getState();\n fetch(`${baseUrl}/${docId}/awareness`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n clientId,\n state: state ? JSON.stringify(state) : null,\n }),\n }).catch(() => {}); // best-effort; poll cycle is the baseline fallback\n }, 150);\n\n _awarenessThrottleTimers.set(key, timer);\n}\n\n// ---------------------------------------------------------------------------\n// Shared per-docId collab connection\n//\n// One CollabDocConnection per (baseUrl, docId) pair is held in a module-level\n// registry (the same pattern as SyncTransport in use-db-sync.ts). Every\n// `useCollaborativeDoc` mount for a docId subscribes to the shared connection,\n// so a tab runs exactly ONE state fetch, ONE poll fallback loop, and ONE\n// awareness POST cycle per document no matter how many components mount the\n// hook (e.g. a presence bar + the editor for the same doc).\n//\n// Lifecycle: the connection is created on first render that needs it (the\n// Y.Doc must exist during render so TipTap can bind on mount), starts its\n// network activity when the first subscriber attaches, and is disposed a short\n// linger after the last subscriber detaches. The linger keeps StrictMode's\n// mount→unmount→mount and rapid route remounts from destroying and refetching\n// the doc, and doubles as the cleanup path for connections created by a render\n// that React later discarded (no subscriber ever attaches).\n// ---------------------------------------------------------------------------\n\n/**\n * Shared reactive state each subscriber mirrors into its own React state.\n * Replaced immutably on every change so hooks can bail out on identity.\n */\ninterface CollabDocSnapshot {\n isLoading: boolean;\n isSynced: boolean;\n activeUsers: CollabUser[];\n agentActive: boolean;\n agentPresent: boolean;\n}\n\ninterface CollabDocSubscription {\n /** Requested poll interval; the connection uses the MIN across subscribers. */\n pollInterval: number;\n /** Requested relaxed interval while SSE is healthy (MIN across subscribers). */\n pollIntervalWithSse: number;\n /**\n * Whether this subscriber wants polling paused while the tab is hidden.\n * The connection pauses only when ALL subscribers request it.\n */\n pauseWhenHidden: boolean;\n /**\n * Echo-suppression tag. The connection adopts the first defined value and\n * uses it for BOTH tagging outgoing updates and filtering incoming echoes,\n * so suppression stays self-consistent even when subscribers pass different\n * per-tab IDs (all values identify the same tab).\n */\n requestSource?: string;\n onSnapshot: (snapshot: CollabDocSnapshot) => void;\n}\n\nconst EMPTY_SNAPSHOT: CollabDocSnapshot = Object.freeze({\n isLoading: false,\n isSynced: false,\n activeUsers: [],\n agentActive: false,\n agentPresent: false,\n});\n\n/**\n * How long a connection with zero subscribers lingers before disposal.\n * Long enough to absorb StrictMode double-mounts and route-level remounts\n * (which would otherwise destroy the Y.Doc, refetch server state, and lose\n * echo-suppression context), short enough that navigating away stops the\n * doc's traffic promptly.\n */\nconst DISPOSE_LINGER_MS = 1000;\n\nclass CollabDocConnection {\n readonly ydoc: Y.Doc;\n readonly awareness: Awareness;\n /** Immutable snapshot of the shared reactive state (replaced on change). */\n snapshot: CollabDocSnapshot;\n disposed = false;\n\n private subscribers = new Map<symbol, CollabDocSubscription>();\n private disposeTimer: ReturnType<typeof setTimeout> | null = null;\n private started = false;\n private docMissing = false;\n private requestSource: string | undefined;\n private lastSetUser: CollabUser | null = null;\n\n // Local-update batching (debounced + coalesced with Y.mergeUpdates).\n private pendingUpdates: Uint8Array[] = [];\n private flushTimer: ReturnType<typeof setTimeout> | null = null;\n private updateHandlerAttached = false;\n\n // Poll loop + SSE fast path.\n private syncActive = false;\n private pollTimer: ReturnType<typeof setTimeout> | null = null;\n private consecutiveErrors = 0;\n private pollCycleCount = 0;\n private pollVersion = 0;\n private lastPolledVersion = 0;\n private sseActive = false;\n private sseSubscribedWithPause: boolean | null = null;\n private unsubscribeCollabEvents: (() => void) | null = null;\n private unsubscribeAwarenessEvents: (() => void) | null = null;\n private agentTimer: ReturnType<typeof setTimeout> | null = null;\n\n constructor(\n readonly docId: string,\n private readonly baseUrl: string,\n /**\n * Detached connections are created for SSR renders only: a per-hook\n * Y.Doc/Awareness with no registry entry and no network activity\n * (matching the previous per-hook behavior on the server). They are\n * never started and are reclaimed by GC with the render.\n */\n readonly detached = false,\n ) {\n this.ydoc = new Y.Doc();\n this.awareness = new Awareness(this.ydoc);\n this.snapshot = {\n isLoading: true,\n isSynced: false,\n activeUsers: [],\n agentActive: false,\n agentPresent: false,\n };\n\n // Track active users / agent presence from awareness changes, and drive\n // the fast (throttled) awareness push once a local user is published.\n this.awareness.on(\"change\", this.handleAwarenessChange);\n\n // Orphan guard: the connection is created during render (the Y.Doc must\n // exist before mount), so a discarded render can create one that never\n // gets a subscriber. The linger timer disposes it; the first `add()`\n // cancels the timer.\n if (!detached) this.scheduleDispose();\n }\n\n private get registryKey(): string {\n return collabRegistryKey(this.docId, this.baseUrl);\n }\n\n // -------------------------------------------------------------------------\n // Subscriber management (ref-counting)\n // -------------------------------------------------------------------------\n\n add(id: symbol, sub: CollabDocSubscription): void {\n this.subscribers.set(id, sub);\n if (this.disposeTimer) {\n clearTimeout(this.disposeTimer);\n this.disposeTimer = null;\n }\n // Adopt the first defined echo-suppression tag for the connection's\n // lifetime (see CollabDocSubscription.requestSource).\n if (!this.requestSource && sub.requestSource) {\n this.requestSource = sub.requestSource;\n }\n if (!this.started) {\n this.started = true;\n this.start();\n } else {\n // A joining subscriber can change the effective poll cadence or the\n // pause-when-hidden aggregate; pick both up without waiting a cycle.\n this.resubscribeCollabEventsIfPauseChanged();\n this.reschedulePoll();\n }\n }\n\n remove(id: symbol): void {\n this.subscribers.delete(id);\n if (this.subscribers.size === 0) {\n this.scheduleDispose();\n } else {\n this.resubscribeCollabEventsIfPauseChanged();\n this.reschedulePoll();\n }\n }\n\n private scheduleDispose(): void {\n if (this.disposeTimer) clearTimeout(this.disposeTimer);\n this.disposeTimer = setTimeout(() => {\n this.disposeTimer = null;\n this.dispose();\n }, DISPOSE_LINGER_MS);\n }\n\n /**\n * Tear the connection down: stop all loops and listeners, flush any pending\n * local updates, clear awareness local state (via destroy), and destroy the\n * Y.Doc. Also used by the test-only registry reset. @internal\n */\n dispose(): void {\n if (this.disposed) return;\n this.disposed = true;\n if (this.disposeTimer) {\n clearTimeout(this.disposeTimer);\n this.disposeTimer = null;\n }\n this.stopSync();\n this.unsubscribeAwarenessEvents?.();\n this.unsubscribeAwarenessEvents = null;\n this.flushPendingUpdates(true);\n this.detachUpdateHandler();\n if (this.agentTimer) {\n clearTimeout(this.agentTimer);\n this.agentTimer = null;\n }\n // Detach our change listener BEFORE destroy so the destroy-time\n // `setLocalState(null)` does not schedule a push (matches the previous\n // per-hook effect cleanup ordering).\n this.awareness.off(\"change\", this.handleAwarenessChange);\n this.awareness.destroy();\n this.ydoc.destroy();\n if (collabConnectionRegistry.get(this.registryKey) === this) {\n collabConnectionRegistry.delete(this.registryKey);\n }\n }\n\n // -------------------------------------------------------------------------\n // Derived settings (aggregate over active subscribers)\n // -------------------------------------------------------------------------\n\n private get effectivePollInterval(): number {\n let min = Infinity;\n for (const sub of this.subscribers.values()) {\n if (sub.pollInterval < min) min = sub.pollInterval;\n }\n return isFinite(min) ? min : 2000;\n }\n\n private get effectivePollIntervalWithSse(): number {\n let min = Infinity;\n for (const sub of this.subscribers.values()) {\n if (sub.pollIntervalWithSse < min) min = sub.pollIntervalWithSse;\n }\n return isFinite(min) ? min : 12_000;\n }\n\n private get effectivePauseWhenHidden(): boolean {\n // Pause only if every subscriber has opted in.\n for (const sub of this.subscribers.values()) {\n if (!sub.pauseWhenHidden) return false;\n }\n return true;\n }\n\n // -------------------------------------------------------------------------\n // Shared state fan-out\n // -------------------------------------------------------------------------\n\n private setSnapshot(patch: Partial<CollabDocSnapshot>): void {\n this.snapshot = { ...this.snapshot, ...patch };\n for (const sub of this.subscribers.values()) {\n sub.onSnapshot(this.snapshot);\n }\n }\n\n private markAgentActive(): void {\n this.setSnapshot({ agentActive: true });\n if (this.agentTimer) clearTimeout(this.agentTimer);\n this.agentTimer = setTimeout(() => {\n this.agentTimer = null;\n this.setSnapshot({ agentActive: false });\n }, 3000);\n }\n\n // -------------------------------------------------------------------------\n // Awareness: local identity, active-user tracking, fast push\n // -------------------------------------------------------------------------\n\n /**\n * Publish the local user identity (cursor label) and current visibility.\n * Set once per tab — repeated calls with the same identity are no-ops so\n * multiple subscribers for the same user don't re-emit awareness updates.\n */\n setUser(user: CollabUser): void {\n if (this.disposed) return;\n const prev = this.lastSetUser;\n if (\n prev &&\n prev.name === user.name &&\n prev.email === user.email &&\n prev.color === user.color\n ) {\n return;\n }\n this.lastSetUser = {\n name: user.name,\n email: user.email,\n color: user.color,\n };\n this.awareness.setLocalStateField(\"user\", {\n name: user.name,\n email: user.email,\n color: user.color,\n });\n // Also publish this tab's visibility so peers can elect a VISIBLE client\n // to apply external snapshots (see isReconcileLeadClient) — a backgrounded\n // tab pauses its poll and must not hold that role.\n this.awareness.setLocalStateField(\"visible\", !isDocumentHidden());\n }\n\n private handleAwarenessChange = (): void => {\n const users: CollabUser[] = [];\n let hasAgent = false;\n this.awareness.getStates().forEach((state, clientId) => {\n if (clientId === this.ydoc.clientID) return; // Skip self\n if (state.user) {\n users.push(state.user as CollabUser);\n if ((state.user as CollabUser).email === \"agent@system\") {\n hasAgent = true;\n }\n }\n });\n this.setSnapshot({\n activeUsers: dedupeCollabUsersByEmail(users),\n agentPresent: hasAgent,\n });\n\n // Fast awareness push: whenever awareness changes (e.g. cursor moves,\n // setPresence() calls), schedule a throttled POST so peers receive updates\n // at ~150ms instead of waiting for the next poll cycle. Only active once a\n // local user identity has been published (matches the previous per-hook\n // gating on `user`). The poll cycle remains the authoritative baseline.\n if (this.lastSetUser && !this.disposed) {\n scheduleAwarenessPush(\n this.baseUrl,\n this.docId,\n this.ydoc.clientID,\n () => this.awareness.getLocalState() as Record<string, unknown> | null,\n );\n }\n };\n\n // -------------------------------------------------------------------------\n // Startup: initial state fetch, update handler, sync loops\n // -------------------------------------------------------------------------\n\n private start(): void {\n this.attachUpdateHandler();\n this.fetchInitialState();\n this.startSync();\n\n // SSE fast-path for awareness: listen on the SHARED framework transport\n // and apply awareness-change events immediately so peers receive cursor\n // moves push-style without waiting for the next poll cycle. Kept alive\n // even when the doc is missing (matches the previous per-hook behavior).\n this.unsubscribeAwarenessEvents = subscribeSyncEvents({\n onEvents: (events) => {\n if (this.disposed) return;\n for (const data of events) this.applyAwarenessEvent(data);\n },\n });\n }\n\n private fetchInitialState(): void {\n fetch(`${this.baseUrl}/${this.docId}/state`)\n .then(async (res) => {\n if (this.disposed) return;\n if (res.status === 404 || res.status === 403) {\n this.markDocMissing();\n return;\n }\n const data = (await res.json().catch(() => null)) as {\n state?: string;\n } | null;\n if (this.disposed) return;\n if (data?.state) {\n const binary = base64ToUint8Array(data.state);\n if (binary.length > 4) {\n Y.applyUpdate(this.ydoc, binary, \"remote\");\n }\n }\n this.setSnapshot({ isLoading: false, isSynced: true });\n })\n .catch(() => {\n if (this.disposed) return;\n this.setSnapshot({ isLoading: false, isSynced: true });\n });\n }\n\n /**\n * The initial state fetch returned 404/403 — the doc doesn't exist or isn't\n * accessible. Stop doc-update traffic (poll loop, update POSTs, collab SSE\n * handling) so we don't spam the console with errors against it. The\n * awareness SSE subscription stays (matches previous behavior).\n */\n private markDocMissing(): void {\n this.docMissing = true;\n this.flushPendingUpdates(true);\n this.detachUpdateHandler();\n this.stopSync();\n this.setSnapshot({ isLoading: false, isSynced: true });\n }\n\n // -------------------------------------------------------------------------\n // Local update batching\n // -------------------------------------------------------------------------\n\n private handleDocUpdate = (update: Uint8Array, origin: unknown): void => {\n if (origin === \"remote\") return;\n this.pendingUpdates.push(update);\n if (this.flushTimer) clearTimeout(this.flushTimer);\n this.flushTimer = setTimeout(\n () => this.flushPendingUpdates(),\n UPDATE_DEBOUNCE_MS,\n );\n };\n\n private handlePageHide = (): void => {\n this.flushPendingUpdates(true /* keepalive */);\n };\n\n private attachUpdateHandler(): void {\n if (this.updateHandlerAttached || this.docMissing) return;\n this.updateHandlerAttached = true;\n this.ydoc.on(\"update\", this.handleDocUpdate);\n if (typeof window !== \"undefined\") {\n window.addEventListener(\"pagehide\", this.handlePageHide);\n }\n }\n\n private detachUpdateHandler(): void {\n if (!this.updateHandlerAttached) return;\n this.updateHandlerAttached = false;\n this.ydoc.off(\"update\", this.handleDocUpdate);\n if (typeof window !== \"undefined\") {\n window.removeEventListener(\"pagehide\", this.handlePageHide);\n }\n }\n\n private flushPendingUpdates(keepalive = false): void {\n if (this.flushTimer) {\n clearTimeout(this.flushTimer);\n this.flushTimer = null;\n }\n if (this.pendingUpdates.length === 0) return;\n const toSend = this.pendingUpdates;\n this.pendingUpdates = [];\n\n const merged = toSend.length === 1 ? toSend[0] : Y.mergeUpdates(toSend);\n fetch(`${this.baseUrl}/${this.docId}/update`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n update: uint8ArrayToBase64(merged),\n requestSource: this.requestSource,\n }),\n ...(keepalive ? { keepalive: true } : {}),\n }).catch(() => {});\n }\n\n // -------------------------------------------------------------------------\n // Remote sync: SSE fast path + poll fallback loop\n // -------------------------------------------------------------------------\n\n private startSync(): void {\n if (this.syncActive || this.docMissing || this.disposed) return;\n this.syncActive = true;\n\n this.subscribeCollabEvents();\n\n if (!this.effectivePauseWhenHidden || !isDocumentHidden()) {\n void this.poll();\n }\n window.addEventListener(\"focus\", this.handleFocus);\n document.addEventListener(\"visibilitychange\", this.handleVisibilityChange);\n }\n\n private stopSync(): void {\n if (!this.syncActive) return;\n this.syncActive = false;\n if (this.pollTimer) {\n clearTimeout(this.pollTimer);\n this.pollTimer = null;\n }\n this.unsubscribeCollabEvents?.();\n this.unsubscribeCollabEvents = null;\n this.sseSubscribedWithPause = null;\n window.removeEventListener(\"focus\", this.handleFocus);\n document.removeEventListener(\n \"visibilitychange\",\n this.handleVisibilityChange,\n );\n }\n\n /**\n * SSE fast-path: subscribe to the SHARED framework transport for\n * /_agent-native/events instead of opening a dedicated EventSource per\n * collab doc. A tab holds exactly one SSE connection regardless of how many\n * docs are mounted. Collab update events arrive push-style; we apply them\n * immediately, avoiding ~2s polling latency for peer edits.\n *\n * NOTE: SSE events are subject to the same server-side access scoping as\n * polling — the server only pushes events that canSeeChangeForUser allows.\n */\n private subscribeCollabEvents(): void {\n const pauseWhenHidden = this.effectivePauseWhenHidden;\n this.sseSubscribedWithPause = pauseWhenHidden;\n this.unsubscribeCollabEvents = subscribeSyncEvents({\n onEvents: (events) => {\n if (this.disposed || !this.syncActive) return;\n for (const change of events) this.handleSharedEvent(change);\n },\n onSseStateChange: (connected) => {\n this.sseActive = connected;\n if (connected) this.consecutiveErrors = 0;\n },\n pauseWhenHidden,\n });\n }\n\n /**\n * The pause-when-hidden aggregate can flip when subscribers join or leave;\n * the shared-transport subscription captures it at subscribe time, so\n * re-subscribe when it changes.\n */\n private resubscribeCollabEventsIfPauseChanged(): void {\n if (!this.syncActive) return;\n if (this.sseSubscribedWithPause === this.effectivePauseWhenHidden) return;\n this.unsubscribeCollabEvents?.();\n this.subscribeCollabEvents();\n }\n\n private handleSharedEvent(change: SyncEvent): void {\n if (\n change.source === \"collab\" &&\n change.docId === this.docId &&\n typeof change.update === \"string\"\n ) {\n // Own echo — skip entirely (including the version tracking below, so\n // the next poll re-delivers and dedupe happens there; matches the\n // previous per-hook behavior).\n if (this.requestSource && change.requestSource === this.requestSource) {\n return;\n }\n try {\n Y.applyUpdate(this.ydoc, base64ToUint8Array(change.update), \"remote\");\n } catch {\n // Malformed update — trigger state-vector fetch on next poll\n }\n\n if (change.requestSource === \"agent\") {\n this.markAgentActive();\n }\n }\n\n // Keep the poll cursor updated from shared-transport events so the poll\n // loop starts from the right version when SSE drops.\n if (typeof change.version === \"number\") {\n this.pollVersion = Math.max(this.pollVersion, change.version);\n }\n }\n\n private getActivePollInterval(): number {\n return this.sseActive\n ? this.effectivePollIntervalWithSse\n : this.effectivePollInterval;\n }\n\n private schedulePoll(): void {\n if (!this.syncActive || this.disposed) return;\n if (this.effectivePauseWhenHidden && isDocumentHidden()) return;\n this.pollTimer = setTimeout(() => {\n this.pollTimer = null;\n void this.poll();\n }, this.getActivePollInterval());\n }\n\n /**\n * A subscriber joined or left, potentially changing the effective interval.\n * If a poll is already scheduled, reschedule with the new cadence (the next\n * natural tick would pick it up anyway; this just avoids a stale long wait\n * when a faster subscriber joins).\n */\n private reschedulePoll(): void {\n if (this.pollTimer === null) return;\n clearTimeout(this.pollTimer);\n this.pollTimer = null;\n this.schedulePoll();\n }\n\n private async fetchStateVector(): Promise<void> {\n try {\n const stateVector = uint8ArrayToBase64(Y.encodeStateVector(this.ydoc));\n const stateRes = await fetch(\n `${this.baseUrl}/${this.docId}/state?stateVector=${encodeURIComponent(stateVector)}`,\n );\n if (stateRes.ok) {\n const stateData = (await stateRes.json().catch(() => null)) as {\n state?: string;\n } | null;\n if (this.disposed) return;\n if (stateData?.state) {\n const binary = base64ToUint8Array(stateData.state);\n if (binary.length > 2) {\n Y.applyUpdate(this.ydoc, binary, \"remote\");\n }\n }\n }\n } catch {\n // Non-fatal; the next poll cycle will retry\n }\n }\n\n private async poll(): Promise<void> {\n if (!this.syncActive || this.disposed) return;\n\n // Flush any pending local updates before polling so the server has the\n // latest state before we read remote changes.\n this.flushPendingUpdates();\n\n try {\n const res = await fetch(\n agentNativePath(`/_agent-native/poll?since=${this.pollVersion}`),\n );\n if (!res.ok) throw new Error(\"HTTP \" + res.status);\n\n const data = await res.json();\n if (!this.syncActive || this.disposed) return;\n const { version, events } = data as {\n version: number;\n events: Array<{\n source: string;\n docId?: string;\n update?: string;\n requestSource?: string;\n }>;\n };\n\n // Detect ring-buffer overflow: if the version jumped by more than the\n // ring buffer size, some events were evicted and we need a state-vector\n // fetch to reconcile the gap.\n const versionGap = version - this.lastPolledVersion;\n const hadGap = versionGap > POLL_RING_BUFFER_SIZE;\n\n for (const evt of events) {\n if (evt.source === \"collab\" && evt.docId === this.docId && evt.update) {\n if (this.requestSource && evt.requestSource === this.requestSource) {\n continue;\n }\n try {\n Y.applyUpdate(this.ydoc, base64ToUint8Array(evt.update), \"remote\");\n } catch {\n // Failed to apply — fetch full state-vector below\n await this.fetchStateVector();\n }\n\n if (evt.requestSource === \"agent\") {\n this.markAgentActive();\n }\n }\n }\n\n this.pollVersion = version;\n this.lastPolledVersion = version;\n this.pollCycleCount++;\n this.consecutiveErrors = 0;\n\n // Fetch state-vector only when needed:\n // 1. Ring-buffer overflow detected (missed events).\n // 2. Low-frequency safety net every STATE_VECTOR_FETCH_INTERVAL cycles.\n // 3. NOT on every cycle (the previous behavior causing 3 requests/cycle).\n const shouldFetchStateVector =\n hadGap || this.pollCycleCount % STATE_VECTOR_FETCH_INTERVAL === 0;\n\n if (shouldFetchStateVector) {\n await this.fetchStateVector();\n }\n\n // Sync awareness (cursor positions)\n const localState = this.awareness.getLocalState();\n if (localState && !this.disposed) {\n try {\n const awarenessRes = await fetch(\n `${this.baseUrl}/${this.docId}/awareness`,\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n clientId: this.ydoc.clientID,\n state: JSON.stringify(localState),\n }),\n },\n );\n if (awarenessRes.ok && !this.disposed) {\n const awarenessData = await awarenessRes.json();\n const remoteStates: RemoteAwarenessSnapshot[] = [];\n for (const remote of awarenessData.states || []) {\n try {\n const remoteState = JSON.parse(remote.state);\n remoteStates.push({\n clientId: Number(remote.clientId),\n state: remoteState,\n });\n } catch {\n // Invalid state — skip\n }\n }\n if (this.disposed) return;\n const changes = reconcileRemoteAwarenessStates(\n this.awareness.getStates() as Map<number, unknown>,\n this.ydoc.clientID,\n remoteStates,\n );\n if (\n changes.added.length ||\n changes.updated.length ||\n changes.removed.length\n ) {\n this.awareness.emit(\"change\", [changes, \"remote\"]);\n }\n }\n } catch {\n // Awareness sync failure is non-fatal\n }\n }\n } catch {\n // Network error — exponential backoff\n this.consecutiveErrors++;\n const backoff = calcBackoff(this.consecutiveErrors);\n if (this.syncActive && !this.disposed) {\n this.pollTimer = setTimeout(() => {\n this.pollTimer = null;\n void this.poll();\n }, backoff);\n }\n return;\n }\n\n this.schedulePoll();\n }\n\n private pollNow(): void {\n if (!this.syncActive || this.disposed) return;\n if (this.effectivePauseWhenHidden && isDocumentHidden()) return;\n if (this.pollTimer) {\n clearTimeout(this.pollTimer);\n this.pollTimer = null;\n }\n void this.poll();\n }\n\n /**\n * Publish this tab's visibility to peers. A hidden tab pauses its poll, so\n * we push the state immediately (keepalive) instead of waiting for the next\n * cycle — otherwise peers keep treating a backgrounded tab as the visible\n * lead and an agent edit never lands on the tab the user is actually viewing.\n */\n private publishVisibility(visible: boolean): void {\n this.awareness.setLocalStateField(\"visible\", visible);\n const localState = this.awareness.getLocalState();\n if (!localState) return;\n fetch(`${this.baseUrl}/${this.docId}/awareness`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n clientId: this.ydoc.clientID,\n state: JSON.stringify(localState),\n }),\n keepalive: true,\n }).catch(() => {});\n }\n\n private handleVisibilityChange = (): void => {\n const visible = document.visibilityState === \"visible\";\n this.publishVisibility(visible);\n if (visible) {\n // Also flush any pending updates when coming back into view\n this.flushPendingUpdates();\n this.pollNow();\n } else if (this.effectivePauseWhenHidden && this.pollTimer) {\n clearTimeout(this.pollTimer);\n this.pollTimer = null;\n }\n };\n\n private handleFocus = (): void => {\n this.pollNow();\n };\n\n // -------------------------------------------------------------------------\n // Awareness SSE fast-path\n // -------------------------------------------------------------------------\n\n private applyAwarenessEvent(data: SyncEvent): void {\n if (\n data.source !== \"awareness\" ||\n data.type !== \"awareness-change\" ||\n data.docId !== this.docId\n ) {\n return;\n }\n const states = Array.isArray(data.states)\n ? (data.states as Array<{ clientId: number; state: string }>)\n : [];\n const remoteStates: RemoteAwarenessSnapshot[] = [];\n for (const remote of states) {\n try {\n remoteStates.push({\n clientId: Number(remote.clientId),\n state: JSON.parse(remote.state),\n });\n } catch {\n // Invalid state entry — skip\n }\n }\n const changes = reconcileRemoteAwarenessStates(\n this.awareness.getStates() as Map<number, unknown>,\n this.ydoc.clientID,\n remoteStates,\n );\n if (\n changes.added.length ||\n changes.updated.length ||\n changes.removed.length\n ) {\n this.awareness.emit(\"change\", [changes, \"remote\"]);\n }\n }\n}\n\n/**\n * Registry of active connections keyed by \"<baseUrl>\\0<docId>\".\n * Module-level singleton: survives React render cycles, shared across all\n * hook instances in the same browser tab.\n */\nconst collabConnectionRegistry = new Map<string, CollabDocConnection>();\n\nfunction collabRegistryKey(docId: string, baseUrl: string): string {\n return `${baseUrl}\\0${docId}`;\n}\n\nfunction getOrCreateCollabConnection(\n docId: string,\n baseUrl: string,\n): CollabDocConnection {\n const key = collabRegistryKey(docId, baseUrl);\n let conn = collabConnectionRegistry.get(key);\n if (!conn || conn.disposed) {\n conn = new CollabDocConnection(docId, baseUrl);\n collabConnectionRegistry.set(key, conn);\n }\n return conn;\n}\n\n// ---------------------------------------------------------------------------\n// Internal test helpers — reset/inspect the connection registry between tests.\n// ---------------------------------------------------------------------------\n/** @internal */\nexport function _resetCollabDocRegistryForTests(): void {\n for (const conn of Array.from(collabConnectionRegistry.values())) {\n conn.dispose();\n }\n collabConnectionRegistry.clear();\n}\n\n/** @internal — current registry size, for leak assertions in tests. */\nexport function _collabDocRegistrySizeForTests(): number {\n return collabConnectionRegistry.size;\n}\n\nexport function useCollaborativeDoc(\n options: UseCollaborativeDocOptions,\n): UseCollaborativeDocResult {\n const {\n docId,\n pollInterval = 2000,\n pollIntervalWithSse = 12000,\n pauseWhenHidden = true,\n baseUrl = agentNativePath(\"/_agent-native/collab\"),\n requestSource,\n user,\n } = options;\n\n // Bumped when the effect finds the memoized connection was disposed in the\n // render→effect gap (rare: a suspended transition outliving the linger\n // window) so the memo below re-acquires a live one.\n const [generation, setGeneration] = useState(0);\n\n // Shared connection per docId. Acquired during render so the Y.Doc identity\n // is available on first render (TipTap binds on mount); get-or-create is\n // idempotent, so StrictMode's double render returns the same instance.\n const conn = useMemo(() => {\n void generation;\n if (!docId) return null;\n if (typeof window === \"undefined\") {\n // SSR render: per-hook detached doc, never started (matches the\n // previous per-hook behavior on the server).\n return new CollabDocConnection(docId, baseUrl, true);\n }\n return getOrCreateCollabConnection(docId, baseUrl);\n }, [docId, baseUrl, generation]);\n\n const [snapshot, setSnapshot] = useState<CollabDocSnapshot>(() =>\n conn ? conn.snapshot : EMPTY_SNAPSHOT,\n );\n\n // Render-time reset when the connection identity changes (docId switch) so\n // consumers never see the previous doc's state for a frame.\n const [prevConn, setPrevConn] = useState(conn);\n if (prevConn !== conn) {\n setPrevConn(conn);\n setSnapshot(conn ? conn.snapshot : EMPTY_SNAPSHOT);\n }\n\n // Subscribe (ref-count) — the first subscriber starts the connection, the\n // last one leaving schedules its teardown.\n useEffect(() => {\n if (!conn || conn.detached) return;\n if (conn.disposed) {\n // Disposed between render and effect — re-acquire a live connection.\n setGeneration((g) => g + 1);\n return;\n }\n const id = Symbol(\"useCollaborativeDoc\");\n conn.add(id, {\n pollInterval,\n pollIntervalWithSse,\n pauseWhenHidden,\n requestSource,\n onSnapshot: setSnapshot,\n });\n // Re-sync in case the connection changed state between render and effect.\n setSnapshot(conn.snapshot);\n return () => {\n conn.remove(id);\n };\n }, [conn, pollInterval, pollIntervalWithSse, pauseWhenHidden, requestSource]);\n\n // Publish local user identity for cursor labels (set once per tab; the\n // connection dedupes repeated identical identities across subscribers).\n useEffect(() => {\n if (!conn || conn.detached || !user) return;\n conn.setUser({ name: user.name, email: user.email, color: user.color });\n }, [conn, user?.name, user?.email, user?.color]);\n\n return {\n ydoc: conn ? conn.ydoc : null,\n awareness: conn ? conn.awareness : null,\n isLoading: snapshot.isLoading,\n isSynced: snapshot.isSynced,\n activeUsers: snapshot.activeUsers,\n agentActive: snapshot.agentActive,\n agentPresent: snapshot.agentPresent,\n };\n}\n"]}
|
|
@@ -8,21 +8,9 @@
|
|
|
8
8
|
* The hook re-renders on every awareness change event and always includes
|
|
9
9
|
* the agent participant (AGENT_CLIENT_ID) as isAgent: true.
|
|
10
10
|
*/
|
|
11
|
+
import type { NormalizedPoint, OtherPresence, PresencePayload } from "@agent-native/toolkit/collab-ui";
|
|
11
12
|
import type { Awareness } from "y-protocols/awareness";
|
|
12
|
-
|
|
13
|
-
/** Arbitrary JSON presence payload published by a participant. */
|
|
14
|
-
export type PresencePayload = Record<string, unknown>;
|
|
15
|
-
/** A remote participant's full presence snapshot. */
|
|
16
|
-
export interface OtherPresence {
|
|
17
|
-
/** Yjs client ID. */
|
|
18
|
-
clientId: number;
|
|
19
|
-
/** User identity (from awareness `user` field). */
|
|
20
|
-
user: CollabUser;
|
|
21
|
-
/** Arbitrary presence fields set via setPresence() / agentUpdateSelection(). */
|
|
22
|
-
presence: PresencePayload;
|
|
23
|
-
/** True when this participant is the AI agent. */
|
|
24
|
-
isAgent: boolean;
|
|
25
|
-
}
|
|
13
|
+
export type { NormalizedPoint, OtherPresence, PresencePayload, } from "@agent-native/toolkit/collab-ui";
|
|
26
14
|
export interface UsePresenceResult {
|
|
27
15
|
/** All remote participants (excludes local client). */
|
|
28
16
|
others: OtherPresence[];
|
|
@@ -40,12 +28,6 @@ export interface UsePresenceResult {
|
|
|
40
28
|
* @param localClientId The local Yjs client ID (to exclude self).
|
|
41
29
|
*/
|
|
42
30
|
export declare function usePresence(awareness: Awareness | null | undefined, localClientId: number | null | undefined): UsePresenceResult;
|
|
43
|
-
export interface NormalizedPoint {
|
|
44
|
-
/** 0–1 fraction of container width. */
|
|
45
|
-
x: number;
|
|
46
|
-
/** 0–1 fraction of container height. */
|
|
47
|
-
y: number;
|
|
48
|
-
}
|
|
49
31
|
/** Convert a pointer event offset to a normalized point. */
|
|
50
32
|
export declare function toNormalized(clientX: number, clientY: number, container: DOMRect): NormalizedPoint;
|
|
51
33
|
/** Convert a normalized point back to absolute offset within a container. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"presence.d.ts","sourceRoot":"","sources":["../../src/collab/presence.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;
|
|
1
|
+
{"version":3,"file":"presence.d.ts","sourceRoot":"","sources":["../../src/collab/presence.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAEV,eAAe,EACf,aAAa,EACb,eAAe,EAChB,MAAM,iCAAiC,CAAC;AAEzC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAIvD,YAAY,EACV,eAAe,EACf,aAAa,EACb,eAAe,GAChB,MAAM,iCAAiC,CAAC;AAEzC,MAAM,WAAW,iBAAiB;IAChC,uDAAuD;IACvD,MAAM,EAAE,aAAa,EAAE,CAAC;IACxB;;;;OAIG;IACH,WAAW,EAAE,CAAC,OAAO,EAAE,eAAe,KAAK,IAAI,CAAC;CACjD;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CACzB,SAAS,EAAE,SAAS,GAAG,IAAI,GAAG,SAAS,EACvC,aAAa,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GACvC,iBAAiB,CAmInB;AAMD,4DAA4D;AAC5D,wBAAgB,YAAY,CAC1B,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,OAAO,GACjB,eAAe,CAKjB;AAED,6EAA6E;AAC7E,wBAAgB,cAAc,CAC5B,KAAK,EAAE,eAAe,EACtB,SAAS,EAAE,OAAO,GACjB;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAK1B"}
|
package/dist/collab/presence.js
CHANGED
|
@@ -132,6 +132,9 @@ export function usePresence(awareness, localClientId) {
|
|
|
132
132
|
}, []);
|
|
133
133
|
return { others, setPresence };
|
|
134
134
|
}
|
|
135
|
+
// ---------------------------------------------------------------------------
|
|
136
|
+
// Normalized cursor coordinate helpers
|
|
137
|
+
// ---------------------------------------------------------------------------
|
|
135
138
|
/** Convert a pointer event offset to a normalized point. */
|
|
136
139
|
export function toNormalized(clientX, clientY, container) {
|
|
137
140
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"presence.js","sourceRoot":"","sources":["../../src/collab/presence.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Presence kit — Liveblocks/collaboration-grade presence primitives.\n *\n * usePresence(awareness) returns:\n * - others: reactive array of remote participants (human + agent)\n * - setPresence(partial): merge fields into local awareness state\n *\n * The hook re-renders on every awareness change event and always includes\n * the agent participant (AGENT_CLIENT_ID) as isAgent: true.\n */\n\nimport { useState, useEffect, useCallback, useRef } from \"react\";\nimport type { Awareness } from \"y-protocols/awareness\";\n\nimport { AGENT_CLIENT_ID } from \"./agent-identity.js\";\nimport type { CollabUser } from \"./client.js\";\n\n/** Arbitrary JSON presence payload published by a participant. */\nexport type PresencePayload = Record<string, unknown>;\n\n/** A remote participant's full presence snapshot. */\nexport interface OtherPresence {\n /** Yjs client ID. */\n clientId: number;\n /** User identity (from awareness `user` field). */\n user: CollabUser;\n /** Arbitrary presence fields set via setPresence() / agentUpdateSelection(). */\n presence: PresencePayload;\n /** True when this participant is the AI agent. */\n isAgent: boolean;\n}\n\nexport interface UsePresenceResult {\n /** All remote participants (excludes local client). */\n others: OtherPresence[];\n /**\n * Merge fields into the local awareness state. These are broadcast to\n * peers by the fast-awareness path in useCollaborativeDoc.\n * Call this to publish cursor position, viewport, or selection.\n */\n setPresence: (partial: PresencePayload) => void;\n}\n\n/**\n * Derive OtherPresence entries from an Awareness instance.\n *\n * @param awareness Awareness instance from useCollaborativeDoc.\n * @param localClientId The local Yjs client ID (to exclude self).\n */\nexport function usePresence(\n awareness: Awareness | null | undefined,\n localClientId: number | null | undefined,\n): UsePresenceResult {\n const [others, setOthers] = useState<OtherPresence[]>([]);\n\n // Keep the latest awareness ref so setPresence closure doesn't go stale.\n const awarenessRef = useRef(awareness);\n awarenessRef.current = awareness;\n\n useEffect(() => {\n if (!awareness) {\n setOthers([]);\n return;\n }\n\n // Keep the last derived snapshot so genuinely no-op change events (e.g. a\n // local-only awareness field flip that doesn't affect any remote entry)\n // can bail out without triggering a subscriber re-render.\n let lastOthers: OtherPresence[] = [];\n\n function shallowEqualOthers(\n a: readonly OtherPresence[],\n b: readonly OtherPresence[],\n ): boolean {\n if (a === b) return true;\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i += 1) {\n const left = a[i]!;\n const right = b[i]!;\n if (left === right) continue;\n if (\n left.clientId !== right.clientId ||\n left.isAgent !== right.isAgent ||\n left.user.name !== right.user.name ||\n left.user.email !== right.user.email ||\n left.user.color !== right.user.color\n ) {\n return false;\n }\n // Compare presence payloads with a stable JSON.stringify — presence\n // fields (cursor/selection/viewport) are small JSON-safe records, so\n // this is cheap and avoids a re-render when nothing actually changed.\n if (JSON.stringify(left.presence) !== JSON.stringify(right.presence)) {\n return false;\n }\n }\n return true;\n }\n\n function derive(): OtherPresence[] {\n const result: OtherPresence[] = [];\n awareness!.getStates().forEach((state, clientId) => {\n if (clientId === localClientId) return; // skip self\n const s = state as Record<string, unknown>;\n const isAgent = clientId === AGENT_CLIENT_ID;\n\n // User identity — fall back to agent defaults or anonymous.\n let user: CollabUser;\n if (isAgent) {\n user = {\n name: (s.user as CollabUser)?.name ?? \"AI Assistant\",\n email: (s.user as CollabUser)?.email ?? \"agent@system\",\n color: (s.user as CollabUser)?.color ?? \"#00B5FF\",\n };\n } else {\n const u = s.user as CollabUser | undefined;\n user = {\n name: u?.name ?? \"Unknown\",\n email: u?.email ?? `client-${clientId}`,\n color: u?.color ?? \"#94a3b8\",\n };\n }\n\n // Everything that isn't `user` or `visible` is presence payload.\n const presence: PresencePayload = {};\n for (const [k, v] of Object.entries(s)) {\n if (k !== \"user\" && k !== \"visible\") {\n presence[k] = v;\n }\n }\n\n result.push({ clientId, user, presence, isAgent });\n });\n return result;\n }\n\n function onAwarenessChange(changes?: {\n added: number[];\n updated: number[];\n removed: number[];\n }) {\n // The awareness \"change\" event fires for local-only state edits too\n // (e.g. this hook's own setPresence() calls, or the doc's\n // activeFileId/visible fields). When every changed client id is the\n // local client, the derived `others` array (which excludes the local\n // client) cannot have changed, so skip the re-render entirely.\n if (changes) {\n const changedIds = [\n ...changes.added,\n ...changes.updated,\n ...changes.removed,\n ];\n if (\n changedIds.length > 0 &&\n changedIds.every((id) => id === localClientId)\n ) {\n return;\n }\n }\n const next = derive();\n if (shallowEqualOthers(lastOthers, next)) return;\n lastOthers = next;\n setOthers(next);\n }\n\n // Derive immediately.\n lastOthers = derive();\n setOthers(lastOthers);\n awareness.on(\"change\", onAwarenessChange);\n return () => {\n awareness.off(\"change\", onAwarenessChange);\n };\n }, [awareness, localClientId]);\n\n const setPresence = useCallback((partial: PresencePayload) => {\n const aw = awarenessRef.current;\n if (!aw) return;\n for (const [k, v] of Object.entries(partial)) {\n aw.setLocalStateField(k, v);\n }\n }, []);\n\n return { others, setPresence };\n}\n\n// ---------------------------------------------------------------------------\n// Normalized cursor coordinate helpers\n// ---------------------------------------------------------------------------\n\nexport interface NormalizedPoint {\n /** 0–1 fraction of container width. */\n x: number;\n /** 0–1 fraction of container height. */\n y: number;\n}\n\n/** Convert a pointer event offset to a normalized point. */\nexport function toNormalized(\n clientX: number,\n clientY: number,\n container: DOMRect,\n): NormalizedPoint {\n return {\n x: Math.max(0, Math.min(1, (clientX - container.left) / container.width)),\n y: Math.max(0, Math.min(1, (clientY - container.top) / container.height)),\n };\n}\n\n/** Convert a normalized point back to absolute offset within a container. */\nexport function fromNormalized(\n point: NormalizedPoint,\n container: DOMRect,\n): { x: number; y: number } {\n return {\n x: point.x * container.width,\n y: point.y * container.height,\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"presence.js","sourceRoot":"","sources":["../../src/collab/presence.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Presence kit — Liveblocks/collaboration-grade presence primitives.\n *\n * usePresence(awareness) returns:\n * - others: reactive array of remote participants (human + agent)\n * - setPresence(partial): merge fields into local awareness state\n *\n * The hook re-renders on every awareness change event and always includes\n * the agent participant (AGENT_CLIENT_ID) as isAgent: true.\n */\n\nimport type {\n CollabUser,\n NormalizedPoint,\n OtherPresence,\n PresencePayload,\n} from \"@agent-native/toolkit/collab-ui\";\nimport { useState, useEffect, useCallback, useRef } from \"react\";\nimport type { Awareness } from \"y-protocols/awareness\";\n\nimport { AGENT_CLIENT_ID } from \"./agent-identity.js\";\n\nexport type {\n NormalizedPoint,\n OtherPresence,\n PresencePayload,\n} from \"@agent-native/toolkit/collab-ui\";\n\nexport interface UsePresenceResult {\n /** All remote participants (excludes local client). */\n others: OtherPresence[];\n /**\n * Merge fields into the local awareness state. These are broadcast to\n * peers by the fast-awareness path in useCollaborativeDoc.\n * Call this to publish cursor position, viewport, or selection.\n */\n setPresence: (partial: PresencePayload) => void;\n}\n\n/**\n * Derive OtherPresence entries from an Awareness instance.\n *\n * @param awareness Awareness instance from useCollaborativeDoc.\n * @param localClientId The local Yjs client ID (to exclude self).\n */\nexport function usePresence(\n awareness: Awareness | null | undefined,\n localClientId: number | null | undefined,\n): UsePresenceResult {\n const [others, setOthers] = useState<OtherPresence[]>([]);\n\n // Keep the latest awareness ref so setPresence closure doesn't go stale.\n const awarenessRef = useRef(awareness);\n awarenessRef.current = awareness;\n\n useEffect(() => {\n if (!awareness) {\n setOthers([]);\n return;\n }\n\n // Keep the last derived snapshot so genuinely no-op change events (e.g. a\n // local-only awareness field flip that doesn't affect any remote entry)\n // can bail out without triggering a subscriber re-render.\n let lastOthers: OtherPresence[] = [];\n\n function shallowEqualOthers(\n a: readonly OtherPresence[],\n b: readonly OtherPresence[],\n ): boolean {\n if (a === b) return true;\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i += 1) {\n const left = a[i]!;\n const right = b[i]!;\n if (left === right) continue;\n if (\n left.clientId !== right.clientId ||\n left.isAgent !== right.isAgent ||\n left.user.name !== right.user.name ||\n left.user.email !== right.user.email ||\n left.user.color !== right.user.color\n ) {\n return false;\n }\n // Compare presence payloads with a stable JSON.stringify — presence\n // fields (cursor/selection/viewport) are small JSON-safe records, so\n // this is cheap and avoids a re-render when nothing actually changed.\n if (JSON.stringify(left.presence) !== JSON.stringify(right.presence)) {\n return false;\n }\n }\n return true;\n }\n\n function derive(): OtherPresence[] {\n const result: OtherPresence[] = [];\n awareness!.getStates().forEach((state, clientId) => {\n if (clientId === localClientId) return; // skip self\n const s = state as Record<string, unknown>;\n const isAgent = clientId === AGENT_CLIENT_ID;\n\n // User identity — fall back to agent defaults or anonymous.\n let user: CollabUser;\n if (isAgent) {\n user = {\n name: (s.user as CollabUser)?.name ?? \"AI Assistant\",\n email: (s.user as CollabUser)?.email ?? \"agent@system\",\n color: (s.user as CollabUser)?.color ?? \"#00B5FF\",\n };\n } else {\n const u = s.user as CollabUser | undefined;\n user = {\n name: u?.name ?? \"Unknown\",\n email: u?.email ?? `client-${clientId}`,\n color: u?.color ?? \"#94a3b8\",\n };\n }\n\n // Everything that isn't `user` or `visible` is presence payload.\n const presence: PresencePayload = {};\n for (const [k, v] of Object.entries(s)) {\n if (k !== \"user\" && k !== \"visible\") {\n presence[k] = v;\n }\n }\n\n result.push({ clientId, user, presence, isAgent });\n });\n return result;\n }\n\n function onAwarenessChange(changes?: {\n added: number[];\n updated: number[];\n removed: number[];\n }) {\n // The awareness \"change\" event fires for local-only state edits too\n // (e.g. this hook's own setPresence() calls, or the doc's\n // activeFileId/visible fields). When every changed client id is the\n // local client, the derived `others` array (which excludes the local\n // client) cannot have changed, so skip the re-render entirely.\n if (changes) {\n const changedIds = [\n ...changes.added,\n ...changes.updated,\n ...changes.removed,\n ];\n if (\n changedIds.length > 0 &&\n changedIds.every((id) => id === localClientId)\n ) {\n return;\n }\n }\n const next = derive();\n if (shallowEqualOthers(lastOthers, next)) return;\n lastOthers = next;\n setOthers(next);\n }\n\n // Derive immediately.\n lastOthers = derive();\n setOthers(lastOthers);\n awareness.on(\"change\", onAwarenessChange);\n return () => {\n awareness.off(\"change\", onAwarenessChange);\n };\n }, [awareness, localClientId]);\n\n const setPresence = useCallback((partial: PresencePayload) => {\n const aw = awarenessRef.current;\n if (!aw) return;\n for (const [k, v] of Object.entries(partial)) {\n aw.setLocalStateField(k, v);\n }\n }, []);\n\n return { others, setPresence };\n}\n\n// ---------------------------------------------------------------------------\n// Normalized cursor coordinate helpers\n// ---------------------------------------------------------------------------\n\n/** Convert a pointer event offset to a normalized point. */\nexport function toNormalized(\n clientX: number,\n clientY: number,\n container: DOMRect,\n): NormalizedPoint {\n return {\n x: Math.max(0, Math.min(1, (clientX - container.left) / container.width)),\n y: Math.max(0, Math.min(1, (clientY - container.top) / container.height)),\n };\n}\n\n/** Convert a normalized point back to absolute offset within a container. */\nexport function fromNormalized(\n point: NormalizedPoint,\n container: DOMRect,\n): { x: number; y: number } {\n return {\n x: point.x * container.width,\n y: point.y * container.height,\n };\n}\n"]}
|
|
@@ -15,44 +15,9 @@
|
|
|
15
15
|
* (e.g. `slides.3.content`) to their rendered element
|
|
16
16
|
* - `{ kind: "doc" }` whole-document change (no region)
|
|
17
17
|
*/
|
|
18
|
+
import { type AttributedRecentEdit, type RecentEdit } from "@agent-native/toolkit/collab-ui";
|
|
18
19
|
import type { OtherPresence } from "./presence.js";
|
|
19
|
-
export type RecentEditDescriptor
|
|
20
|
-
kind: "text";
|
|
21
|
-
quote: string;
|
|
22
|
-
} | {
|
|
23
|
-
kind: "selector";
|
|
24
|
-
selector: string;
|
|
25
|
-
} | {
|
|
26
|
-
kind: "paths";
|
|
27
|
-
paths: string[];
|
|
28
|
-
} | {
|
|
29
|
-
kind: "doc";
|
|
30
|
-
} | {
|
|
31
|
-
kind: string;
|
|
32
|
-
[key: string]: unknown;
|
|
33
|
-
};
|
|
34
|
-
export interface RecentEdit {
|
|
35
|
-
descriptor: RecentEditDescriptor;
|
|
36
|
-
/** Short human-readable label, e.g. "Rewrote intro" or "Slide 3". */
|
|
37
|
-
label?: string;
|
|
38
|
-
/** Epoch ms when the edit landed. */
|
|
39
|
-
at: number;
|
|
40
|
-
}
|
|
41
|
-
/** A recent edit attributed to the participant who made it. */
|
|
42
|
-
export interface AttributedRecentEdit extends RecentEdit {
|
|
43
|
-
clientId: number;
|
|
44
|
-
user: OtherPresence["user"];
|
|
45
|
-
isAgent: boolean;
|
|
46
|
-
}
|
|
47
|
-
/** Max entries kept in a participant's recentEdits ring. */
|
|
48
|
-
export declare const RECENT_EDITS_MAX = 5;
|
|
49
|
-
/**
|
|
50
|
-
* Default time a recent-edit highlight stays visible, measured from the
|
|
51
|
-
* edit's `at` timestamp. Awareness delivery adds up to ~3s (poll cadence),
|
|
52
|
-
* and some actions do post-write work before a viewer looks, so this is
|
|
53
|
-
* deliberately generous — the fade consumes the final 40% of the window.
|
|
54
|
-
*/
|
|
55
|
-
export declare const RECENT_EDIT_TTL_MS = 10000;
|
|
20
|
+
export { RECENT_EDITS_MAX, RECENT_EDIT_TTL_MS, type AttributedRecentEdit, type RecentEdit, type RecentEditDescriptor, } from "@agent-native/toolkit/collab-ui";
|
|
56
21
|
/**
|
|
57
22
|
* Append an edit to a recentEdits ring, keeping the newest
|
|
58
23
|
* {@link RECENT_EDITS_MAX} entries. Pure — returns a new array.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"recent-edits.d.ts","sourceRoot":"","sources":["../../src/collab/recent-edits.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;
|
|
1
|
+
{"version":3,"file":"recent-edits.d.ts","sourceRoot":"","sources":["../../src/collab/recent-edits.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAGL,KAAK,oBAAoB,EACzB,KAAK,UAAU,EAChB,MAAM,iCAAiC,CAAC;AAGzC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAEnD,OAAO,EACL,gBAAgB,EAChB,kBAAkB,EAClB,KAAK,oBAAoB,EACzB,KAAK,UAAU,EACf,KAAK,oBAAoB,GAC1B,MAAM,iCAAiC,CAAC;AAEzC;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,UAAU,EAAE,GAAG,SAAS,EAClC,IAAI,EAAE,UAAU,GACf,UAAU,EAAE,CAOd;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,aAAa,EAAE,EACvB,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,MAAM,GACV,oBAAoB,EAAE,CAmBxB;AAED,MAAM,WAAW,qBAAqB;IACpC,mEAAmE;IACnE,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,aAAa,EAAE,EACvB,OAAO,CAAC,EAAE,qBAAqB,GAC9B,oBAAoB,EAAE,CA0BxB;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE;IACT,aAAa,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACpD,kBAAkB,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;CAC7D,EACD,IAAI,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,GAAG;IAAE,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,GAC7C,IAAI,CAON"}
|
|
@@ -15,16 +15,9 @@
|
|
|
15
15
|
* (e.g. `slides.3.content`) to their rendered element
|
|
16
16
|
* - `{ kind: "doc" }` whole-document change (no region)
|
|
17
17
|
*/
|
|
18
|
+
import { RECENT_EDITS_MAX, RECENT_EDIT_TTL_MS, } from "@agent-native/toolkit/collab-ui";
|
|
18
19
|
import { useEffect, useRef, useState } from "react";
|
|
19
|
-
|
|
20
|
-
export const RECENT_EDITS_MAX = 5;
|
|
21
|
-
/**
|
|
22
|
-
* Default time a recent-edit highlight stays visible, measured from the
|
|
23
|
-
* edit's `at` timestamp. Awareness delivery adds up to ~3s (poll cadence),
|
|
24
|
-
* and some actions do post-write work before a viewer looks, so this is
|
|
25
|
-
* deliberately generous — the fade consumes the final 40% of the window.
|
|
26
|
-
*/
|
|
27
|
-
export const RECENT_EDIT_TTL_MS = 10_000;
|
|
20
|
+
export { RECENT_EDITS_MAX, RECENT_EDIT_TTL_MS, } from "@agent-native/toolkit/collab-ui";
|
|
28
21
|
/**
|
|
29
22
|
* Append an edit to a recentEdits ring, keeping the newest
|
|
30
23
|
* {@link RECENT_EDITS_MAX} entries. Pure — returns a new array.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"recent-edits.js","sourceRoot":"","sources":["../../src/collab/recent-edits.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"recent-edits.js","sourceRoot":"","sources":["../../src/collab/recent-edits.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Recent-edit attribution for collaborative documents.\n *\n * Every participant (human or agent) may publish a short ring of recent edits\n * in its awareness state under the `recentEdits` key. Clients render these as\n * lingering, fading highlights (\"Google Docs / Figma collaborator just edited\n * this\") for a few seconds after the edit lands, with the editor's name and\n * color next to the highlighted region.\n *\n * The descriptor is intentionally open-ended — each app publishes whatever its\n * surfaces can resolve back to a DOM rect:\n * - `{ kind: \"text\", quote }` rich-text apps resolve by text search\n * - `{ kind: \"selector\", selector }` canvas/DOM apps resolve by querySelector\n * - `{ kind: \"paths\", paths }` structured apps resolve JSON paths\n * (e.g. `slides.3.content`) to their rendered element\n * - `{ kind: \"doc\" }` whole-document change (no region)\n */\n\nimport {\n RECENT_EDITS_MAX,\n RECENT_EDIT_TTL_MS,\n type AttributedRecentEdit,\n type RecentEdit,\n} from \"@agent-native/toolkit/collab-ui\";\nimport { useEffect, useRef, useState } from \"react\";\n\nimport type { OtherPresence } from \"./presence.js\";\n\nexport {\n RECENT_EDITS_MAX,\n RECENT_EDIT_TTL_MS,\n type AttributedRecentEdit,\n type RecentEdit,\n type RecentEditDescriptor,\n} from \"@agent-native/toolkit/collab-ui\";\n\n/**\n * Append an edit to a recentEdits ring, keeping the newest\n * {@link RECENT_EDITS_MAX} entries. Pure — returns a new array.\n */\nexport function appendRecentEdit(\n existing: RecentEdit[] | undefined,\n edit: RecentEdit,\n): RecentEdit[] {\n const ring = Array.isArray(existing) ? existing.slice() : [];\n ring.push(edit);\n if (ring.length > RECENT_EDITS_MAX) {\n ring.splice(0, ring.length - RECENT_EDITS_MAX);\n }\n return ring;\n}\n\n/**\n * Flatten non-expired recent edits from remote participants, newest last.\n * Pure — exported for tests and non-React consumers.\n */\nexport function collectRecentEdits(\n others: OtherPresence[],\n ttlMs: number,\n now: number,\n): AttributedRecentEdit[] {\n const result: AttributedRecentEdit[] = [];\n for (const other of others) {\n const ring = other.presence[\"recentEdits\"];\n if (!Array.isArray(ring)) continue;\n for (const raw of ring) {\n const edit = raw as RecentEdit;\n if (!edit || typeof edit.at !== \"number\" || !edit.descriptor) continue;\n if (now - edit.at > ttlMs) continue;\n result.push({\n ...edit,\n clientId: other.clientId,\n user: other.user,\n isAgent: other.isAgent,\n });\n }\n }\n result.sort((a, b) => a.at - b.at);\n return result;\n}\n\nexport interface UseRecentEditsOptions {\n /** How long a highlight lingers after the edit. Default 6000ms. */\n ttlMs?: number;\n}\n\n/**\n * Reactive list of remote participants' recent edits that haven't expired.\n * Ticks internally (~500ms) while any highlight is visible so consumers can\n * render a smooth fade-out without wiring their own timers.\n */\nexport function useRecentEdits(\n others: OtherPresence[],\n options?: UseRecentEditsOptions,\n): AttributedRecentEdit[] {\n const ttlMs = options?.ttlMs ?? RECENT_EDIT_TTL_MS;\n const [edits, setEdits] = useState<AttributedRecentEdit[]>([]);\n const othersRef = useRef(others);\n othersRef.current = others;\n\n useEffect(() => {\n let timer: ReturnType<typeof setTimeout> | null = null;\n\n function tick() {\n const next = collectRecentEdits(othersRef.current, ttlMs, Date.now());\n setEdits((prev) => (recentEditsEqual(prev, next) ? prev : next));\n if (next.length > 0) {\n timer = setTimeout(tick, 500);\n } else {\n timer = null;\n }\n }\n\n tick();\n return () => {\n if (timer) clearTimeout(timer);\n };\n }, [others, ttlMs]);\n\n return edits;\n}\n\n/**\n * Publish a local edit into this client's awareness ring so peers render a\n * lingering highlight for it. Call from app mutation paths (throttled by the\n * ring size + TTL; safe to call per committed edit, not per keystroke).\n */\nexport function publishRecentEdit(\n awareness: {\n getLocalState: () => Record<string, unknown> | null;\n setLocalStateField: (field: string, value: unknown) => void;\n },\n edit: Omit<RecentEdit, \"at\"> & { at?: number },\n): void {\n const local = awareness.getLocalState();\n const existing = local?.[\"recentEdits\"] as RecentEdit[] | undefined;\n awareness.setLocalStateField(\n \"recentEdits\",\n appendRecentEdit(existing, { ...edit, at: edit.at ?? Date.now() }),\n );\n}\n\nfunction recentEditsEqual(\n a: AttributedRecentEdit[],\n b: AttributedRecentEdit[],\n): boolean {\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i++) {\n if (a[i].clientId !== b[i].clientId || a[i].at !== b[i].at) return false;\n }\n return true;\n}\n"]}
|
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
* Body: { json: any, fieldName?: string, type?: "map"|"array", requestSource?: string }
|
|
14
14
|
*/
|
|
15
15
|
export declare const postCollabJson: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
|
|
16
|
-
error: string;
|
|
17
16
|
ok?: undefined;
|
|
17
|
+
error: string;
|
|
18
18
|
} | {
|
|
19
19
|
error?: undefined;
|
|
20
20
|
ok: boolean;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Actions exposed for the data-programs primitive: save/preview/run/list/get/
|
|
3
|
+
* delete. Mirrors the repo's `defineAction` conventions (see
|
|
4
|
+
* `../mcp/actions/create-org-service-token.ts`, `../sharing/actions/*`).
|
|
5
|
+
*
|
|
6
|
+
* Security: every action that EXECUTES code (save — which dry-runs before
|
|
7
|
+
* persisting — preview, run) or MUTATES stored code (delete) is
|
|
8
|
+
* `toolCallable: false`, so the sandboxed tools-iframe bridge can never
|
|
9
|
+
* invoke stored/arbitrary code under the opener's session — the same
|
|
10
|
+
* rationale as `provider-api-request`. `list`/`get` are read-only and
|
|
11
|
+
* access-scoped through the sharing helpers.
|
|
12
|
+
*/
|
|
13
|
+
import type { ActionEntry } from "../agent/production-agent.js";
|
|
14
|
+
export interface CreateDataProgramActionsOptions {
|
|
15
|
+
appId: string;
|
|
16
|
+
getActions: () => Record<string, ActionEntry>;
|
|
17
|
+
}
|
|
18
|
+
export declare function createDataProgramActions(options: CreateDataProgramActionsOptions): Record<string, ActionEntry>;
|
|
19
|
+
//# sourceMappingURL=actions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../../src/data-programs/actions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAKH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAqBhE,MAAM,WAAW,+BAA+B;IAC9C,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;CAC/C;AAED,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,+BAA+B,GACvC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAkS7B"}
|