@agent-native/core 0.169.0 → 0.170.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 +4 -1
- package/bin/agent-native.js +23 -5
- package/corpus/README.md +1 -1
- package/corpus/templates/analytics/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/analytics/actions/bigquery-table-info.ts +3 -2
- package/corpus/templates/analytics/actions/query-agent-native-analytics.ts +1 -1
- package/corpus/templates/analytics/actions/search-bigquery-schema.ts +130 -4
- package/corpus/templates/analytics/agent-native.config.ts +1 -0
- package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +36 -23
- package/corpus/templates/analytics/app/i18n-data.ts +28 -0
- package/corpus/templates/analytics/app/lib/dashboard-visibility.ts +41 -0
- package/corpus/templates/analytics/app/pages/Agents.tsx +25 -1
- package/corpus/templates/analytics/app/pages/DashboardOverview.tsx +34 -9
- package/corpus/templates/analytics/app/routes/$.tsx +10 -0
- package/corpus/templates/analytics/app/routes.ts +3 -1
- package/corpus/templates/analytics/changelog/2026-08-21-dashboard-filters-keep-other-users-dashboards-out-of-mine.md +6 -0
- package/corpus/templates/analytics/changelog/2026-08-22-fixed-the-agent-native-templates-first-party-dashboard-panel.md +6 -0
- package/corpus/templates/analytics/changelog/2026-08-22-org-admin-panels-no-longer-report-a-database-error-as-a-per.md +9 -0
- package/corpus/templates/analytics/changelog/2026-08-22-slack-requests-report-invalid-inputs.md +6 -0
- package/corpus/templates/analytics/changelog/2026-08-22-unknown-analytics-links-now-return-a-real-not-found-status.md +6 -0
- package/corpus/templates/analytics/docs/schemas/first-party-analytics.md +2 -1
- package/corpus/templates/analytics/docs/schemas/tracked-events.md +2 -0
- package/corpus/templates/analytics/scripts/emit-netlify-dashboard-report-cron.ts +29 -7
- package/corpus/templates/analytics/server/handlers/slack.ts +59 -5
- package/corpus/templates/analytics/server/lib/db-admin-connections.ts +11 -6
- package/corpus/templates/analytics/server/lib/first-party-analytics.ts +132 -2
- package/corpus/templates/analytics/server/lib/real-data-actions.ts +14 -3
- package/corpus/templates/analytics/server/lib/slack.ts +4 -2
- package/corpus/templates/analytics/server/plugins/agent-chat.ts +33 -3
- package/corpus/templates/analytics/vitest.config.ts +6 -1
- package/corpus/templates/assets/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/assets/app/routes/library.tsx +5 -3
- package/corpus/templates/assets/app/routes.ts +3 -1
- package/corpus/templates/assets/changelog/2026-08-22-library-page-loads-again-instead-of-crashing-on-open.md +6 -0
- package/corpus/templates/assets/vitest.config.ts +6 -1
- package/corpus/templates/brain/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/brain/app/components/ui/pointer-lock.ts +1 -0
- package/corpus/templates/brain/app/routes/sources.tsx +8 -3
- package/corpus/templates/brain/changelog/2026-08-22-tuning-or-adding-a-source-no-longer-leaves-the-sources-page.md +6 -0
- package/corpus/templates/brain/server/lib/brain.ts +27 -2
- package/corpus/templates/brain/vitest.config.ts +1 -0
- package/corpus/templates/calendar/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/calendar/actions/list-booking-links.ts +83 -4
- package/corpus/templates/calendar/actions/update-booking-link.ts +4 -3
- package/corpus/templates/calendar/app/components/calendar/EventDetailPanel.tsx +11 -3
- package/corpus/templates/calendar/app/components/calendar/EventDetailPopover.tsx +1 -1
- package/corpus/templates/calendar/app/components/calendar/GoogleConnectBanner.tsx +103 -44
- package/corpus/templates/calendar/app/components/calendar/OutOfOfficeEvent.tsx +28 -24
- package/corpus/templates/calendar/app/components/layout/AppLayout.tsx +9 -2
- package/corpus/templates/calendar/app/components/layout/Sidebar.tsx +47 -58
- package/corpus/templates/calendar/app/hooks/use-booking-links.ts +5 -1
- package/corpus/templates/calendar/app/lib/event-layout.ts +52 -26
- package/corpus/templates/calendar/app/pages/BookingLinksPage.tsx +126 -98
- package/corpus/templates/calendar/app/pages/CalendarView.tsx +1 -0
- package/corpus/templates/calendar/app/pages/Settings.tsx +88 -81
- package/corpus/templates/calendar/app/routes.ts +3 -1
- package/corpus/templates/calendar/changelog/2026-08-22-booking-link-visibility-respects-shared-access.md +6 -0
- package/corpus/templates/calendar/changelog/2026-08-22-clicking-an-out-of-office-event-s-marker-no-longer-creates-a.md +6 -0
- package/corpus/templates/calendar/changelog/2026-08-22-event-detail-views-now-show-your-calendar-timezone.md +6 -0
- package/corpus/templates/calendar/changelog/2026-08-22-google-calendar-can-now-connect-with-the-shared-google-oauth.md +6 -0
- package/corpus/templates/calendar/changelog/2026-08-22-overlapping-events-now-show-each-others-boundaries.md +6 -0
- package/corpus/templates/calendar/changelog/2026-08-22-public-booking-pages-now-offer-time-slots-from-the-host-s-we.md +6 -0
- package/corpus/templates/calendar/server/handlers/bookings.ts +5 -7
- package/corpus/templates/calendar/server/handlers/google-auth.ts +10 -2
- package/corpus/templates/calendar/server/lib/google-calendar.ts +139 -14
- package/corpus/templates/calendar/server/onboarding.ts +85 -0
- package/corpus/templates/calendar/server/plugins/agent-chat.ts +2 -0
- package/corpus/templates/calendar/shared/api.ts +9 -1
- package/corpus/templates/chat/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/chat/app/routes.ts +3 -1
- package/corpus/templates/chat/vitest.config.ts +8 -0
- package/corpus/templates/clips/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/clips/actions/get-meeting.ts +9 -4
- package/corpus/templates/clips/actions/list-recordings.ts +16 -3
- package/corpus/templates/clips/actions/search-meetings.ts +1 -0
- package/corpus/templates/clips/actions/stop-meeting-recording.ts +87 -6
- package/corpus/templates/clips/actions/view-screen.ts +8 -1
- package/corpus/templates/clips/app/components/library/search-bar.tsx +1 -1
- package/corpus/templates/clips/app/components/meetings/meeting-history-row.tsx +32 -1
- package/corpus/templates/clips/app/components/player/delete-recording-menu.tsx +1 -1
- package/corpus/templates/clips/app/components/recorder/recorder-engine.ts +29 -1
- package/corpus/templates/clips/app/i18n/en-US.ts +5 -0
- package/corpus/templates/clips/app/routes/_app.meetings.$meetingId.tsx +33 -4
- package/corpus/templates/clips/app/routes/_app.meetings._index.tsx +1 -0
- package/corpus/templates/clips/app/routes/access-request.approve.tsx +16 -9
- package/corpus/templates/clips/app/routes/embed.$shareId.tsx +17 -7
- package/corpus/templates/clips/app/routes/share.$shareId.tsx +17 -7
- package/corpus/templates/clips/changelog/2026-08-21-camera-bubble-black-circle.md +6 -0
- package/corpus/templates/clips/changelog/2026-08-22-screen-recordings-respect-the-microphone-toggle.md +6 -0
- package/corpus/templates/clips/changelog/2026-08-22-the-recordings-library-no-longer-fails-right-after-server-start.md +6 -0
- package/corpus/templates/clips/changelog/2026-08-23-the-agent-can-see-your-library-right-after-server-start.md +6 -0
- package/corpus/templates/clips/chrome-extension/src/background.ts +1 -2
- package/corpus/templates/clips/chrome-extension/src/native-transcription.ts +39 -7
- package/corpus/templates/clips/chrome-extension/src/offscreen.ts +21 -25
- package/corpus/templates/clips/desktop/src/app.tsx +53 -24
- package/corpus/templates/clips/desktop/src/lib/bubble-playback.ts +68 -0
- package/corpus/templates/clips/desktop/src/lib/recorder.ts +3 -0
- package/corpus/templates/clips/desktop/src/lib/transcription-capture.ts +72 -14
- package/corpus/templates/clips/desktop/src/lib/updater.ts +8 -3
- package/corpus/templates/clips/desktop/src/overlays/bubble.tsx +162 -20
- package/corpus/templates/clips/desktop/src-tauri/src/clips/mod.rs +43 -6
- package/corpus/templates/clips/desktop/src-tauri/src/native_screen/custom_capture.rs +150 -13
- package/corpus/templates/clips/desktop/src-tauri/src/tray.rs +12 -0
- package/corpus/templates/clips/server/lib/calendar-event-meetings.ts +28 -3
- package/corpus/templates/clips/server/lib/emails.ts +17 -33
- package/corpus/templates/content/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/content/app/components/editor/VisualEditor.tsx +140 -15
- package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +12 -14
- package/corpus/templates/content/app/components/ui/pointer-lock.ts +1 -0
- package/corpus/templates/content/app/hooks/use-content-database.ts +18 -2
- package/corpus/templates/content/app/hooks/use-local-storage.ts +38 -22
- package/corpus/templates/content/app/i18n-data.ts +25 -0
- package/corpus/templates/content/app/routes.ts +3 -1
- package/corpus/templates/content/changelog/2026-08-22-code-blocks-inserted-from-the-slash-menu-no-longer-get-stuck.md +6 -0
- package/corpus/templates/content/changelog/2026-08-22-the-sidebar-page-tree-no-longer-flashes-empty-after-creating-a-page.md +6 -0
- package/corpus/templates/content/docs/solutions/2026-08-21-content-mermaid-rendering-shape.md +233 -0
- package/corpus/templates/content/server/plugins/agent-chat.ts +9 -2
- package/corpus/templates/content/vitest.config.ts +7 -1
- package/corpus/templates/crm/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/design/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/design/.generated/bridge/editor-chrome.generated.ts +1386 -92
- package/corpus/templates/design/actions/generate-design.ts +98 -47
- package/corpus/templates/design/actions/get-design-system.ts +6 -1
- package/corpus/templates/design/actions/refresh-design-system-with-builder.ts +146 -0
- package/corpus/templates/design/app/components/design/DesignCanvas.tsx +70 -26
- package/corpus/templates/design/app/components/design/EditPanel.tsx +15 -47
- package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +284 -136
- package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +2060 -144
- package/corpus/templates/design/app/components/design/editor/DesignBottomToolbar.tsx +6 -2
- package/corpus/templates/design/app/components/design/editor/DesignWorkspaceRail.tsx +4 -4
- package/corpus/templates/design/app/components/design/keyboard-shortcuts.ts +10 -8
- package/corpus/templates/design/app/components/design/multi-screen/alt-hover-measurement.ts +19 -2
- package/corpus/templates/design/app/components/design/multi-screen/types.ts +9 -2
- package/corpus/templates/design/app/components/layout/Header.tsx +15 -0
- package/corpus/templates/design/app/components/layout/Layout.tsx +7 -2
- package/corpus/templates/design/app/hooks/useDesignHotkeys.ts +13 -8
- package/corpus/templates/design/app/i18n-data.ts +11 -10
- package/corpus/templates/design/app/i18n-keyboard-shortcuts.ts +12 -0
- package/corpus/templates/design/app/lib/design-system-data.ts +68 -0
- package/corpus/templates/design/app/pages/DesignEditor.tsx +99 -57
- package/corpus/templates/design/app/pages/DesignSystemSetup.tsx +39 -8
- package/corpus/templates/design/app/pages/DesignSystems.tsx +137 -43
- package/corpus/templates/design/app/pages/Index.tsx +3 -1
- package/corpus/templates/design/app/pages/Templates.tsx +0 -10
- package/corpus/templates/design/app/pages/design-editor/code-layer-state.ts +10 -0
- package/corpus/templates/design/app/pages/design-editor/collab-sync.ts +50 -0
- package/corpus/templates/design/app/pages/design-editor/commands/apply-design-editor-command.ts +1 -1
- package/corpus/templates/design/app/pages/design-editor/commands/apply-file-content-update.ts +10 -8
- package/corpus/templates/design/app/pages/design-editor/commands/apply-local-content-update.ts +6 -6
- package/corpus/templates/design/app/pages/design-editor/commands/apply-pending-visual-styles-with-agent.ts +1 -1
- package/corpus/templates/design/app/pages/design-editor/commands/commit-visual-styles.ts +18 -7
- package/corpus/templates/design/app/pages/design-editor/commands/escape-hotkey.ts +4 -90
- package/corpus/templates/design/app/pages/design-editor/commands/layer-marquee-selection-change.ts +2 -1
- package/corpus/templates/design/app/pages/design-editor/commands/layer-selection-change.ts +4 -3
- package/corpus/templates/design/app/pages/design-editor/commands/screen-element-select.ts +12 -2
- package/corpus/templates/design/app/pages/design-editor/commands/screen-visual-style-change.ts +9 -2
- package/corpus/templates/design/app/pages/design-editor/commands/send-runtime-layer-move-semantic-handoff.ts +1 -1
- package/corpus/templates/design/app/pages/design-editor/commands/send-runtime-layer-semantic-handoff.ts +1 -1
- package/corpus/templates/design/app/pages/design-editor/commands/send-runtime-layer-state-semantic-handoff.ts +1 -1
- package/corpus/templates/design/app/pages/design-editor/commands/start-sidebar-resize.ts +1 -1
- package/corpus/templates/design/app/pages/design-editor/editor-state.ts +11 -1
- package/corpus/templates/design/app/pages/design-editor/effects/adopt-db-file-content.ts +11 -19
- package/corpus/templates/design/app/pages/design-editor/effects/observe-collab-text.ts +6 -6
- package/corpus/templates/design/app/pages/design-editor/effects/publish-agent-selection-context.ts +1 -1
- package/corpus/templates/design/app/pages/design-editor/effects/seed-collab-content.ts +12 -15
- package/corpus/templates/design/app/pages/design-editor/preview-navigation.ts +25 -0
- package/corpus/templates/design/app/pages/design-editor/selection-state.ts +5 -59
- package/corpus/templates/design/app/pages/design-editor/tool-state.ts +8 -0
- package/corpus/templates/design/app/pages/design-editor/types.ts +3 -3
- package/corpus/templates/design/app/routes.ts +3 -1
- package/corpus/templates/design/changelog/2026-08-20-canvas-edits-patch-the-frame-instead-of-rebuilding-it.md +6 -0
- package/corpus/templates/design/changelog/2026-08-21-builder-design-system-imports-reconcile-after-indexing.md +6 -0
- package/corpus/templates/design/changelog/2026-08-21-draw-mode-needs-shift-y.md +6 -0
- package/corpus/templates/design/changelog/2026-08-21-eyedropper-shortcut.md +6 -0
- package/corpus/templates/design/changelog/2026-08-21-figma-style-alignment-guides-and-snapping.md +6 -0
- package/corpus/templates/design/changelog/2026-08-21-group-transforms-keep-the-selection.md +6 -0
- package/corpus/templates/design/changelog/2026-08-21-inspector-fields-keep-focus-on-enter.md +6 -0
- package/corpus/templates/design/changelog/2026-08-21-pen-alt-keeps-the-incoming-handle.md +6 -0
- package/corpus/templates/design/changelog/2026-08-21-pen-on-the-board-creates-one-vector.md +6 -0
- package/corpus/templates/design/changelog/2026-08-21-scale-a-multi-selection-from-the-group-handles.md +6 -0
- package/corpus/templates/design/changelog/2026-08-21-scale-resizes-text-with-the-object.md +6 -0
- package/corpus/templates/design/changelog/2026-08-21-selecting-another-object-keeps-the-scale-tool-armed.md +6 -0
- package/corpus/templates/design/changelog/2026-08-21-the-shape-tool-remembers-the-shape-you-picked.md +6 -0
- package/corpus/templates/design/changelog/2026-08-21-vectors-drawn-in-a-frame-land-where-you-drew-them.md +6 -0
- package/corpus/templates/design/changelog/2026-08-22-multi-screen-generation-no-longer-loses-a-saved-screens-layo.md +6 -0
- package/corpus/templates/design/changelog/2026-08-22-rename-and-search-fields-are-labeled-for-screen-readers.md +6 -0
- package/corpus/templates/design/package.json +2 -0
- package/corpus/templates/design/server/lib/builder-design-system-proxy.ts +311 -0
- package/corpus/templates/design/shared/canvas-math.ts +612 -206
- package/corpus/templates/design/shared/pen-path.ts +37 -0
- package/corpus/templates/design/vitest.config.ts +7 -1
- package/corpus/templates/dispatch/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/dispatch/actions/list-workspace-connections.ts +34 -3
- package/corpus/templates/dispatch/app/routes/integrations.tsx +55 -21
- package/corpus/templates/dispatch/app/routes.ts +3 -1
- package/corpus/templates/factory/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/factory/.env.example +2 -7
- package/corpus/templates/factory/AGENTS.md +3 -0
- package/corpus/templates/factory/README.md +5 -3
- package/corpus/templates/factory/actions/create-factory.ts +16 -3
- package/corpus/templates/factory/actions/get-slack-feedback-context.ts +2 -0
- package/corpus/templates/factory/actions/get-triage-item.ts +2 -0
- package/corpus/templates/factory/actions/list-factory-audit.ts +116 -36
- package/corpus/templates/factory/actions/list-factory-automations.ts +2 -1
- package/corpus/templates/factory/actions/list-triage-items.ts +22 -19
- package/corpus/templates/factory/actions/run-factory-automation.ts +7 -3
- package/corpus/templates/factory/actions/save-factory-automation.ts +5 -2
- package/corpus/templates/factory/actions/save-triage-config.ts +2 -8
- package/corpus/templates/factory/actions/start-builder-for-item.ts +21 -0
- package/corpus/templates/factory/app/components/factory/FactoryAuditView.tsx +229 -297
- package/corpus/templates/factory/app/components/factory/FactorySettingsView.tsx +397 -247
- package/corpus/templates/factory/app/components/factory/FactorySourceSettingsGroup.tsx +33 -0
- package/corpus/templates/factory/app/components/factory/NewFactoryForm.tsx +202 -162
- package/corpus/templates/factory/app/i18n/en-US.ts +32 -4
- package/corpus/templates/factory/app/routes/factory.tsx +84 -11
- package/corpus/templates/factory/app/routes.ts +3 -1
- package/corpus/templates/factory/changelog/2026-08-21-activity-runs-use-automation-display-names.md +6 -0
- package/corpus/templates/factory/changelog/2026-08-21-create-and-settings-source-cards.md +6 -0
- package/corpus/templates/factory/changelog/2026-08-21-keep-automations-visible-while-running.md +6 -0
- package/corpus/templates/factory/changelog/2026-08-21-nested-factory-automations-can-poll.md +6 -0
- package/corpus/templates/factory/changelog/2026-08-21-settings-sticky-unsaved-bar.md +6 -0
- package/corpus/templates/factory/server/connectors/credentials.ts +10 -5
- package/corpus/templates/factory/server/lib/factory-audit-report.ts +412 -0
- package/corpus/templates/factory/server/lib/factory-config-reconcile.ts +321 -0
- package/corpus/templates/factory/server/lib/factory-scope.ts +25 -2
- package/corpus/templates/factory/server/lib/require-factory-automation.ts +13 -4
- package/corpus/templates/factory/server/plugins/factory-migrations.ts +148 -4
- package/corpus/templates/factory/server/plugins/factory-scheduler-job.ts +4 -6
- package/corpus/templates/factory/vitest.config.ts +17 -2
- package/corpus/templates/forms/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/forms/app/routes/_app.settings.tsx +4 -1
- package/corpus/templates/forms/changelog/2026-08-22-the-extensions-link-now-opens-the-extensions-tab-instead-o.md +6 -0
- package/corpus/templates/forms/server/lib/public-form-ssr.ts +11 -1
- package/corpus/templates/forms/vitest.config.ts +1 -0
- package/corpus/templates/macros/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/macros/app/routes.ts +3 -1
- package/corpus/templates/macros/vitest.config.ts +6 -1
- package/corpus/templates/mail/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/mail/actions/manage-gmail-filters.ts +10 -2
- package/corpus/templates/mail/app/components/GoogleConnectBanner.tsx +100 -37
- package/corpus/templates/mail/app/components/email/IntegrationsSidebar.tsx +14 -2
- package/corpus/templates/mail/app/components/layout/AppLayout.tsx +66 -36
- package/corpus/templates/mail/app/hooks/use-emails.ts +13 -3
- package/corpus/templates/mail/app/hooks/use-google-auth.ts +2 -0
- package/corpus/templates/mail/app/lib/google-oauth-setup.ts +17 -0
- package/corpus/templates/mail/app/pages/InboxPage.tsx +69 -9
- package/corpus/templates/mail/app/routes/$.tsx +9 -0
- package/corpus/templates/mail/app/routes/$view.$threadId.tsx +23 -1
- package/corpus/templates/mail/app/routes/$view.tsx +47 -1
- package/corpus/templates/mail/app/routes.ts +3 -1
- package/corpus/templates/mail/changelog/2026-08-22-gmail-can-now-connect-with-the-shared-google-oauth.md +6 -0
- package/corpus/templates/mail/changelog/2026-08-22-gmail-filters-now-shows-the-real-error.md +6 -0
- package/corpus/templates/mail/changelog/2026-08-22-unknown-mail-urls-now-show-the-404-page.md +6 -0
- package/corpus/templates/mail/server/handlers/google-auth.ts +11 -2
- package/corpus/templates/mail/server/lib/google-auth.ts +92 -12
- package/corpus/templates/mail/server/onboarding.ts +66 -18
- package/corpus/templates/mail/vitest.config.ts +6 -1
- package/corpus/templates/plan/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/plan/app/routes/settings.tsx +4 -1
- package/corpus/templates/plan/app/routes.ts +3 -1
- package/corpus/templates/plan/changelog/2026-08-22-the-extensions-link-now-opens-the-extensions-tab-instead-o.md +6 -0
- package/corpus/templates/plan/netlify.toml +1 -1
- package/corpus/templates/slides/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/slides/actions/patch-deck.ts +79 -10
- package/corpus/templates/slides/actions/update-slide.ts +11 -1
- package/corpus/templates/slides/app/components/deck/SlideRenderer.tsx +14 -4
- package/corpus/templates/slides/app/components/editor/ExportMenu.tsx +10 -52
- package/corpus/templates/slides/app/components/editor/GoogleDocImportHint.tsx +8 -53
- package/corpus/templates/slides/app/components/editor/GoogleDriveConnectionCta.tsx +9 -75
- package/corpus/templates/slides/app/components/editor/GoogleSlidesReferenceImport.tsx +8 -60
- package/corpus/templates/slides/app/components/editor/SlideContextToolbar.tsx +10 -2
- package/corpus/templates/slides/app/components/editor/SlideEditor.tsx +19 -7
- package/corpus/templates/slides/app/lib/sanitize-slide-html.ts +49 -36
- package/corpus/templates/slides/app/routes/access-request.approve.tsx +16 -9
- package/corpus/templates/slides/app/routes.ts +3 -1
- package/corpus/templates/slides/changelog/2026-08-22-already-uploaded-chat-images-are-no-longer-dropped.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-22-google-drive-and-slides-can-now-connect-with-the-shared-google-oauth.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-22-multi-slide-repairs-now-report-slides-that-still-overflow.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-22-update-slide-now-reports-which-batched-edit-was-skipped.md +6 -0
- package/corpus/templates/slides/server/handlers/google-docs-auth.ts +52 -1
- package/corpus/templates/slides/server/lib/chat-attachments.ts +29 -3
- package/corpus/templates/slides/server/lib/google-docs-oauth.ts +66 -16
- package/corpus/templates/slides/server/lib/slide-content-patch.ts +13 -2
- package/corpus/templates/slides/server/plugins/agent-chat.ts +5 -2
- package/corpus/templates/slides/tsconfig.json +5 -0
- package/corpus/templates/slides/vitest.config.ts +6 -1
- package/corpus/templates/tasks/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/tasks/app/routes/settings.tsx +4 -1
- package/corpus/templates/tasks/app/routes.ts +3 -1
- package/corpus/templates/tasks/changelog/2026-08-22-the-extensions-link-now-opens-the-extensions-tab-instead-o.md +6 -0
- package/corpus/templates/tasks/vitest.config.ts +7 -1
- package/dist/action.d.ts +91 -0
- package/dist/action.js +50 -0
- package/dist/agent/abort-reasons.d.ts +38 -0
- package/dist/agent/abort-reasons.js +49 -0
- package/dist/agent/engine/ai-sdk-engine.js +8 -5
- package/dist/agent/engine/anthropic-engine.js +7 -5
- package/dist/agent/engine/credential-errors.d.ts +1 -1
- package/dist/agent/engine/credential-errors.js +2 -2
- package/dist/agent/engine/first-event-timeout.d.ts +42 -17
- package/dist/agent/engine/first-event-timeout.js +67 -25
- package/dist/agent/production-agent.d.ts +23 -0
- package/dist/agent/production-agent.js +107 -102
- package/dist/agent/run-loop-with-resume.d.ts +2 -28
- package/dist/agent/run-loop-with-resume.js +25 -40
- package/dist/agent/run-manager.js +5 -4
- package/dist/agent/run-store.d.ts +55 -0
- package/dist/agent/run-store.js +124 -1
- package/dist/agent/tool-search.js +2 -1
- package/dist/agent/types.d.ts +9 -4
- package/dist/app-config/configuration-error.d.ts +11 -0
- package/dist/app-config/configuration-error.js +14 -0
- package/dist/app-config/index.d.ts +1 -0
- package/dist/app-config/index.js +1 -0
- package/dist/app-config/integrations.d.ts +1 -0
- package/dist/app-config/integrations.js +10 -0
- package/dist/app-config/plugins.d.ts +34 -0
- package/dist/app-config/plugins.js +39 -0
- package/dist/app-config/run-lifecycle-invariants.d.ts +18 -9
- package/dist/app-config/run-lifecycle-invariants.js +18 -25
- package/dist/app-config/schema.d.ts +16 -0
- package/dist/app-config/schema.js +2 -0
- package/dist/chat-threads/schema-migrations.js +20 -0
- package/dist/chat-threads/store.js +21 -4
- package/dist/cli/native-dependencies.d.ts +4 -0
- package/dist/cli/native-dependencies.js +15 -0
- package/dist/client/AssistantChat.js +47 -15
- package/dist/client/ConnectBuilderCard.d.ts +3 -1
- package/dist/client/ConnectBuilderCard.js +6 -3
- package/dist/client/EnvironmentBadge.d.ts +1 -1
- package/dist/client/EnvironmentBadge.js +40 -5
- package/dist/client/MultiTabAssistantChat.d.ts +1 -1
- package/dist/client/MultiTabAssistantChat.js +35 -14
- package/dist/client/agent-chat/index.d.ts +1 -1
- package/dist/client/agent-chat/index.js +1 -1
- package/dist/client/agent-page/use-jobs.d.ts +2 -1
- package/dist/client/agent-page/use-jobs.js +3 -5
- package/dist/client/agent-sidebar-state.js +3 -1
- package/dist/client/blocks/library/code-tabs.js +5 -0
- package/dist/client/blocks/library/code.js +1 -0
- package/dist/client/chat/message-components.d.ts +7 -0
- package/dist/client/chat/message-components.js +1 -1
- package/dist/client/chat/run-recovery.js +5 -2
- package/dist/client/chat/tool-call-display.js +9 -3
- package/dist/client/chat-first/apps-rail.js +2 -2
- package/dist/client/chat-model-groups.d.ts +12 -0
- package/dist/client/chat-model-groups.js +3 -2
- package/dist/client/error-format.js +12 -0
- package/dist/client/integrations/GoogleProductLogo.d.ts +5 -0
- package/dist/client/integrations/GoogleProductLogo.js +45 -0
- package/dist/client/integrations/index.d.ts +2 -0
- package/dist/client/integrations/index.js +2 -0
- package/dist/client/integrations/workspace-provider-oauth.d.ts +8 -0
- package/dist/client/integrations/workspace-provider-oauth.js +13 -0
- package/dist/client/navigation/index.d.ts +1 -0
- package/dist/client/navigation/index.js +1 -0
- package/dist/client/resources/mcp-integration-catalog.js +0 -29
- package/dist/client/route-state.js +6 -0
- package/dist/client/settings/SettingsTabsPage.js +10 -6
- package/dist/client/sharing/ShareButton.js +11 -2
- package/dist/client/use-chat-models.d.ts +6 -0
- package/dist/client/use-chat-models.js +10 -0
- package/dist/client/use-db-sync.js +27 -9
- package/dist/client/workspace-app-navigation.d.ts +10 -0
- package/dist/client/workspace-app-navigation.js +38 -0
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/connections/catalog.d.ts +111 -9
- package/dist/connections/catalog.js +86 -30
- package/dist/db/create-get-db.js +18 -0
- package/dist/db/ddl-guard.d.ts +0 -4
- package/dist/db/ddl-guard.js +46 -0
- package/dist/deploy/build.d.ts +32 -0
- package/dist/deploy/build.js +241 -16
- package/dist/deploy/function-bundle.d.ts +45 -0
- package/dist/deploy/function-bundle.js +337 -0
- package/dist/deploy/workspace-deploy.js +19 -1
- package/dist/eject/workspace-connections.js +4 -0
- package/dist/email-catalog/registry.d.ts +4 -0
- package/dist/email-catalog/registry.js +79 -14
- package/dist/extensions/content-patch.js +14 -2
- package/dist/file-upload/actions/upload-image.d.ts +1 -1
- package/dist/integrations/plugin.d.ts +10 -0
- package/dist/integrations/plugin.js +40 -6
- package/dist/jobs/actions/run-automation-now.d.ts +2 -1
- package/dist/jobs/actions/run-automation-now.js +11 -5
- package/dist/jobs/frontmatter.js +53 -2
- package/dist/jobs/run-now.d.ts +11 -1
- package/dist/jobs/run-now.js +42 -7
- package/dist/jobs/scheduler.d.ts +1 -0
- package/dist/jobs/scheduler.js +2 -1
- package/dist/localization/core-messages/ar-SA.js +4 -1
- package/dist/localization/core-messages/de-DE.js +4 -1
- package/dist/localization/core-messages/en-US.d.ts +4 -1
- package/dist/localization/core-messages/en-US.js +4 -1
- package/dist/localization/core-messages/es-ES.js +4 -1
- package/dist/localization/core-messages/fr-FR.js +4 -1
- package/dist/localization/core-messages/hi-IN.js +4 -1
- package/dist/localization/core-messages/ja-JP.js +4 -1
- package/dist/localization/core-messages/ko-KR.js +4 -1
- package/dist/localization/core-messages/pt-BR.js +4 -1
- package/dist/localization/core-messages/zh-CN.js +4 -1
- package/dist/localization/core-messages/zh-TW.js +4 -1
- package/dist/localization/core-messages.d.ts +4 -1
- package/dist/localization/default-messages.d.ts +2 -5
- package/dist/localization/default-messages.js +2 -5
- package/dist/mcp/build-server.d.ts +9 -0
- package/dist/mcp/build-server.js +37 -8
- package/dist/mcp-client/oauth-client.d.ts +7 -0
- package/dist/mcp-client/oauth-client.js +12 -1
- package/dist/notifications/routes.d.ts +1 -1
- package/dist/oauth-tokens/index.d.ts +1 -1
- package/dist/oauth-tokens/index.js +1 -1
- package/dist/oauth-tokens/lifecycle.d.ts +11 -0
- package/dist/oauth-tokens/lifecycle.js +17 -0
- package/dist/oauth-tokens/store.js +7 -0
- package/dist/observability/posthog-ai.d.ts +15 -1
- package/dist/observability/posthog-ai.js +24 -12
- package/dist/observability/traces.js +158 -28
- package/dist/onboarding/app-profile.js +2 -2
- package/dist/onboarding/plugin.js +10 -2
- package/dist/onboarding/types.d.ts +2 -0
- package/dist/provider-api/actions/custom-provider-registration.d.ts +12 -12
- package/dist/provider-api/actions/provider-api.d.ts +11 -11
- package/dist/provider-api/corpus-jobs.d.ts +2 -2
- package/dist/provider-api/index.js +2 -0
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/resources/store.js +13 -4
- package/dist/scripts/agent-engines/list-agent-engines.js +29 -3
- package/dist/scripts/db/check-scoping.js +9 -6
- package/dist/secrets/register-framework-secrets.js +1 -1
- package/dist/secrets/routes.d.ts +6 -6
- package/dist/server/action-discovery.js +5 -0
- package/dist/server/agent-chat/action-filters-a2a.d.ts +27 -3
- package/dist/server/agent-chat/action-filters-a2a.js +48 -9
- package/dist/server/agent-chat-plugin.js +36 -9
- package/dist/server/agent-discovery.js +43 -20
- package/dist/server/auth.js +18 -16
- package/dist/server/beta-opt-out-html.js +45 -4
- package/dist/server/better-auth-instance.d.ts +2 -1
- package/dist/server/better-auth-instance.js +23 -7
- package/dist/server/builder-browser.d.ts +4 -0
- package/dist/server/builder-browser.js +23 -1
- package/dist/server/builder-design-systems.d.ts +4 -1
- package/dist/server/builder-design-systems.js +87 -6
- package/dist/server/builder-oauth.d.ts +1 -7
- package/dist/server/builder-oauth.js +80 -163
- package/dist/server/core-routes-plugin.d.ts +29 -0
- package/dist/server/core-routes-plugin.js +113 -21
- package/dist/server/default-plugins.d.ts +18 -0
- package/dist/server/default-plugins.js +22 -0
- package/dist/server/edge.d.ts +1 -0
- package/dist/server/edge.js +1 -0
- package/dist/server/framework-request-handler.js +31 -3
- package/dist/server/google-oauth.d.ts +3 -0
- package/dist/server/google-oauth.js +3 -0
- package/dist/server/index.d.ts +4 -4
- package/dist/server/index.js +3 -3
- package/dist/server/onboarding-html.js +37 -3
- package/dist/server/workspace-provider-oauth.d.ts +6 -1
- package/dist/server/workspace-provider-oauth.js +72 -20
- package/dist/shared/agent-sidebar-url.d.ts +1 -0
- package/dist/shared/agent-sidebar-url.js +1 -0
- package/dist/shared/environment-lanes.d.ts +2 -0
- package/dist/shared/environment-lanes.js +3 -1
- package/dist/shared/index.d.ts +3 -1
- package/dist/shared/index.js +3 -1
- package/dist/shared/surface-visibility.d.ts +31 -0
- package/dist/shared/surface-visibility.js +57 -0
- package/dist/templates/chat/.agents/skills/secrets/SKILL.md +11 -4
- package/dist/templates/chat/app/routes.ts +3 -1
- package/dist/templates/chat/vitest.config.ts +8 -0
- package/dist/templates/default/.agents/skills/secrets/SKILL.md +11 -4
- package/dist/templates/default/app/routes.ts +3 -1
- package/dist/templates/headless/.agents/skills/secrets/SKILL.md +11 -4
- package/dist/templates/workspace-core/.agents/skills/secrets/SKILL.md +11 -4
- package/dist/tracking/registry.d.ts +11 -0
- package/dist/tracking/registry.js +5 -2
- package/dist/triggers/actions.js +10 -3
- package/dist/usage/store.js +23 -3
- package/dist/user-profile/actions/get-auth-methods.js +18 -5
- package/dist/vite/client.js +24 -5
- package/docs/content/actions-access-control.mdx +43 -4
- package/docs/content/actions-defining.mdx +16 -0
- package/docs/content/template-clips-capture-everywhere.mdx +29 -30
- package/docs/content/template-clips-developers.mdx +4 -4
- package/docs/content/template-clips.mdx +3 -1
- package/package.json +3 -3
- package/src/eject/workspace-connections.ts +4 -0
- package/src/templates/chat/.agents/skills/secrets/SKILL.md +11 -4
- package/src/templates/chat/app/routes.ts +3 -1
- package/src/templates/chat/vitest.config.ts +8 -0
- package/src/templates/default/.agents/skills/secrets/SKILL.md +11 -4
- package/src/templates/default/app/routes.ts +3 -1
- package/src/templates/headless/.agents/skills/secrets/SKILL.md +11 -4
- package/src/templates/workspace-core/.agents/skills/secrets/SKILL.md +11 -4
- /package/corpus/templates/dispatch/app/routes/{apps.$appId.tsx → apps.$appId.$.tsx} +0 -0
|
@@ -56,6 +56,10 @@ import {
|
|
|
56
56
|
SelectValue,
|
|
57
57
|
} from "@/components/ui/select";
|
|
58
58
|
import { Skeleton } from "@/components/ui/skeleton";
|
|
59
|
+
import {
|
|
60
|
+
isDashboardMine,
|
|
61
|
+
type DashboardVisibility,
|
|
62
|
+
} from "@/lib/dashboard-visibility";
|
|
59
63
|
import { dashboardCacheScope } from "@/lib/prefetch-keys";
|
|
60
64
|
|
|
61
65
|
import { NewDashboardDialog } from "../components/layout/NewDashboardDialog";
|
|
@@ -65,7 +69,8 @@ type Dashboard = {
|
|
|
65
69
|
id: string;
|
|
66
70
|
name?: string;
|
|
67
71
|
title?: string;
|
|
68
|
-
visibility?:
|
|
72
|
+
visibility?: DashboardVisibility;
|
|
73
|
+
ownerEmail?: string | null;
|
|
69
74
|
folderId?: string | null;
|
|
70
75
|
};
|
|
71
76
|
type Folder = {
|
|
@@ -125,10 +130,15 @@ export default function DashboardOverview() {
|
|
|
125
130
|
) {
|
|
126
131
|
continue;
|
|
127
132
|
}
|
|
133
|
+
const ownerEmail =
|
|
134
|
+
typeof dashboard.ownerEmail === "string"
|
|
135
|
+
? dashboard.ownerEmail
|
|
136
|
+
: undefined;
|
|
128
137
|
validDashboards.push({
|
|
129
138
|
id: dashboard.id,
|
|
130
139
|
name: dashboard.name,
|
|
131
140
|
visibility: dashboard.visibility,
|
|
141
|
+
...(ownerEmail ? { ownerEmail } : {}),
|
|
132
142
|
folderId: dashboard.folderId ?? null,
|
|
133
143
|
});
|
|
134
144
|
}
|
|
@@ -394,6 +404,7 @@ export default function DashboardOverview() {
|
|
|
394
404
|
folders={folders}
|
|
395
405
|
grouped={grouped}
|
|
396
406
|
onMove={moveDashboard}
|
|
407
|
+
currentUserEmail={auth?.email}
|
|
397
408
|
t={t}
|
|
398
409
|
/>
|
|
399
410
|
))}
|
|
@@ -428,6 +439,7 @@ function DashboardScopeSection({
|
|
|
428
439
|
folders,
|
|
429
440
|
grouped,
|
|
430
441
|
onMove,
|
|
442
|
+
currentUserEmail,
|
|
431
443
|
t,
|
|
432
444
|
}: {
|
|
433
445
|
scope: Scope;
|
|
@@ -435,11 +447,12 @@ function DashboardScopeSection({
|
|
|
435
447
|
folders: Folder[];
|
|
436
448
|
grouped: Map<string, Dashboard[]>;
|
|
437
449
|
onMove: (dashboard: Dashboard, folderId: string | null) => void;
|
|
450
|
+
currentUserEmail?: string | null;
|
|
438
451
|
t: ReturnType<typeof useT>;
|
|
439
452
|
}) {
|
|
440
453
|
const scopeFolders = folders.filter((folder) => folder.scope === scope);
|
|
441
454
|
const scopeDashboards = dashboards.filter((dashboard) =>
|
|
442
|
-
isDashboardInScope(dashboard, scope),
|
|
455
|
+
isDashboardInScope(dashboard, scope, currentUserEmail),
|
|
443
456
|
);
|
|
444
457
|
const Icon = scope === "personal" ? IconLock : IconUsers;
|
|
445
458
|
|
|
@@ -476,6 +489,7 @@ function DashboardScopeSection({
|
|
|
476
489
|
folders={folders}
|
|
477
490
|
scope={scope}
|
|
478
491
|
onMove={onMove}
|
|
492
|
+
currentUserEmail={currentUserEmail}
|
|
479
493
|
t={t}
|
|
480
494
|
/>
|
|
481
495
|
))}
|
|
@@ -485,6 +499,7 @@ function DashboardScopeSection({
|
|
|
485
499
|
folders={folders}
|
|
486
500
|
scope={scope}
|
|
487
501
|
onMove={onMove}
|
|
502
|
+
currentUserEmail={currentUserEmail}
|
|
488
503
|
t={t}
|
|
489
504
|
hideWhenEmpty
|
|
490
505
|
/>
|
|
@@ -500,6 +515,7 @@ function FolderSection({
|
|
|
500
515
|
folders,
|
|
501
516
|
scope,
|
|
502
517
|
onMove,
|
|
518
|
+
currentUserEmail,
|
|
503
519
|
t,
|
|
504
520
|
hideWhenEmpty = false,
|
|
505
521
|
}: {
|
|
@@ -508,11 +524,12 @@ function FolderSection({
|
|
|
508
524
|
folders: Folder[];
|
|
509
525
|
scope: Scope;
|
|
510
526
|
onMove: (dashboard: Dashboard, folderId: string | null) => void;
|
|
527
|
+
currentUserEmail?: string | null;
|
|
511
528
|
t: ReturnType<typeof useT>;
|
|
512
529
|
hideWhenEmpty?: boolean;
|
|
513
530
|
}) {
|
|
514
531
|
const scopedDashboards = dashboards.filter((dashboard) =>
|
|
515
|
-
isDashboardInScope(dashboard, scope),
|
|
532
|
+
isDashboardInScope(dashboard, scope, currentUserEmail),
|
|
516
533
|
);
|
|
517
534
|
if (hideWhenEmpty && scopedDashboards.length === 0) return null;
|
|
518
535
|
|
|
@@ -540,6 +557,7 @@ function FolderSection({
|
|
|
540
557
|
folders={folders}
|
|
541
558
|
currentFolderId={folder?.id ?? null}
|
|
542
559
|
onMove={onMove}
|
|
560
|
+
currentUserEmail={currentUserEmail}
|
|
543
561
|
t={t}
|
|
544
562
|
/>
|
|
545
563
|
))}
|
|
@@ -554,23 +572,26 @@ function DashboardRow({
|
|
|
554
572
|
folders,
|
|
555
573
|
currentFolderId,
|
|
556
574
|
onMove,
|
|
575
|
+
currentUserEmail,
|
|
557
576
|
t,
|
|
558
577
|
}: {
|
|
559
578
|
dashboard: Dashboard;
|
|
560
579
|
folders: Folder[];
|
|
561
580
|
currentFolderId: string | null;
|
|
562
581
|
onMove: (dashboard: Dashboard, folderId: string | null) => void;
|
|
582
|
+
currentUserEmail?: string | null;
|
|
563
583
|
t: ReturnType<typeof useT>;
|
|
564
584
|
}) {
|
|
565
585
|
const name =
|
|
566
586
|
dashboard.name || dashboard.title || t("sidebar.untitledDashboard");
|
|
587
|
+
const mine = isDashboardMine(dashboard, currentUserEmail);
|
|
567
588
|
const candidateFolders = folders.filter((folder) => {
|
|
568
|
-
if (
|
|
589
|
+
if (mine) {
|
|
569
590
|
return folder.scope === "personal";
|
|
570
591
|
}
|
|
571
592
|
return dashboard.visibility === "org" && folder.scope === "shared";
|
|
572
593
|
});
|
|
573
|
-
const canOrganize = dashboard.visibility
|
|
594
|
+
const canOrganize = mine || dashboard.visibility === "org";
|
|
574
595
|
|
|
575
596
|
return (
|
|
576
597
|
<div className="group flex items-center gap-3 px-4 py-3 transition-colors hover:bg-muted/30">
|
|
@@ -586,7 +607,7 @@ function DashboardRow({
|
|
|
586
607
|
{name}
|
|
587
608
|
</p>
|
|
588
609
|
<p className="truncate text-xs text-muted-foreground">
|
|
589
|
-
{
|
|
610
|
+
{mine
|
|
590
611
|
? t("dashboardOverview.personal")
|
|
591
612
|
: t("dashboardOverview.shared")}
|
|
592
613
|
</p>
|
|
@@ -635,8 +656,12 @@ function DashboardRow({
|
|
|
635
656
|
);
|
|
636
657
|
}
|
|
637
658
|
|
|
638
|
-
function isDashboardInScope(
|
|
659
|
+
function isDashboardInScope(
|
|
660
|
+
dashboard: Dashboard,
|
|
661
|
+
scope: Scope,
|
|
662
|
+
currentUserEmail?: string | null,
|
|
663
|
+
): boolean {
|
|
639
664
|
return scope === "personal"
|
|
640
|
-
? dashboard
|
|
641
|
-
: dashboard
|
|
665
|
+
? isDashboardMine(dashboard, currentUserEmail)
|
|
666
|
+
: !isDashboardMine(dashboard, currentUserEmail);
|
|
642
667
|
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { data } from "react-router";
|
|
2
|
+
|
|
1
3
|
import { messagesByLocale } from "@/i18n-data";
|
|
2
4
|
import NotFound from "@/pages/NotFound";
|
|
3
5
|
|
|
@@ -5,6 +7,14 @@ export function meta() {
|
|
|
5
7
|
return [{ title: messagesByLocale["en-US"].routeTitles.notFound }];
|
|
6
8
|
}
|
|
7
9
|
|
|
10
|
+
// The splat route matches every unmatched path, so React Router's "no routes
|
|
11
|
+
// matched" 404 branch never fires here and the response defaults to 200. Set
|
|
12
|
+
// the status explicitly so the shell is served (and CDN-cached) as the
|
|
13
|
+
// not-found page it actually is.
|
|
14
|
+
export function loader() {
|
|
15
|
+
return data(null, { status: 404 });
|
|
16
|
+
}
|
|
17
|
+
|
|
8
18
|
export default function CatchAllRoute() {
|
|
9
19
|
return <NotFound />;
|
|
10
20
|
}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { type RouteConfig } from "@react-router/dev/routes";
|
|
2
2
|
import { flatRoutes } from "@react-router/fs-routes";
|
|
3
3
|
|
|
4
|
-
export default flatRoutes(
|
|
4
|
+
export default flatRoutes({
|
|
5
|
+
ignoredRouteFiles: ["**/*.test.{ts,tsx}", "**/*.spec.{ts,tsx}"],
|
|
6
|
+
}) satisfies RouteConfig;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: fixed
|
|
3
|
+
date: 2026-08-22
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Org admin panels no longer report a database error as a permission denial. A failed
|
|
7
|
+
organization-role lookup now surfaces as a retryable error instead of silently reading
|
|
8
|
+
as "you are not an owner or admin", which had been 403-ing the usage stats panel for
|
|
9
|
+
real admins whenever the database was briefly unreachable.
|
|
@@ -128,7 +128,8 @@ Useful query fields live in `properties`:
|
|
|
128
128
|
| `cache_read_tokens`, `cache_write_tokens` | Prompt-cache token counts |
|
|
129
129
|
| `$ai_total_cost_usd`, `cost_usd` | Estimated run cost in USD |
|
|
130
130
|
| `cost_cents_x100` | Estimated run cost in centicents |
|
|
131
|
-
|
|
|
131
|
+
| `duration_ms` | Run duration in milliseconds |
|
|
132
|
+
| `$ai_latency` | Model time in seconds (run duration minus tool time), on `$ai_generation` |
|
|
132
133
|
| `tool_calls`, `successful_tools`, `failed_tools` | Complete tool-call counts |
|
|
133
134
|
| `tools`, `tools_truncated` | First 50 tool names, offsets, durations, statuses, and error classes, including interrupted calls |
|
|
134
135
|
| `delegated`, `delegation_protocol`, `caller_app` | Delegated-run attribution |
|
|
@@ -29,6 +29,8 @@ Events tracked by application instrumentation and stored in the configured appli
|
|
|
29
29
|
`$ai_model`, `$ai_provider`, `$ai_input_tokens`, `$ai_output_tokens`,
|
|
30
30
|
`$ai_latency`, `$ai_total_cost_usd`, `run_id`, `thread_id`,
|
|
31
31
|
`cost_cents_x100`, `duration_ms`, `tool_calls`, `status`, and error fields.
|
|
32
|
+
`$ai_latency` is model time in seconds; `duration_ms` is the full run in
|
|
33
|
+
milliseconds, and the two differ by the time spent in tools.
|
|
32
34
|
A bounded `tools` array records only tool names, relative start times,
|
|
33
35
|
durations, statuses, and coarse error classes; interrupted tools and failed
|
|
34
36
|
runs remain visible, and `tools_truncated` marks runs above the 50-entry cap.
|
|
@@ -5,7 +5,29 @@ import { existsSync, rmSync, writeFileSync, mkdirSync } from "node:fs";
|
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
7
7
|
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
cloneServerBundleForFunction,
|
|
10
|
+
pruneBrowserRuntimeFromNonAgentClone,
|
|
11
|
+
pruneSsrIslandFromRewritingClone,
|
|
12
|
+
} from "@agent-native/core/deploy/function-bundle";
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Each sweep worker is a full clone of the server bundle, but its entry rewrites
|
|
16
|
+
* the pathname to one scheduled route. It can reach neither the SSR pages nor an
|
|
17
|
+
* agent turn, yet it shipped both the page island and the 79MB browser runtime —
|
|
18
|
+
* six times over, and Netlify zips every function separately.
|
|
19
|
+
*/
|
|
20
|
+
function writeWorkerEntry(dest: string, name: string, source: string): void {
|
|
21
|
+
writeFileSync(path.join(dest, `${name}.mjs`), source);
|
|
22
|
+
const freed =
|
|
23
|
+
pruneSsrIslandFromRewritingClone(dest, source) +
|
|
24
|
+
pruneBrowserRuntimeFromNonAgentClone(dest, source);
|
|
25
|
+
if (freed > 0) {
|
|
26
|
+
console.log(
|
|
27
|
+
`[deploy] Pruned ${(freed / 1024 / 1024).toFixed(1)}MB of unreachable modules from ${name}.`,
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
9
31
|
|
|
10
32
|
const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
11
33
|
const FUNCTIONS_DIR = path.join(ROOT, ".netlify", "functions-internal");
|
|
@@ -164,7 +186,7 @@ export const config = {
|
|
|
164
186
|
};
|
|
165
187
|
`;
|
|
166
188
|
|
|
167
|
-
|
|
189
|
+
writeWorkerEntry(dest, WORKER_NAME, source);
|
|
168
190
|
}
|
|
169
191
|
|
|
170
192
|
function emitAlertScheduledTrigger(token: string) {
|
|
@@ -282,7 +304,7 @@ export const config = {
|
|
|
282
304
|
};
|
|
283
305
|
`;
|
|
284
306
|
|
|
285
|
-
|
|
307
|
+
writeWorkerEntry(dest, ALERT_WORKER_NAME, source);
|
|
286
308
|
}
|
|
287
309
|
|
|
288
310
|
function emitUptimeScheduledTrigger(token: string) {
|
|
@@ -400,7 +422,7 @@ export const config = {
|
|
|
400
422
|
};
|
|
401
423
|
`;
|
|
402
424
|
|
|
403
|
-
|
|
425
|
+
writeWorkerEntry(dest, UPTIME_WORKER_NAME, source);
|
|
404
426
|
}
|
|
405
427
|
|
|
406
428
|
function emitRollupScheduledTrigger(token: string) {
|
|
@@ -500,7 +522,7 @@ export const config = {
|
|
|
500
522
|
};
|
|
501
523
|
`;
|
|
502
524
|
|
|
503
|
-
|
|
525
|
+
writeWorkerEntry(dest, ROLLUP_WORKER_NAME, source);
|
|
504
526
|
}
|
|
505
527
|
|
|
506
528
|
function emitBigQueryScheduledTrigger(token: string) {
|
|
@@ -600,7 +622,7 @@ export const config = {
|
|
|
600
622
|
};
|
|
601
623
|
`;
|
|
602
624
|
|
|
603
|
-
|
|
625
|
+
writeWorkerEntry(dest, BIGQUERY_WORKER_NAME, source);
|
|
604
626
|
}
|
|
605
627
|
|
|
606
628
|
function emitRetentionScheduledTrigger(token: string) {
|
|
@@ -702,7 +724,7 @@ export const config = {
|
|
|
702
724
|
};
|
|
703
725
|
`;
|
|
704
726
|
|
|
705
|
-
|
|
727
|
+
writeWorkerEntry(dest, RETENTION_WORKER_NAME, source);
|
|
706
728
|
}
|
|
707
729
|
|
|
708
730
|
function isDirectRun(): boolean {
|
|
@@ -19,8 +19,57 @@ import {
|
|
|
19
19
|
type SlackMessage,
|
|
20
20
|
} from "../lib/slack";
|
|
21
21
|
|
|
22
|
-
function parseWorkspace(raw?:
|
|
23
|
-
|
|
22
|
+
export function parseWorkspace(raw?: unknown): Workspace | null {
|
|
23
|
+
if (raw === undefined || raw === null || raw === "" || raw === "primary") {
|
|
24
|
+
return "primary";
|
|
25
|
+
}
|
|
26
|
+
if (raw === "secondary") return "secondary";
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function invalidWorkspace(event: H3Event) {
|
|
31
|
+
setResponseStatus(event, 400);
|
|
32
|
+
return { error: "workspace must be primary or secondary" };
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function parseCursorMap(
|
|
36
|
+
raw?: unknown,
|
|
37
|
+
): { ok: true; value: Record<string, string> } | { ok: false } {
|
|
38
|
+
if (raw === undefined || raw === null || raw === "") {
|
|
39
|
+
return { ok: true, value: {} };
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
try {
|
|
43
|
+
const parsed: unknown = JSON.parse(String(raw));
|
|
44
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
45
|
+
return { ok: false };
|
|
46
|
+
}
|
|
47
|
+
const entries = Object.entries(parsed);
|
|
48
|
+
if (
|
|
49
|
+
entries.some(
|
|
50
|
+
([, value]) =>
|
|
51
|
+
typeof value !== "string" ||
|
|
52
|
+
!/^\d+(?:\.\d{1,6})?$/.test(value.trim()),
|
|
53
|
+
)
|
|
54
|
+
) {
|
|
55
|
+
return { ok: false };
|
|
56
|
+
}
|
|
57
|
+
return {
|
|
58
|
+
ok: true,
|
|
59
|
+
value: Object.fromEntries(
|
|
60
|
+
entries.map(([channelId, value]) => [channelId, value.trim()]),
|
|
61
|
+
),
|
|
62
|
+
};
|
|
63
|
+
} catch {
|
|
64
|
+
return { ok: false };
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function invalidCursors(event: H3Event) {
|
|
69
|
+
setResponseStatus(event, 400);
|
|
70
|
+
return {
|
|
71
|
+
error: "cursors must be a JSON object of channel IDs to timestamps",
|
|
72
|
+
};
|
|
24
73
|
}
|
|
25
74
|
|
|
26
75
|
async function requireSlackCredential(event: H3Event, workspace: Workspace) {
|
|
@@ -34,6 +83,7 @@ export const handleSlackTeam = defineEventHandler((event) =>
|
|
|
34
83
|
try {
|
|
35
84
|
const { workspace: workspaceParam } = getQuery(event);
|
|
36
85
|
const workspace = parseWorkspace(workspaceParam as string);
|
|
86
|
+
if (!workspace) return invalidWorkspace(event);
|
|
37
87
|
const missing = await requireSlackCredential(event, workspace);
|
|
38
88
|
if (missing) return missing;
|
|
39
89
|
const team = await getTeamInfo(workspace);
|
|
@@ -51,6 +101,7 @@ export const handleSlackChannels = defineEventHandler((event) =>
|
|
|
51
101
|
try {
|
|
52
102
|
const { workspace: workspaceParam, cursor } = getQuery(event);
|
|
53
103
|
const workspace = parseWorkspace(workspaceParam as string);
|
|
104
|
+
if (!workspace) return invalidWorkspace(event);
|
|
54
105
|
const missing = await requireSlackCredential(event, workspace);
|
|
55
106
|
if (missing) return missing;
|
|
56
107
|
const result = await listChannelsWithCoverage(
|
|
@@ -102,6 +153,7 @@ export const handleSlackHistory = defineEventHandler((event) =>
|
|
|
102
153
|
cursor,
|
|
103
154
|
} = getQuery(event);
|
|
104
155
|
const workspace = parseWorkspace(workspaceParam as string);
|
|
156
|
+
if (!workspace) return invalidWorkspace(event);
|
|
105
157
|
const missing = await requireSlackCredential(event, workspace);
|
|
106
158
|
if (missing) return missing;
|
|
107
159
|
const limit = parseInt((limitParam as string) || "50", 10);
|
|
@@ -174,6 +226,7 @@ export const handleSlackMultiHistory = defineEventHandler((event) =>
|
|
|
174
226
|
cursors: cursorsParam,
|
|
175
227
|
} = getQuery(event);
|
|
176
228
|
const workspace = parseWorkspace(workspaceParam as string);
|
|
229
|
+
if (!workspace) return invalidWorkspace(event);
|
|
177
230
|
const missing = await requireSlackCredential(event, workspace);
|
|
178
231
|
if (missing) return missing;
|
|
179
232
|
// cursors is a JSON-encoded object: { channelId: timestamp }
|
|
@@ -188,9 +241,9 @@ export const handleSlackMultiHistory = defineEventHandler((event) =>
|
|
|
188
241
|
const channelNamesList = namesParam
|
|
189
242
|
? (namesParam as string).split(",")
|
|
190
243
|
: channelIds;
|
|
191
|
-
const
|
|
192
|
-
|
|
193
|
-
|
|
244
|
+
const parsedCursors = parseCursorMap(cursorsParam);
|
|
245
|
+
if (!parsedCursors.ok) return invalidCursors(event);
|
|
246
|
+
const cursors = parsedCursors.value;
|
|
194
247
|
|
|
195
248
|
// Fetch pageSize messages from each channel in parallel while preserving
|
|
196
249
|
// partial results when the bot is not invited to one of the channels.
|
|
@@ -358,6 +411,7 @@ export const handleSlackSearch = defineEventHandler((event) =>
|
|
|
358
411
|
try {
|
|
359
412
|
const { workspace: workspaceParam, query } = getQuery(event);
|
|
360
413
|
const workspace = parseWorkspace(workspaceParam as string);
|
|
414
|
+
if (!workspace) return invalidWorkspace(event);
|
|
361
415
|
const missing = await requireSlackCredential(event, workspace);
|
|
362
416
|
if (missing) return missing;
|
|
363
417
|
|
|
@@ -69,15 +69,20 @@ async function resolveOrgRole(
|
|
|
69
69
|
userEmail: string,
|
|
70
70
|
orgId: string,
|
|
71
71
|
): Promise<string | null> {
|
|
72
|
-
|
|
73
|
-
|
|
72
|
+
// A failed lookup must never collapse into "no role": that reads downstream as
|
|
73
|
+
// a denial and 403s org owners whenever the database is briefly unreachable.
|
|
74
|
+
const { rows } = await getDbExec()
|
|
75
|
+
.execute({
|
|
74
76
|
sql: `SELECT role FROM org_members WHERE org_id = ? AND LOWER(email) = ? LIMIT 1`,
|
|
75
77
|
args: [orgId, userEmail.toLowerCase()],
|
|
78
|
+
})
|
|
79
|
+
.catch((error: unknown) => {
|
|
80
|
+
throw new DbAdminConnectionError(
|
|
81
|
+
503,
|
|
82
|
+
`Couldn't verify your organization role: ${redactDbAdminError(error)}`,
|
|
83
|
+
);
|
|
76
84
|
});
|
|
77
|
-
|
|
78
|
-
} catch {
|
|
79
|
-
return null;
|
|
80
|
-
}
|
|
85
|
+
return readString((rows[0] ?? {}) as Record<string, unknown>, "role");
|
|
81
86
|
}
|
|
82
87
|
|
|
83
88
|
export async function requireAnalyticsAdminContext(input?: {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getDbExec } from "@agent-native/core/db";
|
|
1
|
+
import { getDbExec, isPostgres } from "@agent-native/core/db";
|
|
2
2
|
import { runWithRequestContext } from "@agent-native/core/server";
|
|
3
3
|
import { and, eq, isNull, lt, or } from "drizzle-orm";
|
|
4
4
|
|
|
@@ -1072,6 +1072,130 @@ export function scopedAnalyticsSql(
|
|
|
1072
1072
|
return { sql: rewritten, args };
|
|
1073
1073
|
}
|
|
1074
1074
|
|
|
1075
|
+
/**
|
|
1076
|
+
* Dashboard panel SQL (seeded and agent/user-authored) is written against
|
|
1077
|
+
* PostgreSQL date/JSON syntax — `to_char`/`INTERVAL`/`::date`/`::jsonb ->>` —
|
|
1078
|
+
* because that's the dialect this app runs against in production. A local
|
|
1079
|
+
* SQLite dev database doesn't understand any of that and throws a syntax
|
|
1080
|
+
* error before a row is ever read. Rather than hand-rewrite every seeded
|
|
1081
|
+
* panel's SQL (this app also lets the agent/UI author new first-party SQL
|
|
1082
|
+
* panels through this exact same execution path), translate the handful of
|
|
1083
|
+
* Postgres-only shapes this query surface actually produces into SQLite
|
|
1084
|
+
* equivalents right here at the execution boundary. PostgreSQL SQL is never
|
|
1085
|
+
* touched: this only runs when the active database is not Postgres.
|
|
1086
|
+
*/
|
|
1087
|
+
export function toSqliteCompatibleFirstPartySql(sql: string): string {
|
|
1088
|
+
let out = sql;
|
|
1089
|
+
|
|
1090
|
+
// properties::jsonb ->> 'key' -> json_extract(properties, '$."key"')
|
|
1091
|
+
// (a quoted JSON path member tolerates keys like "$ai_model" that start
|
|
1092
|
+
// with a character SQLite's unquoted path syntax can't lead with).
|
|
1093
|
+
out = out.replace(
|
|
1094
|
+
/([A-Za-z_][A-Za-z0-9_.]*)::jsonb\s*->>\s*'([^']*)'/g,
|
|
1095
|
+
(_match, column: string, key: string) =>
|
|
1096
|
+
`json_extract(${column}, '$."${key}"')`,
|
|
1097
|
+
);
|
|
1098
|
+
|
|
1099
|
+
// Postgres chr(N) -> SQLite char(N).
|
|
1100
|
+
out = out.replace(/\bchr\(/g, "char(");
|
|
1101
|
+
|
|
1102
|
+
// Any other Postgres type cast (::date, ::float, ::timestamptz, ...) is a
|
|
1103
|
+
// no-op on SQLite's dynamically-typed columns.
|
|
1104
|
+
out = out.replace(/::[A-Za-z_][A-Za-z0-9_]*/g, "");
|
|
1105
|
+
|
|
1106
|
+
// to_char(date_trunc('week', X), 'YYYY-MM-DD') -> Monday of X's week.
|
|
1107
|
+
// ('weekday 0' finds the next Sunday, '-6 days' steps back to that week's
|
|
1108
|
+
// Monday, matching Postgres's ISO week truncation.)
|
|
1109
|
+
out = out.replace(
|
|
1110
|
+
/to_char\(\s*date_trunc\(\s*'week'\s*,\s*([^()]+?)\s*\)\s*,\s*'YYYY-MM-DD'\s*\)/g,
|
|
1111
|
+
(_match, expr: string) => `date(${expr}, 'weekday 0', '-6 days')`,
|
|
1112
|
+
);
|
|
1113
|
+
|
|
1114
|
+
// <dateish-expr> (+|-) INTERVAL 'N days' -> the same day count applied
|
|
1115
|
+
// through SQLite's julian-day arithmetic, immediately reformatted back to
|
|
1116
|
+
// 'YYYY-MM-DD' text. Re-wrapping right away (instead of leaving a bare
|
|
1117
|
+
// julian-day number) matters: this expression sometimes appears outside
|
|
1118
|
+
// any to_char() call, compared directly against a text date column, and
|
|
1119
|
+
// SQLite treats any numeric value as less than any text value — a bare
|
|
1120
|
+
// number here would make that comparison silently always-true.
|
|
1121
|
+
out = out.replace(
|
|
1122
|
+
/([A-Za-z_][A-Za-z0-9_.]*|CURRENT_DATE)\s*(\+|-)\s*INTERVAL\s*'(\d+)\s*days?'/g,
|
|
1123
|
+
(_match, base: string, op: string, days: string) => {
|
|
1124
|
+
const juliandayBase = base === "CURRENT_DATE" ? "'now'" : base;
|
|
1125
|
+
return `date(julianday(${juliandayBase}) ${op} ${days})`;
|
|
1126
|
+
},
|
|
1127
|
+
);
|
|
1128
|
+
|
|
1129
|
+
// <dateish-expr ending in "date"> (+|-) <identifier> (no INTERVAL
|
|
1130
|
+
// keyword) — e.g. `bounds.start_date + offsets.n` in a generated date
|
|
1131
|
+
// series. Scoped to identifiers ending in "date" so unrelated integer
|
|
1132
|
+
// arithmetic (e.g. building the offsets themselves) is left alone.
|
|
1133
|
+
out = out.replace(
|
|
1134
|
+
/([A-Za-z_][A-Za-z0-9_.]*date)\s*(\+|-)\s*([A-Za-z_][A-Za-z0-9_.]*)/g,
|
|
1135
|
+
(_match, base: string, op: string, rhs: string) =>
|
|
1136
|
+
`date(julianday(${base}) ${op} ${rhs})`,
|
|
1137
|
+
);
|
|
1138
|
+
|
|
1139
|
+
// Every surviving to_char(expr, 'YYYY-MM-DD') now wraps an expr that
|
|
1140
|
+
// already evaluates to 'YYYY-MM-DD' text (a bare CURRENT_DATE, or one of
|
|
1141
|
+
// the date(...) forms produced above) — unwrap the call instead of
|
|
1142
|
+
// re-wrapping it. A regex can't balance the arbitrarily nested parens
|
|
1143
|
+
// `date(julianday(...) ...)` can produce, so walk the string instead.
|
|
1144
|
+
out = unwrapPostgresToChar(out);
|
|
1145
|
+
|
|
1146
|
+
return out;
|
|
1147
|
+
}
|
|
1148
|
+
|
|
1149
|
+
/**
|
|
1150
|
+
* Finds each top-level `to_char(expr, 'YYYY-MM-DD')` call and replaces it
|
|
1151
|
+
* with `expr` alone. Balances parens by hand rather than by regex so nested
|
|
1152
|
+
* calls (`date(julianday(...) - 7)`) unwrap correctly regardless of depth.
|
|
1153
|
+
*/
|
|
1154
|
+
function unwrapPostgresToChar(sql: string): string {
|
|
1155
|
+
const marker = "to_char(";
|
|
1156
|
+
let out = "";
|
|
1157
|
+
let i = 0;
|
|
1158
|
+
while (i < sql.length) {
|
|
1159
|
+
const idx = sql.indexOf(marker, i);
|
|
1160
|
+
if (idx === -1) {
|
|
1161
|
+
out += sql.slice(i);
|
|
1162
|
+
break;
|
|
1163
|
+
}
|
|
1164
|
+
out += sql.slice(i, idx);
|
|
1165
|
+
const openParen = idx + marker.length - 1;
|
|
1166
|
+
let depth = 0;
|
|
1167
|
+
let closeParen = openParen;
|
|
1168
|
+
for (; closeParen < sql.length; closeParen++) {
|
|
1169
|
+
if (sql[closeParen] === "(") depth++;
|
|
1170
|
+
else if (sql[closeParen] === ")") {
|
|
1171
|
+
depth--;
|
|
1172
|
+
if (depth === 0) break;
|
|
1173
|
+
}
|
|
1174
|
+
}
|
|
1175
|
+
const inner = sql.slice(openParen + 1, closeParen);
|
|
1176
|
+
let innerDepth = 0;
|
|
1177
|
+
let topLevelCommaIdx = -1;
|
|
1178
|
+
for (let k = 0; k < inner.length; k++) {
|
|
1179
|
+
if (inner[k] === "(") innerDepth++;
|
|
1180
|
+
else if (inner[k] === ")") innerDepth--;
|
|
1181
|
+
else if (inner[k] === "," && innerDepth === 0) topLevelCommaIdx = k;
|
|
1182
|
+
}
|
|
1183
|
+
const expr =
|
|
1184
|
+
topLevelCommaIdx === -1 ? inner : inner.slice(0, topLevelCommaIdx);
|
|
1185
|
+
const format =
|
|
1186
|
+
topLevelCommaIdx === -1 ? "" : inner.slice(topLevelCommaIdx + 1).trim();
|
|
1187
|
+
if (format === "'YYYY-MM-DD'") {
|
|
1188
|
+
out += expr.trim();
|
|
1189
|
+
} else {
|
|
1190
|
+
// Not the to_char(expr, 'YYYY-MM-DD') shape this app's SQL uses;
|
|
1191
|
+
// leave it untouched rather than guess at unfamiliar formats.
|
|
1192
|
+
out += sql.slice(idx, closeParen + 1);
|
|
1193
|
+
}
|
|
1194
|
+
i = closeParen + 1;
|
|
1195
|
+
}
|
|
1196
|
+
return out;
|
|
1197
|
+
}
|
|
1198
|
+
|
|
1075
1199
|
function valueType(value: unknown): string {
|
|
1076
1200
|
if (typeof value === "number") return "number";
|
|
1077
1201
|
if (typeof value === "boolean") return "boolean";
|
|
@@ -1141,7 +1265,13 @@ export async function queryFirstPartyAnalytics(
|
|
|
1141
1265
|
return queryFirstPartyAnalyticsInBigQuery(scoped.sql, scoped.args, table);
|
|
1142
1266
|
}
|
|
1143
1267
|
const scoped = scopedAnalyticsSql(sql, scope);
|
|
1144
|
-
|
|
1268
|
+
// Dashboard SQL is authored against Postgres date/JSON syntax; translate
|
|
1269
|
+
// it for a non-Postgres sql-store (local SQLite dev) at the last possible
|
|
1270
|
+
// moment so Postgres itself never sees a rewritten query.
|
|
1271
|
+
const dialectSql = isPostgres()
|
|
1272
|
+
? scoped.sql
|
|
1273
|
+
: toSqliteCompatibleFirstPartySql(scoped.sql);
|
|
1274
|
+
const wrappedSql = `SELECT * FROM (${dialectSql}) AS first_party_analytics_query LIMIT ${MAX_QUERY_ROWS}`;
|
|
1145
1275
|
const timeoutMs = Math.max(
|
|
1146
1276
|
1,
|
|
1147
1277
|
options.timeoutMs ?? FIRST_PARTY_ANALYTICS_QUERY_TIMEOUT_MS,
|
|
@@ -286,10 +286,13 @@ function looksLikeWorkflowOrAutomationRequest(lower: string): boolean {
|
|
|
286
286
|
}
|
|
287
287
|
|
|
288
288
|
const ANALYTICS_RESULT_TERMS =
|
|
289
|
-
/\b(conversion|conversions|funnel|revenue|payment|payments|traffic|pageviews?|signups?|events?|active users?|sessions?|retention|churn|pipeline|deals?|calls?|transcripts?|sentiment|themes?|objections?|cohorts?|segments?|accounts?|customers?|tickets?|issues?|leads?|opportunities|mrr|arr|ctr|cvr|cac|ltv)\b/;
|
|
289
|
+
/\b(conversion|conversions|funnel|revenue|payment|payments|traffic|pageviews?|signups?|events?|active users?|sessions?|retention|churn|pipeline|deals?|calls?|transcripts?|sentiment|themes?|objections?|cohorts?|segments?|accounts?|customers?|tickets?|issues?|leads?|opportunities|usage|adoption|ai credits?|credit consumption|credits? consumed|allowance|quota|mrr|arr|ctr|cvr|cac|ltv)\b/;
|
|
290
|
+
|
|
291
|
+
const ANALYTICS_DOMAIN_ENTITY_TERMS =
|
|
292
|
+
/\b(?:branch(?:es)?|branch creation|created by|creator identity)\b/;
|
|
290
293
|
|
|
291
294
|
const ANALYTICS_INTENT_TERMS =
|
|
292
|
-
/\b(analy[sz]e|measure|calculate|query|report|summari[sz]e|break ?down|compare|rank|segment|forecast|trend|count|total|average|median|percent(?:age)?|rate|top|bottom|highest|lowest|how many|how much|what (?:is|are|was|were)|which|why)\b/;
|
|
295
|
+
/\b(analy[sz]e|measure|calculate|query|report|summari[sz]e|break ?down|compare|rank|segment|forecast|trend|count|total|average|median|percent(?:age)?|rate|top|bottom|highest|lowest|pull|fetch|retrieve|export|show|how many|how much|what (?:is|are|was|were)|which|why)\b/;
|
|
293
296
|
|
|
294
297
|
const SOURCE_SEARCH_INTENT_TERMS =
|
|
295
298
|
/\b(find|surface|search|scan|grep|review|inspect|check|look through|go find)\b/;
|
|
@@ -308,7 +311,7 @@ const ARTIFACT_DATA_INTENT =
|
|
|
308
311
|
// a live provider data call. They should be answered from the data dictionary,
|
|
309
312
|
// schema introspection tools, or the agent's knowledge of configured sources.
|
|
310
313
|
const METADATA_ONLY_TERMS =
|
|
311
|
-
/\b(what (?:tables?|columns?|fields?|sources?|datasets?|metrics?|schema) (?:are|is|exist|available|do (?:we|you|i) have)|which (?:sources?|tables?|providers?|integrations?) (?:are|is) (?:connected|configured|available|set up)|list (?:the )?(?:tables?|columns?|fields?|sources?|datasets?|schemas?)|show (?:me )?(?:available|the) (?:sources?|tables?|schemas?)|what does .+ (?:mean|measure|represent|track)|how is .+ (?:defined|calculated|computed|measured)|definition of|describe (?:the )?(?:\w+\s+)?(?:table|column|schema|metric|field)|list (?:the )?columns?\s+in|what (?:is|are) (?:the )?(?:data (?:dictionary|schema)|available (?:sources?|tables?))|what (?:source|provider|table) (?:has|stores|contains))\b/;
|
|
314
|
+
/\b(what (?:tables?|columns?|fields?|sources?|datasets?|metrics?|schema) (?:are|is|exist|available|do (?:we|you|i) have)|which (?:sources?|tables?|providers?|integrations?) (?:are|is) (?:connected|configured|available|set up)|list (?:the )?(?:tables?|columns?|fields?|sources?|datasets?|schemas?)|show (?:me )?(?:available|the) (?:data )?(?:sources?|tables?|schemas?)|what does .+ (?:mean|measure|represent|track)|how is .+ (?:defined|calculated|computed|measured)|definition of|describe (?:the )?(?:\w+\s+)?(?:table|column|schema|metric|field)|list (?:the )?columns?\s+in|what (?:is|are) (?:the )?(?:data (?:dictionary|schema)|available (?:data )?(?:sources?|tables?))|what (?:source|provider|table) (?:has|stores|contains))\b/;
|
|
312
315
|
|
|
313
316
|
export function looksLikeAnalyticsDataRequest(text: string): boolean {
|
|
314
317
|
const requestText = stripInjectedAnalyticsGuardContext(text);
|
|
@@ -350,6 +353,14 @@ export function looksLikeAnalyticsDataRequest(text: string): boolean {
|
|
|
350
353
|
if (METADATA_ONLY_TERMS.test(lower)) return false;
|
|
351
354
|
|
|
352
355
|
if (ANALYTICS_RESULT_TERMS.test(lower)) return true;
|
|
356
|
+
if (
|
|
357
|
+
ANALYTICS_DOMAIN_ENTITY_TERMS.test(lower) &&
|
|
358
|
+
(ANALYTICS_INTENT_TERMS.test(lower) ||
|
|
359
|
+
SOURCE_SEARCH_INTENT_TERMS.test(lower) ||
|
|
360
|
+
/\bdata\b/.test(lower))
|
|
361
|
+
) {
|
|
362
|
+
return true;
|
|
363
|
+
}
|
|
353
364
|
if (
|
|
354
365
|
ANALYTICS_INTENT_TERMS.test(lower) &&
|
|
355
366
|
/\b(data|source|table|sql)\b/.test(lower)
|