@agent-native/core 0.169.1 → 0.171.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/query-agent-native-analytics.ts +1 -1
- package/corpus/templates/analytics/app/i18n-data.ts +28 -0
- package/corpus/templates/analytics/app/pages/Agents.tsx +25 -1
- 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-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/slack.ts +4 -2
- 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/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/view-screen.ts +8 -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 +1383 -88
- 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/MultiScreenCanvas.tsx +284 -136
- package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +2057 -141
- 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 -1
- 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 +11 -4
- package/corpus/templates/design/app/i18n-data.ts +1 -0
- 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 +77 -35
- package/corpus/templates/design/app/pages/DesignSystems.tsx +136 -42
- package/corpus/templates/design/app/pages/Index.tsx +2 -0
- 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/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-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/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/auth.d.ts +1 -0
- package/dist/app-config/auth.js +7 -0
- 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 +17 -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/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-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/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/resources/mcp-integration-catalog.js +0 -29
- 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/collab/routes.d.ts +1 -1
- 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 +19 -0
- package/dist/deploy/build.js +190 -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/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 +3 -0
- package/dist/localization/core-messages/de-DE.js +3 -0
- package/dist/localization/core-messages/en-US.d.ts +3 -0
- package/dist/localization/core-messages/en-US.js +3 -0
- package/dist/localization/core-messages/es-ES.js +3 -0
- package/dist/localization/core-messages/fr-FR.js +3 -0
- package/dist/localization/core-messages/hi-IN.js +3 -0
- package/dist/localization/core-messages/ja-JP.js +3 -0
- package/dist/localization/core-messages/ko-KR.js +3 -0
- package/dist/localization/core-messages/pt-BR.js +3 -0
- package/dist/localization/core-messages/zh-CN.js +3 -0
- package/dist/localization/core-messages/zh-TW.js +3 -0
- package/dist/localization/core-messages.d.ts +3 -0
- 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/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 +1 -1
- package/dist/provider-api/actions/provider-api.d.ts +2 -2
- package/dist/provider-api/index.js +2 -0
- package/dist/resources/handlers.d.ts +2 -2
- package/dist/resources/store.js +13 -4
- package/dist/scripts/agent-engines/list-agent-engines.js +29 -3
- package/dist/secrets/register-framework-secrets.js +1 -1
- 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 +37 -7
- 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 +100 -20
- 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/realtime-token.d.ts +1 -1
- 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 +33 -7
- package/docs/content/actions-access-control.mdx +43 -4
- package/docs/content/actions-defining.mdx +16 -0
- package/docs/content/authentication.mdx +40 -21
- package/docs/content/environment-variables.mdx +1 -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 +2 -2
- 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
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
AGENT_NATIVE_SOCIAL_IMAGE_HEIGHT,
|
|
6
6
|
AGENT_NATIVE_SOCIAL_IMAGE_TYPE,
|
|
7
7
|
AGENT_NATIVE_SOCIAL_IMAGE_WIDTH,
|
|
8
|
+
SSR_QUERY_CACHE_KEY_HEADER,
|
|
8
9
|
withAgentNativeSocialImageCacheBuster,
|
|
9
10
|
} from "@agent-native/core/shared";
|
|
10
11
|
import { eq } from "drizzle-orm";
|
|
@@ -321,6 +322,7 @@ export async function renderPublicForm(event: H3Event) {
|
|
|
321
322
|
// short-fresh/long-SWR policy as React Router SSR. Keep all cache headers
|
|
322
323
|
// here; relying on provider config would make templates perform differently.
|
|
323
324
|
Object.assign(headers, resolveSsrCacheHeaders());
|
|
325
|
+
headers[SSR_QUERY_CACHE_KEY_HEADER] = "query";
|
|
324
326
|
}
|
|
325
327
|
return new Response(getMethod(event) === "HEAD" ? null : html, {
|
|
326
328
|
status,
|
|
@@ -472,7 +474,15 @@ function renderFormPage(
|
|
|
472
474
|
|
|
473
475
|
function revalidateFormVersion() {
|
|
474
476
|
fetch(PUBLIC_FORM_API, { cache: "no-store" })
|
|
475
|
-
.then(function(response) {
|
|
477
|
+
.then(function(response) {
|
|
478
|
+
if (response.status === 404) {
|
|
479
|
+
var currentUrl = new URL(window.location.href);
|
|
480
|
+
currentUrl.searchParams.set("v", String(Date.now()));
|
|
481
|
+
window.location.replace(currentUrl.toString());
|
|
482
|
+
return null;
|
|
483
|
+
}
|
|
484
|
+
return response.ok ? response.json() : null;
|
|
485
|
+
})
|
|
476
486
|
.then(function(latest) {
|
|
477
487
|
if (!latest || typeof latest.updatedAt !== "string" || !latest.updatedAt || latest.updatedAt === FORM_VERSION) return;
|
|
478
488
|
var currentUrl = new URL(window.location.href);
|
|
@@ -19,10 +19,17 @@ data, and generated extension/app content may mention credential **names** such
|
|
|
19
19
|
as `OPENAI_API_KEY`, but must not contain real API keys, tokens, webhook URLs,
|
|
20
20
|
signing secrets, OAuth refresh tokens, or private Builder/customer data.
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
`${keys.NAME}` substitution.
|
|
25
|
-
|
|
22
|
+
Provider secret values are supplied at runtime through the encrypted
|
|
23
|
+
`app_secrets` vault, `saveCredential` / `resolveCredential`, OAuth, or
|
|
24
|
+
`${keys.NAME}` substitution. Deployment configuration is reserved for
|
|
25
|
+
deploy-level secrets and non-provider configuration. Examples must use obvious
|
|
26
|
+
placeholders such as `<OPENAI_API_KEY>` or `${keys.SLACK_WEBHOOK}`, not
|
|
27
|
+
real-looking copied values.
|
|
28
|
+
|
|
29
|
+
Provider credentials and provider account identifiers are workspace data. Use
|
|
30
|
+
standard workspace connections and org/workspace vault scopes; never put them
|
|
31
|
+
in `.env` or deployment environment variables, and never add a provider-specific
|
|
32
|
+
action or startup bootstrap just to write a credential for one organization.
|
|
26
33
|
|
|
27
34
|
## Credential Modeling Preflight
|
|
28
35
|
|
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
import type { RouteConfig } from "@react-router/dev/routes";
|
|
2
2
|
import { flatRoutes } from "@react-router/fs-routes";
|
|
3
|
-
export default flatRoutes(
|
|
3
|
+
export default flatRoutes({
|
|
4
|
+
ignoredRouteFiles: ["**/*.test.{ts,tsx}", "**/*.spec.{ts,tsx}"],
|
|
5
|
+
}) satisfies RouteConfig;
|
|
@@ -14,7 +14,12 @@ export default mergeConfig(
|
|
|
14
14
|
},
|
|
15
15
|
test: {
|
|
16
16
|
include: ["**/*.{test,spec}.?(c|m)[jt]s?(x)"],
|
|
17
|
-
exclude: [
|
|
17
|
+
exclude: [
|
|
18
|
+
"**/node_modules/**",
|
|
19
|
+
"**/.git/**",
|
|
20
|
+
"**/dist/**",
|
|
21
|
+
"**/.react-router/**",
|
|
22
|
+
],
|
|
18
23
|
},
|
|
19
24
|
}),
|
|
20
25
|
);
|
|
@@ -19,10 +19,17 @@ data, and generated extension/app content may mention credential **names** such
|
|
|
19
19
|
as `OPENAI_API_KEY`, but must not contain real API keys, tokens, webhook URLs,
|
|
20
20
|
signing secrets, OAuth refresh tokens, or private Builder/customer data.
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
`${keys.NAME}` substitution.
|
|
25
|
-
|
|
22
|
+
Provider secret values are supplied at runtime through the encrypted
|
|
23
|
+
`app_secrets` vault, `saveCredential` / `resolveCredential`, OAuth, or
|
|
24
|
+
`${keys.NAME}` substitution. Deployment configuration is reserved for
|
|
25
|
+
deploy-level secrets and non-provider configuration. Examples must use obvious
|
|
26
|
+
placeholders such as `<OPENAI_API_KEY>` or `${keys.SLACK_WEBHOOK}`, not
|
|
27
|
+
real-looking copied values.
|
|
28
|
+
|
|
29
|
+
Provider credentials and provider account identifiers are workspace data. Use
|
|
30
|
+
standard workspace connections and org/workspace vault scopes; never put them
|
|
31
|
+
in `.env` or deployment environment variables, and never add a provider-specific
|
|
32
|
+
action or startup bootstrap just to write a credential for one organization.
|
|
26
33
|
|
|
27
34
|
## Credential Modeling Preflight
|
|
28
35
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { defineAction } from "@agent-native/core";
|
|
1
|
+
import { ActionContractError, defineAction } from "@agent-native/core";
|
|
2
2
|
import { writeAppState } from "@agent-native/core/application-state";
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
|
|
@@ -499,7 +499,15 @@ function accountLabel(account: ConnectedAccount) {
|
|
|
499
499
|
async function allAccounts(): Promise<ConnectedAccount[]> {
|
|
500
500
|
const accounts = await getAccessTokens();
|
|
501
501
|
if (accounts.length === 0) {
|
|
502
|
-
|
|
502
|
+
// A plain Error has no statusCode, so action-routes.ts can't tell this
|
|
503
|
+
// deterministic, caller-correctable precondition apart from a real server
|
|
504
|
+
// fault — it collapses to a 500 and the specific message never reaches
|
|
505
|
+
// the UI. ActionContractError carries an explicit sub-500 statusCode the
|
|
506
|
+
// route treats as user-facing and echoes as-is.
|
|
507
|
+
throw new ActionContractError(
|
|
508
|
+
"No Google account connected. Connect Gmail first.",
|
|
509
|
+
{ errorCode: "GOOGLE_ACCOUNT_NOT_CONNECTED", statusCode: 400 },
|
|
510
|
+
);
|
|
503
511
|
}
|
|
504
512
|
return accounts;
|
|
505
513
|
}
|
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
oauthRedirectUri,
|
|
5
5
|
} from "@agent-native/core/client/host";
|
|
6
6
|
import { useT } from "@agent-native/core/client/i18n";
|
|
7
|
+
import { startWorkspaceProviderOAuth } from "@agent-native/core/client/integrations";
|
|
7
8
|
import {
|
|
8
9
|
IconMail,
|
|
9
10
|
IconX,
|
|
@@ -25,6 +26,7 @@ import {
|
|
|
25
26
|
useGoogleAddAccountUrl,
|
|
26
27
|
useDisconnectGoogle,
|
|
27
28
|
} from "@/hooks/use-google-auth";
|
|
29
|
+
import { shouldOfferGoogleOAuthSetup } from "@/lib/google-oauth-setup";
|
|
28
30
|
|
|
29
31
|
interface EnvKeyStatus {
|
|
30
32
|
key: string;
|
|
@@ -76,6 +78,15 @@ const ADD_ACCOUNT_POLL_ABORT_MS = Math.max(
|
|
|
76
78
|
ADD_ACCOUNT_POLL_INTERVAL_MS * 4,
|
|
77
79
|
);
|
|
78
80
|
|
|
81
|
+
function startManagedGoogleOAuth(): void {
|
|
82
|
+
const returnPath = `${window.location.pathname}${window.location.search}`;
|
|
83
|
+
startWorkspaceProviderOAuth("gmail", {
|
|
84
|
+
appId: "mail",
|
|
85
|
+
returnPath,
|
|
86
|
+
scope: "user",
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
|
|
79
90
|
function newDesktopOAuthVerifier(): string | null {
|
|
80
91
|
const cryptoApi = globalThis.crypto;
|
|
81
92
|
const randomUuid = cryptoApi?.randomUUID;
|
|
@@ -125,6 +136,8 @@ export function GoogleConnectBanner({
|
|
|
125
136
|
|
|
126
137
|
const accounts = googleStatus.data?.accounts ?? [];
|
|
127
138
|
const hasAccounts = accounts.length > 0;
|
|
139
|
+
const googleConfigured = googleStatus.data?.configured === true;
|
|
140
|
+
const canOfferOAuthSetup = useMemo(() => shouldOfferGoogleOAuthSetup(), []);
|
|
128
141
|
|
|
129
142
|
const isBuilderFrame = useMemo(() => isInBuilderFrame(), []);
|
|
130
143
|
const useDesktopAuth = useMemo(
|
|
@@ -336,13 +349,15 @@ export function GoogleConnectBanner({
|
|
|
336
349
|
useEffect(() => {
|
|
337
350
|
if (authUrl.error) {
|
|
338
351
|
setWantAuthUrl(false);
|
|
339
|
-
|
|
340
|
-
|
|
352
|
+
if (canOfferOAuthSetup) {
|
|
353
|
+
setShowWizard(true);
|
|
354
|
+
fetchStatus();
|
|
355
|
+
}
|
|
341
356
|
setAuthError(
|
|
342
357
|
(authUrl.error as any)?.message || t("mail.error.failedToConnect"),
|
|
343
358
|
);
|
|
344
359
|
}
|
|
345
|
-
}, [authUrl.error, fetchStatus]);
|
|
360
|
+
}, [authUrl.error, canOfferOAuthSetup, fetchStatus]);
|
|
346
361
|
|
|
347
362
|
const allConfigured =
|
|
348
363
|
envStatus.length > 0 && envStatus.every((k) => k.configured);
|
|
@@ -419,20 +434,22 @@ export function GoogleConnectBanner({
|
|
|
419
434
|
}, [wantAddAccount, addAccountUrl.data, isBuilderFrame]);
|
|
420
435
|
|
|
421
436
|
function handleConnect() {
|
|
437
|
+
if (!googleConfigured && !canOfferOAuthSetup) return;
|
|
422
438
|
setDesktopAuthIssue(null);
|
|
423
439
|
if (useDesktopAuth) {
|
|
424
440
|
signInViaDesktopBrowser();
|
|
425
441
|
return;
|
|
426
442
|
}
|
|
427
|
-
|
|
443
|
+
startManagedGoogleOAuth();
|
|
428
444
|
}
|
|
429
445
|
|
|
430
446
|
function handleAddAccount() {
|
|
447
|
+
if (!googleConfigured && !canOfferOAuthSetup) return;
|
|
431
448
|
if (useDesktopAuth) {
|
|
432
449
|
signInViaDesktopBrowser(true);
|
|
433
450
|
return;
|
|
434
451
|
}
|
|
435
|
-
|
|
452
|
+
startManagedGoogleOAuth();
|
|
436
453
|
}
|
|
437
454
|
|
|
438
455
|
async function handleJsonUpload(file: File) {
|
|
@@ -489,6 +506,15 @@ export function GoogleConnectBanner({
|
|
|
489
506
|
}
|
|
490
507
|
|
|
491
508
|
if (dismissed) return null;
|
|
509
|
+
if (!googleStatus.data && !canOfferOAuthSetup && !googleStatus.isError)
|
|
510
|
+
return null;
|
|
511
|
+
if (
|
|
512
|
+
!googleConfigured &&
|
|
513
|
+
!canOfferOAuthSetup &&
|
|
514
|
+
!hasAccounts &&
|
|
515
|
+
!googleStatus.isError
|
|
516
|
+
)
|
|
517
|
+
return null;
|
|
492
518
|
|
|
493
519
|
// Full-page hero for setup / reconnection
|
|
494
520
|
if (variant === "hero") {
|
|
@@ -503,22 +529,34 @@ export function GoogleConnectBanner({
|
|
|
503
529
|
<p className="mt-2 max-w-sm text-sm text-muted-foreground leading-relaxed">
|
|
504
530
|
{t("mail.googleConnect.heroDescription")}
|
|
505
531
|
</p>
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
532
|
+
{googleStatus.isError ? (
|
|
533
|
+
<Button
|
|
534
|
+
size="sm"
|
|
535
|
+
variant="outline"
|
|
536
|
+
className="mt-8 gap-2 px-5 h-9 text-sm font-medium"
|
|
537
|
+
onClick={() => void googleStatus.refetch()}
|
|
538
|
+
disabled={googleStatus.isFetching}
|
|
539
|
+
>
|
|
540
|
+
{t("mail.error.tryAgain")}
|
|
541
|
+
</Button>
|
|
542
|
+
) : googleConfigured || canOfferOAuthSetup ? (
|
|
543
|
+
<Button
|
|
544
|
+
size="sm"
|
|
545
|
+
className="mt-8 gap-2 px-5 h-9 text-sm font-medium bg-primary text-primary-foreground hover:bg-primary/90"
|
|
546
|
+
onClick={() => {
|
|
547
|
+
setAuthError(null);
|
|
548
|
+
handleConnect();
|
|
549
|
+
}}
|
|
550
|
+
disabled={authUrl.isLoading || authUrl.isFetching}
|
|
551
|
+
>
|
|
552
|
+
<GoogleIcon className="h-4 w-4" />
|
|
553
|
+
{authUrl.isLoading
|
|
554
|
+
? t("mail.accounts.connecting")
|
|
555
|
+
: allConfigured
|
|
556
|
+
? t("mail.accounts.signInWithGoogle")
|
|
557
|
+
: t("mail.accounts.connectGoogle")}
|
|
558
|
+
</Button>
|
|
559
|
+
) : null}
|
|
522
560
|
|
|
523
561
|
<GoogleAuthIssuePanel
|
|
524
562
|
issue={desktopAuthIssue}
|
|
@@ -531,7 +569,7 @@ export function GoogleConnectBanner({
|
|
|
531
569
|
<p className="mt-3 text-xs text-red-400">{authError}</p>
|
|
532
570
|
)}
|
|
533
571
|
|
|
534
|
-
{showWizard && !allConfigured && (
|
|
572
|
+
{showWizard && !allConfigured && canOfferOAuthSetup && (
|
|
535
573
|
<div className="mt-10 w-full max-w-lg text-start">
|
|
536
574
|
<p className="text-xs text-muted-foreground mb-3">
|
|
537
575
|
{t("mail.googleConnect.setupIntro")}
|
|
@@ -711,21 +749,25 @@ export function GoogleConnectBanner({
|
|
|
711
749
|
className="group flex items-center gap-1.5 text-xs text-foreground/60"
|
|
712
750
|
>
|
|
713
751
|
<span className="truncate">{account.email}</span>
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
752
|
+
{!account.shared && (
|
|
753
|
+
<button
|
|
754
|
+
onClick={() => disconnectGoogle.mutate(account.email)}
|
|
755
|
+
className="opacity-0 group-hover:opacity-100 transition-opacity text-foreground/30 hover:text-foreground/60"
|
|
756
|
+
>
|
|
757
|
+
<IconX className="h-3 w-3" />
|
|
758
|
+
</button>
|
|
759
|
+
)}
|
|
720
760
|
</div>
|
|
721
761
|
))}
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
762
|
+
{(googleConfigured || canOfferOAuthSetup) && (
|
|
763
|
+
<button
|
|
764
|
+
onClick={handleAddAccount}
|
|
765
|
+
disabled={addAccountUrl.isLoading || addAccountUrl.isFetching}
|
|
766
|
+
className="text-xs text-foreground/40 hover:text-foreground/60 transition-colors whitespace-nowrap"
|
|
767
|
+
>
|
|
768
|
+
+ {t("mail.accounts.addAccount")}
|
|
769
|
+
</button>
|
|
770
|
+
)}
|
|
729
771
|
</div>
|
|
730
772
|
<Button
|
|
731
773
|
variant="ghost"
|
|
@@ -742,6 +784,17 @@ export function GoogleConnectBanner({
|
|
|
742
784
|
onDismiss={() => setDesktopAuthIssue(null)}
|
|
743
785
|
className="mx-4 mb-3"
|
|
744
786
|
/>
|
|
787
|
+
{googleStatus.isError && (
|
|
788
|
+
<Button
|
|
789
|
+
variant="ghost"
|
|
790
|
+
size="sm"
|
|
791
|
+
className="mx-4 mb-2"
|
|
792
|
+
onClick={() => void googleStatus.refetch()}
|
|
793
|
+
disabled={googleStatus.isFetching}
|
|
794
|
+
>
|
|
795
|
+
{t("mail.error.tryAgain")}
|
|
796
|
+
</Button>
|
|
797
|
+
)}
|
|
745
798
|
</div>
|
|
746
799
|
);
|
|
747
800
|
}
|
|
@@ -763,7 +816,17 @@ export function GoogleConnectBanner({
|
|
|
763
816
|
</div>
|
|
764
817
|
|
|
765
818
|
<div className="flex items-center gap-1.5 shrink-0">
|
|
766
|
-
{
|
|
819
|
+
{googleStatus.isError ? (
|
|
820
|
+
<Button
|
|
821
|
+
size="sm"
|
|
822
|
+
variant="outline"
|
|
823
|
+
className="gap-1.5 text-xs h-7 font-medium"
|
|
824
|
+
onClick={() => void googleStatus.refetch()}
|
|
825
|
+
disabled={googleStatus.isFetching}
|
|
826
|
+
>
|
|
827
|
+
{t("mail.error.tryAgain")}
|
|
828
|
+
</Button>
|
|
829
|
+
) : showWizard && !allConfigured && canOfferOAuthSetup ? (
|
|
767
830
|
<Button
|
|
768
831
|
size="sm"
|
|
769
832
|
variant="outline"
|
|
@@ -817,7 +880,7 @@ export function GoogleConnectBanner({
|
|
|
817
880
|
/>
|
|
818
881
|
|
|
819
882
|
{/* Inline setup wizard */}
|
|
820
|
-
{showWizard && !allConfigured && (
|
|
883
|
+
{showWizard && !allConfigured && canOfferOAuthSetup && (
|
|
821
884
|
<div className="px-4 pb-4 pt-1 max-w-2xl">
|
|
822
885
|
<p className="text-xs text-muted-foreground mb-3">
|
|
823
886
|
{t("mail.googleConnect.setupIntro")}
|
|
@@ -187,15 +187,18 @@ export function IntegrationsSidebar({
|
|
|
187
187
|
email,
|
|
188
188
|
displayName,
|
|
189
189
|
recentEmails,
|
|
190
|
+
recentEmailsError,
|
|
190
191
|
threadId,
|
|
191
192
|
focusedEmailId,
|
|
192
193
|
}: {
|
|
193
194
|
email: string;
|
|
194
195
|
displayName: string;
|
|
195
196
|
recentEmails: { id: string; subject: string }[];
|
|
197
|
+
recentEmailsError?: boolean;
|
|
196
198
|
threadId?: string;
|
|
197
199
|
focusedEmailId?: string;
|
|
198
200
|
}) {
|
|
201
|
+
const t = useT();
|
|
199
202
|
const statuses = useAllIntegrations();
|
|
200
203
|
const anyConnected =
|
|
201
204
|
statuses.apollo || statuses.hubspot || statuses.gong || statuses.pylon;
|
|
@@ -226,7 +229,16 @@ export function IntegrationsSidebar({
|
|
|
226
229
|
)}
|
|
227
230
|
|
|
228
231
|
{/* Recent emails */}
|
|
229
|
-
{
|
|
232
|
+
{recentEmailsError ? (
|
|
233
|
+
<div
|
|
234
|
+
className="mx-4 border-t border-border/30 px-0 py-3"
|
|
235
|
+
aria-live="polite"
|
|
236
|
+
>
|
|
237
|
+
<p className="text-[11px] text-muted-foreground/70">
|
|
238
|
+
{t("mail.error.loadTitle")}
|
|
239
|
+
</p>
|
|
240
|
+
</div>
|
|
241
|
+
) : recentEmails.length > 0 ? (
|
|
230
242
|
<>
|
|
231
243
|
<div className="h-px bg-border/30 mx-4" />
|
|
232
244
|
<div className="px-4 py-3">
|
|
@@ -245,7 +257,7 @@ export function IntegrationsSidebar({
|
|
|
245
257
|
))}
|
|
246
258
|
</div>
|
|
247
259
|
</>
|
|
248
|
-
)}
|
|
260
|
+
) : null}
|
|
249
261
|
|
|
250
262
|
{/* Tool extension-point slot — user-installed widgets render here */}
|
|
251
263
|
<ExtensionSlot
|
|
@@ -7,6 +7,7 @@ import { appApiPath } from "@agent-native/core/client/api-path";
|
|
|
7
7
|
import { DevDatabaseLink } from "@agent-native/core/client/db-admin";
|
|
8
8
|
import { usePerAppChatOpen } from "@agent-native/core/client/hooks";
|
|
9
9
|
import { useT } from "@agent-native/core/client/i18n";
|
|
10
|
+
import { startWorkspaceProviderOAuth } from "@agent-native/core/client/integrations";
|
|
10
11
|
import { openCommandMenu } from "@agent-native/core/client/navigation";
|
|
11
12
|
import { InvitationBanner, OrgSwitcher } from "@agent-native/core/client/org";
|
|
12
13
|
import { FeedbackButton } from "@agent-native/core/client/ui";
|
|
@@ -82,6 +83,7 @@ import {
|
|
|
82
83
|
} from "@/hooks/use-keyboard-shortcuts";
|
|
83
84
|
import { useIsMobile } from "@/hooks/use-mobile";
|
|
84
85
|
import { runUndo } from "@/hooks/use-undo";
|
|
86
|
+
import { shouldOfferGoogleOAuthSetup } from "@/lib/google-oauth-setup";
|
|
85
87
|
import {
|
|
86
88
|
OTHER_INBOX_TAB_ID,
|
|
87
89
|
OTHER_INBOX_TAB_PARAM,
|
|
@@ -91,6 +93,7 @@ import {
|
|
|
91
93
|
} from "@/lib/inbox-tabs";
|
|
92
94
|
import { isMcpEmbedSurface } from "@/lib/mcp-embed";
|
|
93
95
|
import { cn } from "@/lib/utils";
|
|
96
|
+
import { isKnownMailView } from "@/routes/$view";
|
|
94
97
|
|
|
95
98
|
import { CommandPalette } from "./CommandPalette";
|
|
96
99
|
import { useHeaderTitle, useHeaderActions } from "./HeaderActions";
|
|
@@ -328,6 +331,11 @@ function AppLayoutInner({ children }: AppLayoutProps) {
|
|
|
328
331
|
const googleStatus = useGoogleAuthStatus();
|
|
329
332
|
const accounts = googleStatus.data?.accounts ?? [];
|
|
330
333
|
const hasAccounts = accounts.length > 0;
|
|
334
|
+
const googleConfigured = googleStatus.data?.configured === true;
|
|
335
|
+
const canOfferGoogleOAuthSetup = useMemo(
|
|
336
|
+
() => shouldOfferGoogleOAuthSetup(),
|
|
337
|
+
[],
|
|
338
|
+
);
|
|
331
339
|
const googleStatusReady = !googleStatus.isLoading && !googleStatus.isError;
|
|
332
340
|
const [accountPopoverOpen, setAccountPopoverOpen] = useState(false);
|
|
333
341
|
// Account filter: which accounts' emails to show. Empty set = all accounts.
|
|
@@ -1063,18 +1071,18 @@ function AppLayoutInner({ children }: AppLayoutProps) {
|
|
|
1063
1071
|
const localCountsForKind = (kind: CountKind) =>
|
|
1064
1072
|
kind === "total" ? labelThreadCounts.total : labelThreadCounts.unread;
|
|
1065
1073
|
|
|
1066
|
-
//
|
|
1067
|
-
//
|
|
1068
|
-
//
|
|
1074
|
+
// Prefer the complete server count when Gmail provides one. Falling back to
|
|
1075
|
+
// loaded rows is useful for local/demo mail, but merging the two with
|
|
1076
|
+
// Math.max makes badges grow as more pages happen to be loaded.
|
|
1069
1077
|
const getInboxCount = (kind: CountKind) => {
|
|
1070
1078
|
const inboxLabel = resolveLabelForCount("inbox");
|
|
1071
1079
|
const countField = countFieldForKind(kind);
|
|
1072
1080
|
const localCounts = localCountsForKind(kind);
|
|
1073
|
-
const serverCount =
|
|
1074
|
-
? (inboxLabel?.[countField] ?? 0)
|
|
1075
|
-
: 0;
|
|
1081
|
+
const serverCount = inboxLabel?.[countField];
|
|
1076
1082
|
const localCount = localCounts["__inboxTotal"] ?? 0;
|
|
1077
|
-
return
|
|
1083
|
+
return typeof serverCount === "number" && useServerLabelCounts
|
|
1084
|
+
? serverCount
|
|
1085
|
+
: localCount;
|
|
1078
1086
|
};
|
|
1079
1087
|
|
|
1080
1088
|
const getOtherCount = (kind: CountKind) => {
|
|
@@ -1096,12 +1104,11 @@ function AppLayoutInner({ children }: AppLayoutProps) {
|
|
|
1096
1104
|
const localCounts = localCountsForKind(kind);
|
|
1097
1105
|
const localCount =
|
|
1098
1106
|
localCounts[viewId] ?? (label ? (localCounts[label.id] ?? 0) : 0);
|
|
1099
|
-
const serverCount =
|
|
1100
|
-
useServerLabelCounts && viewId !== "note-to-self"
|
|
1101
|
-
? (label?.[countField] ?? 0)
|
|
1102
|
-
: 0;
|
|
1103
1107
|
if (inboxPartitionTabIds.has(viewId)) return localCount;
|
|
1104
|
-
|
|
1108
|
+
const serverCount = label?.[countField];
|
|
1109
|
+
return typeof serverCount === "number" && useServerLabelCounts
|
|
1110
|
+
? serverCount
|
|
1111
|
+
: localCount;
|
|
1105
1112
|
};
|
|
1106
1113
|
const getTopBarCount = (viewId: string) => getTabCount(viewId, "total");
|
|
1107
1114
|
const getUnreadCount = (viewId: string) => getTabCount(viewId, "unread");
|
|
@@ -1494,6 +1501,7 @@ function AppLayoutInner({ children }: AppLayoutProps) {
|
|
|
1494
1501
|
>
|
|
1495
1502
|
<AccountPopover
|
|
1496
1503
|
accounts={accounts}
|
|
1504
|
+
canAddAccount={googleConfigured || canOfferGoogleOAuthSetup}
|
|
1497
1505
|
activeAccounts={activeAccounts}
|
|
1498
1506
|
onToggleAccount={(email) => {
|
|
1499
1507
|
setActiveAccounts((prev) => {
|
|
@@ -1899,13 +1907,17 @@ function AppLayoutInner({ children }: AppLayoutProps) {
|
|
|
1899
1907
|
</div>
|
|
1900
1908
|
)}
|
|
1901
1909
|
|
|
1902
|
-
{/* Show full-page takeover when no accounts connected (except on
|
|
1910
|
+
{/* Show full-page takeover when no accounts connected (except on
|
|
1911
|
+
settings page, or on an unknown route — an unmatched path must
|
|
1912
|
+
still reach the routed NotFound content, not this gate). */}
|
|
1903
1913
|
{!googleStatus.isLoading &&
|
|
1904
1914
|
!googleStatus.isError &&
|
|
1905
1915
|
!hasAccounts &&
|
|
1906
1916
|
!hasLocalMailboxData &&
|
|
1907
1917
|
view !== "settings" &&
|
|
1908
|
-
view !== "draft-queue"
|
|
1918
|
+
view !== "draft-queue" &&
|
|
1919
|
+
isKnownMailView(view) &&
|
|
1920
|
+
(googleConfigured || canOfferGoogleOAuthSetup) ? (
|
|
1909
1921
|
<GoogleConnectBanner variant="hero" />
|
|
1910
1922
|
) : (
|
|
1911
1923
|
<main className="agent-native-app-main flex flex-1 overflow-hidden">
|
|
@@ -2561,11 +2573,18 @@ function TabSettingsPopover({
|
|
|
2561
2573
|
|
|
2562
2574
|
function AccountPopover({
|
|
2563
2575
|
accounts,
|
|
2576
|
+
canAddAccount,
|
|
2564
2577
|
activeAccounts,
|
|
2565
2578
|
onToggleAccount,
|
|
2566
2579
|
onRemoveAccount,
|
|
2567
2580
|
}: {
|
|
2568
|
-
accounts: Array<{
|
|
2581
|
+
accounts: Array<{
|
|
2582
|
+
email: string;
|
|
2583
|
+
displayName?: string;
|
|
2584
|
+
photoUrl?: string;
|
|
2585
|
+
shared?: boolean;
|
|
2586
|
+
}>;
|
|
2587
|
+
canAddAccount: boolean;
|
|
2569
2588
|
activeAccounts: Set<string>;
|
|
2570
2589
|
onToggleAccount: (email: string) => void;
|
|
2571
2590
|
onRemoveAccount: (email: string) => void;
|
|
@@ -2668,32 +2687,43 @@ function AccountPopover({
|
|
|
2668
2687
|
</span>
|
|
2669
2688
|
)}
|
|
2670
2689
|
</span>
|
|
2671
|
-
|
|
2672
|
-
|
|
2673
|
-
|
|
2674
|
-
|
|
2675
|
-
|
|
2676
|
-
|
|
2677
|
-
|
|
2678
|
-
|
|
2679
|
-
|
|
2690
|
+
{!account.shared && (
|
|
2691
|
+
<button
|
|
2692
|
+
onClick={() => {
|
|
2693
|
+
onRemoveAccount(account.email);
|
|
2694
|
+
disconnectGoogle.mutate(account.email);
|
|
2695
|
+
}}
|
|
2696
|
+
className="opacity-0 group-hover:opacity-100 text-[11px] text-muted-foreground hover:text-destructive transition-all"
|
|
2697
|
+
>
|
|
2698
|
+
{t("mail.accounts.remove")}
|
|
2699
|
+
</button>
|
|
2700
|
+
)}
|
|
2680
2701
|
</div>
|
|
2681
2702
|
);
|
|
2682
2703
|
})}
|
|
2683
2704
|
</div>
|
|
2684
2705
|
|
|
2685
|
-
|
|
2686
|
-
<
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
|
|
2690
|
-
|
|
2691
|
-
|
|
2692
|
-
|
|
2693
|
-
|
|
2694
|
-
|
|
2695
|
-
|
|
2696
|
-
|
|
2706
|
+
{canAddAccount ? (
|
|
2707
|
+
<div className="border-t border-border/30 px-3 py-2">
|
|
2708
|
+
<button
|
|
2709
|
+
onClick={() => {
|
|
2710
|
+
const returnPath = `${window.location.pathname}${window.location.search}`;
|
|
2711
|
+
startWorkspaceProviderOAuth("gmail", {
|
|
2712
|
+
appId: "mail",
|
|
2713
|
+
returnPath,
|
|
2714
|
+
scope: "user",
|
|
2715
|
+
});
|
|
2716
|
+
}}
|
|
2717
|
+
disabled={authUrl.isLoading || authUrl.isFetching}
|
|
2718
|
+
className="flex items-center gap-2 w-full text-[13px] text-muted-foreground hover:text-foreground transition-colors py-1"
|
|
2719
|
+
>
|
|
2720
|
+
<IconPlus className="h-3.5 w-3.5" />
|
|
2721
|
+
{authUrl.isFetching
|
|
2722
|
+
? t("mail.accounts.connecting")
|
|
2723
|
+
: t("mail.accounts.addAccount")}
|
|
2724
|
+
</button>
|
|
2725
|
+
</div>
|
|
2726
|
+
) : null}
|
|
2697
2727
|
</>
|
|
2698
2728
|
);
|
|
2699
2729
|
}
|
|
@@ -8,9 +8,11 @@ export interface GoogleAuthAccount {
|
|
|
8
8
|
displayName?: string;
|
|
9
9
|
expiresAt?: string;
|
|
10
10
|
photoUrl?: string;
|
|
11
|
+
shared?: boolean;
|
|
11
12
|
}
|
|
12
13
|
|
|
13
14
|
export interface GoogleAuthStatus {
|
|
15
|
+
configured?: boolean;
|
|
14
16
|
connected: boolean;
|
|
15
17
|
accounts: GoogleAuthAccount[];
|
|
16
18
|
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
function localHostname(hostname: string): boolean {
|
|
2
|
+
return (
|
|
3
|
+
hostname === "localhost" ||
|
|
4
|
+
hostname === "127.0.0.1" ||
|
|
5
|
+
hostname === "::1" ||
|
|
6
|
+
hostname.endsWith(".localhost") ||
|
|
7
|
+
hostname.endsWith(".local")
|
|
8
|
+
);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function shouldOfferGoogleOAuthSetup(): boolean {
|
|
12
|
+
const env = (import.meta.env ?? {}) as Record<string, unknown>;
|
|
13
|
+
if (env.DEV === true) return true;
|
|
14
|
+
if (env.VITE_ENABLE_GOOGLE_OAUTH_SETUP === "true") return true;
|
|
15
|
+
if (typeof window === "undefined") return false;
|
|
16
|
+
return localHostname(window.location.hostname.toLowerCase());
|
|
17
|
+
}
|