@agent-native/core 0.115.4 → 0.117.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/agent-native.eject.json +1 -0
- package/corpus/README.md +3 -3
- package/corpus/core/CHANGELOG.md +43 -0
- package/corpus/core/agent-native.eject.json +1 -0
- package/corpus/core/docs/AGENTS.md +1 -1
- package/corpus/core/docs/content/agent-mentions.mdx +2 -2
- package/corpus/core/docs/content/{workspace.mdx → agent-resources.mdx} +1 -7
- package/corpus/core/docs/content/agent-teams.mdx +4 -4
- package/corpus/core/docs/content/dispatch.mdx +10 -10
- package/corpus/core/docs/content/drop-in-agent.mdx +4 -4
- package/corpus/core/docs/content/external-agents.mdx +1 -1
- package/corpus/core/docs/content/frames.mdx +1 -1
- package/corpus/core/docs/content/integrations.mdx +13 -2
- package/corpus/core/docs/content/key-concepts.mdx +2 -2
- package/corpus/core/docs/content/mcp-clients.mdx +7 -1
- package/corpus/core/docs/content/multi-app-workspace.mdx +3 -3
- package/corpus/core/docs/content/real-time-collaboration.mdx +33 -15
- package/corpus/core/docs/content/recurring-jobs.mdx +7 -7
- package/corpus/core/docs/content/skills-guide.mdx +4 -4
- package/corpus/core/docs/content/template-brain.mdx +1 -1
- package/corpus/core/docs/content/toolkit-collaboration.mdx +1 -1
- package/corpus/core/docs/content/using-your-agent.mdx +1 -1
- package/corpus/core/docs/content/what-is-agent-native.mdx +4 -4
- package/corpus/core/docs/content/workspace-management.mdx +4 -4
- package/corpus/core/package.json +4 -1
- package/corpus/core/src/agent/production-agent.ts +13 -3
- package/corpus/core/src/cli/doctor.ts +6 -1
- package/corpus/core/src/client/AgentPanel.tsx +79 -41
- package/corpus/core/src/client/AssistantChat.tsx +71 -25
- package/corpus/core/src/client/FeedbackButton.tsx +33 -7
- package/corpus/core/src/client/MultiTabAssistantChat.tsx +6 -8
- package/corpus/core/src/client/agent-chat-adapter.ts +11 -2
- package/corpus/core/src/client/agent-page/AgentTabFrame.tsx +22 -3
- package/corpus/core/src/client/agent-page/AgentTabsPage.tsx +34 -19
- package/corpus/core/src/client/analytics.ts +7 -0
- package/corpus/core/src/client/chat/message-components.tsx +43 -16
- package/corpus/core/src/client/chat/tool-call-display.tsx +30 -18
- package/corpus/core/src/client/chat/tool-render-registry.tsx +2 -0
- package/corpus/core/src/client/resources/McpConnectionSuggestion.tsx +19 -2
- package/corpus/core/src/client/resources/ResourceTree.tsx +7 -10
- package/corpus/core/src/client/resources/ResourcesPanel.tsx +33 -70
- package/corpus/core/src/client/resources/mcp-connection-resume.ts +107 -0
- package/corpus/core/src/client/resources/mcp-integration-catalog.ts +65 -12
- package/corpus/core/src/client/resources/mcp-integration-logos.ts +4 -0
- package/corpus/core/src/client/sse-event-processor.ts +50 -14
- package/corpus/core/src/client/use-db-sync.ts +370 -21
- package/corpus/core/src/collab/client.ts +26 -2
- package/corpus/core/src/connections/catalog.ts +7 -1
- package/corpus/core/src/db/ddl-guard.ts +49 -10
- package/corpus/core/src/deploy/build.ts +25 -2
- package/corpus/core/src/eject/remote-mcp-presets.ts +37 -5
- package/corpus/core/src/guards/explicit-collab-access.ts +229 -0
- package/corpus/core/src/guards/index.ts +1 -0
- package/corpus/core/src/localization/default-messages.ts +54 -5
- package/corpus/core/src/mcp/connect-route.ts +34 -51
- package/corpus/core/src/provider-api/index.ts +1 -1
- package/corpus/core/src/realtime-protocol.ts +92 -0
- package/corpus/core/src/server/collab-plugin.ts +137 -18
- package/corpus/core/src/server/core-routes-plugin.ts +7 -0
- package/corpus/core/src/server/index.ts +2 -0
- package/corpus/core/src/server/poll-events.ts +29 -8
- package/corpus/core/src/server/poll.ts +1123 -865
- package/corpus/core/src/server/realtime-token.ts +106 -0
- package/corpus/core/src/server/sentry-config.ts +40 -0
- package/corpus/core/src/server/short-lived-token.ts +156 -0
- package/corpus/core/src/server/sse.ts +15 -0
- package/corpus/core/src/server/ssr-handler.ts +9 -3
- package/corpus/core/src/styles/agent-native.css +40 -0
- package/corpus/core/src/templates/default/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
- package/corpus/core/src/templates/default/.agents/skills/real-time-collab/SKILL.md +35 -13
- package/corpus/core/src/templates/default/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/corpus/core/src/templates/headless/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
- package/corpus/core/src/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
- package/corpus/core/src/templates/workspace-core/.agents/skills/real-time-collab/SKILL.md +35 -13
- package/corpus/core/src/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/corpus/core/src/templates/workspace-core/.agents/skills/voice-transcription/SKILL.md +12 -8
- package/corpus/templates/analytics/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
- package/corpus/templates/analytics/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/corpus/templates/analytics/AGENTS.md +7 -2
- package/corpus/templates/analytics/actions/export-dashboard-panel-to-google-sheet.ts +144 -0
- package/corpus/templates/analytics/app/components/layout/Layout.tsx +7 -88
- package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +34 -37
- package/corpus/templates/analytics/app/global.css +0 -4
- package/corpus/templates/analytics/app/hooks/use-navigation-state.ts +2 -7
- package/corpus/templates/analytics/app/i18n-data.ts +107 -0
- package/corpus/templates/analytics/app/lib/data-source-status.ts +9 -0
- package/corpus/templates/analytics/app/lib/sql-query.ts +1 -2
- package/corpus/templates/analytics/app/pages/Ask.tsx +2 -7
- package/corpus/templates/analytics/app/pages/DataSources.tsx +48 -0
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/SqlChartCard.tsx +59 -0
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +2 -0
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/report-panel-window.ts +3 -1
- package/corpus/templates/analytics/changelog/2026-07-22-clear-background-chat-progress.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-22-daily-dashboard-email-query-batches.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-22-export-table-panels-directly-to-google-sheets.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-22-full-page-chat-keeps-the-active-conversation-when-moving-to-.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-22-recent-chats-can-expand-in-the-sidebar.md +6 -0
- package/corpus/templates/analytics/seeds/dashboards/agent-native-templates-first-party.json +8 -8
- package/corpus/templates/analytics/server/lib/canonical-first-party-dashboard-repair.ts +31 -0
- package/corpus/templates/analytics/server/lib/dashboard-report-subscriptions.ts +3 -5
- package/corpus/templates/analytics/server/lib/dashboard-report.ts +12 -0
- package/corpus/templates/analytics/server/lib/first-party-dashboard-repair.ts +3 -5
- package/corpus/templates/analytics/server/lib/first-party-metric-catalog.ts +150 -21
- package/corpus/templates/analytics/server/lib/google-sheets-export.ts +188 -0
- package/corpus/templates/analytics/server/lib/provider-api.ts +7 -2
- package/corpus/templates/analytics/server/plugins/collab.ts +6 -3
- package/corpus/templates/analytics/shared/sql-query-limits.ts +1 -0
- package/corpus/templates/assets/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
- package/corpus/templates/assets/.agents/skills/real-time-collab/SKILL.md +35 -13
- package/corpus/templates/assets/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/corpus/templates/assets/app/components/layout/Layout.tsx +1 -1
- package/corpus/templates/assets/app/components/layout/Sidebar.tsx +54 -62
- package/corpus/templates/assets/app/hooks/use-navigation-state.ts +2 -6
- package/corpus/templates/assets/app/routes/_index.tsx +8 -5
- package/corpus/templates/assets/changelog/2026-07-22-full-page-chat-keeps-the-active-conversation-when-moving-to-.md +6 -0
- package/corpus/templates/assets/changelog/2026-07-22-recent-chats-expand-from-a-compact-list.md +6 -0
- package/corpus/templates/brain/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
- package/corpus/templates/brain/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/corpus/templates/brain/actions/rotate-source-ingest-token.ts +77 -0
- package/corpus/templates/brain/app/components/layout/Layout.tsx +5 -1
- package/corpus/templates/brain/app/components/layout/Sidebar.tsx +38 -51
- package/corpus/templates/brain/app/hooks/use-navigation-state.ts +2 -9
- package/corpus/templates/brain/app/i18n-data.ts +120 -0
- package/corpus/templates/brain/app/routes/sources.tsx +156 -5
- package/corpus/templates/brain/changelog/2026-07-22-chat-runs-always-end-with-an-answer.md +6 -0
- package/corpus/templates/brain/changelog/2026-07-22-clear-background-chat-progress.md +6 -0
- package/corpus/templates/brain/changelog/2026-07-22-compact-sidebar-footer.md +6 -0
- package/corpus/templates/brain/changelog/2026-07-22-full-page-chat-keeps-the-active-conversation-when-moving-to-.md +6 -0
- package/corpus/templates/brain/changelog/2026-07-22-long-chat-titles-stay-inside-the-sidebar.md +6 -0
- package/corpus/templates/brain/changelog/2026-07-22-new-clips-and-webhook-sources-now-show-their-secure-connecti.md +6 -0
- package/corpus/templates/brain/jobs/emit-netlify-brain-queue-cron.ts +125 -0
- package/corpus/templates/brain/netlify.toml +5 -1
- package/corpus/templates/brain/scripts/configure-prod-clips-source.ts +50 -0
- package/corpus/templates/brain/server/lib/capture-sanitization.ts +64 -6
- package/corpus/templates/brain/server/plugins/agent-chat.ts +4 -0
- package/corpus/templates/brain/server/plugins/brain-jobs.ts +1 -0
- package/corpus/templates/brain/server/routes/api/brain/queue/run.post.ts +55 -0
- package/corpus/templates/calendar/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
- package/corpus/templates/calendar/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/corpus/templates/chat/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
- package/corpus/templates/chat/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/corpus/templates/chat/app/components/layout/Layout.tsx +1 -0
- package/corpus/templates/chat/app/components/layout/Sidebar.tsx +43 -67
- package/corpus/templates/chat/app/hooks/use-navigation-state.ts +2 -7
- package/corpus/templates/chat/app/routes/_index.tsx +8 -5
- package/corpus/templates/chat/changelog/2026-07-22-compact-sidebar-footer.md +6 -0
- package/corpus/templates/chat/changelog/2026-07-22-full-page-chat-keeps-the-active-conversation-when-moving-to-.md +6 -0
- package/corpus/templates/chat/changelog/2026-07-22-recent-chats-are-easier-to-scan-and-expand.md +6 -0
- package/corpus/templates/clips/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
- package/corpus/templates/clips/AGENTS.md +9 -1
- package/corpus/templates/clips/actions/export-to-brain.ts +82 -6
- package/corpus/templates/clips/actions/request-transcript.ts +25 -14
- package/corpus/templates/clips/app/components/sharing/share-ui.tsx +12 -0
- package/corpus/templates/clips/app/i18n/en-US.ts +1 -0
- package/corpus/templates/clips/changelog/2026-07-22-clips-transcripts-now-retry-brain-export.md +5 -0
- package/corpus/templates/clips/changelog/2026-07-22-german-umlauts-and-other-non-ascii-characters-now-paste-corr.md +6 -0
- package/corpus/templates/clips/desktop/src-tauri/src/clips/mod.rs +26 -3
- package/corpus/templates/clips/jobs/emit-netlify-brain-export-cron.ts +118 -0
- package/corpus/templates/clips/netlify.toml +4 -1
- package/corpus/templates/clips/scripts/configure-prod-brain-export.ts +92 -0
- package/corpus/templates/clips/server/jobs/brain-export.ts +182 -0
- package/corpus/templates/clips/server/lib/brain-export-state.ts +42 -0
- package/corpus/templates/clips/server/lib/post-finalize-dispatch.ts +5 -1
- package/corpus/templates/clips/server/plugins/calendar-jobs.ts +2 -0
- package/corpus/templates/clips/server/register-secrets.ts +42 -0
- package/corpus/templates/clips/server/routes/api/_agent-native-background/post-finalize-worker.post.ts +10 -1
- package/corpus/templates/clips/server/routes/api/clips/brain-export/run.post.ts +45 -0
- package/corpus/templates/content/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
- package/corpus/templates/content/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/corpus/templates/content/app/components/editor/DocumentProperties.tsx +566 -299
- package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +14 -0
- package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +1 -1
- package/corpus/templates/content/app/i18n-data.ts +90 -0
- package/corpus/templates/content/server/plugins/collab.ts +1 -1
- package/corpus/templates/crm/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
- package/corpus/templates/crm/actions/_crm-data-program-actions.ts +15 -0
- package/corpus/templates/crm/actions/get-crm-dashboard-panel.ts +2 -0
- package/corpus/templates/crm/actions/run.ts +2 -6
- package/corpus/templates/crm/actions/update-crm-record.ts +4 -2
- package/corpus/templates/crm/app/components/layout/CrmLayout.tsx +6 -0
- package/corpus/templates/crm/changelog/2026-07-22-crm-field-validation-now-explains-which-fields-cannot-be-edi.md +6 -0
- package/corpus/templates/crm/changelog/2026-07-22-fixed-hubspot-contact-syncs-missing-records-updated-after-th.md +6 -0
- package/corpus/templates/crm/changelog/2026-07-22-fixed-pipeline-dashboard-panels-so-their-opportunity-data-lo.md +6 -0
- package/corpus/templates/crm/changelog/2026-07-22-full-page-chat-keeps-the-active-conversation-when-moving-to-.md +6 -0
- package/corpus/templates/crm/server/crm/hubspot-adapter.ts +4 -1
- package/corpus/templates/design/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
- package/corpus/templates/design/app/components/layout/Sidebar.tsx +1 -1
- package/corpus/templates/design/server/plugins/collab.ts +11 -8
- package/corpus/templates/dispatch/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
- package/corpus/templates/forms/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
- package/corpus/templates/forms/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/corpus/templates/forms/app/components/layout/Layout.tsx +1 -0
- package/corpus/templates/forms/app/components/layout/Sidebar.tsx +1 -1
- package/corpus/templates/forms/app/hooks/use-navigation-state.ts +2 -9
- package/corpus/templates/forms/app/root.tsx +1 -6
- package/corpus/templates/forms/changelog/2026-07-22-full-page-chat-keeps-the-active-conversation-when-moving-to-.md +6 -0
- package/corpus/templates/macros/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
- package/corpus/templates/mail/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
- package/corpus/templates/mail/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/corpus/templates/mail/app/components/layout/AppLayout.tsx +2 -2
- package/corpus/templates/plan/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
- package/corpus/templates/plan/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/corpus/templates/plan/app/components/layout/Layout.tsx +5 -1
- package/corpus/templates/plan/app/components/layout/Sidebar.tsx +57 -72
- package/corpus/templates/plan/app/hooks/use-navigation-state.ts +2 -9
- package/corpus/templates/plan/app/lib/create-plan-routing.ts +2 -2
- package/corpus/templates/plan/app/pages/PlanChatPage.tsx +0 -1
- package/corpus/templates/plan/changelog/2026-07-22-compact-sidebar-footer.md +6 -0
- package/corpus/templates/plan/changelog/2026-07-22-full-page-chat-keeps-the-active-conversation-when-moving-to-.md +6 -0
- package/corpus/templates/plan/changelog/2026-07-22-recent-chats-and-sidebar-controls-are-more-compact.md +6 -0
- package/corpus/templates/plan/server/plugins/collab.ts +5 -2
- package/corpus/templates/slides/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
- package/corpus/templates/slides/app/components/layout/Sidebar.tsx +1 -1
- package/corpus/templates/slides/server/plugins/collab.ts +11 -8
- package/corpus/templates/tasks/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
- package/corpus/templates/tasks/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/corpus/templates/tasks/app/components/layout/Sidebar.tsx +5 -22
- package/corpus/templates/tasks/changelog/2026-07-22-compact-sidebar-footer.md +6 -0
- package/corpus/toolkit/CHANGELOG.md +7 -0
- package/corpus/toolkit/README.md +12 -3
- package/corpus/toolkit/package.json +1 -1
- package/corpus/toolkit/src/chat-history/ChatHistoryRail.tsx +89 -0
- package/corpus/toolkit/src/chat-history/index.ts +5 -0
- package/corpus/toolkit/src/chat-history.css +59 -0
- package/corpus/toolkit/src/composer/RealtimeVoiceMode.tsx +106 -36
- package/corpus/toolkit/src/composer/VoiceButton.tsx +49 -0
- package/corpus/toolkit/src/composer/realtime-voice-audio-level.ts +2 -1
- package/corpus/toolkit/src/composer/useRealtimeVoiceMode.tsx +5 -3
- package/corpus/toolkit/src/styles.css +35 -0
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +13 -3
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/cli/doctor.d.ts +1 -1
- package/dist/cli/doctor.d.ts.map +1 -1
- package/dist/cli/doctor.js +5 -2
- package/dist/cli/doctor.js.map +1 -1
- package/dist/client/AgentPanel.d.ts +1 -0
- package/dist/client/AgentPanel.d.ts.map +1 -1
- package/dist/client/AgentPanel.js +38 -18
- package/dist/client/AgentPanel.js.map +1 -1
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +55 -20
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/FeedbackButton.d.ts +4 -2
- package/dist/client/FeedbackButton.d.ts.map +1 -1
- package/dist/client/FeedbackButton.js +18 -2
- package/dist/client/FeedbackButton.js.map +1 -1
- package/dist/client/MultiTabAssistantChat.d.ts +1 -1
- package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
- package/dist/client/MultiTabAssistantChat.js +2 -3
- package/dist/client/MultiTabAssistantChat.js.map +1 -1
- package/dist/client/agent-chat-adapter.d.ts.map +1 -1
- package/dist/client/agent-chat-adapter.js +11 -3
- package/dist/client/agent-chat-adapter.js.map +1 -1
- package/dist/client/agent-page/AgentTabFrame.d.ts +3 -1
- package/dist/client/agent-page/AgentTabFrame.d.ts.map +1 -1
- package/dist/client/agent-page/AgentTabFrame.js +3 -2
- package/dist/client/agent-page/AgentTabFrame.js.map +1 -1
- package/dist/client/agent-page/AgentTabsPage.d.ts +2 -0
- package/dist/client/agent-page/AgentTabsPage.d.ts.map +1 -1
- package/dist/client/agent-page/AgentTabsPage.js +26 -15
- package/dist/client/agent-page/AgentTabsPage.js.map +1 -1
- package/dist/client/analytics.d.ts +10 -0
- package/dist/client/analytics.d.ts.map +1 -1
- package/dist/client/analytics.js.map +1 -1
- package/dist/client/chat/message-components.d.ts +6 -1
- package/dist/client/chat/message-components.d.ts.map +1 -1
- package/dist/client/chat/message-components.js +17 -11
- package/dist/client/chat/message-components.js.map +1 -1
- package/dist/client/chat/tool-call-display.d.ts +11 -1
- package/dist/client/chat/tool-call-display.d.ts.map +1 -1
- package/dist/client/chat/tool-call-display.js +16 -17
- package/dist/client/chat/tool-call-display.js.map +1 -1
- package/dist/client/chat/tool-render-registry.d.ts +2 -0
- package/dist/client/chat/tool-render-registry.d.ts.map +1 -1
- package/dist/client/chat/tool-render-registry.js.map +1 -1
- package/dist/client/resources/McpConnectionSuggestion.d.ts.map +1 -1
- package/dist/client/resources/McpConnectionSuggestion.js +15 -1
- package/dist/client/resources/McpConnectionSuggestion.js.map +1 -1
- package/dist/client/resources/ResourceTree.d.ts.map +1 -1
- package/dist/client/resources/ResourceTree.js +3 -3
- package/dist/client/resources/ResourceTree.js.map +1 -1
- package/dist/client/resources/ResourcesPanel.d.ts +1 -0
- package/dist/client/resources/ResourcesPanel.d.ts.map +1 -1
- package/dist/client/resources/ResourcesPanel.js +34 -20
- package/dist/client/resources/ResourcesPanel.js.map +1 -1
- package/dist/client/resources/mcp-connection-resume.d.ts +11 -0
- package/dist/client/resources/mcp-connection-resume.d.ts.map +1 -0
- package/dist/client/resources/mcp-connection-resume.js +95 -0
- package/dist/client/resources/mcp-connection-resume.js.map +1 -0
- package/dist/client/resources/mcp-integration-catalog.d.ts +1 -0
- package/dist/client/resources/mcp-integration-catalog.d.ts.map +1 -1
- package/dist/client/resources/mcp-integration-catalog.js +63 -8
- package/dist/client/resources/mcp-integration-catalog.js.map +1 -1
- package/dist/client/resources/mcp-integration-logos.d.ts.map +1 -1
- package/dist/client/resources/mcp-integration-logos.js +4 -0
- package/dist/client/resources/mcp-integration-logos.js.map +1 -1
- package/dist/client/sse-event-processor.d.ts +5 -0
- package/dist/client/sse-event-processor.d.ts.map +1 -1
- package/dist/client/sse-event-processor.js +39 -13
- package/dist/client/sse-event-processor.js.map +1 -1
- package/dist/client/use-db-sync.d.ts +4 -3
- package/dist/client/use-db-sync.d.ts.map +1 -1
- package/dist/client/use-db-sync.js +332 -21
- package/dist/client/use-db-sync.js.map +1 -1
- package/dist/collab/client.d.ts.map +1 -1
- package/dist/collab/client.js +26 -2
- package/dist/collab/client.js.map +1 -1
- package/dist/collab/routes.d.ts +1 -1
- package/dist/connections/catalog.d.ts +1 -1
- package/dist/connections/catalog.d.ts.map +1 -1
- package/dist/connections/catalog.js +7 -1
- package/dist/connections/catalog.js.map +1 -1
- package/dist/db/ddl-guard.d.ts +7 -2
- package/dist/db/ddl-guard.d.ts.map +1 -1
- package/dist/db/ddl-guard.js +21 -9
- package/dist/db/ddl-guard.js.map +1 -1
- package/dist/deploy/build.d.ts.map +1 -1
- package/dist/deploy/build.js +25 -2
- package/dist/deploy/build.js.map +1 -1
- package/dist/eject/remote-mcp-presets.d.ts.map +1 -1
- package/dist/eject/remote-mcp-presets.js +33 -3
- package/dist/eject/remote-mcp-presets.js.map +1 -1
- package/dist/guards/explicit-collab-access.d.ts +8 -0
- package/dist/guards/explicit-collab-access.d.ts.map +1 -0
- package/dist/guards/explicit-collab-access.js +214 -0
- package/dist/guards/explicit-collab-access.js.map +1 -0
- package/dist/guards/index.d.ts +1 -0
- package/dist/guards/index.d.ts.map +1 -1
- package/dist/guards/index.js +1 -0
- package/dist/guards/index.js.map +1 -1
- package/dist/localization/default-messages.d.ts +43 -0
- package/dist/localization/default-messages.d.ts.map +1 -1
- package/dist/localization/default-messages.js +48 -5
- package/dist/localization/default-messages.js.map +1 -1
- package/dist/mcp/connect-route.d.ts.map +1 -1
- package/dist/mcp/connect-route.js +34 -48
- package/dist/mcp/connect-route.js.map +1 -1
- package/dist/observability/routes.d.ts +5 -5
- package/dist/provider-api/actions/custom-provider-registration.d.ts +7 -7
- package/dist/provider-api/actions/provider-api.d.ts +7 -7
- package/dist/provider-api/corpus-jobs.d.ts +2 -2
- package/dist/provider-api/index.js +1 -1
- package/dist/provider-api/index.js.map +1 -1
- package/dist/realtime-protocol.d.ts +40 -0
- package/dist/realtime-protocol.d.ts.map +1 -0
- package/dist/realtime-protocol.js +69 -0
- package/dist/realtime-protocol.js.map +1 -0
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/secrets/routes.d.ts +3 -3
- package/dist/server/collab-plugin.d.ts +34 -3
- package/dist/server/collab-plugin.d.ts.map +1 -1
- package/dist/server/collab-plugin.js +65 -12
- package/dist/server/collab-plugin.js.map +1 -1
- package/dist/server/core-routes-plugin.d.ts.map +1 -1
- package/dist/server/core-routes-plugin.js +3 -0
- package/dist/server/core-routes-plugin.js.map +1 -1
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js.map +1 -1
- package/dist/server/poll-events.d.ts +7 -1
- package/dist/server/poll-events.d.ts.map +1 -1
- package/dist/server/poll-events.js +24 -7
- package/dist/server/poll-events.js.map +1 -1
- package/dist/server/poll.d.ts +223 -42
- package/dist/server/poll.d.ts.map +1 -1
- package/dist/server/poll.js +849 -737
- package/dist/server/poll.js.map +1 -1
- package/dist/server/realtime-token.d.ts +34 -0
- package/dist/server/realtime-token.d.ts.map +1 -0
- package/dist/server/realtime-token.js +85 -0
- package/dist/server/realtime-token.js.map +1 -0
- package/dist/server/sentry-config.d.ts +12 -0
- package/dist/server/sentry-config.d.ts.map +1 -1
- package/dist/server/sentry-config.js +34 -0
- package/dist/server/sentry-config.js.map +1 -1
- package/dist/server/short-lived-token.d.ts +46 -0
- package/dist/server/short-lived-token.d.ts.map +1 -1
- package/dist/server/short-lived-token.js +104 -0
- package/dist/server/short-lived-token.js.map +1 -1
- package/dist/server/sse.d.ts +1 -1
- package/dist/server/sse.d.ts.map +1 -1
- package/dist/server/sse.js +4 -0
- package/dist/server/sse.js.map +1 -1
- package/dist/server/ssr-handler.d.ts.map +1 -1
- package/dist/server/ssr-handler.js +5 -3
- package/dist/server/ssr-handler.js.map +1 -1
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/dist/styles/agent-native.css +40 -0
- package/dist/templates/chat/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
- package/dist/templates/chat/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/dist/templates/chat/app/components/layout/Layout.tsx +1 -0
- package/dist/templates/chat/app/components/layout/Sidebar.tsx +43 -67
- package/dist/templates/chat/app/hooks/use-navigation-state.ts +2 -7
- package/dist/templates/chat/app/routes/_index.tsx +8 -5
- package/dist/templates/chat/changelog/2026-07-22-compact-sidebar-footer.md +6 -0
- package/dist/templates/chat/changelog/2026-07-22-full-page-chat-keeps-the-active-conversation-when-moving-to-.md +6 -0
- package/dist/templates/chat/changelog/2026-07-22-recent-chats-are-easier-to-scan-and-expand.md +6 -0
- package/dist/templates/default/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
- package/dist/templates/default/.agents/skills/real-time-collab/SKILL.md +35 -13
- package/dist/templates/default/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/dist/templates/headless/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
- package/dist/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
- package/dist/templates/workspace-core/.agents/skills/real-time-collab/SKILL.md +35 -13
- package/dist/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/dist/templates/workspace-core/.agents/skills/voice-transcription/SKILL.md +12 -8
- package/docs/AGENTS.md +1 -1
- package/docs/content/agent-mentions.mdx +2 -2
- package/docs/content/{workspace.mdx → agent-resources.mdx} +1 -7
- package/docs/content/agent-teams.mdx +4 -4
- package/docs/content/dispatch.mdx +10 -10
- package/docs/content/drop-in-agent.mdx +4 -4
- package/docs/content/external-agents.mdx +1 -1
- package/docs/content/frames.mdx +1 -1
- package/docs/content/integrations.mdx +13 -2
- package/docs/content/key-concepts.mdx +2 -2
- package/docs/content/mcp-clients.mdx +7 -1
- package/docs/content/multi-app-workspace.mdx +3 -3
- package/docs/content/real-time-collaboration.mdx +33 -15
- package/docs/content/recurring-jobs.mdx +7 -7
- package/docs/content/skills-guide.mdx +4 -4
- package/docs/content/template-brain.mdx +1 -1
- package/docs/content/toolkit-collaboration.mdx +1 -1
- package/docs/content/using-your-agent.mdx +1 -1
- package/docs/content/what-is-agent-native.mdx +4 -4
- package/docs/content/workspace-management.mdx +4 -4
- package/package.json +6 -3
- package/src/agent/production-agent.ts +13 -3
- package/src/cli/doctor.ts +6 -1
- package/src/client/AgentPanel.tsx +79 -41
- package/src/client/AssistantChat.tsx +71 -25
- package/src/client/FeedbackButton.tsx +33 -7
- package/src/client/MultiTabAssistantChat.tsx +6 -8
- package/src/client/agent-chat-adapter.ts +11 -2
- package/src/client/agent-page/AgentTabFrame.tsx +22 -3
- package/src/client/agent-page/AgentTabsPage.tsx +34 -19
- package/src/client/analytics.ts +7 -0
- package/src/client/chat/message-components.tsx +43 -16
- package/src/client/chat/tool-call-display.tsx +30 -18
- package/src/client/chat/tool-render-registry.tsx +2 -0
- package/src/client/resources/McpConnectionSuggestion.tsx +19 -2
- package/src/client/resources/ResourceTree.tsx +7 -10
- package/src/client/resources/ResourcesPanel.tsx +33 -70
- package/src/client/resources/mcp-connection-resume.ts +107 -0
- package/src/client/resources/mcp-integration-catalog.ts +65 -12
- package/src/client/resources/mcp-integration-logos.ts +4 -0
- package/src/client/sse-event-processor.ts +50 -14
- package/src/client/use-db-sync.ts +370 -21
- package/src/collab/client.ts +26 -2
- package/src/connections/catalog.ts +7 -1
- package/src/db/ddl-guard.ts +49 -10
- package/src/deploy/build.ts +25 -2
- package/src/eject/remote-mcp-presets.ts +37 -5
- package/src/guards/explicit-collab-access.ts +229 -0
- package/src/guards/index.ts +1 -0
- package/src/localization/default-messages.ts +54 -5
- package/src/mcp/connect-route.ts +34 -51
- package/src/provider-api/index.ts +1 -1
- package/src/realtime-protocol.ts +92 -0
- package/src/server/collab-plugin.ts +137 -18
- package/src/server/core-routes-plugin.ts +7 -0
- package/src/server/index.ts +2 -0
- package/src/server/poll-events.ts +29 -8
- package/src/server/poll.ts +1123 -865
- package/src/server/realtime-token.ts +106 -0
- package/src/server/sentry-config.ts +40 -0
- package/src/server/short-lived-token.ts +156 -0
- package/src/server/sse.ts +15 -0
- package/src/server/ssr-handler.ts +9 -3
- package/src/styles/agent-native.css +40 -0
- package/src/templates/chat/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
- package/src/templates/chat/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/src/templates/chat/app/components/layout/Layout.tsx +1 -0
- package/src/templates/chat/app/components/layout/Sidebar.tsx +43 -67
- package/src/templates/chat/app/hooks/use-navigation-state.ts +2 -7
- package/src/templates/chat/app/routes/_index.tsx +8 -5
- package/src/templates/chat/changelog/2026-07-22-compact-sidebar-footer.md +6 -0
- package/src/templates/chat/changelog/2026-07-22-full-page-chat-keeps-the-active-conversation-when-moving-to-.md +6 -0
- package/src/templates/chat/changelog/2026-07-22-recent-chats-are-easier-to-scan-and-expand.md +6 -0
- package/src/templates/default/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
- package/src/templates/default/.agents/skills/real-time-collab/SKILL.md +35 -13
- package/src/templates/default/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/src/templates/headless/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
- package/src/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
- package/src/templates/workspace-core/.agents/skills/real-time-collab/SKILL.md +35 -13
- package/src/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/src/templates/workspace-core/.agents/skills/voice-transcription/SKILL.md +12 -8
package/src/mcp/connect-route.ts
CHANGED
|
@@ -467,10 +467,6 @@ function renderConnectPage(params: {
|
|
|
467
467
|
});
|
|
468
468
|
const safeMcpUrl = escapeHtml(mcpUrl);
|
|
469
469
|
const connectTemplateValues = { appName, appUrl, mcpUrl, serverId };
|
|
470
|
-
const brandMarkSvg = agentNativeMarkSvg(
|
|
471
|
-
"brand-mark",
|
|
472
|
-
"agent-native-connect-brand-gradient",
|
|
473
|
-
);
|
|
474
470
|
const flowMarkSvg = agentNativeMarkSvg(
|
|
475
471
|
"flow-mark",
|
|
476
472
|
"agent-native-connect-flow-gradient",
|
|
@@ -561,21 +557,6 @@ function renderConnectPage(params: {
|
|
|
561
557
|
0 30px 90px rgba(0,0,0,0.5);
|
|
562
558
|
padding: 1.25rem;
|
|
563
559
|
}
|
|
564
|
-
.topbar {
|
|
565
|
-
display: flex; align-items: center; justify-content: space-between;
|
|
566
|
-
gap: 0.75rem; margin-bottom: 1.75rem;
|
|
567
|
-
}
|
|
568
|
-
.brand-lockup {
|
|
569
|
-
display: flex; align-items: center; gap: 0.55rem;
|
|
570
|
-
color: var(--muted); font-size: 0.78rem; font-weight: 600;
|
|
571
|
-
}
|
|
572
|
-
.brand-mark { width: 18px; height: auto; display: block; }
|
|
573
|
-
.app-pill {
|
|
574
|
-
max-width: 50%; border: 1px solid var(--border);
|
|
575
|
-
border-radius: 999px; padding: 0.28rem 0.55rem;
|
|
576
|
-
color: var(--subtle); font-size: 0.72rem; line-height: 1;
|
|
577
|
-
overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
|
578
|
-
}
|
|
579
560
|
.hero { padding: 0 0.75rem; text-align: center; }
|
|
580
561
|
.flow {
|
|
581
562
|
display: flex; align-items: center; justify-content: center;
|
|
@@ -597,11 +578,6 @@ function renderConnectPage(params: {
|
|
|
597
578
|
background: linear-gradient(90deg, transparent, var(--border-strong), transparent);
|
|
598
579
|
background-position: center;
|
|
599
580
|
}
|
|
600
|
-
.eyebrow {
|
|
601
|
-
text-align: center; font-size: 0.72rem; font-weight: 600;
|
|
602
|
-
letter-spacing: 0.08em; text-transform: uppercase;
|
|
603
|
-
color: var(--subtle); margin-bottom: 0.55rem;
|
|
604
|
-
}
|
|
605
581
|
h1 {
|
|
606
582
|
text-align: center; font-size: 1.45rem; font-weight: 680;
|
|
607
583
|
line-height: 1.25; margin-bottom: 0.7rem;
|
|
@@ -714,8 +690,7 @@ function renderConnectPage(params: {
|
|
|
714
690
|
.connections-title { font-weight: 600; color: var(--muted); }
|
|
715
691
|
.connections-state {
|
|
716
692
|
margin-left: auto; color: var(--subtle); font-size: 0.73rem;
|
|
717
|
-
|
|
718
|
-
padding: 0.18rem 0.45rem; line-height: 1;
|
|
693
|
+
line-height: 1;
|
|
719
694
|
}
|
|
720
695
|
.connections .chev {
|
|
721
696
|
width: 7px; height: 7px; border-right: 1.5px solid currentColor;
|
|
@@ -738,8 +713,16 @@ function renderConnectPage(params: {
|
|
|
738
713
|
margin-bottom: 0.9rem; display: none; line-height: 1.4; }
|
|
739
714
|
.msg.err { display: block; color: var(--error); background: var(--error-bg);
|
|
740
715
|
border: 1px solid rgba(252,165,165,0.16); }
|
|
741
|
-
.msg.ok { display: block;
|
|
716
|
+
.msg.ok { display: block; background: var(--ok-bg);
|
|
742
717
|
border: 1px solid var(--ok-border); }
|
|
718
|
+
.msg-title {
|
|
719
|
+
display: block; color: var(--ok); font-size: 0.95rem;
|
|
720
|
+
font-weight: 700; line-height: 1.25;
|
|
721
|
+
}
|
|
722
|
+
.msg-copy {
|
|
723
|
+
display: block; color: rgba(134,239,172,0.72); font-size: 0.78rem;
|
|
724
|
+
line-height: 1.4; margin-top: 0.2rem;
|
|
725
|
+
}
|
|
743
726
|
.result-panel { padding-top: 0.15rem; }
|
|
744
727
|
.result-title {
|
|
745
728
|
color: var(--text); font-size: 0.95rem; font-weight: 650;
|
|
@@ -757,9 +740,7 @@ function renderConnectPage(params: {
|
|
|
757
740
|
body { align-items: flex-start; padding: 0.75rem; }
|
|
758
741
|
.card { padding: 1rem; }
|
|
759
742
|
.hero { padding: 0; }
|
|
760
|
-
.topbar { margin-bottom: 1.35rem; }
|
|
761
743
|
h1 { font-size: 1.3rem; }
|
|
762
|
-
.app-pill { max-width: 46%; }
|
|
763
744
|
pre { font-size: 0.72rem; }
|
|
764
745
|
}
|
|
765
746
|
/* MCP URL display + per-host tabs (the non-dev path). */
|
|
@@ -861,9 +842,6 @@ function renderConnectPage(params: {
|
|
|
861
842
|
border-color: var(--ok-border) !important;
|
|
862
843
|
}
|
|
863
844
|
.static-token-mint .static-token-body { padding-top: 0.5rem; }
|
|
864
|
-
.static-token-mint > summary .connections-state {
|
|
865
|
-
font-style: normal;
|
|
866
|
-
}
|
|
867
845
|
@media (min-width: 560px) {
|
|
868
846
|
.card { max-width: 580px; }
|
|
869
847
|
}
|
|
@@ -872,17 +850,8 @@ function renderConnectPage(params: {
|
|
|
872
850
|
</head>
|
|
873
851
|
<body>
|
|
874
852
|
<div class="card">
|
|
875
|
-
<div class="topbar">
|
|
876
|
-
<div class="brand-lockup">
|
|
877
|
-
${brandMarkSvg}
|
|
878
|
-
<span>Agent Native</span>
|
|
879
|
-
</div>
|
|
880
|
-
<div class="app-pill" title="${safeApp}">${safeApp}</div>
|
|
881
|
-
</div>
|
|
882
|
-
|
|
883
853
|
<div class="hero">
|
|
884
|
-
|
|
885
|
-
<div class="flow" role="img" aria-label="Connect an external agent to ${safeApp}">
|
|
854
|
+
<div class="flow" role="img" aria-label="Authorize ${safeApp}">
|
|
886
855
|
<span class="tile" aria-hidden="true">
|
|
887
856
|
${flowMarkSvg}
|
|
888
857
|
</span>
|
|
@@ -892,7 +861,6 @@ function renderConnectPage(params: {
|
|
|
892
861
|
</span>
|
|
893
862
|
</div>
|
|
894
863
|
|
|
895
|
-
<div class="eyebrow">Connect an external agent</div>
|
|
896
864
|
<h1>${safeUserCode ? `Authorize ${safeApp} from your terminal?` : `Use ${safeApp} from your AI assistant`}</h1>
|
|
897
865
|
<p class="identity">
|
|
898
866
|
<span>Signed in as <strong>${safeEmail}</strong></span>
|
|
@@ -909,7 +877,6 @@ function renderConnectPage(params: {
|
|
|
909
877
|
<details id="staticTokenMint" class="connections static-token-mint"${safeUserCode ? " open" : ""}>
|
|
910
878
|
<summary>
|
|
911
879
|
<span class="connections-title">${safeUserCode ? "Authorize this device" : MCP_STATIC_TOKEN_FALLBACK.title}</span>
|
|
912
|
-
<span class="connections-state">${safeUserCode ? "From your terminal" : MCP_STATIC_TOKEN_FALLBACK.state}</span>
|
|
913
880
|
<span class="chev" aria-hidden="true"></span>
|
|
914
881
|
</summary>
|
|
915
882
|
<div class="static-token-body">
|
|
@@ -939,7 +906,7 @@ function renderConnectPage(params: {
|
|
|
939
906
|
<details id="connections" class="connections">
|
|
940
907
|
<summary>
|
|
941
908
|
<span class="connections-title">Existing connections</span>
|
|
942
|
-
<span id="connectionsState" class="connections-state"
|
|
909
|
+
<span id="connectionsState" class="connections-state hidden" aria-live="polite"></span>
|
|
943
910
|
<span class="chev" aria-hidden="true"></span>
|
|
944
911
|
</summary>
|
|
945
912
|
<div id="tokenList" class="token-list"><div class="empty-state">Checking connections...</div></div>
|
|
@@ -990,8 +957,20 @@ function renderConnectPage(params: {
|
|
|
990
957
|
}, 1400);
|
|
991
958
|
});
|
|
992
959
|
});
|
|
993
|
-
function showMsg(text, kind) {
|
|
994
|
-
msgEl.textContent =
|
|
960
|
+
function showMsg(text, kind, title) {
|
|
961
|
+
msgEl.textContent = "";
|
|
962
|
+
if (title) {
|
|
963
|
+
var titleEl = document.createElement("strong");
|
|
964
|
+
titleEl.className = "msg-title";
|
|
965
|
+
titleEl.textContent = title;
|
|
966
|
+
msgEl.appendChild(titleEl);
|
|
967
|
+
var copyEl = document.createElement("span");
|
|
968
|
+
copyEl.className = "msg-copy";
|
|
969
|
+
copyEl.textContent = text;
|
|
970
|
+
msgEl.appendChild(copyEl);
|
|
971
|
+
} else {
|
|
972
|
+
msgEl.textContent = text;
|
|
973
|
+
}
|
|
995
974
|
msgEl.className = "msg " + (kind || "err");
|
|
996
975
|
}
|
|
997
976
|
function clearMsg() { msgEl.className = "msg"; msgEl.textContent = ""; }
|
|
@@ -1039,19 +1018,22 @@ function renderConnectPage(params: {
|
|
|
1039
1018
|
var res = await fetch(BASE + "/tokens", { credentials: "same-origin" });
|
|
1040
1019
|
if (!res.ok) {
|
|
1041
1020
|
connectionsStateEl.textContent = "Unavailable";
|
|
1021
|
+
connectionsStateEl.classList.remove("hidden");
|
|
1042
1022
|
listEl.innerHTML = '<div class="empty-state">Could not load connections.</div>';
|
|
1043
1023
|
return;
|
|
1044
1024
|
}
|
|
1045
1025
|
var data = await res.json();
|
|
1046
1026
|
var tokens = (data && data.tokens) || [];
|
|
1047
1027
|
if (!tokens.length) {
|
|
1048
|
-
connectionsStateEl.textContent = "
|
|
1028
|
+
connectionsStateEl.textContent = "";
|
|
1029
|
+
connectionsStateEl.classList.add("hidden");
|
|
1049
1030
|
connectionsEl.open = false;
|
|
1050
1031
|
listEl.innerHTML = '<div class="empty-state">Created connections will appear here for revoking later.</div>';
|
|
1051
1032
|
return;
|
|
1052
1033
|
}
|
|
1053
1034
|
var activeCount = tokens.filter(function (t) { return !t.revokedAt; }).length;
|
|
1054
|
-
connectionsStateEl.textContent = activeCount
|
|
1035
|
+
connectionsStateEl.textContent = activeCount ? String(activeCount) : "";
|
|
1036
|
+
connectionsStateEl.classList.toggle("hidden", activeCount === 0);
|
|
1055
1037
|
listEl.innerHTML = "";
|
|
1056
1038
|
tokens.forEach(function (t) {
|
|
1057
1039
|
var div = document.createElement("div");
|
|
@@ -1082,6 +1064,7 @@ function renderConnectPage(params: {
|
|
|
1082
1064
|
});
|
|
1083
1065
|
} catch (e) {
|
|
1084
1066
|
connectionsStateEl.textContent = "Unavailable";
|
|
1067
|
+
connectionsStateEl.classList.remove("hidden");
|
|
1085
1068
|
listEl.innerHTML = '<div class="empty-state">Could not load connections.</div>';
|
|
1086
1069
|
}
|
|
1087
1070
|
}
|
|
@@ -1098,7 +1081,7 @@ function renderConnectPage(params: {
|
|
|
1098
1081
|
showMsg((a.data && a.data.error) || "Could not authorize this device code.");
|
|
1099
1082
|
return;
|
|
1100
1083
|
}
|
|
1101
|
-
showMsg("
|
|
1084
|
+
showMsg("Finishing connection… you can return to your terminal.", "ok", "Device authorized");
|
|
1102
1085
|
btn.classList.add("hidden");
|
|
1103
1086
|
document.getElementById("mintForm").classList.add("hidden");
|
|
1104
1087
|
var cc = document.getElementById("codeCallout");
|
|
@@ -1133,7 +1116,7 @@ function renderConnectPage(params: {
|
|
|
1133
1116
|
});
|
|
1134
1117
|
if (fresh.length > 0) {
|
|
1135
1118
|
clearInterval(iv);
|
|
1136
|
-
showMsg("
|
|
1119
|
+
showMsg("This device can now act as you — manage or revoke it below.", "ok", "Connected");
|
|
1137
1120
|
loadTokens();
|
|
1138
1121
|
return;
|
|
1139
1122
|
}
|
|
@@ -1100,7 +1100,7 @@ const PROVIDER_CONFIGS: Record<ProviderApiId, ProviderApiConfig> = {
|
|
|
1100
1100
|
docsUrls: ["https://developers.google.com/drive/api/reference/rest/v3"],
|
|
1101
1101
|
specUrls: ["https://www.googleapis.com/discovery/v1/apis/drive/v3/rest"],
|
|
1102
1102
|
allowedHostSuffixes: ["googleapis.com"],
|
|
1103
|
-
templateUses: ["brain", "content", "slides", "dispatch"],
|
|
1103
|
+
templateUses: ["brain", "content", "slides", "dispatch", "analytics"],
|
|
1104
1104
|
examples: [
|
|
1105
1105
|
{ label: "List files", method: "GET", path: "/files" },
|
|
1106
1106
|
{ label: "Get file metadata", method: "GET", path: "/files/{fileId}" },
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Realtime SSE wire protocol — shared by the server SSE handlers (framework
|
|
3
|
+
* in-process path + the hosted Realtime Gateway) and the client transport.
|
|
4
|
+
*
|
|
5
|
+
* Pure constants, types, and parsers only — NO h3/node/browser deps — so both
|
|
6
|
+
* the Node server and the browser client import it.
|
|
7
|
+
*
|
|
8
|
+
* Frame taxonomy:
|
|
9
|
+
* - CHANGE / batch frames ride the default (unnamed) SSE `message` event and
|
|
10
|
+
* are parsed by the client's existing `normalizeEventPayload`. Unchanged.
|
|
11
|
+
* - CONTROL frames (handshake, token rotation) ride NAMED SSE events, so
|
|
12
|
+
* `EventSource.addEventListener(name)` routes them separately and an older
|
|
13
|
+
* client that only reads `onmessage` silently ignores them (backward safe).
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
export const REALTIME_PROTOCOL_VERSION = 1;
|
|
17
|
+
|
|
18
|
+
/** Named SSE event carrying the one-time handshake ({@link RealtimeHandshake}). */
|
|
19
|
+
export const REALTIME_SSE_HANDSHAKE_EVENT = "handshake";
|
|
20
|
+
/** Named SSE event carrying a rotated subscribe token ({@link RealtimeTokenFrame}). */
|
|
21
|
+
export const REALTIME_SSE_TOKEN_EVENT = "token";
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Capability advertised by the hosted gateway: awareness/presence is NOT
|
|
25
|
+
* forwarded (it lives only on the in-process emitter, never in `sync_events`),
|
|
26
|
+
* so the collab client must keep its own presence cadence. The framework's
|
|
27
|
+
* in-process SSE path forwards awareness and therefore sends no handshake — the
|
|
28
|
+
* client treats an absent handshake as "all capabilities present."
|
|
29
|
+
*/
|
|
30
|
+
export const REALTIME_CAP_NO_AWARENESS = "no-awareness";
|
|
31
|
+
|
|
32
|
+
export interface RealtimeHandshake {
|
|
33
|
+
protocol: number;
|
|
34
|
+
capabilities: string[];
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface RealtimeTokenFrame {
|
|
38
|
+
token: string;
|
|
39
|
+
/** ISO expiry, informational; the client re-mints/rotates before this. */
|
|
40
|
+
expiresAt?: string;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function buildHandshakeFrame(
|
|
44
|
+
capabilities: readonly string[] = [],
|
|
45
|
+
): RealtimeHandshake {
|
|
46
|
+
return {
|
|
47
|
+
protocol: REALTIME_PROTOCOL_VERSION,
|
|
48
|
+
capabilities: [...capabilities],
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function parseHandshakeFrame(data: string): RealtimeHandshake | null {
|
|
53
|
+
try {
|
|
54
|
+
const parsed = JSON.parse(data);
|
|
55
|
+
if (
|
|
56
|
+
parsed &&
|
|
57
|
+
typeof parsed === "object" &&
|
|
58
|
+
typeof parsed.protocol === "number" &&
|
|
59
|
+
Array.isArray(parsed.capabilities)
|
|
60
|
+
) {
|
|
61
|
+
return {
|
|
62
|
+
protocol: parsed.protocol,
|
|
63
|
+
capabilities: parsed.capabilities.filter(
|
|
64
|
+
(c: unknown): c is string => typeof c === "string",
|
|
65
|
+
),
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
} catch {
|
|
69
|
+
// fall through
|
|
70
|
+
}
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export function parseTokenFrame(data: string): RealtimeTokenFrame | null {
|
|
75
|
+
try {
|
|
76
|
+
const parsed = JSON.parse(data);
|
|
77
|
+
if (
|
|
78
|
+
parsed &&
|
|
79
|
+
typeof parsed === "object" &&
|
|
80
|
+
typeof parsed.token === "string"
|
|
81
|
+
) {
|
|
82
|
+
return {
|
|
83
|
+
token: parsed.token,
|
|
84
|
+
expiresAt:
|
|
85
|
+
typeof parsed.expiresAt === "string" ? parsed.expiresAt : undefined,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
} catch {
|
|
89
|
+
// fall through
|
|
90
|
+
}
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
@@ -5,7 +5,11 @@
|
|
|
5
5
|
* ```ts
|
|
6
6
|
* // server/plugins/collab.ts
|
|
7
7
|
* import { createCollabPlugin } from "@agent-native/core/server";
|
|
8
|
-
* export default createCollabPlugin({
|
|
8
|
+
* export default createCollabPlugin({
|
|
9
|
+
* table: "documents",
|
|
10
|
+
* contentColumn: "content",
|
|
11
|
+
* access: { mode: "resource", resourceType: "document" },
|
|
12
|
+
* });
|
|
9
13
|
* ```
|
|
10
14
|
*/
|
|
11
15
|
|
|
@@ -52,12 +56,47 @@ type CollabAwarenessScope = {
|
|
|
52
56
|
resourceId?: string;
|
|
53
57
|
};
|
|
54
58
|
|
|
59
|
+
export type CollabResourceIdResolver = (
|
|
60
|
+
docId: string,
|
|
61
|
+
) => string | null | Promise<string | null>;
|
|
62
|
+
|
|
63
|
+
export type CollabAccess =
|
|
64
|
+
| {
|
|
65
|
+
mode: "resource";
|
|
66
|
+
/** The shareable resource type registered via `registerShareableResource`. */
|
|
67
|
+
resourceType: string;
|
|
68
|
+
/** Map a collab document id to its parent shareable resource id. */
|
|
69
|
+
resolveResourceId?: CollabResourceIdResolver;
|
|
70
|
+
}
|
|
71
|
+
| {
|
|
72
|
+
/** Deliver collaboration events to every authenticated user. */
|
|
73
|
+
mode: "all-authenticated";
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
type NormalizedCollabAccess =
|
|
77
|
+
| {
|
|
78
|
+
mode: "resource";
|
|
79
|
+
resourceType: string;
|
|
80
|
+
resolveResourceId?: CollabResourceIdResolver;
|
|
81
|
+
}
|
|
82
|
+
| {
|
|
83
|
+
mode: "all-authenticated";
|
|
84
|
+
explicit: boolean;
|
|
85
|
+
};
|
|
86
|
+
|
|
55
87
|
/**
|
|
56
|
-
*
|
|
57
|
-
* process. Avoids
|
|
58
|
-
*
|
|
88
|
+
* Tables whose implicit all-authenticated warning has already been logged in
|
|
89
|
+
* this process. Avoids duplicate warnings during hot reloads while still
|
|
90
|
+
* identifying every affected table.
|
|
59
91
|
*/
|
|
60
|
-
|
|
92
|
+
const COLLAB_WARNING_TABLES_KEY =
|
|
93
|
+
"__agentNativeImplicitCollabAccessWarningTables__";
|
|
94
|
+
const collabWarningGlobal = globalThis as typeof globalThis & {
|
|
95
|
+
[COLLAB_WARNING_TABLES_KEY]?: Set<string>;
|
|
96
|
+
};
|
|
97
|
+
const _unscoped_warning_tables = (collabWarningGlobal[
|
|
98
|
+
COLLAB_WARNING_TABLES_KEY
|
|
99
|
+
] ??= new Set<string>());
|
|
61
100
|
|
|
62
101
|
export interface CollabPluginOptions {
|
|
63
102
|
/** Table name containing document content. Default: "documents" */
|
|
@@ -77,18 +116,25 @@ export interface CollabPluginOptions {
|
|
|
77
116
|
contentType?: "text" | "json";
|
|
78
117
|
/** Column name for JSON content (used when contentType is "json"). */
|
|
79
118
|
jsonColumn?: string;
|
|
119
|
+
/**
|
|
120
|
+
* Access policy for collaboration routes and event delivery.
|
|
121
|
+
* Use `resource` for registered shareable resources, or explicitly choose
|
|
122
|
+
* `all-authenticated` for deployment-wide collaboration.
|
|
123
|
+
*/
|
|
124
|
+
access?: CollabAccess;
|
|
80
125
|
/**
|
|
81
126
|
* The shareable resource type registered via `registerShareableResource`.
|
|
82
127
|
* Used to enforce access checks on collab routes.
|
|
83
|
-
*
|
|
128
|
+
* @deprecated Use `access: { mode: "resource", resourceType }`.
|
|
84
129
|
*/
|
|
85
130
|
resourceType?: string;
|
|
86
131
|
/**
|
|
87
132
|
* Map the collab document id to the shareable resource id. Many templates
|
|
88
133
|
* use route-specific collab ids (for example, one doc per slide inside a
|
|
89
134
|
* deck) while sharing is enforced at the parent resource level.
|
|
135
|
+
* @deprecated Use `access: { mode: "resource", resourceType, resolveResourceId }`.
|
|
90
136
|
*/
|
|
91
|
-
resolveResourceId?:
|
|
137
|
+
resolveResourceId?: CollabResourceIdResolver;
|
|
92
138
|
/**
|
|
93
139
|
* Maximum allowed body size in bytes for write operations
|
|
94
140
|
* (update/text/json/patch). Requests exceeding this are rejected with 413.
|
|
@@ -97,18 +143,100 @@ export interface CollabPluginOptions {
|
|
|
97
143
|
maxPayloadBytes?: number;
|
|
98
144
|
}
|
|
99
145
|
|
|
146
|
+
export function normalizeCollabAccess(
|
|
147
|
+
options: Pick<
|
|
148
|
+
CollabPluginOptions,
|
|
149
|
+
"access" | "resourceType" | "resolveResourceId"
|
|
150
|
+
>,
|
|
151
|
+
): NormalizedCollabAccess {
|
|
152
|
+
const hasLegacyAccess =
|
|
153
|
+
options.resourceType !== undefined ||
|
|
154
|
+
options.resolveResourceId !== undefined;
|
|
155
|
+
|
|
156
|
+
if (options.access && hasLegacyAccess) {
|
|
157
|
+
throw new Error(
|
|
158
|
+
'createCollabPlugin cannot combine "access" with the deprecated root "resourceType" or "resolveResourceId" options. Move those fields into access.',
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (options.access?.mode === "resource") {
|
|
163
|
+
if (!options.access.resourceType.trim()) {
|
|
164
|
+
throw new Error(
|
|
165
|
+
'createCollabPlugin access mode "resource" requires a non-empty resourceType.',
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
return options.access;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
if (options.access?.mode === "all-authenticated") {
|
|
172
|
+
return { mode: "all-authenticated", explicit: true };
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
if (options.access) {
|
|
176
|
+
throw new Error(
|
|
177
|
+
`createCollabPlugin received an unsupported access mode: ${String((options.access as { mode?: unknown }).mode)}`,
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
if (options.resourceType !== undefined) {
|
|
182
|
+
if (!options.resourceType.trim()) {
|
|
183
|
+
throw new Error(
|
|
184
|
+
'createCollabPlugin "resourceType" must be a non-empty string when provided.',
|
|
185
|
+
);
|
|
186
|
+
}
|
|
187
|
+
return {
|
|
188
|
+
mode: "resource",
|
|
189
|
+
resourceType: options.resourceType,
|
|
190
|
+
resolveResourceId: options.resolveResourceId,
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
if (options.resolveResourceId !== undefined) {
|
|
195
|
+
throw new Error(
|
|
196
|
+
'createCollabPlugin "resolveResourceId" requires a non-empty "resourceType".',
|
|
197
|
+
);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
return { mode: "all-authenticated", explicit: false };
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
function warnForImplicitAllAuthenticatedAccess(table: string): void {
|
|
204
|
+
if (_unscoped_warning_tables.has(table)) return;
|
|
205
|
+
_unscoped_warning_tables.add(table);
|
|
206
|
+
console.warn(
|
|
207
|
+
`[collab] WARNING: createCollabPlugin for table "${table}" does not declare an access policy. ` +
|
|
208
|
+
"Collab events will be delivered to ALL authenticated users on this deployment without document-level access scoping. " +
|
|
209
|
+
'Use access: { mode: "resource", resourceType: "..." } for access-scoped delivery, ' +
|
|
210
|
+
'or access: { mode: "all-authenticated" } to explicitly acknowledge deployment-wide delivery.',
|
|
211
|
+
);
|
|
212
|
+
}
|
|
213
|
+
|
|
100
214
|
export function createCollabPlugin(
|
|
101
215
|
options: CollabPluginOptions = {},
|
|
102
216
|
): NitroPluginDef {
|
|
217
|
+
const normalizedAccess = normalizeCollabAccess(options);
|
|
103
218
|
const {
|
|
104
219
|
table = "documents",
|
|
105
220
|
contentColumn = "content",
|
|
106
221
|
idColumn = "id",
|
|
107
222
|
autoSeed = true,
|
|
108
|
-
resourceType,
|
|
109
|
-
resolveResourceId,
|
|
110
223
|
maxPayloadBytes = DEFAULT_MAX_PAYLOAD_BYTES,
|
|
111
224
|
} = options;
|
|
225
|
+
const resourceType =
|
|
226
|
+
normalizedAccess.mode === "resource"
|
|
227
|
+
? normalizedAccess.resourceType
|
|
228
|
+
: undefined;
|
|
229
|
+
const resolveResourceId =
|
|
230
|
+
normalizedAccess.mode === "resource"
|
|
231
|
+
? normalizedAccess.resolveResourceId
|
|
232
|
+
: undefined;
|
|
233
|
+
|
|
234
|
+
if (
|
|
235
|
+
normalizedAccess.mode === "all-authenticated" &&
|
|
236
|
+
!normalizedAccess.explicit
|
|
237
|
+
) {
|
|
238
|
+
warnForImplicitAllAuthenticatedAccess(table);
|
|
239
|
+
}
|
|
112
240
|
|
|
113
241
|
return async (nitroApp: any) => {
|
|
114
242
|
await awaitBootstrap(nitroApp);
|
|
@@ -129,15 +257,6 @@ export function createCollabPlugin(
|
|
|
129
257
|
// who don't match owner/org — instead of only degrading them to the
|
|
130
258
|
// poll fallback.
|
|
131
259
|
// See also: SECURITY comment in poll.ts on canSeeChangeForUser.
|
|
132
|
-
if (!resourceType && !_unscoped_warning_logged) {
|
|
133
|
-
_unscoped_warning_logged = true;
|
|
134
|
-
console.warn(
|
|
135
|
-
"[collab] WARNING: createCollabPlugin called without resourceType. " +
|
|
136
|
-
"Collab events will be delivered to ALL authenticated users on this deployment " +
|
|
137
|
-
"without document-level access scoping. Set resourceType to enable access-scoped delivery.",
|
|
138
|
-
);
|
|
139
|
-
}
|
|
140
|
-
|
|
141
260
|
const collabEmitter = getCollabEmitter();
|
|
142
261
|
collabEmitter.on("collab", async (event) => {
|
|
143
262
|
if (!resourceType) {
|
|
@@ -170,6 +170,7 @@ import { handleIdentitySso } from "./identity-sso.js";
|
|
|
170
170
|
import { createOpenRouteHandler } from "./open-route.js";
|
|
171
171
|
import { createPollEventsHandler } from "./poll-events.js";
|
|
172
172
|
import { createPollHandler } from "./poll.js";
|
|
173
|
+
import { createRealtimeTokenHandler } from "./realtime-token.js";
|
|
173
174
|
import { runWithRequestContext } from "./request-context.js";
|
|
174
175
|
import {
|
|
175
176
|
findUnsupportedScopedKeyNames,
|
|
@@ -1414,6 +1415,12 @@ export function createCoreRoutesPlugin(
|
|
|
1414
1415
|
// Polling
|
|
1415
1416
|
getH3App(nitroApp).use(`${P}/poll`, createPollHandler());
|
|
1416
1417
|
|
|
1418
|
+
// Realtime subscribe-token mint (hosted gateway path)
|
|
1419
|
+
getH3App(nitroApp).use(
|
|
1420
|
+
`${P}/realtime-token`,
|
|
1421
|
+
createRealtimeTokenHandler(),
|
|
1422
|
+
);
|
|
1423
|
+
|
|
1417
1424
|
// SSE
|
|
1418
1425
|
if (!options.disableSSE) {
|
|
1419
1426
|
for (const route of resolveFrameworkSseRoutes(options.sseRoute)) {
|
package/src/server/index.ts
CHANGED
|
@@ -7,10 +7,11 @@ import {
|
|
|
7
7
|
} from "../collab/awareness.js";
|
|
8
8
|
import { getSession } from "./auth.js";
|
|
9
9
|
import {
|
|
10
|
+
type AppSyncState,
|
|
10
11
|
canSeeChangeForUser,
|
|
11
|
-
getPollEmitter,
|
|
12
|
-
POLL_CHANGE_EVENT,
|
|
13
12
|
type ChangeEvent,
|
|
13
|
+
getDefaultAppSyncState,
|
|
14
|
+
POLL_CHANGE_EVENT,
|
|
14
15
|
} from "./poll.js";
|
|
15
16
|
|
|
16
17
|
export function canSeeAwarenessChangeForUser(
|
|
@@ -37,8 +38,15 @@ export function canSeeAwarenessChangeForUser(
|
|
|
37
38
|
* connected peers receive cursor moves push-style instead of waiting for
|
|
38
39
|
* the next poll cycle. Polling fallback keeps working — cursors degrade
|
|
39
40
|
* gracefully to poll cadence without SSE.
|
|
41
|
+
*
|
|
42
|
+
* `state` defaults to the process-wide instance so self-hosted apps are
|
|
43
|
+
* unchanged; the hosted gateway passes a per-app instance to fan out that
|
|
44
|
+
* app's events (awareness stays on the process-global emitter and is a v0
|
|
45
|
+
* gateway Non-Goal).
|
|
40
46
|
*/
|
|
41
|
-
export function createPollEventsHandler(
|
|
47
|
+
export function createPollEventsHandler(
|
|
48
|
+
state: AppSyncState = getDefaultAppSyncState(),
|
|
49
|
+
) {
|
|
42
50
|
return defineEventHandler(async (event) => {
|
|
43
51
|
const session = await getSession(event).catch(() => null);
|
|
44
52
|
if (!session?.email) {
|
|
@@ -60,7 +68,9 @@ export function createPollEventsHandler() {
|
|
|
60
68
|
|
|
61
69
|
const push = (change: ChangeEvent) => {
|
|
62
70
|
if (closed) return;
|
|
63
|
-
if (!canSeeChangeForUser(change, session.email, session.orgId))
|
|
71
|
+
if (!state.canSeeChangeForUser(change, session.email, session.orgId)) {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
64
74
|
safePush(JSON.stringify(change));
|
|
65
75
|
};
|
|
66
76
|
|
|
@@ -74,13 +84,24 @@ export function createPollEventsHandler() {
|
|
|
74
84
|
safePush(JSON.stringify(change));
|
|
75
85
|
};
|
|
76
86
|
|
|
77
|
-
getPollEmitter().on(POLL_CHANGE_EVENT, push);
|
|
78
|
-
|
|
87
|
+
state.getPollEmitter().on(POLL_CHANGE_EVENT, push);
|
|
88
|
+
// Awareness lives ONLY on the process-global emitter and is filtered via the
|
|
89
|
+
// module-level (default-state) access path — both untenable in a multi-app
|
|
90
|
+
// gateway process, where they'd leak another app's presence/document id and
|
|
91
|
+
// resolve access against the wrong tenant. Fail closed: only the default
|
|
92
|
+
// (in-process) instance forwards awareness. The gateway advertises
|
|
93
|
+
// `no-awareness` so collab keeps its own presence cadence.
|
|
94
|
+
const forwardAwareness = state === getDefaultAppSyncState();
|
|
95
|
+
if (forwardAwareness) {
|
|
96
|
+
getAwarenessEmitter().on(AWARENESS_CHANGE_EVENT, pushAwareness);
|
|
97
|
+
}
|
|
79
98
|
|
|
80
99
|
stream.onClosed(() => {
|
|
81
100
|
closed = true;
|
|
82
|
-
getPollEmitter().off(POLL_CHANGE_EVENT, push);
|
|
83
|
-
|
|
101
|
+
state.getPollEmitter().off(POLL_CHANGE_EVENT, push);
|
|
102
|
+
if (forwardAwareness) {
|
|
103
|
+
getAwarenessEmitter().off(AWARENESS_CHANGE_EVENT, pushAwareness);
|
|
104
|
+
}
|
|
84
105
|
});
|
|
85
106
|
|
|
86
107
|
return stream.send();
|