@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
|
@@ -46,8 +46,14 @@ const PLAIN_IDENTIFIER = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
|
46
46
|
export async function pgTableExists(
|
|
47
47
|
table: string,
|
|
48
48
|
injectedClient?: DbExec,
|
|
49
|
+
dialectIsPostgres?: boolean,
|
|
49
50
|
): Promise<boolean> {
|
|
50
|
-
|
|
51
|
+
// The dialect override travels with an injected client: a multi-app process
|
|
52
|
+
// (the hosted Realtime Gateway) probes a per-app Postgres DB even when its
|
|
53
|
+
// own process-global DB is absent or SQLite.
|
|
54
|
+
if (!(dialectIsPostgres ?? isPostgres()) || !PLAIN_IDENTIFIER.test(table)) {
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
51
57
|
const client = injectedClient ?? getDbExec();
|
|
52
58
|
try {
|
|
53
59
|
const { rows } = await client.execute({
|
|
@@ -106,8 +112,14 @@ export async function pgColumnExists(
|
|
|
106
112
|
export async function pgIndexExists(
|
|
107
113
|
indexName: string,
|
|
108
114
|
injectedClient?: DbExec,
|
|
115
|
+
dialectIsPostgres?: boolean,
|
|
109
116
|
): Promise<boolean> {
|
|
110
|
-
if (
|
|
117
|
+
if (
|
|
118
|
+
!(dialectIsPostgres ?? isPostgres()) ||
|
|
119
|
+
!PLAIN_IDENTIFIER.test(indexName)
|
|
120
|
+
) {
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
111
123
|
const client = injectedClient ?? getDbExec();
|
|
112
124
|
try {
|
|
113
125
|
const { rows } = await client.execute({
|
|
@@ -158,10 +170,17 @@ export async function ensureSchemaObject(options: {
|
|
|
158
170
|
lockTimeout?: string;
|
|
159
171
|
/** Injectable client for tests. */
|
|
160
172
|
injectedClient?: DbExec;
|
|
173
|
+
/** Dialect override for injected per-app clients; defaults to the global. */
|
|
174
|
+
dialectIsPostgres?: boolean;
|
|
161
175
|
}): Promise<boolean> {
|
|
162
|
-
const { probe, ddl, label, lockTimeout, injectedClient } =
|
|
176
|
+
const { probe, ddl, label, lockTimeout, injectedClient, dialectIsPostgres } =
|
|
177
|
+
options;
|
|
163
178
|
if (await probe()) return false;
|
|
164
|
-
const ran = await runGuardedDdl(ddl, {
|
|
179
|
+
const ran = await runGuardedDdl(ddl, {
|
|
180
|
+
lockTimeout,
|
|
181
|
+
injectedClient,
|
|
182
|
+
dialectIsPostgres,
|
|
183
|
+
});
|
|
165
184
|
if (ran) return true;
|
|
166
185
|
// The DDL was swallowed by a lock-timeout. The object is virtually always
|
|
167
186
|
// already correct by the time a contended boot retries (a concurrent
|
|
@@ -185,14 +204,20 @@ export async function ensureSchemaObject(options: {
|
|
|
185
204
|
export async function ensureTableExists(
|
|
186
205
|
table: string,
|
|
187
206
|
createSql: string,
|
|
188
|
-
options: {
|
|
207
|
+
options: {
|
|
208
|
+
lockTimeout?: string;
|
|
209
|
+
injectedClient?: DbExec;
|
|
210
|
+
dialectIsPostgres?: boolean;
|
|
211
|
+
} = {},
|
|
189
212
|
): Promise<boolean> {
|
|
190
213
|
return ensureSchemaObject({
|
|
191
|
-
probe: () =>
|
|
214
|
+
probe: () =>
|
|
215
|
+
pgTableExists(table, options.injectedClient, options.dialectIsPostgres),
|
|
192
216
|
ddl: createSql,
|
|
193
217
|
label: `table ${table}`,
|
|
194
218
|
lockTimeout: options.lockTimeout,
|
|
195
219
|
injectedClient: options.injectedClient,
|
|
220
|
+
dialectIsPostgres: options.dialectIsPostgres,
|
|
196
221
|
});
|
|
197
222
|
}
|
|
198
223
|
|
|
@@ -222,14 +247,24 @@ export async function ensureColumnExists(
|
|
|
222
247
|
export async function ensureIndexExists(
|
|
223
248
|
indexName: string,
|
|
224
249
|
createIndexSql: string,
|
|
225
|
-
options: {
|
|
250
|
+
options: {
|
|
251
|
+
lockTimeout?: string;
|
|
252
|
+
injectedClient?: DbExec;
|
|
253
|
+
dialectIsPostgres?: boolean;
|
|
254
|
+
} = {},
|
|
226
255
|
): Promise<boolean> {
|
|
227
256
|
return ensureSchemaObject({
|
|
228
|
-
probe: () =>
|
|
257
|
+
probe: () =>
|
|
258
|
+
pgIndexExists(
|
|
259
|
+
indexName,
|
|
260
|
+
options.injectedClient,
|
|
261
|
+
options.dialectIsPostgres,
|
|
262
|
+
),
|
|
229
263
|
ddl: createIndexSql,
|
|
230
264
|
label: `index ${indexName}`,
|
|
231
265
|
lockTimeout: options.lockTimeout,
|
|
232
266
|
injectedClient: options.injectedClient,
|
|
267
|
+
dialectIsPostgres: options.dialectIsPostgres,
|
|
233
268
|
});
|
|
234
269
|
}
|
|
235
270
|
|
|
@@ -263,10 +298,14 @@ export function isLockTimeoutError(err: unknown): boolean {
|
|
|
263
298
|
*/
|
|
264
299
|
export async function runGuardedDdl(
|
|
265
300
|
ddl: string,
|
|
266
|
-
options: {
|
|
301
|
+
options: {
|
|
302
|
+
lockTimeout?: string;
|
|
303
|
+
injectedClient?: DbExec;
|
|
304
|
+
dialectIsPostgres?: boolean;
|
|
305
|
+
} = {},
|
|
267
306
|
): Promise<boolean> {
|
|
268
307
|
const client = options.injectedClient ?? getDbExec();
|
|
269
|
-
if (!isPostgres()) {
|
|
308
|
+
if (!(options.dialectIsPostgres ?? isPostgres())) {
|
|
270
309
|
await client.execute(ddl);
|
|
271
310
|
return true;
|
|
272
311
|
}
|
|
@@ -951,6 +951,26 @@ function getSentryClientConfigScript() {
|
|
|
951
951
|
);
|
|
952
952
|
}
|
|
953
953
|
|
|
954
|
+
function getRealtimeClientConfigScript() {
|
|
955
|
+
// MUST stay byte-for-byte consistent with resolveRealtimeClientConfig in
|
|
956
|
+
// server/sentry-config.ts (worker bundles a string copy; it can't import it).
|
|
957
|
+
// Fail closed: require BOTH hosted transport AND an explicit gateway URL — no
|
|
958
|
+
// production default, since this ships into the CDN-cached shell.
|
|
959
|
+
const env = globalThis.process?.env || {};
|
|
960
|
+
if (firstNonEmpty(env.AGENT_NATIVE_REALTIME_TRANSPORT) !== "hosted") {
|
|
961
|
+
return null;
|
|
962
|
+
}
|
|
963
|
+
const gatewayBaseUrl = firstNonEmpty(env.AGENT_NATIVE_REALTIME_GATEWAY_URL);
|
|
964
|
+
if (!gatewayBaseUrl) return null;
|
|
965
|
+
const config = { realtime: { transport: "hosted", gatewayBaseUrl } };
|
|
966
|
+
return (
|
|
967
|
+
'<script data-agent-native-realtime-config>' +
|
|
968
|
+
'window.__AGENT_NATIVE_CONFIG__=Object.assign({},window.__AGENT_NATIVE_CONFIG__,' +
|
|
969
|
+
JSON.stringify(config) +
|
|
970
|
+
");</script>"
|
|
971
|
+
);
|
|
972
|
+
}
|
|
973
|
+
|
|
954
974
|
function injectHeadScript(html, script) {
|
|
955
975
|
if (!script) return html;
|
|
956
976
|
const headCloseIdx = html.indexOf("</head>");
|
|
@@ -1102,7 +1122,10 @@ function applyImmutableAssetCacheHeaders(response, request) {
|
|
|
1102
1122
|
}
|
|
1103
1123
|
|
|
1104
1124
|
async function rewriteMountedResponse(response, basePath, pathname, request) {
|
|
1105
|
-
const
|
|
1125
|
+
const clientConfigScript =
|
|
1126
|
+
[getSentryClientConfigScript(), getRealtimeClientConfigScript()]
|
|
1127
|
+
.filter(Boolean)
|
|
1128
|
+
.join("") || null;
|
|
1106
1129
|
const headers = new Headers(response.headers);
|
|
1107
1130
|
applyDefaultSsrCacheHeader(headers, response.status, pathname);
|
|
1108
1131
|
applyDefaultSpeculationRulesHeader(headers, response.status, basePath);
|
|
@@ -1129,7 +1152,7 @@ async function rewriteMountedResponse(response, basePath, pathname, request) {
|
|
|
1129
1152
|
prefixMountedHtml(html, basePath),
|
|
1130
1153
|
defaultSocialImageUrl(request, basePath),
|
|
1131
1154
|
),
|
|
1132
|
-
|
|
1155
|
+
clientConfigScript,
|
|
1133
1156
|
),
|
|
1134
1157
|
{
|
|
1135
1158
|
status: response.status,
|
|
@@ -18,17 +18,49 @@ import { createElement, type ComponentType, type ReactElement } from "react";
|
|
|
18
18
|
export * from "@agent-native/core/client/resources/runtime";
|
|
19
19
|
|
|
20
20
|
function preset(id: string): DefaultMcpIntegration {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
21
|
+
const runtimePreset = RUNTIME_DEFAULT_MCP_INTEGRATIONS.find(
|
|
22
|
+
(integration) => integration.id === id,
|
|
23
|
+
);
|
|
24
|
+
if (runtimePreset) return { ...runtimePreset };
|
|
25
|
+
|
|
26
|
+
if (id === "granola") {
|
|
27
|
+
return {
|
|
28
|
+
id: "granola",
|
|
29
|
+
name: "Granola",
|
|
30
|
+
provider: "granola",
|
|
31
|
+
description: "Search meeting notes, transcripts, and action items.",
|
|
32
|
+
descriptionKey: "mcpIntegrations.catalog.granola.description",
|
|
33
|
+
useCase:
|
|
34
|
+
"meeting notes, recordings, transcripts, action items, follow-ups",
|
|
35
|
+
useCaseKey: "mcpIntegrations.catalog.granola.useCase",
|
|
36
|
+
url: "https://mcp.granola.ai/mcp",
|
|
37
|
+
authMode: "oauth",
|
|
38
|
+
connectionMode: "oauth",
|
|
39
|
+
availability: "ready",
|
|
40
|
+
verification: "preflight-only",
|
|
41
|
+
logoUrl: "",
|
|
42
|
+
docsUrl: "https://docs.granola.ai/help-center/sharing/integrations/mcp",
|
|
43
|
+
setupNoteKey: "mcpIntegrations.catalog.granola.setupNote",
|
|
44
|
+
keywords: [
|
|
45
|
+
"meetings",
|
|
46
|
+
"meeting notes",
|
|
47
|
+
"recordings",
|
|
48
|
+
"transcripts",
|
|
49
|
+
"action items",
|
|
50
|
+
"follow-ups",
|
|
51
|
+
"decisions",
|
|
52
|
+
],
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
throw new Error(`MCP preset ${id} is missing from the runtime catalog.`);
|
|
26
57
|
}
|
|
27
58
|
|
|
28
59
|
export const DEFAULT_MCP_INTEGRATIONS: DefaultMcpIntegration[] = [
|
|
29
60
|
preset("context7"),
|
|
30
61
|
preset("sentry"),
|
|
31
62
|
preset("notion"),
|
|
63
|
+
preset("granola"),
|
|
32
64
|
preset("semgrep"),
|
|
33
65
|
preset("linear"),
|
|
34
66
|
preset("atlassian"),
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Require generated apps to choose how collaboration events are scoped.
|
|
3
|
+
* Legacy `resourceType` callers remain valid during the access-option
|
|
4
|
+
* migration; this guard only reports implicit createCollabPlugin configs.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
lineColForOffset,
|
|
9
|
+
readFileSafe,
|
|
10
|
+
relPosix,
|
|
11
|
+
walk,
|
|
12
|
+
} from "./scan-utils.js";
|
|
13
|
+
import type { GuardFinding, GuardResult, GuardScanOptions } from "./types.js";
|
|
14
|
+
|
|
15
|
+
const SOURCE_FILE = /\.(?:[cm]?[jt]s|[jt]sx)$/;
|
|
16
|
+
const CALL = /\bcreateCollabPlugin\s*\(/g;
|
|
17
|
+
const EXPLICIT_ACCESS_KEYS = new Set(["access", "resourceType"]);
|
|
18
|
+
const FINDING_MESSAGE =
|
|
19
|
+
'createCollabPlugin must declare access explicitly. Use access: { mode: "resource", resourceType: "..." } for scoped resources or access: { mode: "all-authenticated" } when deployment-wide delivery is intentional. Legacy resourceType is also accepted during migration.';
|
|
20
|
+
|
|
21
|
+
function maskCommentsAndStrings(contents: string): string {
|
|
22
|
+
const masked = contents.split("");
|
|
23
|
+
for (let i = 0; i < contents.length; i++) {
|
|
24
|
+
const char = contents[i];
|
|
25
|
+
if (char === '"' || char === "'" || char === "`") {
|
|
26
|
+
const end = skipQuoted(contents, i);
|
|
27
|
+
for (let cursor = i; cursor < end; cursor++) {
|
|
28
|
+
if (masked[cursor] !== "\n") masked[cursor] = " ";
|
|
29
|
+
}
|
|
30
|
+
i = end - 1;
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
if (contents.startsWith("//", i)) {
|
|
34
|
+
const newline = contents.indexOf("\n", i + 2);
|
|
35
|
+
const end = newline === -1 ? contents.length : newline;
|
|
36
|
+
for (let cursor = i; cursor < end; cursor++) masked[cursor] = " ";
|
|
37
|
+
i = end - 1;
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
if (contents.startsWith("/*", i)) {
|
|
41
|
+
const commentEnd = contents.indexOf("*/", i + 2);
|
|
42
|
+
const end = commentEnd === -1 ? contents.length : commentEnd + 2;
|
|
43
|
+
for (let cursor = i; cursor < end; cursor++) {
|
|
44
|
+
if (masked[cursor] !== "\n") masked[cursor] = " ";
|
|
45
|
+
}
|
|
46
|
+
i = end - 1;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return masked.join("");
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function skipQuoted(contents: string, start: number): number {
|
|
53
|
+
const quote = contents[start];
|
|
54
|
+
let escaped = false;
|
|
55
|
+
for (let i = start + 1; i < contents.length; i++) {
|
|
56
|
+
const char = contents[i];
|
|
57
|
+
if (escaped) {
|
|
58
|
+
escaped = false;
|
|
59
|
+
} else if (char === "\\") {
|
|
60
|
+
escaped = true;
|
|
61
|
+
} else if (char === quote) {
|
|
62
|
+
return i + 1;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return contents.length;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function skipTrivia(contents: string, start: number): number {
|
|
69
|
+
let i = start;
|
|
70
|
+
while (i < contents.length) {
|
|
71
|
+
if (/\s/.test(contents[i] ?? "")) {
|
|
72
|
+
i++;
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
if (contents.startsWith("//", i)) {
|
|
76
|
+
const newline = contents.indexOf("\n", i + 2);
|
|
77
|
+
i = newline === -1 ? contents.length : newline + 1;
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
if (contents.startsWith("/*", i)) {
|
|
81
|
+
const end = contents.indexOf("*/", i + 2);
|
|
82
|
+
i = end === -1 ? contents.length : end + 2;
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
break;
|
|
86
|
+
}
|
|
87
|
+
return i;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function findObjectEnd(contents: string, start: number): number | null {
|
|
91
|
+
let depth = 0;
|
|
92
|
+
for (let i = start; i < contents.length; i++) {
|
|
93
|
+
const char = contents[i];
|
|
94
|
+
if (char === '"' || char === "'" || char === "`") {
|
|
95
|
+
i = skipQuoted(contents, i) - 1;
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
if (contents.startsWith("//", i)) {
|
|
99
|
+
const newline = contents.indexOf("\n", i + 2);
|
|
100
|
+
i = newline === -1 ? contents.length : newline;
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
if (contents.startsWith("/*", i)) {
|
|
104
|
+
const end = contents.indexOf("*/", i + 2);
|
|
105
|
+
i = end === -1 ? contents.length : end + 1;
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
108
|
+
if (char === "{") depth++;
|
|
109
|
+
if (char === "}" && --depth === 0) return i;
|
|
110
|
+
}
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function hasExplicitAccessProperty(
|
|
115
|
+
contents: string,
|
|
116
|
+
objectStart: number,
|
|
117
|
+
objectEnd: number,
|
|
118
|
+
): boolean {
|
|
119
|
+
let braceDepth = 0;
|
|
120
|
+
let bracketDepth = 0;
|
|
121
|
+
let parenDepth = 0;
|
|
122
|
+
let expectingProperty = true;
|
|
123
|
+
|
|
124
|
+
for (let i = objectStart + 1; i < objectEnd; i++) {
|
|
125
|
+
i = skipTrivia(contents, i);
|
|
126
|
+
if (i >= objectEnd) break;
|
|
127
|
+
const char = contents[i];
|
|
128
|
+
|
|
129
|
+
if (expectingProperty && (char === '"' || char === "'")) {
|
|
130
|
+
const tokenEnd = skipQuoted(contents, i);
|
|
131
|
+
const key = contents.slice(i + 1, tokenEnd - 1);
|
|
132
|
+
const afterKey = skipTrivia(contents, tokenEnd);
|
|
133
|
+
if (EXPLICIT_ACCESS_KEYS.has(key) && contents[afterKey] === ":") {
|
|
134
|
+
return true;
|
|
135
|
+
}
|
|
136
|
+
i = tokenEnd - 1;
|
|
137
|
+
expectingProperty = false;
|
|
138
|
+
continue;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
if (expectingProperty && /[A-Za-z_$]/.test(char ?? "")) {
|
|
142
|
+
let tokenEnd = i + 1;
|
|
143
|
+
while (/[A-Za-z0-9_$]/.test(contents[tokenEnd] ?? "")) tokenEnd++;
|
|
144
|
+
const key = contents.slice(i, tokenEnd);
|
|
145
|
+
const afterKey = skipTrivia(contents, tokenEnd);
|
|
146
|
+
const delimiter = contents[afterKey];
|
|
147
|
+
if (
|
|
148
|
+
EXPLICIT_ACCESS_KEYS.has(key) &&
|
|
149
|
+
(delimiter === ":" || delimiter === "," || afterKey >= objectEnd)
|
|
150
|
+
) {
|
|
151
|
+
return true;
|
|
152
|
+
}
|
|
153
|
+
i = tokenEnd - 1;
|
|
154
|
+
expectingProperty = false;
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
if (char === '"' || char === "'" || char === "`") {
|
|
159
|
+
i = skipQuoted(contents, i) - 1;
|
|
160
|
+
continue;
|
|
161
|
+
}
|
|
162
|
+
if (contents.startsWith("//", i) || contents.startsWith("/*", i)) {
|
|
163
|
+
i = skipTrivia(contents, i) - 1;
|
|
164
|
+
continue;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
if (char === "{") braceDepth++;
|
|
168
|
+
else if (char === "}") braceDepth--;
|
|
169
|
+
else if (char === "[") bracketDepth++;
|
|
170
|
+
else if (char === "]") bracketDepth--;
|
|
171
|
+
else if (char === "(") parenDepth++;
|
|
172
|
+
else if (char === ")") parenDepth--;
|
|
173
|
+
else if (
|
|
174
|
+
char === "," &&
|
|
175
|
+
braceDepth === 0 &&
|
|
176
|
+
bracketDepth === 0 &&
|
|
177
|
+
parenDepth === 0
|
|
178
|
+
) {
|
|
179
|
+
expectingProperty = true;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
return false;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
export function scanExplicitCollabAccess(
|
|
187
|
+
options: GuardScanOptions,
|
|
188
|
+
): GuardResult {
|
|
189
|
+
const { root } = options;
|
|
190
|
+
const findings: GuardFinding[] = [];
|
|
191
|
+
|
|
192
|
+
for (const file of walk(root)) {
|
|
193
|
+
if (!SOURCE_FILE.test(file) || file.endsWith(".d.ts")) continue;
|
|
194
|
+
const contents = readFileSafe(file);
|
|
195
|
+
if (contents === null || !contents.includes("createCollabPlugin")) continue;
|
|
196
|
+
const searchable = maskCommentsAndStrings(contents);
|
|
197
|
+
|
|
198
|
+
CALL.lastIndex = 0;
|
|
199
|
+
let match: RegExpExecArray | null;
|
|
200
|
+
while ((match = CALL.exec(searchable)) !== null) {
|
|
201
|
+
const callStart = match.index;
|
|
202
|
+
const objectStart = skipTrivia(contents, CALL.lastIndex);
|
|
203
|
+
if (contents[objectStart] !== "{") {
|
|
204
|
+
if (contents[objectStart] === ")") {
|
|
205
|
+
const { line } = lineColForOffset(contents, callStart);
|
|
206
|
+
findings.push({
|
|
207
|
+
file: relPosix(root, file),
|
|
208
|
+
line,
|
|
209
|
+
message: FINDING_MESSAGE,
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
continue;
|
|
213
|
+
}
|
|
214
|
+
const objectEnd = findObjectEnd(contents, objectStart);
|
|
215
|
+
if (objectEnd === null) continue;
|
|
216
|
+
CALL.lastIndex = objectEnd + 1;
|
|
217
|
+
|
|
218
|
+
if (hasExplicitAccessProperty(contents, objectStart, objectEnd)) continue;
|
|
219
|
+
const { line } = lineColForOffset(contents, callStart);
|
|
220
|
+
findings.push({
|
|
221
|
+
file: relPosix(root, file),
|
|
222
|
+
line,
|
|
223
|
+
message: FINDING_MESSAGE,
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
return { name: "explicit-collab-access", findings };
|
|
229
|
+
}
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
|
|
13
13
|
export { scanDbToolScoping } from "./db-tool-scoping.js";
|
|
14
14
|
export type { DbToolScopingOptions } from "./db-tool-scoping.js";
|
|
15
|
+
export { scanExplicitCollabAccess } from "./explicit-collab-access.js";
|
|
15
16
|
export { scanDrizzlePush } from "./no-drizzle-push.js";
|
|
16
17
|
export { scanEnvCredentials } from "./no-env-credentials.js";
|
|
17
18
|
export { scanEnvMutation } from "./no-env-mutation.js";
|
|
@@ -33,6 +33,47 @@ const messages = {
|
|
|
33
33
|
openResourceSettings: "Open resource settings",
|
|
34
34
|
backHome: "Back to home",
|
|
35
35
|
},
|
|
36
|
+
agentResources: {
|
|
37
|
+
openDocs: "Open {{section}} documentation",
|
|
38
|
+
backToResources: "Back to agent resources",
|
|
39
|
+
createFile: {
|
|
40
|
+
nameLabel: "File name",
|
|
41
|
+
namePlaceholder: "notes/ideas",
|
|
42
|
+
menuDescription: "Add a new file by name",
|
|
43
|
+
},
|
|
44
|
+
files: {
|
|
45
|
+
title: "Files",
|
|
46
|
+
description: "Files the agent can read and write.",
|
|
47
|
+
},
|
|
48
|
+
instructions: {
|
|
49
|
+
title: "Instructions",
|
|
50
|
+
description:
|
|
51
|
+
"The rules, preferences, and project guidance that steer the agent.",
|
|
52
|
+
},
|
|
53
|
+
agents: {
|
|
54
|
+
title: "Agents",
|
|
55
|
+
description:
|
|
56
|
+
"Reusable profiles for focused sub-agents and delegated work.",
|
|
57
|
+
},
|
|
58
|
+
memory: {
|
|
59
|
+
title: "Memory",
|
|
60
|
+
description: "Durable notes the agent can retrieve across conversations.",
|
|
61
|
+
},
|
|
62
|
+
skills: {
|
|
63
|
+
title: "Skills",
|
|
64
|
+
description:
|
|
65
|
+
"Specialized instructions that give the agent repeatable abilities.",
|
|
66
|
+
},
|
|
67
|
+
learnings: {
|
|
68
|
+
title: "Learnings",
|
|
69
|
+
description:
|
|
70
|
+
"Corrections and patterns worth carrying forward for future work.",
|
|
71
|
+
},
|
|
72
|
+
remoteAgents: {
|
|
73
|
+
title: "Remote agents",
|
|
74
|
+
description: "Other agents this agent can call through A2A.",
|
|
75
|
+
},
|
|
76
|
+
},
|
|
36
77
|
featureFlags: {
|
|
37
78
|
title: "Feature flags",
|
|
38
79
|
description: "Control staged capabilities without changing a deployment.",
|
|
@@ -276,7 +317,7 @@ const messages = {
|
|
|
276
317
|
checkingAiConnection: "Checking AI connection...",
|
|
277
318
|
voiceMode: {
|
|
278
319
|
entryButtonLabel: "Use microphone",
|
|
279
|
-
promptTitle: "
|
|
320
|
+
promptTitle: "Use your voice",
|
|
280
321
|
promptDescription:
|
|
281
322
|
"Voice mode keeps listening while the agent navigates and takes actions.",
|
|
282
323
|
setupTitle: "Set up voice mode",
|
|
@@ -285,8 +326,9 @@ const messages = {
|
|
|
285
326
|
connectBuilder: "Connect Builder.io",
|
|
286
327
|
useOpenAiKey: "Add your own keys",
|
|
287
328
|
startWithOpenAiKey: "Start with OpenAI key",
|
|
288
|
-
start: "
|
|
289
|
-
keepDictating: "
|
|
329
|
+
start: "Real-time voice",
|
|
330
|
+
keepDictating: "Dictate",
|
|
331
|
+
rememberPreference: "Remember my preference",
|
|
290
332
|
showChat: "Show chat",
|
|
291
333
|
hideChat: "Hide chat",
|
|
292
334
|
end: "End voice mode",
|
|
@@ -744,9 +786,9 @@ const messages = {
|
|
|
744
786
|
connect: "Connect",
|
|
745
787
|
connectWithOAuth: "Connect with OAuth",
|
|
746
788
|
useApiToken: "Use API token",
|
|
747
|
-
connectSuggestion: "Connect {{name}} to use
|
|
789
|
+
connectSuggestion: "Connect {{name}} to use it in chat",
|
|
748
790
|
connectSuggestionWithApiToken:
|
|
749
|
-
"Connect {{name}} with an API token to use
|
|
791
|
+
"Connect {{name}} with an API token to use it in chat",
|
|
750
792
|
dismissSuggestion: "Dismiss integration suggestion",
|
|
751
793
|
backToIntegrations: "Back to integrations",
|
|
752
794
|
customTitle: "Add custom MCP server",
|
|
@@ -795,6 +837,13 @@ const messages = {
|
|
|
795
837
|
setupNote:
|
|
796
838
|
"Notion MCP uses user OAuth. Enterprise workspaces can audit MCP usage and allow or block clients; reconnect after admin policy changes.",
|
|
797
839
|
},
|
|
840
|
+
granola: {
|
|
841
|
+
description: "Search meeting notes, transcripts, and action items.",
|
|
842
|
+
useCase:
|
|
843
|
+
"Meeting notes, recordings, transcripts, action items, follow-ups",
|
|
844
|
+
setupNote:
|
|
845
|
+
"Granola MCP uses browser OAuth. Authorize the signed-in Granola account and review which meeting notes and transcripts the agent can access.",
|
|
846
|
+
},
|
|
798
847
|
semgrep: {
|
|
799
848
|
description: "Scan code for security findings.",
|
|
800
849
|
useCase: "Security scanning, vulnerability detection, code analysis",
|