@agent-native/core 0.92.0 → 0.92.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/corpus/README.md +1 -1
- package/corpus/core/CHANGELOG.md +14 -0
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/application-state/store.ts +12 -1
- package/corpus/core/src/client/AssistantChat.tsx +27 -14
- package/corpus/core/src/client/PoweredByBadge.tsx +1 -8
- package/corpus/core/src/client/agent-chat-adapter.ts +37 -10
- package/corpus/core/src/client/chat/widgets/DataTableWidget.tsx +52 -1
- package/corpus/core/src/client/db-admin/TableEditor.tsx +49 -0
- package/corpus/core/src/client/db-admin/export-utils.ts +13 -4
- package/corpus/core/src/client/db-admin/useAgentSync.ts +72 -0
- package/corpus/core/src/client/error-capture.ts +69 -7
- package/corpus/core/src/client/extensions/EmbeddedExtension.tsx +5 -1
- package/corpus/core/src/client/extensions/ExtensionViewer.tsx +53 -8
- package/corpus/core/src/client/extensions/InlineExtensionFrame.tsx +5 -1
- package/corpus/core/src/client/extensions/portable-extension.ts +1 -0
- package/corpus/core/src/client/org/OrgSwitcher.tsx +12 -9
- package/corpus/core/src/client/org/TeamPage.tsx +77 -71
- package/corpus/core/src/client/settings/SettingsPanel.tsx +205 -52
- package/corpus/core/src/client/settings/SettingsSection.tsx +8 -1
- package/corpus/core/src/client/settings/SettingsTabsPage.tsx +25 -9
- package/corpus/core/src/db-admin/agent-tools.ts +8 -2
- package/corpus/core/src/db-admin/operations.ts +116 -4
- package/corpus/core/src/db-admin/routes.ts +1 -0
- package/corpus/core/src/db-admin/types.ts +4 -0
- package/corpus/core/src/extensions/html-shell.ts +5 -4
- package/corpus/core/src/extensions/routes.ts +10 -0
- package/corpus/core/src/navigation/index.ts +1 -1
- package/corpus/core/src/resources/handlers.ts +10 -8
- package/corpus/core/src/server/poll.ts +293 -8
- package/corpus/core/src/styles/agent-native.css +27 -0
- package/corpus/core/src/templates/default/.agents/skills/actions/SKILL.md +5 -0
- package/corpus/core/src/templates/default/.agents/skills/adding-a-feature/SKILL.md +5 -0
- package/corpus/core/src/templates/default/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/corpus/core/src/templates/default/.agents/skills/security/SKILL.md +7 -0
- package/corpus/core/src/templates/default/.agents/skills/storing-data/SKILL.md +5 -1
- package/corpus/core/src/templates/default/AGENTS.md +4 -2
- package/corpus/core/src/templates/headless/AGENTS.md +4 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/actions/SKILL.md +5 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/adding-a-feature/SKILL.md +5 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/context-awareness/SKILL.md +4 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +6 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/performance/SKILL.md +4 -0
- 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/security/SKILL.md +7 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/storing-data/SKILL.md +5 -1
- package/corpus/core/src/templates/workspace-core/AGENTS.md +7 -1
- package/corpus/core/src/templates/workspace-root/AGENTS.md +7 -1
- package/corpus/templates/analytics/.agents/skills/actions/SKILL.md +5 -0
- package/corpus/templates/analytics/.agents/skills/dashboard-management/SKILL.md +10 -0
- package/corpus/templates/analytics/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/corpus/templates/analytics/.agents/skills/security/SKILL.md +7 -0
- package/corpus/templates/analytics/.agents/skills/storing-data/SKILL.md +5 -1
- package/corpus/templates/analytics/AGENTS.md +33 -14
- package/corpus/templates/analytics/actions/capture-test-error.ts +4 -0
- package/corpus/templates/analytics/actions/get-analytics-alert-rule-defaults.ts +23 -0
- package/corpus/templates/analytics/actions/get-error-issue.ts +1 -1
- package/corpus/templates/analytics/actions/list-analysis-revisions.ts +40 -0
- package/corpus/templates/analytics/actions/list-dashboard-revisions.ts +40 -0
- package/corpus/templates/analytics/actions/list-dashboard-usage-stats.ts +299 -0
- package/corpus/templates/analytics/actions/navigate.ts +4 -2
- package/corpus/templates/analytics/actions/restore-analysis-revision.ts +43 -0
- package/corpus/templates/analytics/actions/restore-dashboard-revision.ts +68 -0
- package/corpus/templates/analytics/actions/save-analytics-alert-rule.ts +14 -0
- package/corpus/templates/analytics/actions/save-monitor.ts +1 -1
- package/corpus/templates/analytics/actions/view-screen.ts +24 -0
- package/corpus/templates/analytics/app/components/analysis/AnalysisHistoryPanel.tsx +181 -0
- package/corpus/templates/analytics/app/components/dashboard/DashboardHistoryPanel.tsx +184 -0
- package/corpus/templates/analytics/app/components/layout/CommandPalette.tsx +22 -16
- package/corpus/templates/analytics/app/components/layout/Header.tsx +1 -1
- package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +27 -21
- package/corpus/templates/analytics/app/hooks/use-analysis-revisions.ts +43 -0
- package/corpus/templates/analytics/app/hooks/use-dashboard-chat-context.ts +110 -0
- package/corpus/templates/analytics/app/hooks/use-dashboard-revisions.ts +43 -0
- package/corpus/templates/analytics/app/hooks/use-navigation-state.ts +8 -3
- package/corpus/templates/analytics/app/i18n/zh-TW.ts +64 -2
- package/corpus/templates/analytics/app/i18n-data.ts +783 -3
- package/corpus/templates/analytics/app/pages/Agents.tsx +359 -19
- package/corpus/templates/analytics/app/pages/Settings.tsx +3 -2
- package/corpus/templates/analytics/app/pages/adhoc/explorer-dashboard/index.tsx +34 -1
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +28 -0
- package/corpus/templates/analytics/app/pages/analyses/AnalysisDetail.tsx +18 -1
- package/corpus/templates/analytics/app/pages/monitoring/ErrorsPanel.tsx +7 -10
- package/corpus/templates/analytics/app/pages/monitoring/errors/IssueDetail.tsx +479 -23
- package/corpus/templates/analytics/app/pages/monitoring/errors/IssueList.tsx +0 -9
- package/corpus/templates/analytics/app/pages/monitoring/errors/i18n.ts +11 -0
- package/corpus/templates/analytics/app/pages/monitoring/errors/types.ts +9 -1
- package/corpus/templates/analytics/app/pages/monitoring/uptime/MonitorFormPage.tsx +6 -3
- package/corpus/templates/analytics/app/pages/sessions/SessionDetailPage.tsx +26 -30
- package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +9 -99
- package/corpus/templates/analytics/app/pages/settings/AlertRulesSettingsCard.tsx +262 -104
- package/corpus/templates/analytics/app/routes/team.tsx +1 -1
- package/corpus/templates/analytics/changelog/2026-07-08-admins-can-audit-dashboard-usage-ownership-and-cleanup-signa.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-08-agent-monitoring-stays-available-to-non-admins.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-08-alert-rules-are-easier-to-scan-expand-and-edit-from-settings.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-08-analytics-alert-forms-remember-last-email-recipients.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-08-analytics-alert-rules-can-now-use-per-rule-slack-and-webhook.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-08-dashboard-history-and-chat-context.md +5 -0
- package/corpus/templates/analytics/changelog/2026-07-08-dashboard-usage-now-counts-explorer-dashboard-traffic.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-08-demo-mode-session-emails-are-filtered-and-anonymized.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-08-error-issue-detail-adds-stack-traces-and-frequency-bars.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-08-error-issue-detail-now-shows-the-latest-occurrence-message-a.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-08-monitoring-errors-only-show-test-action-when-empty.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-08-production-session-replay-now-requires-private-blob-storage-.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-08-shared-extension-links-now-show-a-clear-message-when-you-do-.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-08-team-settings-show-access-controls-next-to-member-lists.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-08-uptime-monitors-now-use-a-10-second-request-timeout-by-defau.md +6 -0
- package/corpus/templates/analytics/server/db/schema-monitoring.ts +1 -1
- package/corpus/templates/analytics/server/db/schema.ts +56 -0
- package/corpus/templates/analytics/server/lib/analytics-alerts.ts +92 -0
- package/corpus/templates/analytics/server/lib/dashboards-store.ts +334 -5
- package/corpus/templates/analytics/server/lib/error-capture.ts +231 -36
- package/corpus/templates/analytics/server/lib/session-replay.ts +114 -8
- package/corpus/templates/analytics/server/lib/uptime-monitors.ts +5 -4
- package/corpus/templates/analytics/server/plugins/db.ts +112 -2
- package/corpus/templates/analytics/server/routes/api/dashboard-agent-context.json.get.ts +1 -0
- package/corpus/templates/assets/.agents/skills/actions/SKILL.md +5 -0
- package/corpus/templates/assets/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/corpus/templates/assets/.agents/skills/security/SKILL.md +7 -0
- package/corpus/templates/assets/.agents/skills/storing-data/SKILL.md +5 -1
- package/corpus/templates/assets/AGENTS.md +4 -0
- package/corpus/templates/assets/app/routes/settings.tsx +1 -1
- package/corpus/templates/assets/app/routes/team.tsx +1 -1
- package/corpus/templates/brain/.agents/skills/actions/SKILL.md +5 -0
- package/corpus/templates/brain/.agents/skills/adding-a-feature/SKILL.md +5 -0
- package/corpus/templates/brain/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/corpus/templates/brain/.agents/skills/security/SKILL.md +7 -0
- package/corpus/templates/brain/AGENTS.md +4 -0
- package/corpus/templates/brain/app/routes/team.tsx +1 -1
- package/corpus/templates/calendar/.agents/skills/actions/SKILL.md +5 -0
- package/corpus/templates/calendar/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/corpus/templates/calendar/.agents/skills/security/SKILL.md +7 -0
- package/corpus/templates/calendar/.agents/skills/storing-data/SKILL.md +5 -1
- package/corpus/templates/calendar/AGENTS.md +4 -0
- package/corpus/templates/calendar/app/components/calendar/DayView.tsx +11 -2
- package/corpus/templates/calendar/app/components/calendar/EventDetailPopover.tsx +21 -8
- package/corpus/templates/calendar/app/components/calendar/MonthView.tsx +7 -1
- package/corpus/templates/calendar/app/components/calendar/WeekView.tsx +11 -2
- package/corpus/templates/calendar/app/lib/popover-click-guard.ts +48 -4
- package/corpus/templates/calendar/app/pages/Settings.tsx +1 -1
- package/corpus/templates/calendar/app/routes/_app.team.tsx +1 -1
- package/corpus/templates/calendar/changelog/2026-07-08-clicking-empty-calendar-space-closes-an-open-event-popover-b.md +6 -0
- package/corpus/templates/chat/.agents/skills/actions/SKILL.md +5 -0
- package/corpus/templates/chat/.agents/skills/adding-a-feature/SKILL.md +5 -0
- package/corpus/templates/chat/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/corpus/templates/chat/.agents/skills/security/SKILL.md +7 -0
- package/corpus/templates/chat/AGENTS.md +4 -0
- package/corpus/templates/chat/app/hooks/use-navigation-state.ts +1 -1
- package/corpus/templates/chat/app/routes/settings.tsx +2 -2
- package/corpus/templates/chat/app/routes/team.tsx +1 -1
- package/corpus/templates/clips/.agents/skills/actions/SKILL.md +5 -0
- package/corpus/templates/clips/.agents/skills/security/SKILL.md +7 -0
- package/corpus/templates/clips/AGENTS.md +4 -0
- package/corpus/templates/clips/actions/finalize-recording.ts +9 -3
- package/corpus/templates/clips/actions/set-thumbnail.ts +11 -2
- package/corpus/templates/clips/app/components/meetings/canvas-editor.tsx +1 -7
- package/corpus/templates/clips/app/components/player/player-controls.tsx +21 -13
- package/corpus/templates/clips/app/components/player/video-player.tsx +30 -75
- package/corpus/templates/clips/app/i18n/ar-SA.ts +6 -5
- package/corpus/templates/clips/app/i18n/de-DE.ts +6 -6
- package/corpus/templates/clips/app/i18n/en-US.ts +6 -5
- package/corpus/templates/clips/app/i18n/es-ES.ts +6 -5
- package/corpus/templates/clips/app/i18n/fr-FR.ts +6 -6
- package/corpus/templates/clips/app/i18n/hi-IN.ts +6 -5
- package/corpus/templates/clips/app/i18n/ja-JP.ts +6 -5
- package/corpus/templates/clips/app/i18n/ko-KR.ts +6 -5
- package/corpus/templates/clips/app/i18n/pt-BR.ts +6 -5
- package/corpus/templates/clips/app/i18n/zh-CN.ts +6 -5
- package/corpus/templates/clips/app/i18n/zh-TW.ts +6 -5
- package/corpus/templates/clips/app/routes/_app.meetings.$meetingId.tsx +51 -118
- package/corpus/templates/clips/changelog/2026-07-08-hosted-clip-uploads-now-clear-failed-buffered-chunks.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-08-hosted-recording-uploads-now-avoid-sql-chunk-storage.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-08-meeting-recaps-now-keep-summaries-action-items-and-transcrip.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-08-video-playback-controls-now-match-loom-style-5-second-skips-.md +6 -0
- package/corpus/templates/clips/server/lib/recording-upload-state.ts +63 -0
- package/corpus/templates/clips/server/lib/video-storage.ts +4 -0
- package/corpus/templates/clips/server/routes/api/recordings/[recordingId]/thumbnail.post.ts +19 -13
- package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/chunk.post.ts +40 -1
- package/corpus/templates/content/.agents/skills/actions/SKILL.md +5 -0
- package/corpus/templates/content/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/corpus/templates/content/.agents/skills/security/SKILL.md +7 -0
- package/corpus/templates/content/.agents/skills/storing-data/SKILL.md +5 -1
- package/corpus/templates/content/AGENTS.md +4 -0
- package/corpus/templates/content/app/routes/_app.settings.tsx +2 -2
- package/corpus/templates/content/app/routes/_app.team.tsx +1 -1
- package/corpus/templates/design/.agents/skills/actions/SKILL.md +5 -0
- package/corpus/templates/design/.agents/skills/security/SKILL.md +7 -0
- package/corpus/templates/design/AGENTS.md +4 -0
- package/corpus/templates/design/actions/take-design-screenshot.ts +12 -9
- package/corpus/templates/design/app/components/design/inspector/ImageFillControls.tsx +57 -13
- package/corpus/templates/design/app/routes/team.tsx +1 -1
- package/corpus/templates/design/changelog/2026-07-08-local-images-added-to-designs-now-upload-to-file-storage-ins.md +6 -0
- package/corpus/templates/dispatch/.agents/skills/actions/SKILL.md +5 -0
- package/corpus/templates/dispatch/.agents/skills/security/SKILL.md +7 -0
- package/corpus/templates/dispatch/AGENTS.md +4 -0
- package/corpus/templates/dispatch/app/hooks/use-navigation-state.ts +1 -1
- package/corpus/templates/dispatch/app/routes/settings.tsx +2 -2
- package/corpus/templates/dispatch/app/routes/team.tsx +1 -1
- package/corpus/templates/forms/.agents/skills/actions/SKILL.md +5 -0
- package/corpus/templates/forms/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/corpus/templates/forms/.agents/skills/security/SKILL.md +7 -0
- package/corpus/templates/forms/.agents/skills/storing-data/SKILL.md +5 -1
- package/corpus/templates/forms/AGENTS.md +4 -0
- package/corpus/templates/forms/app/routes/_app.settings.tsx +2 -2
- package/corpus/templates/forms/app/routes/_app.team.tsx +1 -1
- package/corpus/templates/forms/shared/navigation.ts +1 -1
- package/corpus/templates/macros/.agents/skills/security/SKILL.md +7 -0
- package/corpus/templates/macros/AGENTS.md +4 -0
- package/corpus/templates/macros/app/routes/settings.tsx +2 -2
- package/corpus/templates/macros/app/routes/team.tsx +1 -1
- package/corpus/templates/mail/.agents/skills/actions/SKILL.md +5 -0
- package/corpus/templates/mail/.agents/skills/email-drafts/SKILL.md +1 -1
- package/corpus/templates/mail/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/corpus/templates/mail/.agents/skills/security/SKILL.md +7 -0
- package/corpus/templates/mail/.agents/skills/storing-data/SKILL.md +5 -1
- package/corpus/templates/mail/AGENTS.md +4 -0
- package/corpus/templates/mail/changelog/2026-07-08-mail-attachments-in-hosted-environments-now-require-file-sto.md +6 -0
- package/corpus/templates/mail/server/handlers/media.ts +26 -1
- package/corpus/templates/mail/server/lib/outgoing-email.ts +24 -1
- package/corpus/templates/mail/server/lib/upload-store.ts +2 -1
- package/corpus/templates/plan/.agents/skills/actions/SKILL.md +5 -0
- package/corpus/templates/plan/.agents/skills/adding-a-feature/SKILL.md +5 -0
- package/corpus/templates/plan/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/corpus/templates/plan/.agents/skills/security/SKILL.md +7 -0
- package/corpus/templates/plan/AGENTS.md +4 -0
- package/corpus/templates/plan/app/hooks/use-navigation-state.ts +1 -1
- package/corpus/templates/plan/app/routes/settings.tsx +2 -2
- package/corpus/templates/plan/app/routes/team.tsx +1 -1
- package/corpus/templates/plan/changelog/2026-07-08-hosted-plan-images-now-require-connected-storage.md +6 -0
- package/corpus/templates/plan/server/lib/plan-assets.ts +33 -4
- package/corpus/templates/slides/.agents/skills/actions/SKILL.md +5 -0
- package/corpus/templates/slides/.agents/skills/security/SKILL.md +7 -0
- package/corpus/templates/slides/AGENTS.md +4 -0
- package/corpus/templates/slides/actions/generate-image-api.ts +15 -3
- package/corpus/templates/slides/app/routes/settings.tsx +2 -2
- package/corpus/templates/slides/app/routes/team.tsx +1 -1
- package/corpus/templates/slides/changelog/2026-07-08-generated-slide-images-now-return-hosted-file-storage-urls-i.md +6 -0
- package/corpus/templates/slides/shared/api.ts +1 -1
- package/dist/application-state/store.d.ts.map +1 -1
- package/dist/application-state/store.js +8 -2
- package/dist/application-state/store.js.map +1 -1
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +24 -13
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/PoweredByBadge.d.ts +1 -1
- package/dist/client/PoweredByBadge.d.ts.map +1 -1
- package/dist/client/PoweredByBadge.js +3 -9
- package/dist/client/PoweredByBadge.js.map +1 -1
- package/dist/client/agent-chat-adapter.d.ts.map +1 -1
- package/dist/client/agent-chat-adapter.js +28 -9
- package/dist/client/agent-chat-adapter.js.map +1 -1
- package/dist/client/chat/widgets/DataTableWidget.d.ts.map +1 -1
- package/dist/client/chat/widgets/DataTableWidget.js +19 -2
- package/dist/client/chat/widgets/DataTableWidget.js.map +1 -1
- package/dist/client/db-admin/TableEditor.d.ts.map +1 -1
- package/dist/client/db-admin/TableEditor.js +19 -2
- package/dist/client/db-admin/TableEditor.js.map +1 -1
- package/dist/client/db-admin/export-utils.d.ts +2 -0
- package/dist/client/db-admin/export-utils.d.ts.map +1 -1
- package/dist/client/db-admin/export-utils.js +11 -3
- package/dist/client/db-admin/export-utils.js.map +1 -1
- package/dist/client/db-admin/useAgentSync.d.ts.map +1 -1
- package/dist/client/db-admin/useAgentSync.js +63 -0
- package/dist/client/db-admin/useAgentSync.js.map +1 -1
- package/dist/client/error-capture.d.ts.map +1 -1
- package/dist/client/error-capture.js +41 -7
- package/dist/client/error-capture.js.map +1 -1
- package/dist/client/extensions/EmbeddedExtension.d.ts.map +1 -1
- package/dist/client/extensions/EmbeddedExtension.js +3 -1
- package/dist/client/extensions/EmbeddedExtension.js.map +1 -1
- package/dist/client/extensions/ExtensionViewer.d.ts.map +1 -1
- package/dist/client/extensions/ExtensionViewer.js +32 -5
- package/dist/client/extensions/ExtensionViewer.js.map +1 -1
- package/dist/client/extensions/InlineExtensionFrame.d.ts.map +1 -1
- package/dist/client/extensions/InlineExtensionFrame.js +3 -1
- package/dist/client/extensions/InlineExtensionFrame.js.map +1 -1
- package/dist/client/extensions/portable-extension.d.ts.map +1 -1
- package/dist/client/extensions/portable-extension.js +1 -0
- package/dist/client/extensions/portable-extension.js.map +1 -1
- package/dist/client/org/OrgSwitcher.d.ts +1 -1
- package/dist/client/org/OrgSwitcher.d.ts.map +1 -1
- package/dist/client/org/OrgSwitcher.js +11 -6
- package/dist/client/org/OrgSwitcher.js.map +1 -1
- package/dist/client/org/TeamPage.d.ts.map +1 -1
- package/dist/client/org/TeamPage.js +5 -5
- package/dist/client/org/TeamPage.js.map +1 -1
- package/dist/client/settings/SettingsPanel.d.ts.map +1 -1
- package/dist/client/settings/SettingsPanel.js +37 -14
- package/dist/client/settings/SettingsPanel.js.map +1 -1
- package/dist/client/settings/SettingsSection.js +1 -1
- package/dist/client/settings/SettingsSection.js.map +1 -1
- package/dist/client/settings/SettingsTabsPage.d.ts.map +1 -1
- package/dist/client/settings/SettingsTabsPage.js +21 -10
- package/dist/client/settings/SettingsTabsPage.js.map +1 -1
- package/dist/collab/routes.d.ts +1 -1
- package/dist/db-admin/agent-tools.d.ts.map +1 -1
- package/dist/db-admin/agent-tools.js +7 -2
- package/dist/db-admin/agent-tools.js.map +1 -1
- package/dist/db-admin/operations.d.ts.map +1 -1
- package/dist/db-admin/operations.js +90 -4
- package/dist/db-admin/operations.js.map +1 -1
- package/dist/db-admin/routes.d.ts.map +1 -1
- package/dist/db-admin/routes.js +1 -0
- package/dist/db-admin/routes.js.map +1 -1
- package/dist/db-admin/types.d.ts +4 -0
- package/dist/db-admin/types.d.ts.map +1 -1
- package/dist/db-admin/types.js.map +1 -1
- package/dist/extensions/html-shell.d.ts +5 -4
- package/dist/extensions/html-shell.d.ts.map +1 -1
- package/dist/extensions/html-shell.js.map +1 -1
- package/dist/extensions/routes.d.ts.map +1 -1
- package/dist/extensions/routes.js +8 -0
- package/dist/extensions/routes.js.map +1 -1
- package/dist/navigation/index.d.ts +1 -1
- package/dist/navigation/index.d.ts.map +1 -1
- package/dist/navigation/index.js +1 -1
- package/dist/navigation/index.js.map +1 -1
- package/dist/notifications/routes.d.ts +1 -1
- package/dist/observability/routes.d.ts +1 -1
- package/dist/resources/handlers.d.ts +6 -1
- package/dist/resources/handlers.d.ts.map +1 -1
- package/dist/resources/handlers.js +9 -8
- package/dist/resources/handlers.js.map +1 -1
- package/dist/server/poll.d.ts +12 -4
- package/dist/server/poll.d.ts.map +1 -1
- package/dist/server/poll.js +236 -9
- package/dist/server/poll.js.map +1 -1
- package/dist/styles/agent-native.css +27 -0
- package/dist/templates/default/.agents/skills/actions/SKILL.md +5 -0
- package/dist/templates/default/.agents/skills/adding-a-feature/SKILL.md +5 -0
- package/dist/templates/default/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/dist/templates/default/.agents/skills/security/SKILL.md +7 -0
- package/dist/templates/default/.agents/skills/storing-data/SKILL.md +5 -1
- package/dist/templates/default/AGENTS.md +4 -2
- package/dist/templates/headless/AGENTS.md +4 -0
- package/dist/templates/workspace-core/.agents/skills/actions/SKILL.md +5 -0
- package/dist/templates/workspace-core/.agents/skills/adding-a-feature/SKILL.md +5 -0
- package/dist/templates/workspace-core/.agents/skills/context-awareness/SKILL.md +4 -0
- package/dist/templates/workspace-core/.agents/skills/extensions/SKILL.md +6 -0
- package/dist/templates/workspace-core/.agents/skills/performance/SKILL.md +4 -0
- package/dist/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/dist/templates/workspace-core/.agents/skills/security/SKILL.md +7 -0
- package/dist/templates/workspace-core/.agents/skills/storing-data/SKILL.md +5 -1
- package/dist/templates/workspace-core/AGENTS.md +7 -1
- package/dist/templates/workspace-root/AGENTS.md +7 -1
- package/package.json +1 -1
- package/src/templates/default/.agents/skills/actions/SKILL.md +5 -0
- package/src/templates/default/.agents/skills/adding-a-feature/SKILL.md +5 -0
- package/src/templates/default/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/src/templates/default/.agents/skills/security/SKILL.md +7 -0
- package/src/templates/default/.agents/skills/storing-data/SKILL.md +5 -1
- package/src/templates/default/AGENTS.md +4 -2
- package/src/templates/headless/AGENTS.md +4 -0
- package/src/templates/workspace-core/.agents/skills/actions/SKILL.md +5 -0
- package/src/templates/workspace-core/.agents/skills/adding-a-feature/SKILL.md +5 -0
- package/src/templates/workspace-core/.agents/skills/context-awareness/SKILL.md +4 -0
- package/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +6 -0
- package/src/templates/workspace-core/.agents/skills/performance/SKILL.md +4 -0
- package/src/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/src/templates/workspace-core/.agents/skills/security/SKILL.md +7 -0
- package/src/templates/workspace-core/.agents/skills/storing-data/SKILL.md +5 -1
- package/src/templates/workspace-core/AGENTS.md +7 -1
- package/src/templates/workspace-root/AGENTS.md +7 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handlers.js","sourceRoot":"","sources":["../../src/resources/handlers.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n getQuery,\n getRouterParam,\n setResponseHeader,\n setResponseStatus,\n readMultipartFormData,\n} from \"h3\";\nimport { createError } from \"h3\";\n\nimport { uploadFile } from \"../file-upload/index.js\";\nimport { getOrgContext } from \"../org/context.js\";\nimport { getSession } from \"../server/auth.js\";\nimport {\n readBody,\n DEFAULT_UPLOAD_MAX_FILE_BYTES,\n isAllowedUploadMimeType,\n} from \"../server/h3-helpers.js\";\nimport { runWithRequestContext } from \"../server/request-context.js\";\nimport {\n getResourceKind,\n isRemoteAgentPath,\n parseCustomAgentProfile,\n parseRemoteAgentManifest,\n parseSkillMetadata,\n type CustomAgentProfile,\n type RemoteAgentManifest,\n type SkillMetadata,\n} from \"./metadata.js\";\nimport {\n resourceGet,\n resourceGetByPath,\n resourcePut,\n resourceDelete,\n resourceList,\n resourceListAccessible,\n resourceMove,\n resourceEffectiveContext,\n ensurePersonalDefaults,\n canWriteLocalWorkspaceResourcePath,\n isLocalWorkspaceResourceId,\n SHARED_OWNER,\n WORKSPACE_OWNER,\n type ResourceMeta,\n} from \"./store.js\";\n\n// ---------------------------------------------------------------------------\n// Owner resolution\n// ---------------------------------------------------------------------------\n\nasync function resolveOwner(event: any, shared?: boolean): Promise<string> {\n if (shared) return SHARED_OWNER;\n const session = await getSession(event);\n if (!session?.email) {\n throw createError({ statusCode: 401, statusMessage: \"Unauthenticated\" });\n }\n return session.email;\n}\n\nfunction canReadOwner(owner: string, email: string): boolean {\n return owner === email || owner === SHARED_OWNER || owner === WORKSPACE_OWNER;\n}\n\nasync function resolveEmail(event: any): Promise<string> {\n const session = await getSession(event);\n if (!session?.email) {\n throw createError({ statusCode: 401, statusMessage: \"Unauthenticated\" });\n }\n return session.email;\n}\n\nasync function resolveOrgId(event: any): Promise<string | null> {\n try {\n const ctx = await getOrgContext(event);\n return ctx.orgId ?? null;\n } catch {\n return null;\n }\n}\n\n/**\n * Reject writes to organization-wide resources unless the user is the\n * organization owner/admin (or the deployment is solo — no org membership).\n * Read access remains open to every org member.\n */\nasync function assertCanEditShared(event: any): Promise<void> {\n const session = await getSession(event);\n if (!session?.email) {\n throw createError({ statusCode: 401, statusMessage: \"Unauthenticated\" });\n }\n const ctx = await getOrgContext(event);\n if (!ctx.orgId) return; // solo / dev mode — no org, treat as owner\n if (ctx.role === \"owner\" || ctx.role === \"admin\") return;\n throw createError({\n statusCode: 403,\n message: \"Only organization admins can edit organization files\",\n });\n}\n\nfunction shouldIncludeAgentScratch(query: Record<string, unknown>): boolean {\n return (\n query.includeAgentScratch === \"true\" ||\n query.includeScratch === \"true\" ||\n query.includeAgentScratch === true ||\n query.includeScratch === true\n );\n}\n\n// ---------------------------------------------------------------------------\n// Tree building\n// ---------------------------------------------------------------------------\n\ninterface JobMetadata {\n schedule?: string;\n scheduleDescription?: string;\n enabled?: boolean;\n lastStatus?: string;\n lastRun?: string;\n nextRun?: string;\n}\n\ninterface TreeNode {\n name: string;\n path: string;\n type: \"file\" | \"folder\";\n kind?: \"file\" | \"skill\" | \"job\" | \"agent\" | \"remote-agent\";\n children?: TreeNode[];\n resource?: ResourceMeta;\n jobMeta?: JobMetadata;\n skillMeta?: SkillMetadata;\n agentMeta?: CustomAgentProfile;\n remoteAgentMeta?: RemoteAgentManifest;\n}\n\nfunction buildTree(resources: ResourceMeta[]): TreeNode[] {\n const root: TreeNode[] = [];\n\n for (const res of resources) {\n const parts = res.path.split(\"/\").filter(Boolean);\n let current = root;\n\n for (let i = 0; i < parts.length; i++) {\n const part = parts[i];\n const isLast = i === parts.length - 1;\n const currentPath = \"/\" + parts.slice(0, i + 1).join(\"/\");\n\n if (isLast) {\n current.push({\n name: part,\n path: currentPath,\n type: \"file\",\n kind: getResourceKind(res.path),\n resource: res,\n });\n } else {\n let folder = current.find(\n (n) => n.name === part && n.type === \"folder\",\n );\n if (!folder) {\n folder = {\n name: part,\n path: currentPath,\n type: \"folder\",\n children: [],\n };\n current.push(folder);\n }\n current = folder.children!;\n }\n }\n }\n\n sortTree(root);\n return root;\n}\n\n/** Sort tree nodes: folders first, then files, alphabetically within each group */\nfunction sortTree(nodes: TreeNode[]): void {\n nodes.sort((a, b) => {\n if (a.type !== b.type) return a.type === \"folder\" ? -1 : 1;\n return a.name.localeCompare(b.name, undefined, { sensitivity: \"base\" });\n });\n for (const node of nodes) {\n if (node.children) sortTree(node.children);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Handlers\n// ---------------------------------------------------------------------------\n\n/** GET /_agent-native/resources — list resources */\nexport async function handleListResources(event: any) {\n const query = getQuery(event);\n const prefix = (query.prefix as string) || undefined;\n const scope = (query.scope as string) || \"all\";\n const email = await resolveEmail(event);\n const orgId = await resolveOrgId(event);\n const includeAgentScratch = shouldIncludeAgentScratch(query);\n const localListOptions = includeAgentScratch\n ? { includeAgentScratch: true }\n : undefined;\n const scopedListOptions = includeAgentScratch\n ? { includeAgentScratch: true, userEmail: email, orgId }\n : { userEmail: email, orgId };\n\n // Seed personal AGENTS.md + LEARNINGS.md on first access\n await ensurePersonalDefaults(email);\n\n let resources: ResourceMeta[];\n\n if (scope === \"personal\") {\n resources = localListOptions\n ? await resourceList(email, prefix, localListOptions)\n : await resourceList(email, prefix);\n } else if (scope === \"workspace\") {\n resources = await resourceList(WORKSPACE_OWNER, prefix, scopedListOptions);\n } else if (scope === \"shared\") {\n resources = localListOptions\n ? await resourceList(SHARED_OWNER, prefix, localListOptions)\n : await resourceList(SHARED_OWNER, prefix);\n } else {\n // \"all\" — personal + organization/shared + inherited workspace\n resources = await resourceListAccessible(email, prefix, scopedListOptions);\n }\n\n return { resources };\n}\n\n/** GET /_agent-native/resources/tree — build nested tree */\nexport async function handleGetResourceTree(event: any) {\n const query = getQuery(event);\n const scope = (query.scope as string) || \"all\";\n const email = await resolveEmail(event);\n const orgId = await resolveOrgId(event);\n const includeAgentScratch = shouldIncludeAgentScratch(query);\n const localListOptions = includeAgentScratch\n ? { includeAgentScratch: true }\n : undefined;\n const scopedListOptions = includeAgentScratch\n ? { includeAgentScratch: true, userEmail: email, orgId }\n : { userEmail: email, orgId };\n\n // Seed personal AGENTS.md + LEARNINGS.md on first access\n await ensurePersonalDefaults(email);\n\n let resources: ResourceMeta[];\n\n if (scope === \"personal\") {\n resources = localListOptions\n ? await resourceList(email, undefined, localListOptions)\n : await resourceList(email);\n } else if (scope === \"workspace\") {\n resources = await resourceList(\n WORKSPACE_OWNER,\n undefined,\n scopedListOptions,\n );\n } else if (scope === \"shared\") {\n resources = localListOptions\n ? await resourceList(SHARED_OWNER, undefined, localListOptions)\n : await resourceList(SHARED_OWNER);\n } else {\n resources = await resourceListAccessible(\n email,\n undefined,\n scopedListOptions,\n );\n }\n\n const tree = buildTree(resources);\n\n // Enrich typed resources with parsed metadata for richer UI\n await enrichTreeNodes(tree);\n\n return { tree };\n}\n\n/** GET /_agent-native/resources/effective?path=... — show inheritance stack */\nexport async function handleGetEffectiveResourceContext(event: any) {\n const query = getQuery(event);\n const path = query.path;\n if (typeof path !== \"string\" || path.trim().length === 0) {\n setResponseStatus(event, 400);\n return { error: \"path is required\" };\n }\n\n const email = await resolveEmail(event);\n const orgId = await resolveOrgId(event);\n await ensurePersonalDefaults(email);\n return resourceEffectiveContext(email, path, { userEmail: email, orgId });\n}\n\n/**\n * Walk the tree and add typed metadata for jobs, skills, and agents.\n */\nasync function enrichTreeNodes(nodes: TreeNode[]): Promise<void> {\n let parseFn: typeof import(\"../jobs/scheduler.js\").parseJobFrontmatter;\n let describeFn: typeof import(\"../jobs/cron.js\").describeCron;\n try {\n const scheduler = await import(\"../jobs/scheduler.js\");\n const cron = await import(\"../jobs/cron.js\");\n parseFn = scheduler.parseJobFrontmatter;\n describeFn = cron.describeCron;\n } catch {\n return; // Jobs module not available\n }\n\n for (const node of nodes) {\n if (node.type === \"folder\" && node.children) {\n await enrichTreeNodes(node.children);\n }\n if (node.type === \"file\" && node.resource) {\n try {\n const full = await resourceGet(node.resource.id);\n if (!full?.content) continue;\n\n if (\n node.resource.path.startsWith(\"jobs/\") &&\n node.resource.path.endsWith(\".md\")\n ) {\n const { meta } = parseFn(full.content);\n node.jobMeta = {\n schedule: meta.schedule,\n scheduleDescription: meta.schedule\n ? describeFn(meta.schedule)\n : undefined,\n enabled: meta.enabled,\n lastStatus: meta.lastStatus,\n lastRun: meta.lastRun,\n nextRun: meta.nextRun,\n };\n }\n\n if (\n node.resource.path.startsWith(\"skills/\") &&\n node.resource.path.endsWith(\".md\")\n ) {\n node.skillMeta =\n parseSkillMetadata(full.content, node.resource.path) ?? undefined;\n }\n\n if (\n node.resource.path.startsWith(\"agents/\") &&\n node.resource.path.endsWith(\".md\")\n ) {\n node.agentMeta =\n parseCustomAgentProfile(full.content, node.resource.path) ??\n undefined;\n }\n\n if (isRemoteAgentPath(node.resource.path)) {\n node.remoteAgentMeta =\n parseRemoteAgentManifest(full.content, node.resource.path) ??\n undefined;\n }\n } catch {\n // Skip individual file errors\n }\n }\n }\n}\n\n/** GET /_agent-native/resources/:id — get single resource with content.\n * If the request comes from an <img>/<video>/etc tag (Accept includes the\n * resource's mime type, or query param `?raw` is set), return the raw binary\n * with the correct Content-Type so the browser can render it inline. */\nexport async function handleGetResource(event: any) {\n const id = getRouterParam(event, \"id\") || event.context.params?.id;\n if (!id) {\n setResponseStatus(event, 400);\n return { error: \"Resource ID is required\" };\n }\n\n const email = await resolveEmail(event);\n const orgId = await resolveOrgId(event);\n const resource = await resourceGet(id, { userEmail: email, orgId });\n if (!resource) {\n setResponseStatus(event, 404);\n return { error: \"Resource not found\" };\n }\n\n if (!canReadOwner(resource.owner, email)) {\n setResponseStatus(event, 404);\n return { error: \"Resource not found\" };\n }\n\n // Serve raw binary when ?raw query param is set (used by <img> tags etc.)\n const query = getQuery(event);\n const wantsRaw = query.raw !== undefined;\n\n if (wantsRaw && resource.content) {\n const isText =\n resource.mimeType.startsWith(\"text/\") ||\n resource.mimeType === \"application/json\";\n const buf = isText\n ? Buffer.from(resource.content, \"utf-8\")\n : Buffer.from(resource.content, \"base64\");\n\n setResponseHeader(event, \"Content-Type\", resource.mimeType);\n setResponseHeader(event, \"Content-Length\", String(buf.length));\n return new Response(buf);\n }\n\n // For binary resources (images, audio, video), omit the content field from\n // the JSON response — it can be megabytes of base64. The client fetches\n // the actual bytes via ?raw when it needs to display them.\n const isBinary =\n resource.mimeType.startsWith(\"image/\") ||\n resource.mimeType.startsWith(\"audio/\") ||\n resource.mimeType.startsWith(\"video/\") ||\n resource.mimeType === \"application/octet-stream\";\n\n if (isBinary) {\n const { content: _content, ...meta } = resource;\n return { ...meta, content: \"\" };\n }\n\n return resource;\n}\n\n/** POST /_agent-native/resources — create a resource */\nexport async function handleCreateResource(event: any) {\n const body = await readBody(event);\n\n if (!body?.path || typeof body.path !== \"string\") {\n setResponseStatus(event, 400);\n return { error: \"path is required\" };\n }\n\n if (body.shared) {\n await assertCanEditShared(event);\n }\n\n const owner = await resolveOwner(event, body.shared);\n\n // If ifNotExists is set, skip if the resource already exists\n if (body.ifNotExists) {\n const existing = await resourceGetByPath(owner, body.path);\n if (existing) {\n return existing;\n }\n }\n\n const writeOptions =\n body.metadata !== undefined ? { metadata: body.metadata } : undefined;\n const resource = writeOptions\n ? await resourcePut(\n owner,\n body.path,\n body.content ?? \"\",\n body.mimeType,\n writeOptions,\n )\n : await resourcePut(owner, body.path, body.content ?? \"\", body.mimeType);\n\n setResponseStatus(event, 201);\n return resource;\n}\n\n/** PUT /_agent-native/resources/:id — update an existing resource */\nexport async function handleUpdateResource(event: any) {\n const id = getRouterParam(event, \"id\") || event.context.params?.id;\n if (!id) {\n setResponseStatus(event, 400);\n return { error: \"Resource ID is required\" };\n }\n\n const existing = await resourceGet(id);\n if (!existing) {\n setResponseStatus(event, 404);\n return { error: \"Resource not found\" };\n }\n\n // Ownership check: only the owner (or shared resource editors) can update\n const email = await resolveEmail(event);\n if (!canReadOwner(existing.owner, email)) {\n setResponseStatus(event, 404);\n return { error: \"Resource not found\" };\n }\n const isLocalWorkspaceResource =\n existing.owner === WORKSPACE_OWNER && isLocalWorkspaceResourceId(id);\n if (existing.owner === WORKSPACE_OWNER && !isLocalWorkspaceResource) {\n setResponseStatus(event, 403);\n return { error: \"Workspace resources are managed from Dispatch\" };\n }\n if (existing.owner === SHARED_OWNER) {\n await assertCanEditShared(event);\n }\n\n const body = await readBody(event);\n const nextPath = body.path ?? existing.path;\n\n if (\n isLocalWorkspaceResource &&\n nextPath !== existing.path &&\n !(await canWriteLocalWorkspaceResourcePath(nextPath))\n ) {\n setResponseStatus(event, 400);\n return {\n error:\n \"Local workspace resources can only be moved to AGENTS.md, agent-native.json, mcp.config.json, .mcp.json, or skills/.\",\n };\n }\n\n // If path changed, move it\n if (!isLocalWorkspaceResource && body.path && body.path !== existing.path) {\n await resourceMove(id, body.path);\n }\n\n // Update content/mimeType by re-putting\n const writeOptions =\n body.metadata !== undefined ? { metadata: body.metadata } : undefined;\n const resource = writeOptions\n ? await resourcePut(\n existing.owner,\n nextPath,\n body.content ?? existing.content,\n body.mimeType ?? existing.mimeType,\n writeOptions,\n )\n : await resourcePut(\n existing.owner,\n nextPath,\n body.content ?? existing.content,\n body.mimeType ?? existing.mimeType,\n );\n if (isLocalWorkspaceResource && nextPath !== existing.path) {\n await resourceDelete(id);\n }\n\n return resource;\n}\n\n/** DELETE /_agent-native/resources/:id — delete a resource */\nexport async function handleDeleteResource(event: any) {\n const id = getRouterParam(event, \"id\") || event.context.params?.id;\n if (!id) {\n setResponseStatus(event, 400);\n return { error: \"Resource ID is required\" };\n }\n\n const existing = await resourceGet(id);\n if (!existing) {\n setResponseStatus(event, 404);\n return { error: \"Resource not found\" };\n }\n\n // Ownership check: only the owner (or shared resource editors) can delete\n const email = await resolveEmail(event);\n if (!canReadOwner(existing.owner, email)) {\n setResponseStatus(event, 404);\n return { error: \"Resource not found\" };\n }\n if (\n existing.owner === WORKSPACE_OWNER &&\n !isLocalWorkspaceResourceId(existing.id)\n ) {\n setResponseStatus(event, 403);\n return { error: \"Workspace resources are managed from Dispatch\" };\n }\n if (existing.owner === SHARED_OWNER) {\n await assertCanEditShared(event);\n }\n\n await resourceDelete(id);\n return { ok: true };\n}\n\n/** POST /_agent-native/resources/upload — upload a file as a resource */\nexport async function handleUploadResource(event: any) {\n const parts = await readMultipartFormData(event);\n\n if (!parts || parts.length === 0) {\n setResponseStatus(event, 400);\n return { error: \"No file uploaded\" };\n }\n\n const filePart = parts.find((p) => p.name === \"file\");\n const pathPart = parts.find((p) => p.name === \"path\");\n const sharedPart = parts.find((p) => p.name === \"shared\");\n\n if (!filePart || !filePart.data) {\n setResponseStatus(event, 400);\n return { error: \"No file data found\" };\n }\n\n // Reject oversized uploads before touching any storage.\n if (filePart.data.length > DEFAULT_UPLOAD_MAX_FILE_BYTES) {\n setResponseStatus(event, 413);\n return {\n error: `File too large (max ${Math.round(DEFAULT_UPLOAD_MAX_FILE_BYTES / 1024 / 1024)} MB)`,\n };\n }\n\n const fileName = filePart.filename || \"upload\";\n const path = pathPart?.data?.toString() || `/${fileName}`;\n const shared = sharedPart?.data?.toString() === \"true\";\n const mimeType = filePart.type || \"application/octet-stream\";\n\n // Reject executable / script MIME types.\n if (filePart.type && !isAllowedUploadMimeType(filePart.type)) {\n setResponseStatus(event, 415);\n return { error: `Unsupported file type: ${filePart.type}` };\n }\n if (shared) {\n await assertCanEditShared(event);\n }\n const owner = await resolveOwner(event, shared);\n\n // Prefer a registered file upload provider (e.g. Builder.io) for binary\n // assets so we get a real CDN URL instead of a base64 blob in SQL.\n // Text resources still live in SQL — they're edited inline and benefit\n // from the resource store's metadata/search features.\n const isText =\n mimeType.startsWith(\"text/\") || mimeType === \"application/json\";\n\n if (!isText) {\n // Use the actual session user email for credential resolution — not `owner`,\n // which is \"__shared__\" for org-wide resources and would break the per-user\n // DB credential lookup (resolveBuilderCredential refuses env fallback for any\n // non-null non-local email, including the sentinel value).\n const credentialEmail =\n owner !== SHARED_OWNER\n ? owner\n : (await getSession(event).catch(() => null))?.email;\n const doUpload = () =>\n uploadFile({\n data: filePart.data,\n filename: fileName,\n mimeType,\n ownerEmail: owner,\n });\n const uploaded = credentialEmail\n ? await runWithRequestContext({ userEmail: credentialEmail }, doUpload)\n : await doUpload();\n if (uploaded) {\n const resource = await resourcePut(owner, path, uploaded.url, mimeType);\n setResponseStatus(event, 201);\n return { ...resource, url: uploaded.url, provider: uploaded.provider };\n }\n }\n\n // Fallback: store contents in SQL (base64 for binary, text as-is).\n const content = isText\n ? Buffer.from(filePart.data).toString(\"utf-8\")\n : Buffer.from(filePart.data).toString(\"base64\");\n\n const resource = await resourcePut(owner, path, content, mimeType);\n\n setResponseStatus(event, 201);\n return resource;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"handlers.js","sourceRoot":"","sources":["../../src/resources/handlers.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n getQuery,\n getRouterParam,\n setResponseHeader,\n setResponseStatus,\n readMultipartFormData,\n} from \"h3\";\nimport { createError } from \"h3\";\n\nimport { uploadFile } from \"../file-upload/index.js\";\nimport { getOrgContext } from \"../org/context.js\";\nimport { getSession } from \"../server/auth.js\";\nimport {\n readBody,\n DEFAULT_UPLOAD_MAX_FILE_BYTES,\n isAllowedUploadMimeType,\n} from \"../server/h3-helpers.js\";\nimport { runWithRequestContext } from \"../server/request-context.js\";\nimport {\n getResourceKind,\n isRemoteAgentPath,\n parseCustomAgentProfile,\n parseRemoteAgentManifest,\n parseSkillMetadata,\n type CustomAgentProfile,\n type RemoteAgentManifest,\n type SkillMetadata,\n} from \"./metadata.js\";\nimport {\n resourceGet,\n resourceGetByPath,\n resourcePut,\n resourceDelete,\n resourceList,\n resourceListAccessible,\n resourceMove,\n resourceEffectiveContext,\n ensurePersonalDefaults,\n canWriteLocalWorkspaceResourcePath,\n isLocalWorkspaceResourceId,\n SHARED_OWNER,\n WORKSPACE_OWNER,\n type ResourceMeta,\n} from \"./store.js\";\n\n// ---------------------------------------------------------------------------\n// Owner resolution\n// ---------------------------------------------------------------------------\n\nasync function resolveOwner(event: any, shared?: boolean): Promise<string> {\n if (shared) return SHARED_OWNER;\n const session = await getSession(event);\n if (!session?.email) {\n throw createError({ statusCode: 401, statusMessage: \"Unauthenticated\" });\n }\n return session.email;\n}\n\nfunction canReadOwner(owner: string, email: string): boolean {\n return owner === email || owner === SHARED_OWNER || owner === WORKSPACE_OWNER;\n}\n\nasync function resolveEmail(event: any): Promise<string> {\n const session = await getSession(event);\n if (!session?.email) {\n throw createError({ statusCode: 401, statusMessage: \"Unauthenticated\" });\n }\n return session.email;\n}\n\nasync function resolveOrgId(event: any): Promise<string | null> {\n try {\n const ctx = await getOrgContext(event);\n return ctx.orgId ?? null;\n } catch {\n return null;\n }\n}\n\n/**\n * Reject writes to organization-wide resources unless the user is the\n * organization owner/admin (or the deployment is solo — no org membership).\n * Read access remains open to every org member.\n */\nasync function assertCanEditShared(event: any): Promise<void> {\n const session = await getSession(event);\n if (!session?.email) {\n throw createError({ statusCode: 401, statusMessage: \"Unauthenticated\" });\n }\n const ctx = await getOrgContext(event);\n if (!ctx.orgId) return; // solo / dev mode — no org, treat as owner\n if (ctx.role === \"owner\" || ctx.role === \"admin\") return;\n throw createError({\n statusCode: 403,\n message: \"Only organization admins can edit organization files\",\n });\n}\n\nfunction shouldIncludeAgentScratch(query: Record<string, unknown>): boolean {\n return (\n query.includeAgentScratch === \"true\" ||\n query.includeScratch === \"true\" ||\n query.includeAgentScratch === true ||\n query.includeScratch === true\n );\n}\n\n// ---------------------------------------------------------------------------\n// Tree building\n// ---------------------------------------------------------------------------\n\ninterface JobMetadata {\n schedule?: string;\n scheduleDescription?: string;\n enabled?: boolean;\n lastStatus?: string;\n lastRun?: string;\n nextRun?: string;\n}\n\ninterface TreeNode {\n name: string;\n path: string;\n type: \"file\" | \"folder\";\n kind?: \"file\" | \"skill\" | \"job\" | \"agent\" | \"remote-agent\";\n children?: TreeNode[];\n resource?: ResourceMeta;\n jobMeta?: JobMetadata;\n skillMeta?: SkillMetadata;\n agentMeta?: CustomAgentProfile;\n remoteAgentMeta?: RemoteAgentManifest;\n}\n\nfunction buildTree(resources: ResourceMeta[]): TreeNode[] {\n const root: TreeNode[] = [];\n\n for (const res of resources) {\n const parts = res.path.split(\"/\").filter(Boolean);\n let current = root;\n\n for (let i = 0; i < parts.length; i++) {\n const part = parts[i];\n const isLast = i === parts.length - 1;\n const currentPath = \"/\" + parts.slice(0, i + 1).join(\"/\");\n\n if (isLast) {\n current.push({\n name: part,\n path: currentPath,\n type: \"file\",\n kind: getResourceKind(res.path),\n resource: res,\n });\n } else {\n let folder = current.find(\n (n) => n.name === part && n.type === \"folder\",\n );\n if (!folder) {\n folder = {\n name: part,\n path: currentPath,\n type: \"folder\",\n children: [],\n };\n current.push(folder);\n }\n current = folder.children!;\n }\n }\n }\n\n sortTree(root);\n return root;\n}\n\n/** Sort tree nodes: folders first, then files, alphabetically within each group */\nfunction sortTree(nodes: TreeNode[]): void {\n nodes.sort((a, b) => {\n if (a.type !== b.type) return a.type === \"folder\" ? -1 : 1;\n return a.name.localeCompare(b.name, undefined, { sensitivity: \"base\" });\n });\n for (const node of nodes) {\n if (node.children) sortTree(node.children);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Handlers\n// ---------------------------------------------------------------------------\n\n/** GET /_agent-native/resources — list resources */\nexport async function handleListResources(event: any) {\n const query = getQuery(event);\n const prefix = (query.prefix as string) || undefined;\n const scope = (query.scope as string) || \"all\";\n const email = await resolveEmail(event);\n const orgId = await resolveOrgId(event);\n const includeAgentScratch = shouldIncludeAgentScratch(query);\n const localListOptions = includeAgentScratch\n ? { includeAgentScratch: true }\n : undefined;\n const scopedListOptions = includeAgentScratch\n ? { includeAgentScratch: true, userEmail: email, orgId }\n : { userEmail: email, orgId };\n\n // Seed personal AGENTS.md + LEARNINGS.md on first access\n await ensurePersonalDefaults(email);\n\n let resources: ResourceMeta[];\n\n if (scope === \"personal\") {\n resources = localListOptions\n ? await resourceList(email, prefix, localListOptions)\n : await resourceList(email, prefix);\n } else if (scope === \"workspace\") {\n resources = await resourceList(WORKSPACE_OWNER, prefix, scopedListOptions);\n } else if (scope === \"shared\") {\n resources = localListOptions\n ? await resourceList(SHARED_OWNER, prefix, localListOptions)\n : await resourceList(SHARED_OWNER, prefix);\n } else {\n // \"all\" — personal + organization/shared + inherited workspace\n resources = await resourceListAccessible(email, prefix, scopedListOptions);\n }\n\n return { resources };\n}\n\n/** GET /_agent-native/resources/tree — build nested tree */\nexport async function handleGetResourceTree(event: any) {\n const query = getQuery(event);\n const scope = (query.scope as string) || \"all\";\n const email = await resolveEmail(event);\n const orgId = await resolveOrgId(event);\n const includeAgentScratch = shouldIncludeAgentScratch(query);\n const localListOptions = includeAgentScratch\n ? { includeAgentScratch: true }\n : undefined;\n const scopedListOptions = includeAgentScratch\n ? { includeAgentScratch: true, userEmail: email, orgId }\n : { userEmail: email, orgId };\n\n // Seed personal AGENTS.md + LEARNINGS.md on first access\n await ensurePersonalDefaults(email);\n\n let resources: ResourceMeta[];\n\n if (scope === \"personal\") {\n resources = localListOptions\n ? await resourceList(email, undefined, localListOptions)\n : await resourceList(email);\n } else if (scope === \"workspace\") {\n resources = await resourceList(\n WORKSPACE_OWNER,\n undefined,\n scopedListOptions,\n );\n } else if (scope === \"shared\") {\n resources = localListOptions\n ? await resourceList(SHARED_OWNER, undefined, localListOptions)\n : await resourceList(SHARED_OWNER);\n } else {\n resources = await resourceListAccessible(\n email,\n undefined,\n scopedListOptions,\n );\n }\n\n const tree = buildTree(resources);\n\n // Enrich typed resources with parsed metadata for richer UI\n await enrichTreeNodes(tree);\n\n return { tree };\n}\n\n/** GET /_agent-native/resources/effective?path=... — show inheritance stack */\nexport async function handleGetEffectiveResourceContext(event: any) {\n const query = getQuery(event);\n const path = query.path;\n if (typeof path !== \"string\" || path.trim().length === 0) {\n setResponseStatus(event, 400);\n return { error: \"path is required\" };\n }\n\n const email = await resolveEmail(event);\n const orgId = await resolveOrgId(event);\n await ensurePersonalDefaults(email);\n return resourceEffectiveContext(email, path, { userEmail: email, orgId });\n}\n\n/**\n * Walk the tree and add typed metadata for jobs, skills, and agents.\n */\nasync function enrichTreeNodes(nodes: TreeNode[]): Promise<void> {\n let parseFn: typeof import(\"../jobs/scheduler.js\").parseJobFrontmatter;\n let describeFn: typeof import(\"../jobs/cron.js\").describeCron;\n try {\n const scheduler = await import(\"../jobs/scheduler.js\");\n const cron = await import(\"../jobs/cron.js\");\n parseFn = scheduler.parseJobFrontmatter;\n describeFn = cron.describeCron;\n } catch {\n return; // Jobs module not available\n }\n\n for (const node of nodes) {\n if (node.type === \"folder\" && node.children) {\n await enrichTreeNodes(node.children);\n }\n if (node.type === \"file\" && node.resource) {\n try {\n const full = await resourceGet(node.resource.id);\n if (!full?.content) continue;\n\n if (\n node.resource.path.startsWith(\"jobs/\") &&\n node.resource.path.endsWith(\".md\")\n ) {\n const { meta } = parseFn(full.content);\n node.jobMeta = {\n schedule: meta.schedule,\n scheduleDescription: meta.schedule\n ? describeFn(meta.schedule)\n : undefined,\n enabled: meta.enabled,\n lastStatus: meta.lastStatus,\n lastRun: meta.lastRun,\n nextRun: meta.nextRun,\n };\n }\n\n if (\n node.resource.path.startsWith(\"skills/\") &&\n node.resource.path.endsWith(\".md\")\n ) {\n node.skillMeta =\n parseSkillMetadata(full.content, node.resource.path) ?? undefined;\n }\n\n if (\n node.resource.path.startsWith(\"agents/\") &&\n node.resource.path.endsWith(\".md\")\n ) {\n node.agentMeta =\n parseCustomAgentProfile(full.content, node.resource.path) ??\n undefined;\n }\n\n if (isRemoteAgentPath(node.resource.path)) {\n node.remoteAgentMeta =\n parseRemoteAgentManifest(full.content, node.resource.path) ??\n undefined;\n }\n } catch {\n // Skip individual file errors\n }\n }\n }\n}\n\n/** GET /_agent-native/resources/:id — get single resource with content.\n * If the request comes from an <img>/<video>/etc tag (Accept includes the\n * resource's mime type, or query param `?raw` is set), return the raw binary\n * with the correct Content-Type so the browser can render it inline. */\nexport async function handleGetResource(event: any) {\n const id = getRouterParam(event, \"id\") || event.context.params?.id;\n if (!id) {\n setResponseStatus(event, 400);\n return { error: \"Resource ID is required\" };\n }\n\n const email = await resolveEmail(event);\n const orgId = await resolveOrgId(event);\n const resource = await resourceGet(id, { userEmail: email, orgId });\n if (!resource) {\n setResponseStatus(event, 404);\n return { error: \"Resource not found\" };\n }\n\n if (!canReadOwner(resource.owner, email)) {\n setResponseStatus(event, 404);\n return { error: \"Resource not found\" };\n }\n\n // Serve raw binary when ?raw query param is set (used by <img> tags etc.)\n const query = getQuery(event);\n const wantsRaw = query.raw !== undefined;\n\n if (wantsRaw && resource.content) {\n const isText =\n resource.mimeType.startsWith(\"text/\") ||\n resource.mimeType === \"application/json\";\n const buf = isText\n ? Buffer.from(resource.content, \"utf-8\")\n : Buffer.from(resource.content, \"base64\");\n\n setResponseHeader(event, \"Content-Type\", resource.mimeType);\n setResponseHeader(event, \"Content-Length\", String(buf.length));\n return new Response(buf);\n }\n\n // For binary resources (images, audio, video), omit the content field from\n // the JSON response — it can be megabytes of base64. The client fetches\n // the actual bytes via ?raw when it needs to display them.\n const isBinary =\n resource.mimeType.startsWith(\"image/\") ||\n resource.mimeType.startsWith(\"audio/\") ||\n resource.mimeType.startsWith(\"video/\") ||\n resource.mimeType === \"application/octet-stream\";\n\n if (isBinary) {\n const { content: _content, ...meta } = resource;\n return { ...meta, content: \"\" };\n }\n\n return resource;\n}\n\n/** POST /_agent-native/resources — create a resource */\nexport async function handleCreateResource(event: any) {\n const body = await readBody(event);\n\n if (!body?.path || typeof body.path !== \"string\") {\n setResponseStatus(event, 400);\n return { error: \"path is required\" };\n }\n\n if (body.shared) {\n await assertCanEditShared(event);\n }\n\n const owner = await resolveOwner(event, body.shared);\n\n // If ifNotExists is set, skip if the resource already exists\n if (body.ifNotExists) {\n const existing = await resourceGetByPath(owner, body.path);\n if (existing) {\n return existing;\n }\n }\n\n const writeOptions =\n body.metadata !== undefined ? { metadata: body.metadata } : undefined;\n const resource = writeOptions\n ? await resourcePut(\n owner,\n body.path,\n body.content ?? \"\",\n body.mimeType,\n writeOptions,\n )\n : await resourcePut(owner, body.path, body.content ?? \"\", body.mimeType);\n\n setResponseStatus(event, 201);\n return resource;\n}\n\n/** PUT /_agent-native/resources/:id — update an existing resource */\nexport async function handleUpdateResource(event: any) {\n const id = getRouterParam(event, \"id\") || event.context.params?.id;\n if (!id) {\n setResponseStatus(event, 400);\n return { error: \"Resource ID is required\" };\n }\n\n const existing = await resourceGet(id);\n if (!existing) {\n setResponseStatus(event, 404);\n return { error: \"Resource not found\" };\n }\n\n // Ownership check: only the owner (or shared resource editors) can update\n const email = await resolveEmail(event);\n if (!canReadOwner(existing.owner, email)) {\n setResponseStatus(event, 404);\n return { error: \"Resource not found\" };\n }\n const isLocalWorkspaceResource =\n existing.owner === WORKSPACE_OWNER && isLocalWorkspaceResourceId(id);\n if (existing.owner === WORKSPACE_OWNER && !isLocalWorkspaceResource) {\n setResponseStatus(event, 403);\n return { error: \"Workspace resources are managed from Dispatch\" };\n }\n if (existing.owner === SHARED_OWNER) {\n await assertCanEditShared(event);\n }\n\n const body = await readBody(event);\n const nextPath = body.path ?? existing.path;\n\n if (\n isLocalWorkspaceResource &&\n nextPath !== existing.path &&\n !(await canWriteLocalWorkspaceResourcePath(nextPath))\n ) {\n setResponseStatus(event, 400);\n return {\n error:\n \"Local workspace resources can only be moved to AGENTS.md, agent-native.json, mcp.config.json, .mcp.json, or skills/.\",\n };\n }\n\n // If path changed, move it\n if (!isLocalWorkspaceResource && body.path && body.path !== existing.path) {\n await resourceMove(id, body.path);\n }\n\n // Update content/mimeType by re-putting\n const writeOptions =\n body.metadata !== undefined ? { metadata: body.metadata } : undefined;\n const resource = writeOptions\n ? await resourcePut(\n existing.owner,\n nextPath,\n body.content ?? existing.content,\n body.mimeType ?? existing.mimeType,\n writeOptions,\n )\n : await resourcePut(\n existing.owner,\n nextPath,\n body.content ?? existing.content,\n body.mimeType ?? existing.mimeType,\n );\n if (isLocalWorkspaceResource && nextPath !== existing.path) {\n await resourceDelete(id);\n }\n\n return resource;\n}\n\n/** DELETE /_agent-native/resources/:id — delete a resource */\nexport async function handleDeleteResource(event: any) {\n const id = getRouterParam(event, \"id\") || event.context.params?.id;\n if (!id) {\n setResponseStatus(event, 400);\n return { error: \"Resource ID is required\" };\n }\n\n const existing = await resourceGet(id);\n if (!existing) {\n setResponseStatus(event, 404);\n return { error: \"Resource not found\" };\n }\n\n // Ownership check: only the owner (or shared resource editors) can delete\n const email = await resolveEmail(event);\n if (!canReadOwner(existing.owner, email)) {\n setResponseStatus(event, 404);\n return { error: \"Resource not found\" };\n }\n if (\n existing.owner === WORKSPACE_OWNER &&\n !isLocalWorkspaceResourceId(existing.id)\n ) {\n setResponseStatus(event, 403);\n return { error: \"Workspace resources are managed from Dispatch\" };\n }\n if (existing.owner === SHARED_OWNER) {\n await assertCanEditShared(event);\n }\n\n await resourceDelete(id);\n return { ok: true };\n}\n\n/** POST /_agent-native/resources/upload — upload a file as a resource */\nexport async function handleUploadResource(event: any) {\n const parts = await readMultipartFormData(event);\n\n if (!parts || parts.length === 0) {\n setResponseStatus(event, 400);\n return { error: \"No file uploaded\" };\n }\n\n const filePart = parts.find((p) => p.name === \"file\");\n const pathPart = parts.find((p) => p.name === \"path\");\n const sharedPart = parts.find((p) => p.name === \"shared\");\n\n if (!filePart || !filePart.data) {\n setResponseStatus(event, 400);\n return { error: \"No file data found\" };\n }\n\n // Reject oversized uploads before touching any storage.\n if (filePart.data.length > DEFAULT_UPLOAD_MAX_FILE_BYTES) {\n setResponseStatus(event, 413);\n return {\n error: `File too large (max ${Math.round(DEFAULT_UPLOAD_MAX_FILE_BYTES / 1024 / 1024)} MB)`,\n };\n }\n\n const fileName = filePart.filename || \"upload\";\n const path = pathPart?.data?.toString() || `/${fileName}`;\n const shared = sharedPart?.data?.toString() === \"true\";\n const mimeType = filePart.type || \"application/octet-stream\";\n\n // Reject executable / script MIME types.\n if (filePart.type && !isAllowedUploadMimeType(filePart.type)) {\n setResponseStatus(event, 415);\n return { error: `Unsupported file type: ${filePart.type}` };\n }\n if (shared) {\n await assertCanEditShared(event);\n }\n const owner = await resolveOwner(event, shared);\n\n // Binary assets must live in file storage so resource rows do not become\n // base64 blobs in SQL. Text resources still live in SQL because they are\n // edited inline and benefit from the resource store's metadata/search.\n const isText =\n mimeType.startsWith(\"text/\") || mimeType === \"application/json\";\n\n if (!isText) {\n // Use the actual session user email for credential resolution — not `owner`,\n // which is \"__shared__\" for org-wide resources and would break the per-user\n // DB credential lookup (resolveBuilderCredential refuses env fallback for any\n // non-null non-local email, including the sentinel value).\n const credentialEmail =\n owner !== SHARED_OWNER\n ? owner\n : (await getSession(event).catch(() => null))?.email;\n const doUpload = () =>\n uploadFile({\n data: filePart.data,\n filename: fileName,\n mimeType,\n ownerEmail: owner,\n });\n const uploaded = credentialEmail\n ? await runWithRequestContext({ userEmail: credentialEmail }, doUpload)\n : await doUpload();\n if (uploaded) {\n const resource = await resourcePut(owner, path, uploaded.url, mimeType);\n setResponseStatus(event, 201);\n return { ...resource, url: uploaded.url, provider: uploaded.provider };\n }\n setResponseStatus(event, 503);\n return {\n error:\n \"File storage is not configured. Connect Builder.io or register an S3/R2/GCS file upload provider before uploading binary resources.\",\n storageSetupRequired: true,\n };\n }\n\n const content = Buffer.from(filePart.data).toString(\"utf-8\");\n\n const resource = await resourcePut(owner, path, content, mimeType);\n\n setResponseStatus(event, 201);\n return resource;\n}\n"]}
|
package/dist/server/poll.d.ts
CHANGED
|
@@ -54,6 +54,16 @@ export declare function invalidateCollabAccessCache(resourceType: string, resour
|
|
|
54
54
|
* public API — do not rely on it outside tests.
|
|
55
55
|
*/
|
|
56
56
|
export declare function __resetCollabAccessCacheForTests(): void;
|
|
57
|
+
type ChangeReadResult = {
|
|
58
|
+
version: number;
|
|
59
|
+
events: ChangeEvent[];
|
|
60
|
+
/**
|
|
61
|
+
* True when the returned version is an intentional cursor stop, not the
|
|
62
|
+
* source high-water mark. This happens when access is still pending or when a
|
|
63
|
+
* durable page hit the read limit and more rows may remain unread.
|
|
64
|
+
*/
|
|
65
|
+
cursorLimited?: boolean;
|
|
66
|
+
};
|
|
57
67
|
/**
|
|
58
68
|
* Decide whether a poll/SSE change event should be delivered to a user.
|
|
59
69
|
*
|
|
@@ -102,10 +112,7 @@ export declare function getChangesSince(since: number): {
|
|
|
102
112
|
* viewer+ sharees via the access-aware cache in `canSeeChangeForUser`.
|
|
103
113
|
* - All other owned events are filtered out.
|
|
104
114
|
*/
|
|
105
|
-
export declare function getChangesSinceForUser(since: number, userEmail: string, orgId: string | undefined):
|
|
106
|
-
version: number;
|
|
107
|
-
events: ChangeEvent[];
|
|
108
|
-
};
|
|
115
|
+
export declare function getChangesSinceForUser(since: number, userEmail: string, orgId: string | undefined): ChangeReadResult;
|
|
109
116
|
/**
|
|
110
117
|
* Create an H3 handler for the poll endpoint.
|
|
111
118
|
*
|
|
@@ -123,4 +130,5 @@ export declare function createPollHandler(): import("h3").EventHandlerWithFetch<
|
|
|
123
130
|
} | {
|
|
124
131
|
error: string;
|
|
125
132
|
}>>;
|
|
133
|
+
export {};
|
|
126
134
|
//# sourceMappingURL=poll.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"poll.d.ts","sourceRoot":"","sources":["../../src/server/poll.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"poll.d.ts","sourceRoot":"","sources":["../../src/server/poll.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAoB3C,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,6CAA6C;IAC7C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;;OAMG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CACtB;AAWD,eAAO,MAAM,iBAAiB,gBAAgB,CAAC;AAwQ/C,8CAA8C;AAC9C,wBAAgB,UAAU,IAAI,MAAM,CAEnC;AAED,wBAAgB,cAAc,IAAI,YAAY,CAE7C;AAyCD,wBAAgB,2BAA2B,CACzC,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,GACjB,IAAI,CAaN;AA0DD;;;;GAIG;AACH,wBAAgB,gCAAgC,IAAI,IAAI,CAIvD;AAGD,KAAK,gBAAgB,GAAG;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB;;;;OAIG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,IAAI,CAAC,WAAW,EAAE,OAAO,GAAG,OAAO,GAAG,cAAc,GAAG,YAAY,CAAC,EAC3E,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,GAAG,SAAS,GACxB,OAAO,CAET;AAuCD,0DAA0D;AAC1D,wBAAgB,YAAY,CAAC,KAAK,EAAE;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CACtB,GAAG,IAAI,CAYP;AA+GD,6CAA6C;AAC7C,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG;IAC9C,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,WAAW,EAAE,CAAC;CACvB,CAMA;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,GAAG,SAAS,GACxB,gBAAgB,CAmBlB;AAobD;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB;aAvWX,MAAM;YAAU,WAAW,EAAE;;;IAgYlD"}
|
package/dist/server/poll.js
CHANGED
|
@@ -16,18 +16,25 @@ import { EventEmitter } from "node:events";
|
|
|
16
16
|
import { defineEventHandler, getQuery, setResponseStatus } from "h3";
|
|
17
17
|
import { ACTION_CHANGE_MARKER_KEY, parseActionChangeMarker, } from "../action-change-marker.js";
|
|
18
18
|
import { getAppStateEmitter } from "../application-state/emitter.js";
|
|
19
|
-
import { getDbExec } from "../db/client.js";
|
|
19
|
+
import { getDbExec, isPostgres } from "../db/client.js";
|
|
20
|
+
import { ensureIndexExists, ensureTableExists } from "../db/ddl-guard.js";
|
|
20
21
|
import { EXTENSION_CHANGE_MARKER_KEY, parseExtensionChangeMarker, } from "../extensions/change-marker.js";
|
|
21
22
|
import { getSettingsEmitter } from "../settings/store.js";
|
|
22
23
|
import { getSession } from "./auth.js";
|
|
23
24
|
// In-memory ring buffer of recent changes. Kept small since clients
|
|
24
25
|
// poll frequently (every 2-3s) and only need events since their last poll.
|
|
25
26
|
const MAX_BUFFER = 200;
|
|
27
|
+
const DURABLE_READ_LIMIT = 1000;
|
|
28
|
+
const DURABLE_RETENTION_MS = 24 * 60 * 60 * 1000;
|
|
29
|
+
const LEGACY_DB_CHECK_INTERVAL_MS = 1000;
|
|
30
|
+
const DURABLE_LEGACY_DB_CHECK_INTERVAL_MS = 30_000;
|
|
26
31
|
let _version = 0;
|
|
27
32
|
const _buffer = [];
|
|
28
33
|
export const POLL_CHANGE_EVENT = "poll-change";
|
|
29
34
|
const _pollEmitter = new EventEmitter();
|
|
30
35
|
_pollEmitter.setMaxListeners(0);
|
|
36
|
+
let _syncEventsInitPromise;
|
|
37
|
+
let _lastDurablePrune = 0;
|
|
31
38
|
/**
|
|
32
39
|
* Whether we've seeded _version from the DB. In serverless (Netlify,
|
|
33
40
|
* Vercel, etc.) each invocation starts fresh — without seeding, _version
|
|
@@ -98,6 +105,115 @@ function sqlWatermarkValue(value) {
|
|
|
98
105
|
return value;
|
|
99
106
|
return undefined;
|
|
100
107
|
}
|
|
108
|
+
function syncEventsDisabled() {
|
|
109
|
+
return (process.env.AGENT_NATIVE_SYNC_EVENTS_DISABLE === "1" ||
|
|
110
|
+
(process.env.VITEST === "true" &&
|
|
111
|
+
process.env.AGENT_NATIVE_SYNC_EVENTS_ENABLE_IN_TESTS !== "1"));
|
|
112
|
+
}
|
|
113
|
+
async function ensureSyncEventsTable() {
|
|
114
|
+
if (syncEventsDisabled())
|
|
115
|
+
return false;
|
|
116
|
+
if (!_syncEventsInitPromise) {
|
|
117
|
+
_syncEventsInitPromise = (async () => {
|
|
118
|
+
const client = getDbExec();
|
|
119
|
+
const createSql = `
|
|
120
|
+
CREATE TABLE IF NOT EXISTS sync_events (
|
|
121
|
+
id TEXT PRIMARY KEY,
|
|
122
|
+
version BIGINT NOT NULL,
|
|
123
|
+
event_json TEXT NOT NULL,
|
|
124
|
+
source TEXT NOT NULL,
|
|
125
|
+
type TEXT NOT NULL,
|
|
126
|
+
event_key TEXT,
|
|
127
|
+
owner TEXT,
|
|
128
|
+
org_id TEXT,
|
|
129
|
+
resource_type TEXT,
|
|
130
|
+
resource_id TEXT,
|
|
131
|
+
created_at BIGINT NOT NULL
|
|
132
|
+
)
|
|
133
|
+
`;
|
|
134
|
+
if (isPostgres()) {
|
|
135
|
+
await ensureTableExists("sync_events", createSql);
|
|
136
|
+
await ensureIndexExists("sync_events_version_idx", "CREATE INDEX IF NOT EXISTS sync_events_version_idx ON sync_events (version)");
|
|
137
|
+
await ensureIndexExists("sync_events_owner_version_idx", "CREATE INDEX IF NOT EXISTS sync_events_owner_version_idx ON sync_events (owner, version)");
|
|
138
|
+
await ensureIndexExists("sync_events_org_version_idx", "CREATE INDEX IF NOT EXISTS sync_events_org_version_idx ON sync_events (org_id, version)");
|
|
139
|
+
return true;
|
|
140
|
+
}
|
|
141
|
+
await client.execute(createSql);
|
|
142
|
+
for (const ddl of [
|
|
143
|
+
"CREATE INDEX IF NOT EXISTS sync_events_version_idx ON sync_events (version)",
|
|
144
|
+
"CREATE INDEX IF NOT EXISTS sync_events_owner_version_idx ON sync_events (owner, version)",
|
|
145
|
+
"CREATE INDEX IF NOT EXISTS sync_events_org_version_idx ON sync_events (org_id, version)",
|
|
146
|
+
]) {
|
|
147
|
+
try {
|
|
148
|
+
await client.execute(ddl);
|
|
149
|
+
}
|
|
150
|
+
catch {
|
|
151
|
+
// Index already exists or the dialect rejected a duplicate.
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
return true;
|
|
155
|
+
})().catch(() => {
|
|
156
|
+
_syncEventsInitPromise = undefined;
|
|
157
|
+
return false;
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
return _syncEventsInitPromise;
|
|
161
|
+
}
|
|
162
|
+
function durableEventId(version) {
|
|
163
|
+
return `${version}-${Math.random().toString(36).slice(2, 10)}`;
|
|
164
|
+
}
|
|
165
|
+
async function pruneDurableEvents(client) {
|
|
166
|
+
const now = Date.now();
|
|
167
|
+
if (now - _lastDurablePrune < 5 * 60 * 1000)
|
|
168
|
+
return;
|
|
169
|
+
_lastDurablePrune = now;
|
|
170
|
+
await client
|
|
171
|
+
.execute({
|
|
172
|
+
sql: "DELETE FROM sync_events WHERE created_at < ?",
|
|
173
|
+
args: [now - DURABLE_RETENTION_MS],
|
|
174
|
+
})
|
|
175
|
+
.catch(() => { });
|
|
176
|
+
}
|
|
177
|
+
async function persistSyncEvent(event) {
|
|
178
|
+
if (!(await ensureSyncEventsTable()))
|
|
179
|
+
return;
|
|
180
|
+
const client = getDbExec();
|
|
181
|
+
await client
|
|
182
|
+
.execute({
|
|
183
|
+
sql: isPostgres()
|
|
184
|
+
? `INSERT INTO sync_events (id, version, event_json, source, type, event_key, owner, org_id, resource_type, resource_id, created_at)
|
|
185
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
186
|
+
ON CONFLICT (id) DO NOTHING`
|
|
187
|
+
: `INSERT OR IGNORE INTO sync_events (id, version, event_json, source, type, event_key, owner, org_id, resource_type, resource_id, created_at)
|
|
188
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
189
|
+
args: [
|
|
190
|
+
durableEventId(event.version),
|
|
191
|
+
event.version,
|
|
192
|
+
JSON.stringify(event),
|
|
193
|
+
event.source,
|
|
194
|
+
event.type,
|
|
195
|
+
event.key ?? null,
|
|
196
|
+
event.owner ?? null,
|
|
197
|
+
event.orgId ?? null,
|
|
198
|
+
event.resourceType ?? null,
|
|
199
|
+
event.resourceId ?? null,
|
|
200
|
+
Date.now(),
|
|
201
|
+
],
|
|
202
|
+
})
|
|
203
|
+
.catch(() => { });
|
|
204
|
+
await pruneDurableEvents(client);
|
|
205
|
+
}
|
|
206
|
+
async function readMaxSyncEventVersion() {
|
|
207
|
+
if (!(await ensureSyncEventsTable()))
|
|
208
|
+
return 0;
|
|
209
|
+
try {
|
|
210
|
+
const result = await getDbExec().execute("SELECT MAX(version) as max_version FROM sync_events");
|
|
211
|
+
return timestampValue(result.rows[0]?.max_version);
|
|
212
|
+
}
|
|
213
|
+
catch {
|
|
214
|
+
return 0;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
101
217
|
async function readMaxUpdatedAtRaw(db, table) {
|
|
102
218
|
try {
|
|
103
219
|
const result = await db.execute(`SELECT MAX(updated_at) as max_ts FROM ${table}`);
|
|
@@ -313,6 +429,7 @@ export function recordChange(event) {
|
|
|
313
429
|
_buffer.splice(0, _buffer.length - MAX_BUFFER);
|
|
314
430
|
}
|
|
315
431
|
_pollEmitter.emit(POLL_CHANGE_EVENT, entry);
|
|
432
|
+
void persistSyncEvent(entry);
|
|
316
433
|
}
|
|
317
434
|
function extensionTargetKey(target) {
|
|
318
435
|
if (target.owner)
|
|
@@ -437,11 +554,114 @@ export function getChangesSinceForUser(since, userEmail, orgId) {
|
|
|
437
554
|
}
|
|
438
555
|
if (visibility === "pending") {
|
|
439
556
|
version = Math.max(since, event.version - 1);
|
|
440
|
-
|
|
557
|
+
return { version, events, cursorLimited: true };
|
|
441
558
|
}
|
|
442
559
|
}
|
|
443
560
|
return { version, events };
|
|
444
561
|
}
|
|
562
|
+
async function getDurableChangesSinceForUser(since, userEmail, orgId) {
|
|
563
|
+
if (since <= 0 || !(await ensureSyncEventsTable())) {
|
|
564
|
+
return { version: _version, events: [] };
|
|
565
|
+
}
|
|
566
|
+
try {
|
|
567
|
+
const result = await getDbExec().execute({
|
|
568
|
+
sql: `SELECT version, event_json FROM sync_events WHERE version > ? ORDER BY version ASC LIMIT ?`,
|
|
569
|
+
args: [since, DURABLE_READ_LIMIT + 1],
|
|
570
|
+
});
|
|
571
|
+
const events = [];
|
|
572
|
+
let version = Math.max(_version, since);
|
|
573
|
+
let lastDurableVersion = since;
|
|
574
|
+
const rows = result.rows.slice(0, DURABLE_READ_LIMIT);
|
|
575
|
+
const overflowVersion = timestampValue(result.rows[DURABLE_READ_LIMIT]?.version);
|
|
576
|
+
for (const row of rows) {
|
|
577
|
+
const rawVersion = timestampValue(row.version);
|
|
578
|
+
if (rawVersion > lastDurableVersion)
|
|
579
|
+
lastDurableVersion = rawVersion;
|
|
580
|
+
if (rawVersion > version)
|
|
581
|
+
version = rawVersion;
|
|
582
|
+
let event = null;
|
|
583
|
+
try {
|
|
584
|
+
const parsed = JSON.parse(String(row.event_json));
|
|
585
|
+
if (parsed &&
|
|
586
|
+
typeof parsed === "object" &&
|
|
587
|
+
typeof parsed.source === "string" &&
|
|
588
|
+
typeof parsed.type === "string") {
|
|
589
|
+
event = {
|
|
590
|
+
...parsed,
|
|
591
|
+
version: rawVersion || parsed.version,
|
|
592
|
+
};
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
catch {
|
|
596
|
+
event = null;
|
|
597
|
+
}
|
|
598
|
+
if (!event)
|
|
599
|
+
continue;
|
|
600
|
+
const visibility = getChangeVisibilityForUser(event, userEmail, orgId);
|
|
601
|
+
if (visibility === "visible") {
|
|
602
|
+
events.push(event);
|
|
603
|
+
continue;
|
|
604
|
+
}
|
|
605
|
+
if (visibility === "pending") {
|
|
606
|
+
return {
|
|
607
|
+
version: Math.max(since, event.version - 1),
|
|
608
|
+
events,
|
|
609
|
+
cursorLimited: true,
|
|
610
|
+
};
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
if (rows.length >= DURABLE_READ_LIMIT) {
|
|
614
|
+
if (overflowVersion === lastDurableVersion) {
|
|
615
|
+
const boundaryVersion = lastDurableVersion;
|
|
616
|
+
return {
|
|
617
|
+
version: Math.max(since, boundaryVersion - 1),
|
|
618
|
+
events: events.filter((event) => event.version < boundaryVersion),
|
|
619
|
+
cursorLimited: true,
|
|
620
|
+
};
|
|
621
|
+
}
|
|
622
|
+
return {
|
|
623
|
+
version: Math.max(since, lastDurableVersion),
|
|
624
|
+
events,
|
|
625
|
+
cursorLimited: true,
|
|
626
|
+
};
|
|
627
|
+
}
|
|
628
|
+
return { version, events };
|
|
629
|
+
}
|
|
630
|
+
catch {
|
|
631
|
+
return { version: _version, events: [] };
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
async function getCombinedChangesSinceForUser(since, userEmail, orgId, useDurableEvents) {
|
|
635
|
+
const memory = getChangesSinceForUser(since, userEmail, orgId);
|
|
636
|
+
if (!useDurableEvents)
|
|
637
|
+
return memory;
|
|
638
|
+
const durable = await getDurableChangesSinceForUser(since, userEmail, orgId);
|
|
639
|
+
const byIdentity = new Map();
|
|
640
|
+
for (const event of [...durable.events, ...memory.events]) {
|
|
641
|
+
byIdentity.set(JSON.stringify([
|
|
642
|
+
event.version,
|
|
643
|
+
event.source,
|
|
644
|
+
event.type,
|
|
645
|
+
event.key,
|
|
646
|
+
event.owner,
|
|
647
|
+
event.orgId,
|
|
648
|
+
event.resourceType,
|
|
649
|
+
event.resourceId,
|
|
650
|
+
]), event);
|
|
651
|
+
}
|
|
652
|
+
const events = Array.from(byIdentity.values()).sort((a, b) => a.version - b.version);
|
|
653
|
+
const limitedVersions = [memory, durable]
|
|
654
|
+
.filter((result) => result.cursorLimited)
|
|
655
|
+
.map((result) => result.version);
|
|
656
|
+
return {
|
|
657
|
+
version: limitedVersions.length > 0
|
|
658
|
+
? Math.min(...limitedVersions)
|
|
659
|
+
: Math.max(memory.version, durable.version, since),
|
|
660
|
+
events: limitedVersions.length > 0
|
|
661
|
+
? events.filter((event) => event.version <= Math.min(...limitedVersions))
|
|
662
|
+
: events,
|
|
663
|
+
};
|
|
664
|
+
}
|
|
445
665
|
/**
|
|
446
666
|
* Seed _version from DB timestamps on the first call so serverless
|
|
447
667
|
* cold starts don't return version 0 and confuse polling clients.
|
|
@@ -452,7 +672,8 @@ async function seedVersionFromDb() {
|
|
|
452
672
|
_versionSeeded = true;
|
|
453
673
|
try {
|
|
454
674
|
const db = getDbExec();
|
|
455
|
-
const [appTs, settingsTs, extensionsMaxUpdatedAt, extensionMarkerTs, actionMarkerTs, refreshResult,] = await Promise.all([
|
|
675
|
+
const [syncEventsTs, appTs, settingsTs, extensionsMaxUpdatedAt, extensionMarkerTs, actionMarkerTs, refreshResult,] = await Promise.all([
|
|
676
|
+
readMaxSyncEventVersion(),
|
|
456
677
|
readMaxUpdatedAt(db, "application_state"),
|
|
457
678
|
readMaxUpdatedAt(db, "settings"),
|
|
458
679
|
readMaxUpdatedAtRaw(db, "tools"),
|
|
@@ -471,7 +692,7 @@ async function seedVersionFromDb() {
|
|
|
471
692
|
refreshTs = Math.max(refreshTs, timestampValue(row.updated_at));
|
|
472
693
|
}
|
|
473
694
|
// Seed version — never decrease an already-set value
|
|
474
|
-
_version = Math.max(_version, appTs, settingsTs, extensionsTs, extensionMarkerTs, actionMarkerTs);
|
|
695
|
+
_version = Math.max(_version, syncEventsTs, appTs, settingsTs, extensionsTs, extensionMarkerTs, actionMarkerTs);
|
|
475
696
|
// Set baselines so checkExternalDbChanges detects future writes
|
|
476
697
|
_lastAppStateTs = appTs;
|
|
477
698
|
_lastSettingsTs = settingsTs;
|
|
@@ -502,9 +723,12 @@ async function seedVersionFromDb() {
|
|
|
502
723
|
* Check for cross-process DB writes by comparing updated_at timestamps.
|
|
503
724
|
* Runs at most once per second to avoid excessive queries.
|
|
504
725
|
*/
|
|
505
|
-
async function checkExternalDbChanges() {
|
|
726
|
+
async function checkExternalDbChanges(options) {
|
|
506
727
|
const now = Date.now();
|
|
507
|
-
|
|
728
|
+
const interval = options.durableEvents
|
|
729
|
+
? DURABLE_LEGACY_DB_CHECK_INTERVAL_MS
|
|
730
|
+
: LEGACY_DB_CHECK_INTERVAL_MS;
|
|
731
|
+
if (now - _lastDbCheck < interval)
|
|
508
732
|
return;
|
|
509
733
|
// Coalesce: if a check is already running, await it instead of starting a
|
|
510
734
|
// second overlapping run that would double-advance the shared watermarks
|
|
@@ -707,11 +931,14 @@ export function createPollHandler() {
|
|
|
707
931
|
}
|
|
708
932
|
// On cold start, seed _version from DB so we don't return version: 0
|
|
709
933
|
await seedVersionFromDb();
|
|
710
|
-
|
|
711
|
-
|
|
934
|
+
const durableEvents = await ensureSyncEventsTable();
|
|
935
|
+
// Durable sync_events rows are the cheap cross-process path. Keep the
|
|
936
|
+
// legacy watermark scan as a slower safety net for direct SQL writes and
|
|
937
|
+
// older processes that have not started writing durable events yet.
|
|
938
|
+
await checkExternalDbChanges({ durableEvents });
|
|
712
939
|
const query = getQuery(event);
|
|
713
940
|
const since = parseInt(String(query.since ?? "0"), 10) || 0;
|
|
714
|
-
return
|
|
941
|
+
return getCombinedChangesSinceForUser(since, session.email, session.orgId, durableEvents);
|
|
715
942
|
});
|
|
716
943
|
}
|
|
717
944
|
//# sourceMappingURL=poll.js.map
|