@agent-native/core 0.176.1 → 0.176.2-nightly-20260831184159
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/corpus/README.md +1 -1
- package/corpus/templates/analytics/.agents/skills/frontend-design/SKILL.md +4 -0
- package/corpus/templates/analytics/.agents/skills/secrets/SKILL.md +47 -0
- package/corpus/templates/analytics/AGENTS.md +13 -2
- package/corpus/templates/analytics/CHANGELOG.md +8 -0
- package/corpus/templates/analytics/actions/certify-dashboard.ts +39 -0
- package/corpus/templates/analytics/actions/get-sql-dashboard.ts +1 -1
- package/corpus/templates/analytics/actions/list-analysis-revisions.ts +4 -2
- package/corpus/templates/analytics/actions/list-dashboard-revisions.ts +4 -2
- package/corpus/templates/analytics/actions/search-analytics-query-catalog.ts +1 -0
- package/corpus/templates/analytics/actions/search-dashboard-references.ts +2 -1
- package/corpus/templates/analytics/actions/set-workspace-feature-flag.ts +2 -2
- package/corpus/templates/analytics/app/components/agents/FeatureFlagsFleetPanel.tsx +16 -1
- package/corpus/templates/analytics/app/components/layout/Layout.tsx +58 -0
- package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +7 -19
- package/corpus/templates/analytics/app/global.css +0 -7
- package/corpus/templates/analytics/app/hooks/use-navigation-state.ts +1 -1
- package/corpus/templates/analytics/app/i18n-data.ts +42 -0
- package/corpus/templates/analytics/app/lib/track-metric.ts +15 -0
- package/corpus/templates/analytics/app/pages/NotFound.tsx +1 -1
- package/corpus/templates/analytics/app/pages/Placeholder.tsx +1 -1
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +115 -2
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/types.ts +8 -0
- package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +23 -25
- package/corpus/templates/analytics/app/root.tsx +5 -5
- package/corpus/templates/analytics/app/routes/_index.tsx +18 -20
- package/corpus/templates/analytics/app/routes/dashboard.tsx +1 -1
- package/corpus/templates/analytics/app/routes/home.tsx +39 -0
- package/corpus/templates/analytics/changelog/2026-08-27-show-analytics-s-own-registered-flags-in-fleet-feature-flag-.md +6 -0
- package/corpus/templates/analytics/changelog/2026-08-28-analytics-loading-placeholders-now-use-a-smooth-whole-surfac.md +6 -0
- package/corpus/templates/analytics/changelog/2026-08-28-analytics-loading-states-use-a-softer-whole-surfac.md +6 -0
- package/corpus/templates/analytics/changelog/2026-08-28-analytics-sidebar-horizontal-spacing-is-tighter.md +6 -0
- package/corpus/templates/analytics/changelog/2026-08-28-sidebar-branding-matches-the-app-text-color-with-a-tighter-m.md +6 -0
- package/corpus/templates/analytics/changelog/2026-08-28-sidebar-branding-uses-a-monochrome-agent-native-mark.md +6 -0
- package/corpus/templates/analytics/changelog/2026-08-29-analytics-loading-shine-is-more-subtle.md +6 -0
- package/corpus/templates/analytics/changelog/2026-08-29-chat-edits-can-be-reverted-to-saved-checkpoints.md +6 -0
- package/corpus/templates/analytics/changelog/2026-08-29-dashboard-certification-lives-in-the-overflow-menu.md +6 -0
- package/corpus/templates/analytics/changelog/2026-08-29-public-marketing-home.md +6 -0
- package/corpus/templates/analytics/package.json +2 -0
- package/corpus/templates/analytics/public/manifest.json +1 -1
- package/corpus/templates/analytics/server/db/schema.ts +4 -0
- package/corpus/templates/analytics/server/handlers/events.ts +10 -1
- package/corpus/templates/analytics/server/handlers/first-party-analytics.ts +9 -1
- package/corpus/templates/analytics/server/handlers/session-replay.ts +10 -1
- package/corpus/templates/analytics/server/lib/agent-readable-resource-context.ts +22 -2
- package/corpus/templates/analytics/server/lib/analytics-query-catalog.ts +82 -7
- package/corpus/templates/analytics/server/lib/dashboard-certification.ts +58 -0
- package/corpus/templates/analytics/server/lib/dashboard-report.ts +1 -0
- package/corpus/templates/analytics/server/lib/dashboards-store.ts +429 -46
- package/corpus/templates/analytics/server/lib/workspace-feature-flags.ts +204 -32
- package/corpus/templates/analytics/server/plugins/agent-chat.ts +139 -0
- package/corpus/templates/analytics/server/plugins/auth.ts +1 -0
- package/corpus/templates/analytics/server/plugins/core-routes.ts +3 -2
- package/corpus/templates/analytics/server/plugins/db.ts +11 -0
- package/corpus/templates/assets/.agents/skills/frontend-design/SKILL.md +4 -0
- package/corpus/templates/assets/.agents/skills/secrets/SKILL.md +47 -0
- package/corpus/templates/assets/app/components/layout/Header.tsx +2 -2
- package/corpus/templates/assets/app/components/layout/Layout.tsx +4 -3
- package/corpus/templates/assets/app/components/layout/Sidebar.tsx +14 -27
- package/corpus/templates/assets/app/hooks/use-navigation-state.ts +2 -2
- package/corpus/templates/assets/app/root.tsx +29 -9
- package/corpus/templates/assets/app/routes/_index.tsx +15 -116
- package/corpus/templates/assets/app/routes/chat.$threadId.tsx +1 -1
- package/corpus/templates/assets/app/routes/home.tsx +137 -0
- package/corpus/templates/assets/app/routes/library.tsx +5 -1
- package/corpus/templates/assets/app/routes/settings.tsx +28 -25
- package/corpus/templates/assets/changelog/2026-08-26-templates-across-brand-kits.md +1 -0
- package/corpus/templates/assets/public/manifest.json +1 -1
- package/corpus/templates/assets/server/plugins/auth.ts +1 -0
- package/corpus/templates/brain/.agents/skills/frontend-design/SKILL.md +4 -0
- package/corpus/templates/brain/.agents/skills/secrets/SKILL.md +47 -0
- package/corpus/templates/brain/app/components/layout/Layout.tsx +3 -3
- package/corpus/templates/brain/app/components/layout/Sidebar.tsx +10 -23
- package/corpus/templates/brain/app/lib/brain.ts +2 -2
- package/corpus/templates/brain/app/root.tsx +13 -3
- package/corpus/templates/brain/app/routes/_index.tsx +15 -55
- package/corpus/templates/brain/app/routes/home.tsx +76 -0
- package/corpus/templates/brain/app/routes.ts +1 -0
- package/corpus/templates/brain/public/manifest.json +1 -1
- package/corpus/templates/brain/server/lib/brain-health.ts +2 -2
- package/corpus/templates/brain/server/plugins/auth.ts +1 -1
- package/corpus/templates/brain/server/plugins/core-routes.ts +2 -1
- package/corpus/templates/calendar/.agents/skills/frontend-design/SKILL.md +4 -0
- package/corpus/templates/calendar/.agents/skills/secrets/SKILL.md +47 -0
- package/corpus/templates/calendar/CHANGELOG.md +12 -0
- package/corpus/templates/calendar/actions/event-action-helpers.ts +2 -1
- package/corpus/templates/calendar/actions/manage-event-draft.ts +1 -1
- package/corpus/templates/calendar/actions/update-event.ts +8 -1
- package/corpus/templates/calendar/amplify.yml +15 -0
- package/corpus/templates/calendar/app/components/calendar/ApolloPanel.tsx +2 -2
- package/corpus/templates/calendar/app/components/calendar/CreateEventDialog.tsx +102 -109
- package/corpus/templates/calendar/app/components/calendar/DayView.tsx +23 -10
- package/corpus/templates/calendar/app/components/calendar/DeleteEventDialog.tsx +2 -11
- package/corpus/templates/calendar/app/components/calendar/EventAttendeesSection.tsx +150 -141
- package/corpus/templates/calendar/app/components/calendar/EventCard.tsx +3 -1
- package/corpus/templates/calendar/app/components/calendar/EventDescription.tsx +2 -2
- package/corpus/templates/calendar/app/components/calendar/EventDetailPopover.tsx +359 -222
- package/corpus/templates/calendar/app/components/calendar/InlineEventPickers.tsx +13 -5
- package/corpus/templates/calendar/app/components/calendar/WeekView.tsx +21 -9
- package/corpus/templates/calendar/app/components/layout/Sidebar.tsx +21 -32
- package/corpus/templates/calendar/app/global.css +11 -0
- package/corpus/templates/calendar/app/hooks/use-meeting-start-notifications.ts +10 -0
- package/corpus/templates/calendar/app/hooks/use-navigation-state.ts +3 -3
- package/corpus/templates/calendar/app/i18n-data.ts +110 -0
- package/corpus/templates/calendar/app/lib/calendar-timezone.ts +12 -3
- package/corpus/templates/calendar/app/lib/event-popover-style.ts +43 -0
- package/corpus/templates/calendar/app/lib/mcp-embed.ts +8 -2
- package/corpus/templates/calendar/app/lib/utils.ts +3 -1
- package/corpus/templates/calendar/app/pages/BookingPage.tsx +2 -8
- package/corpus/templates/calendar/app/pages/CalendarView.tsx +9 -11
- package/corpus/templates/calendar/app/pages/ManageBookingPage.tsx +2 -6
- package/corpus/templates/calendar/app/pages/NotFound.tsx +1 -1
- package/corpus/templates/calendar/app/pages/Settings.tsx +54 -0
- package/corpus/templates/calendar/app/root.tsx +9 -1
- package/corpus/templates/calendar/app/routes/{_app._index.tsx → _app.home.tsx} +1 -1
- package/corpus/templates/calendar/app/routes/_index.tsx +34 -0
- package/corpus/templates/calendar/app/routes/event.tsx +2 -6
- package/corpus/templates/calendar/changelog/2026-08-28-all-day-events-stay-in-the-compact-top-bar-in-day-and-week-v.md +6 -0
- package/corpus/templates/calendar/changelog/2026-08-28-calendar-organizer-note-emails-now-link-back-to-agent-native.md +6 -0
- package/corpus/templates/calendar/changelog/2026-08-28-calendar-shows-google-profile-photos-in-the-desktop-app.md +6 -0
- package/corpus/templates/calendar/changelog/2026-08-28-event-creators-can-choose-whether-a-meeting-shows-as-free-or.md +6 -0
- package/corpus/templates/calendar/changelog/2026-08-28-event-popovers-match-notion-calendar-s-density-a-284px-blurr.md +6 -0
- package/corpus/templates/calendar/changelog/2026-08-28-fixed-calendar-navigation-scheduling-permissions-and-action-.md +6 -0
- package/corpus/templates/calendar/changelog/2026-08-28-google-calendar-connections-use-the-registered-callback-on-m.md +6 -0
- package/corpus/templates/calendar/changelog/2026-08-28-sidebar-branding-matches-the-app-text-color-with-a-tighter-m.md +6 -0
- package/corpus/templates/calendar/changelog/2026-08-28-sidebar-branding-uses-a-monochrome-agent-native-mark.md +6 -0
- package/corpus/templates/calendar/changelog/2026-08-28-the-calendar-sidebar-keeps-the-settings-link-compact.md +6 -0
- package/corpus/templates/calendar/changelog/2026-08-28-the-calendar-sidebar-keeps-the-workspace-picker-compact.md +6 -0
- package/corpus/templates/calendar/changelog/2026-08-29-public-marketing-home.md +6 -0
- package/corpus/templates/calendar/public/manifest.json +1 -1
- package/corpus/templates/calendar/server/handlers/google-auth.ts +10 -2
- package/corpus/templates/calendar/server/lib/emails.ts +2 -1
- package/corpus/templates/calendar/server/lib/event-guest-notifications.ts +31 -5
- package/corpus/templates/calendar/server/lib/google-calendar.ts +4 -2
- package/corpus/templates/calendar/server/plugins/auth.ts +1 -0
- package/corpus/templates/calendar/server/plugins/core-routes.ts +5 -3
- package/corpus/templates/calendar/shared/event-permissions.ts +12 -0
- package/corpus/templates/chat/.agents/skills/frontend-design/SKILL.md +4 -0
- package/corpus/templates/chat/.agents/skills/secrets/SKILL.md +47 -0
- package/corpus/templates/chat/AGENTS.md +5 -4
- package/corpus/templates/chat/app/components/layout/Header.tsx +1 -1
- package/corpus/templates/chat/app/components/layout/Layout.tsx +5 -4
- package/corpus/templates/chat/app/components/layout/Sidebar.tsx +16 -25
- package/corpus/templates/chat/app/hooks/use-navigation-state.ts +5 -5
- package/corpus/templates/chat/app/root.tsx +16 -3
- package/corpus/templates/chat/app/routes/_index.tsx +17 -74
- package/corpus/templates/chat/app/routes/chat.$threadId.tsx +1 -1
- package/corpus/templates/chat/app/routes/home.tsx +94 -0
- package/corpus/templates/chat/netlify.toml +2 -1
- package/corpus/templates/chat/public/manifest.json +1 -1
- package/corpus/templates/chat/server/plugins/auth.ts +1 -0
- package/corpus/templates/clips/.agents/skills/frontend-design/SKILL.md +4 -0
- package/corpus/templates/clips/.agents/skills/secrets/SKILL.md +47 -0
- package/corpus/templates/clips/actions/add-comment.ts +18 -1
- package/corpus/templates/clips/actions/get-recording-player-data.ts +2 -0
- package/corpus/templates/clips/actions/list-comments.ts +2 -0
- package/corpus/templates/clips/actions/list-notifications.ts +60 -28
- package/corpus/templates/clips/actions/list-recording-mention-members.ts +64 -0
- package/corpus/templates/clips/actions/list-recordings.ts +1 -1
- package/corpus/templates/clips/actions/reply-to-comment.ts +17 -1
- package/corpus/templates/clips/actions/update-comment.ts +36 -2
- package/corpus/templates/clips/app/components/library/empty-state.tsx +1 -3
- package/corpus/templates/clips/app/components/library/library-grid.tsx +18 -6
- package/corpus/templates/clips/app/components/library/library-layout.tsx +6 -58
- package/corpus/templates/clips/app/components/library/recording-card.tsx +101 -3
- package/corpus/templates/clips/app/components/library/sort-menu.tsx +2 -2
- package/corpus/templates/clips/app/components/player/comment-composer.tsx +284 -0
- package/corpus/templates/clips/app/components/player/comments-panel.tsx +162 -46
- package/corpus/templates/clips/app/components/player/transcript-panel.tsx +38 -133
- package/corpus/templates/clips/app/components/player/video-player.tsx +1 -1
- package/corpus/templates/clips/app/components/recorder/recorder-engine.ts +99 -20
- package/corpus/templates/clips/app/components/recorder/recording-toolbar.tsx +110 -116
- package/corpus/templates/clips/app/components/recorder/storage-setup-card.tsx +83 -60
- package/corpus/templates/clips/app/components/settings/ai-setup-section.tsx +17 -11
- package/corpus/templates/clips/app/components/settings/types.ts +5 -1
- package/corpus/templates/clips/app/components/settings/video-storage-section.tsx +21 -12
- package/corpus/templates/clips/app/global.css +0 -27
- package/corpus/templates/clips/app/hooks/use-desktop-promo.ts +3 -17
- package/corpus/templates/clips/app/hooks/use-mention-members.ts +24 -0
- package/corpus/templates/clips/app/hooks/use-navigation-state.ts +2 -2
- package/corpus/templates/clips/app/i18n/en-US.ts +15 -0
- package/corpus/templates/clips/app/lib/recording-backup.ts +245 -0
- package/corpus/templates/clips/app/lib/recording-retry.ts +189 -0
- package/corpus/templates/clips/app/lib/recording-status.ts +32 -0
- package/corpus/templates/clips/app/root.tsx +11 -2
- package/corpus/templates/clips/app/routes/_app.home.tsx +62 -0
- package/corpus/templates/clips/app/routes/_app.notifications.tsx +45 -12
- package/corpus/templates/clips/app/routes/_app.settings._index.tsx +2 -0
- package/corpus/templates/clips/app/routes/_index.tsx +11 -40
- package/corpus/templates/clips/app/routes/download.tsx +148 -15
- package/corpus/templates/clips/app/routes/embed.$shareId.tsx +4 -3
- package/corpus/templates/clips/app/routes/r.$recordingId.tsx +6 -11
- package/corpus/templates/clips/app/routes/record.tsx +72 -13
- package/corpus/templates/clips/app/routes/share.$shareId.tsx +40 -24
- package/corpus/templates/clips/app/routes/share.meeting.$meetingId.tsx +2 -7
- package/corpus/templates/clips/changelog/2026-08-28-chrome-extension-download-help.md +6 -0
- package/corpus/templates/clips/changelog/2026-08-28-clips-loading-skeletons-use-a-softer-whole-surface.md +6 -0
- package/corpus/templates/clips/changelog/2026-08-28-comment-composer-no-longer-has-an-outer-border.md +6 -0
- package/corpus/templates/clips/changelog/2026-08-29-clips-loading-shine-is-more-subtle.md +6 -0
- package/corpus/templates/clips/desktop/src/app.tsx +377 -476
- package/corpus/templates/clips/desktop/src/components/ui/skeleton.tsx +1 -1
- package/corpus/templates/clips/desktop/src/components/ui/spinner.tsx +1 -17
- package/corpus/templates/clips/desktop/src/lib/recorder.ts +4 -0
- package/corpus/templates/clips/desktop/src/overlays/countdown.tsx +0 -8
- package/corpus/templates/clips/desktop/src/overlays/record-pill.tsx +221 -460
- package/corpus/templates/clips/desktop/src/styles.css +0 -40
- package/corpus/templates/clips/desktop/src/tailwind.css +28 -14
- package/corpus/templates/clips/desktop/src-tauri/src/clips/mod.rs +15 -11
- package/corpus/templates/clips/desktop/src-tauri/src/lib.rs +9 -0
- package/corpus/templates/clips/desktop/src-tauri/src/native_screen.rs +192 -57
- package/corpus/templates/clips/desktop/src-tauri/src/recording_indicator.rs +9 -3
- package/corpus/templates/clips/desktop/src-tauri/src/tray.rs +12 -0
- package/corpus/templates/clips/desktop/src-tauri/src/util.rs +97 -3
- package/corpus/templates/clips/public/manifest.json +1 -1
- package/corpus/templates/clips/server/db/schema.ts +1 -0
- package/corpus/templates/clips/server/lib/activity-notifications.ts +30 -5
- package/corpus/templates/clips/server/lib/comment-mentions.ts +23 -0
- package/corpus/templates/clips/server/lib/emails.ts +2 -2
- package/corpus/templates/clips/server/lib/recording-page-access.ts +16 -0
- package/corpus/templates/clips/server/lib/transactional-email-templates.ts +14 -7
- package/corpus/templates/clips/server/plugins/auth.ts +1 -0
- package/corpus/templates/clips/server/plugins/core-routes.ts +5 -0
- package/corpus/templates/clips/server/plugins/db.ts +5 -0
- package/corpus/templates/clips/server/routes/api/auth/google-calendar.get.ts +4 -2
- package/corpus/templates/clips/server/routes/api/clips-latest.json.get.ts +77 -22
- package/corpus/templates/clips/server/routes/api/public-recording.get.ts +11 -0
- package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/interrupt.post.ts +4 -4
- package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/resume.get.ts +1 -1
- package/corpus/templates/clips/shared/comment-mentions.ts +71 -0
- package/corpus/templates/clips/shared/prerendered-public-paths.ts +1 -1
- package/corpus/templates/clips/shared/recording-core.ts +5 -0
- package/corpus/templates/clips/shared/recording-playhead.css +207 -0
- package/corpus/templates/clips/shared/recording-playhead.tsx +616 -0
- package/corpus/templates/content/.agents/skills/frontend-design/SKILL.md +4 -0
- package/corpus/templates/content/.agents/skills/secrets/SKILL.md +47 -0
- package/corpus/templates/content/CHANGELOG.md +6 -0
- package/corpus/templates/content/actions/_property-utils.ts +45 -9
- package/corpus/templates/content/actions/edit-document.ts +17 -0
- package/corpus/templates/content/actions/get-document.ts +31 -11
- package/corpus/templates/content/actions/list-document-properties.ts +30 -2
- package/corpus/templates/content/actions/list-document-versions.ts +49 -17
- package/corpus/templates/content/actions/list-documents.ts +13 -2
- package/corpus/templates/content/actions/restore-document-version.ts +8 -1
- package/corpus/templates/content/actions/update-document.ts +8 -0
- package/corpus/templates/content/app/components/QueryErrorState.tsx +1 -0
- package/corpus/templates/content/app/components/editor/DocumentBlockFields.tsx +28 -8
- package/corpus/templates/content/app/components/editor/DocumentEditor.tsx +94 -61
- package/corpus/templates/content/app/components/editor/DocumentProperties.tsx +24 -10
- package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +16 -13
- package/corpus/templates/content/app/components/editor/database/settings.tsx +16 -13
- package/corpus/templates/content/app/components/layout/Layout.tsx +35 -1
- package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +5 -18
- package/corpus/templates/content/app/hooks/use-document-properties.ts +5 -3
- package/corpus/templates/content/app/hooks/use-documents.ts +3 -1
- package/corpus/templates/content/app/hooks/use-navigation-state.ts +3 -3
- package/corpus/templates/content/app/root.tsx +9 -4
- package/corpus/templates/content/app/routes/{_app._index.tsx → _app.home.tsx} +12 -4
- package/corpus/templates/content/app/routes/_index.tsx +33 -0
- package/corpus/templates/content/changelog/2026-08-26-shared-page-load-failures-now-stay-visible-and-safe.md +6 -0
- package/corpus/templates/content/docs/product/capabilities/content.workspace.session-restore.md +2 -2
- package/corpus/templates/content/e2e/playwright.config.ts +1 -1
- package/corpus/templates/content/package.json +2 -0
- package/corpus/templates/content/parity/matrix.md +1 -1
- package/corpus/templates/content/parity/matrix.ts +1 -1
- package/corpus/templates/content/public/manifest.json +1 -1
- package/corpus/templates/content/server/db/schema.ts +1 -0
- package/corpus/templates/content/server/lib/document-version-context.ts +67 -0
- package/corpus/templates/content/server/plugins/agent-chat.ts +155 -0
- package/corpus/templates/content/server/plugins/auth.ts +1 -0
- package/corpus/templates/content/server/plugins/core-routes.ts +3 -2
- package/corpus/templates/content/server/plugins/db.ts +5 -0
- package/corpus/templates/content/shared/api.ts +6 -4
- package/corpus/templates/crm/.agents/skills/frontend-design/SKILL.md +4 -0
- package/corpus/templates/crm/.agents/skills/secrets/SKILL.md +47 -0
- package/corpus/templates/crm/actions/list-crm-dashboard-revisions.ts +1 -1
- package/corpus/templates/crm/agent-native.app-skill.json +1 -1
- package/corpus/templates/crm/app/components/layout/CrmCommandMenu.tsx +1 -1
- package/corpus/templates/crm/app/components/layout/CrmLayout.tsx +36 -1
- package/corpus/templates/crm/app/components/layout/CrmSidebar.tsx +3 -3
- package/corpus/templates/crm/app/root.tsx +28 -7
- package/corpus/templates/crm/app/routes/_index.tsx +28 -18
- package/corpus/templates/crm/app/routes/home.tsx +27 -0
- package/corpus/templates/crm/app/routes/setup.tsx +2 -2
- package/corpus/templates/crm/app/routes.ts +1 -0
- package/corpus/templates/crm/public/manifest.json +1 -1
- package/corpus/templates/crm/server/plugins/agent-chat.ts +81 -0
- package/corpus/templates/crm/server/plugins/auth.ts +1 -0
- package/corpus/templates/crm/server/plugins/core-routes.ts +2 -1
- package/corpus/templates/crm/server/plugins/db.ts +7 -1
- package/corpus/templates/crm/shared/crm-navigation.ts +3 -2
- package/corpus/templates/design/.agents/skills/design-generation/SKILL.md +13 -0
- package/corpus/templates/design/.agents/skills/frontend-design/SKILL.md +4 -0
- package/corpus/templates/design/.agents/skills/secrets/SKILL.md +47 -0
- package/corpus/templates/design/.generated/bridge/editor-chrome.generated.ts +22 -10
- package/corpus/templates/design/AGENTS.md +1 -1
- package/corpus/templates/design/actions/add-breakpoint.ts +3 -1
- package/corpus/templates/design/actions/add-fusion-screens.ts +2 -0
- package/corpus/templates/design/actions/add-localhost-screens.ts +16 -11
- package/corpus/templates/design/actions/apply-a11y-fix.ts +6 -8
- package/corpus/templates/design/actions/apply-component-prop-edit.ts +3 -1
- package/corpus/templates/design/actions/apply-design-token-edit.ts +3 -1
- package/corpus/templates/design/actions/apply-motion-edit.ts +18 -13
- package/corpus/templates/design/actions/apply-shader-fill.ts +3 -1
- package/corpus/templates/design/actions/apply-source-edit.ts +6 -1
- package/corpus/templates/design/actions/apply-tweaks.ts +3 -1
- package/corpus/templates/design/actions/apply-visual-edit.ts +14 -9
- package/corpus/templates/design/actions/clone-creative-context-design.ts +6 -1
- package/corpus/templates/design/actions/create-component.ts +3 -1
- package/corpus/templates/design/actions/create-file.ts +3 -1
- package/corpus/templates/design/actions/delete-file.ts +3 -1
- package/corpus/templates/design/actions/detach-component-instance.ts +3 -1
- package/corpus/templates/design/actions/edit-design.ts +16 -11
- package/corpus/templates/design/actions/generate-design.ts +19 -14
- package/corpus/templates/design/actions/get-design-branch-diff.ts +26 -31
- package/corpus/templates/design/actions/get-design-review.ts +25 -31
- package/corpus/templates/design/actions/get-design-system-index-status.ts +55 -0
- package/corpus/templates/design/actions/get-design-system.ts +1 -1
- package/corpus/templates/design/actions/hydrate-figma-paste-images.ts +3 -1
- package/corpus/templates/design/actions/import-design-source.ts +16 -9
- package/corpus/templates/design/actions/import-design-tokens.ts +3 -1
- package/corpus/templates/design/actions/import-figma-clipboard.ts +28 -16
- package/corpus/templates/design/actions/import-figma-frame.ts +3 -1
- package/corpus/templates/design/actions/insert-asset.ts +3 -1
- package/corpus/templates/design/actions/insert-design-native-asset.ts +3 -1
- package/corpus/templates/design/actions/insert-figma-library-asset.ts +3 -1
- package/corpus/templates/design/actions/list-design-versions.ts +23 -0
- package/corpus/templates/design/actions/migrate-board-objects-to-file.ts +3 -1
- package/corpus/templates/design/actions/open-visual-edit.ts +23 -20
- package/corpus/templates/design/actions/present-design-variants.ts +7 -2
- package/corpus/templates/design/actions/refresh-design-system-with-builder.ts +66 -10
- package/corpus/templates/design/actions/remove-breakpoint.ts +3 -1
- package/corpus/templates/design/actions/remove-motion-timeline.ts +3 -1
- package/corpus/templates/design/actions/restore-design-version.ts +16 -0
- package/corpus/templates/design/actions/set-layout-grid.ts +94 -0
- package/corpus/templates/design/actions/swap-component-instance.ts +6 -1
- package/corpus/templates/design/actions/update-design.ts +16 -11
- package/corpus/templates/design/actions/update-file.ts +2 -0
- package/corpus/templates/design/app/components/design/DesignCanvas.tsx +25 -0
- package/corpus/templates/design/app/components/design/EditPanel.tsx +36 -8
- package/corpus/templates/design/app/components/design/LayersPanel.tsx +6 -6
- package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +185 -29
- package/corpus/templates/design/app/components/design/ReviewCommentsPanel.tsx +4 -4
- package/corpus/templates/design/app/components/design/ReviewPanel.tsx +1 -1
- package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +35 -10
- package/corpus/templates/design/app/components/design/canvas-primitive-style.ts +16 -9
- package/corpus/templates/design/app/components/design/edit-panel/component-section.tsx +51 -21
- package/corpus/templates/design/app/components/design/edit-panel/effects-properties.tsx +18 -17
- package/corpus/templates/design/app/components/design/edit-panel/field-primitives.tsx +6 -1
- package/corpus/templates/design/app/components/design/edit-panel/frame-presets-panel.tsx +3 -3
- package/corpus/templates/design/app/components/design/edit-panel/layout-grid-properties.tsx +88 -0
- package/corpus/templates/design/app/components/design/edit-panel/panel-primitives.tsx +5 -2
- package/corpus/templates/design/app/components/design/edit-panel/position-layout-properties.tsx +8 -4
- package/corpus/templates/design/app/components/design/edit-panel/typography-helpers.ts +8 -103
- package/corpus/templates/design/app/components/design/edit-panel/typography-properties.tsx +68 -83
- package/corpus/templates/design/app/components/design/editor/MakeRealDialog.tsx +35 -10
- package/corpus/templates/design/app/components/design/inspector/AutoLayoutMatrix.tsx +29 -24
- package/corpus/templates/design/app/components/design/inspector/DesignColorPicker.tsx +6 -0
- package/corpus/templates/design/app/components/design/inspector/GlslShaderPanel.tsx +72 -71
- package/corpus/templates/design/app/components/design/inspector/InspectorControlPopover.tsx +1 -1
- package/corpus/templates/design/app/components/design/keyboard-shortcuts.ts +9 -0
- package/corpus/templates/design/app/components/design/multi-screen/types.ts +8 -0
- package/corpus/templates/design/app/components/layout/Layout.tsx +32 -0
- package/corpus/templates/design/app/components/layout/Sidebar.tsx +8 -21
- package/corpus/templates/design/app/global.css +72 -1
- package/corpus/templates/design/app/hooks/use-navigation-state.ts +1 -1
- package/corpus/templates/design/app/hooks/useDesignHotkeys.ts +32 -1
- package/corpus/templates/design/app/i18n-data.ts +116 -12
- package/corpus/templates/design/app/i18n-keyboard-shortcuts.ts +3 -1
- package/corpus/templates/design/app/lib/design-system-data.ts +36 -0
- package/corpus/templates/design/app/pages/DesignEditor.tsx +170 -34
- package/corpus/templates/design/app/pages/DesignSystems.tsx +126 -11
- package/corpus/templates/design/app/pages/Index.tsx +15 -7
- package/corpus/templates/design/app/pages/NotFound.tsx +1 -1
- package/corpus/templates/design/app/pages/Templates.tsx +18 -3
- package/corpus/templates/design/app/pages/VisualEdit.tsx +1 -1
- package/corpus/templates/design/app/pages/design-editor/code-layer-state.ts +3 -3
- package/corpus/templates/design/app/pages/design-editor/commands/README.md +1 -0
- package/corpus/templates/design/app/pages/design-editor/commands/geometry-commit.ts +2 -1
- package/corpus/templates/design/app/pages/design-editor/commands/set-layout-grid.ts +66 -0
- package/corpus/templates/design/app/pages/design-editor/design-data-geometry-utils.ts +5 -0
- package/corpus/templates/design/app/pages/design-editor/effects/publish-agent-selection-context.ts +9 -1
- package/corpus/templates/design/app/pages/design-editor/effects/resume-pending-generation.ts +39 -9
- package/corpus/templates/design/app/pages/design-editor/generation-prompt-directives.ts +31 -2
- package/corpus/templates/design/app/pages/design-editor/geometry-persistence.ts +26 -0
- package/corpus/templates/design/app/pages/design-editor/intake-question-topics.ts +335 -0
- package/corpus/templates/design/app/pages/design-editor/nudge-intent.ts +8 -1
- package/corpus/templates/design/app/root.tsx +12 -2
- package/corpus/templates/design/app/routes/_index.tsx +14 -1
- package/corpus/templates/design/app/routes/home.tsx +21 -0
- package/corpus/templates/design/changelog/2026-08-21-builder-design-system-imports-reconcile-after-indexing.md +1 -1
- package/corpus/templates/design/changelog/2026-08-28-frames-can-carry-an-8px-layout-grid-that-positions-snap-to.md +6 -0
- package/corpus/templates/design/changelog/2026-08-28-x-and-y-are-always-whole-numbers.md +6 -0
- package/corpus/templates/design/public/manifest.json +1 -1
- package/corpus/templates/design/server/db/schema.ts +2 -0
- package/corpus/templates/design/server/handlers/design-system-builder-link.ts +84 -0
- package/corpus/templates/design/server/lib/builder-design-system-proxy.ts +9 -1
- package/corpus/templates/design/server/lib/design-versions.ts +1017 -0
- package/corpus/templates/design/server/plugins/agent-chat.ts +144 -0
- package/corpus/templates/design/server/plugins/auth.ts +1 -1
- package/corpus/templates/design/server/plugins/core-routes.ts +3 -2
- package/corpus/templates/design/server/plugins/db.ts +7 -0
- package/corpus/templates/design/server/routes/api/design-system-builder-link.get.ts +1 -0
- package/corpus/templates/design/shared/canvas-math.ts +106 -14
- package/corpus/templates/design/shared/layout-grid.ts +80 -0
- package/corpus/templates/dispatch/.agents/skills/frontend-design/SKILL.md +4 -0
- package/corpus/templates/dispatch/.agents/skills/secrets/SKILL.md +47 -0
- package/corpus/templates/dispatch/AGENTS.md +11 -13
- package/corpus/templates/dispatch/actions/list-workspace-connections.ts +10 -5
- package/corpus/templates/dispatch/app/i18n-data.ts +120 -0
- package/corpus/templates/dispatch/app/root.tsx +11 -1
- package/corpus/templates/dispatch/app/routes/_index.tsx +34 -7
- package/corpus/templates/dispatch/app/routes/home.tsx +7 -0
- package/corpus/templates/dispatch/package.json +1 -0
- package/corpus/templates/dispatch/public/manifest.json +1 -1
- package/corpus/templates/factory/.agents/skills/factory-graphs/SKILL.md +11 -2
- package/corpus/templates/factory/.agents/skills/frontend-design/SKILL.md +4 -0
- package/corpus/templates/factory/.agents/skills/secrets/SKILL.md +47 -0
- package/corpus/templates/factory/.env.example +2 -14
- package/corpus/templates/factory/AGENTS.md +12 -11
- package/corpus/templates/factory/README.md +15 -17
- package/corpus/templates/factory/actions/{babysit-agent-native-pull-request.ts → babysit-factory-pull-request.ts} +125 -88
- package/corpus/templates/factory/actions/create-factory-automation.ts +161 -0
- package/corpus/templates/factory/actions/create-factory.ts +4 -124
- package/corpus/templates/factory/actions/delete-factory.ts +11 -23
- package/corpus/templates/factory/actions/{start-builder-for-item.ts → dispatch-factory-item.ts} +169 -57
- package/corpus/templates/factory/actions/get-slack-feedback-context.ts +30 -10
- package/corpus/templates/factory/actions/get-triage-config.ts +22 -0
- package/corpus/templates/factory/actions/get-triage-item.ts +49 -2
- package/corpus/templates/factory/actions/{govern-agent-native-pull-request.ts → govern-factory-pull-request.ts} +95 -112
- package/corpus/templates/factory/actions/ingest-github-observation.ts +9 -2
- package/corpus/templates/factory/actions/list-factory-audit.ts +85 -12
- package/corpus/templates/factory/actions/list-factory-automation-templates.ts +56 -0
- package/corpus/templates/factory/actions/list-factory-automations.ts +36 -3
- package/corpus/templates/factory/actions/list-factory-graph-versions.ts +37 -10
- package/corpus/templates/factory/actions/list-triage-items.ts +120 -15
- package/corpus/templates/factory/actions/poll-github-sources.ts +102 -58
- package/corpus/templates/factory/actions/poll-sentry-errors.ts +73 -36
- package/corpus/templates/factory/actions/poll-slack-channel.ts +112 -28
- package/corpus/templates/factory/actions/{babysit-pull-request.ts → propose-pr-babysit-status.ts} +9 -47
- package/corpus/templates/factory/actions/reconcile-triage-run.ts +1 -1
- package/corpus/templates/factory/actions/save-factory-automation.ts +131 -33
- package/corpus/templates/factory/actions/save-factory-graph.ts +31 -8
- package/corpus/templates/factory/actions/save-triage-config.ts +7 -27
- package/corpus/templates/factory/actions/save-triage-rule.ts +1 -1
- package/corpus/templates/factory/app/components/factory/CreateFactoryAutomationView.tsx +258 -0
- package/corpus/templates/factory/app/components/factory/FactoryAuditView.tsx +349 -106
- package/corpus/templates/factory/app/components/factory/FactoryAutomationFields.tsx +614 -0
- package/corpus/templates/factory/app/components/factory/FactoryInboxView.tsx +1136 -0
- package/corpus/templates/factory/app/components/factory/FactoryInspector.tsx +7 -14
- package/corpus/templates/factory/app/components/factory/FactorySettingsView.tsx +4 -223
- package/corpus/templates/factory/app/components/factory/NewFactoryForm.tsx +10 -205
- package/corpus/templates/factory/app/components/factory/SlackMrkdwn.tsx +100 -0
- package/corpus/templates/factory/app/components/factory/audit-filters.ts +30 -0
- package/corpus/templates/factory/app/components/factory/factory-automation-form.ts +120 -0
- package/corpus/templates/factory/app/components/factory/inbox-filters.ts +84 -0
- package/corpus/templates/factory/app/components/factory/inbox-source-url.ts +23 -0
- package/corpus/templates/factory/app/components/factory/slack-emoji.ts +165 -0
- package/corpus/templates/factory/app/components/factory/slack-mrkdwn.ts +128 -0
- package/corpus/templates/factory/app/components/layout/Header.tsx +1 -1
- package/corpus/templates/factory/app/components/layout/Layout.tsx +63 -6
- package/corpus/templates/factory/app/components/layout/Sidebar.tsx +13 -26
- package/corpus/templates/factory/app/components/triage/triage-status-pill.tsx +63 -14
- package/corpus/templates/factory/app/global.css +106 -0
- package/corpus/templates/factory/app/hooks/use-navigation-state.ts +16 -10
- package/corpus/templates/factory/app/i18n/en-US.ts +154 -7
- package/corpus/templates/factory/app/lib/factory-tab-params.ts +59 -0
- package/corpus/templates/factory/app/lib/safe-http-url.ts +8 -0
- package/corpus/templates/factory/app/root.tsx +16 -3
- package/corpus/templates/factory/app/routes/_index.tsx +27 -5
- package/corpus/templates/factory/app/routes/factory.tsx +325 -733
- package/corpus/templates/factory/app/routes/home.tsx +13 -0
- package/corpus/templates/factory/app/routes/new-factory.tsx +3 -5
- package/corpus/templates/factory/changelog/2026-08-26-inbox-full-screen-thread.md +6 -0
- package/corpus/templates/factory/changelog/2026-08-26-inbox-thread-and-audit-labels.md +6 -0
- package/corpus/templates/factory/changelog/2026-08-27-audit-run-list-stacks.md +6 -0
- package/corpus/templates/factory/changelog/2026-08-27-audit-run-names-wrap.md +6 -0
- package/corpus/templates/factory/changelog/2026-08-27-factory-opens-on-inbox.md +6 -0
- package/corpus/templates/factory/changelog/2026-08-27-github-repository-url.md +6 -0
- package/corpus/templates/factory/changelog/2026-08-27-inbox-filters.md +6 -0
- package/corpus/templates/factory/changelog/2026-08-27-polling-does-not-enable-automations.md +6 -0
- package/corpus/templates/factory/changelog/2026-08-27-pr-babysit-can-poll-github.md +6 -0
- package/corpus/templates/factory/changelog/2026-08-28-factory-automations-use-workspace-connections.md +6 -0
- package/corpus/templates/factory/changelog/2026-08-28-inbox-approve-and-start-removed.md +6 -0
- package/corpus/templates/factory/changelog/2026-08-28-pr-babysit-audit-shows-decisions.md +6 -0
- package/corpus/templates/factory/changelog/2026-08-28-pr-babysit-reviews-next-github-prs.md +6 -0
- package/corpus/templates/factory/changelog/2026-08-28-pr-babysit-sticky-out-of-scope.md +6 -0
- package/corpus/templates/factory/changelog/2026-08-28-pr-babysit-uses-github-evidence.md +6 -0
- package/corpus/templates/factory/changelog/2026-08-29-audit-filters-pagination-scroll.md +6 -0
- package/corpus/templates/factory/changelog/2026-08-29-create-factory-automations.md +6 -0
- package/corpus/templates/factory/changelog/2026-08-29-dispatch-reaction-argument.md +6 -0
- package/corpus/templates/factory/changelog/2026-08-29-factory-action-names-match-behavior.md +6 -0
- package/corpus/templates/factory/public/manifest.json +1 -1
- package/corpus/templates/factory/server/connectors/slack.ts +8 -6
- package/corpus/templates/factory/server/db/schema.ts +23 -0
- package/corpus/templates/factory/server/lib/audit-cursor.ts +44 -0
- package/corpus/templates/factory/server/lib/factory-action-names.ts +15 -0
- package/corpus/templates/factory/server/lib/factory-audit-report.ts +29 -9
- package/corpus/templates/factory/server/lib/factory-automation-caller.ts +38 -0
- package/corpus/templates/factory/server/lib/factory-automation-config.ts +543 -0
- package/corpus/templates/factory/server/lib/factory-automation-plan.ts +0 -48
- package/corpus/templates/factory/server/lib/factory-automation-repair.ts +2 -18
- package/corpus/templates/factory/server/lib/factory-poll-cursors.ts +98 -0
- package/corpus/templates/factory/server/lib/factory-scope.ts +8 -0
- package/corpus/templates/factory/server/lib/github-repository.ts +104 -0
- package/corpus/templates/factory/server/lib/inbox-cursor.ts +34 -0
- package/corpus/templates/factory/server/lib/pr-babysit-prompt.ts +33 -0
- package/corpus/templates/factory/server/lib/require-factory-automation.ts +58 -17
- package/corpus/templates/factory/server/lib/safe-http-url.ts +8 -0
- package/corpus/templates/factory/server/lib/slack-feedback-prompt.ts +19 -10
- package/corpus/templates/factory/server/lib/source-reaction.ts +37 -0
- package/corpus/templates/factory/server/plugins/agent-chat.ts +18 -22
- package/corpus/templates/factory/server/plugins/auth.ts +1 -0
- package/corpus/templates/factory/server/plugins/factory-migrations.ts +26 -0
- package/corpus/templates/factory/server/plugins/factory-scheduler-job.ts +277 -164
- package/corpus/templates/factory/server/plugins/integrations.ts +5 -7
- package/corpus/templates/factory/server/triage/github-client.ts +274 -3
- package/corpus/templates/factory/server/triage/github-ingestion.ts +3 -1
- package/corpus/templates/factory/server/triage/metadata.ts +12 -0
- package/corpus/templates/factory/server/triage/pr-babysit.ts +22 -21
- package/corpus/templates/factory/server/triage/review-skill-alignment.ts +11 -11
- package/corpus/templates/factory/server/triage/review-state.ts +39 -0
- package/corpus/templates/factory/server/triage/slack-client.ts +14 -6
- package/corpus/templates/factory/server/triage/slack-poller.ts +34 -65
- package/corpus/templates/factory/server/triage/slack-user-labels.ts +126 -0
- package/corpus/templates/forms/.agents/skills/frontend-design/SKILL.md +4 -0
- package/corpus/templates/forms/.agents/skills/secrets/SKILL.md +47 -0
- package/corpus/templates/forms/AGENTS.md +4 -3
- package/corpus/templates/forms/actions/response-insights.ts +4 -4
- package/corpus/templates/forms/actions/retry-response-deliveries.ts +26 -0
- package/corpus/templates/forms/app/components/layout/Sidebar.tsx +8 -33
- package/corpus/templates/forms/app/hooks/use-navigation-state.ts +1 -1
- package/corpus/templates/forms/app/lib/route-prewarm.ts +1 -1
- package/corpus/templates/forms/app/root.tsx +3 -2
- package/corpus/templates/forms/app/routes/_app.home.tsx +47 -0
- package/corpus/templates/forms/app/routes/_app.tsx +2 -1
- package/corpus/templates/forms/app/routes/_index.tsx +10 -23
- package/corpus/templates/forms/public/manifest.json +1 -1
- package/corpus/templates/forms/server/db/schema.ts +64 -17
- package/corpus/templates/forms/server/handlers/submissions.ts +1022 -94
- package/corpus/templates/forms/server/lib/integrations.ts +100 -33
- package/corpus/templates/forms/server/middleware/00-public-cors.ts +1 -1
- package/corpus/templates/forms/server/plugins/auth.ts +1 -0
- package/corpus/templates/forms/server/plugins/core-routes.ts +1 -0
- package/corpus/templates/forms/server/plugins/db.ts +40 -0
- package/corpus/templates/macros/.agents/skills/frontend-design/SKILL.md +4 -0
- package/corpus/templates/macros/.agents/skills/secrets/SKILL.md +47 -0
- package/corpus/templates/macros/actions/view-screen.ts +1 -1
- package/corpus/templates/macros/app/components/layout/AppLayout.tsx +9 -21
- package/corpus/templates/macros/app/components/layout/Header.tsx +1 -1
- package/corpus/templates/macros/app/root.tsx +22 -8
- package/corpus/templates/macros/app/routes/_index.tsx +16 -291
- package/corpus/templates/macros/app/routes/home.tsx +312 -0
- package/corpus/templates/macros/server/plugins/auth.ts +9 -7
- package/corpus/templates/macros/server/plugins/core-routes.ts +1 -0
- package/corpus/templates/mail/.agents/skills/frontend-design/SKILL.md +4 -0
- package/corpus/templates/mail/.agents/skills/inbox-automations/SKILL.md +13 -2
- package/corpus/templates/mail/.agents/skills/inbox-reads-and-triage/SKILL.md +1 -1
- package/corpus/templates/mail/.agents/skills/secrets/SKILL.md +47 -0
- package/corpus/templates/mail/AGENTS.md +5 -2
- package/corpus/templates/mail/actions/apply-ai-filter.ts +294 -0
- package/corpus/templates/mail/actions/create-automation.ts +1 -0
- package/corpus/templates/mail/actions/get-ai-filter.ts +19 -0
- package/corpus/templates/mail/actions/manage-automations.ts +162 -157
- package/corpus/templates/mail/actions/manage-email-rules.ts +3 -0
- package/corpus/templates/mail/actions/navigate.ts +1 -1
- package/corpus/templates/mail/actions/update-automation.ts +1 -0
- package/corpus/templates/mail/actions/update-mail-preferences.ts +1 -0
- package/corpus/templates/mail/app/components/email/AiFilterDialog.tsx +127 -0
- package/corpus/templates/mail/app/components/email/EmailList.tsx +63 -0
- package/corpus/templates/mail/app/components/email/EmailThread.tsx +95 -0
- package/corpus/templates/mail/app/components/email/MobileActionBar.tsx +35 -3
- package/corpus/templates/mail/app/components/layout/AppLayout.tsx +17 -22
- package/corpus/templates/mail/app/components/settings/AiFilterSection.tsx +401 -0
- package/corpus/templates/mail/app/hooks/use-ai-filter.ts +48 -0
- package/corpus/templates/mail/app/hooks/use-automations.ts +1 -0
- package/corpus/templates/mail/app/hooks/use-emails.ts +11 -3
- package/corpus/templates/mail/app/i18n/en-US.ts +55 -0
- package/corpus/templates/mail/app/lib/automation-visibility.ts +17 -0
- package/corpus/templates/mail/app/pages/InboxPage.tsx +5 -2
- package/corpus/templates/mail/app/pages/SettingsPage.tsx +16 -8
- package/corpus/templates/mail/app/pages/inbox-zero.ts +1 -2
- package/corpus/templates/mail/app/root.tsx +20 -8
- package/corpus/templates/mail/app/routes/_index.tsx +16 -55
- package/corpus/templates/mail/app/routes/home.tsx +71 -0
- package/corpus/templates/mail/changelog/2026-08-28-mail-settings-show-chat-created-automations.md +6 -0
- package/corpus/templates/mail/public/manifest.json +1 -1
- package/corpus/templates/mail/server/db/schema.ts +3 -0
- package/corpus/templates/mail/server/handlers/emails.ts +34 -11
- package/corpus/templates/mail/server/handlers/google-auth.ts +1 -1
- package/corpus/templates/mail/server/lib/ai-filter.ts +103 -0
- package/corpus/templates/mail/server/lib/automation-actions.ts +14 -9
- package/corpus/templates/mail/server/lib/automation-engine.ts +142 -18
- package/corpus/templates/mail/server/lib/automations.ts +9 -0
- package/corpus/templates/mail/server/lib/email-state.ts +7 -2
- package/corpus/templates/mail/server/lib/gmail-query.ts +10 -0
- package/corpus/templates/mail/server/lib/google-auth.ts +5 -8
- package/corpus/templates/mail/server/lib/jobs.ts +1 -5
- package/corpus/templates/mail/server/onboarding.ts +2 -2
- package/corpus/templates/mail/server/plugins/agent-chat.ts +5 -2
- package/corpus/templates/mail/server/plugins/auth.ts +1 -0
- package/corpus/templates/mail/server/plugins/core-routes.ts +4 -1
- package/corpus/templates/mail/server/plugins/db.ts +6 -0
- package/corpus/templates/mail/server/routes/api/attachments.get.ts +1 -5
- package/corpus/templates/mail/shared/ai-filter.ts +74 -0
- package/corpus/templates/mail/shared/types.ts +2 -0
- package/corpus/templates/plan/.agents/skills/frontend-design/SKILL.md +4 -0
- package/corpus/templates/plan/.agents/skills/secrets/SKILL.md +47 -0
- package/corpus/templates/plan/actions/list-plan-versions.ts +20 -5
- package/corpus/templates/plan/agent-native.json +1 -4
- package/corpus/templates/plan/app/components/editor/PlanDocumentEditor.tsx +5 -2
- package/corpus/templates/plan/app/components/layout/Layout.tsx +41 -1
- package/corpus/templates/plan/app/components/layout/Sidebar.tsx +4 -16
- package/corpus/templates/plan/app/components/plan/PlanMarkdownEditor.tsx +7 -4
- package/corpus/templates/plan/app/components/plan/wireframe/Wireframe.tsx +1 -1
- package/corpus/templates/plan/app/components/plan/wireframe/html-artboard.css +15 -0
- package/corpus/templates/plan/app/components/plan/wireframe/kit/plan-wireframe-tokens.css +0 -15
- package/corpus/templates/plan/app/components/plan/wireframe/kit/primitives.tsx +2 -2
- package/corpus/templates/plan/app/hooks/use-plan-presence.ts +20 -10
- package/corpus/templates/plan/app/pages/PlansPage.tsx +2 -2
- package/corpus/templates/plan/app/root.tsx +13 -7
- package/corpus/templates/plan/app/routes/_index.tsx +31 -6
- package/corpus/templates/plan/app/routes/chat.tsx +3 -6
- package/corpus/templates/plan/app/routes/home.tsx +11 -0
- package/corpus/templates/plan/app/routes/local-plans.$slug.tsx +2 -6
- package/corpus/templates/plan/app/routes/plans.$id.tsx +3 -6
- package/corpus/templates/plan/app/routes/plans.tsx +3 -6
- package/corpus/templates/plan/app/routes/recaps.$id.tsx +3 -6
- package/corpus/templates/plan/app/routes/recaps.tsx +3 -6
- package/corpus/templates/plan/changelog/2026-08-28-plan-loading-skeletons-use-a-softer-whole-surface.md +6 -0
- package/corpus/templates/plan/changelog/2026-08-29-plan-loading-shine-is-more-subtle.md +6 -0
- package/corpus/templates/plan/public/manifest.json +1 -1
- package/corpus/templates/plan/server/db/schema.ts +1 -0
- package/corpus/templates/plan/server/lib/plan-versions.ts +57 -0
- package/corpus/templates/plan/server/plugins/agent-chat.ts +83 -0
- package/corpus/templates/plan/server/plugins/core-routes.ts +1 -0
- package/corpus/templates/plan/server/plugins/db.ts +10 -0
- package/corpus/templates/slides/.agents/skills/frontend-design/SKILL.md +4 -0
- package/corpus/templates/slides/.agents/skills/secrets/SKILL.md +47 -0
- package/corpus/templates/slides/CHANGELOG.md +9 -0
- package/corpus/templates/slides/actions/_deck-write.ts +65 -0
- package/corpus/templates/slides/actions/add-slide.ts +44 -24
- package/corpus/templates/slides/actions/clone-context-slide.ts +22 -12
- package/corpus/templates/slides/actions/create-deck.ts +36 -21
- package/corpus/templates/slides/actions/delete-design-system.ts +10 -3
- package/corpus/templates/slides/actions/import-file.ts +9 -3
- package/corpus/templates/slides/actions/import-pptx.ts +11 -4
- package/corpus/templates/slides/actions/list-deck-versions.ts +20 -8
- package/corpus/templates/slides/actions/patch-deck.ts +29 -3
- package/corpus/templates/slides/actions/restore-deck-version.ts +37 -22
- package/corpus/templates/slides/actions/save-deck.ts +35 -22
- package/corpus/templates/slides/actions/update-deck-aspect-ratio.ts +31 -16
- package/corpus/templates/slides/actions/update-slide.ts +250 -37
- package/corpus/templates/slides/app/components/deck/SlideRenderer.tsx +10 -4
- package/corpus/templates/slides/app/components/editor/EditorActionCluster.tsx +2 -2
- package/corpus/templates/slides/app/components/editor/EditorToolbar.tsx +7 -8
- package/corpus/templates/slides/app/components/editor/ImageOverlay.tsx +78 -12
- package/corpus/templates/slides/app/components/editor/SlideContextToolbar.tsx +42 -4
- package/corpus/templates/slides/app/components/editor/SlideEditor.tsx +381 -53
- package/corpus/templates/slides/app/components/editor/SlidesLayersPanel.tsx +20 -34
- package/corpus/templates/slides/app/components/editor/slide-style.ts +5 -0
- package/corpus/templates/slides/app/components/editor/style-clipboard.ts +2 -0
- package/corpus/templates/slides/app/components/layout/AgentWorkIndicator.tsx +18 -2
- package/corpus/templates/slides/app/components/layout/Header.tsx +1 -1
- package/corpus/templates/slides/app/components/layout/Layout.tsx +39 -10
- package/corpus/templates/slides/app/components/layout/Sidebar.tsx +7 -20
- package/corpus/templates/slides/app/components/presentation/PresenterView.tsx +35 -15
- package/corpus/templates/slides/app/components/presentation/present-channel.ts +12 -0
- package/corpus/templates/slides/app/global.css +45 -13
- package/corpus/templates/slides/app/hooks/use-navigation-state.ts +1 -1
- package/corpus/templates/slides/app/i18n/en-US.ts +11 -0
- package/corpus/templates/slides/app/lib/sanitize-slide-html.ts +133 -5
- package/corpus/templates/slides/app/lib/slide-image-replacement.ts +741 -17
- package/corpus/templates/slides/app/lib/validate-native-slide-html.ts +1 -0
- package/corpus/templates/slides/app/pages/DeckEditor.tsx +288 -95
- package/corpus/templates/slides/app/pages/DesignSystems.tsx +5 -5
- package/corpus/templates/slides/app/pages/Index.tsx +7 -7
- package/corpus/templates/slides/app/pages/NotFound.tsx +1 -1
- package/corpus/templates/slides/app/pages/SharedPresentation.tsx +1 -1
- package/corpus/templates/slides/app/root.tsx +4 -23
- package/corpus/templates/slides/app/routes/_index.tsx +18 -7
- package/corpus/templates/slides/app/routes/home.tsx +26 -0
- package/corpus/templates/slides/changelog/2026-08-27-image-fit-controls-apply-cover-crops-and-position.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-28-image-edits-persist-while-dropped-images-finish-uploading.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-28-shared-slides-with-a-style-block-render-again.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-28-slides-loading-skeletons-use-a-softer-whole-surface.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-28-standard-empty-home-layout.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-29-chat-imports-attached-decks-on-request.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-29-slides-loading-shine-is-more-subtle.md +6 -0
- package/corpus/templates/slides/package.json +3 -0
- package/corpus/templates/slides/public/manifest.json +1 -1
- package/corpus/templates/slides/server/db/schema.ts +1 -0
- package/corpus/templates/slides/server/handlers/google-docs-auth.ts +1 -1
- package/corpus/templates/slides/server/lib/chat-attachments.ts +102 -7
- package/corpus/templates/slides/server/lib/deck-versions.ts +77 -2
- package/corpus/templates/slides/server/plugins/agent-chat.ts +95 -1
- package/corpus/templates/slides/server/plugins/auth.ts +1 -0
- package/corpus/templates/slides/server/plugins/core-routes.ts +8 -1
- package/corpus/templates/slides/server/plugins/db.ts +5 -0
- package/corpus/templates/tasks/.agents/skills/frontend-design/SKILL.md +4 -0
- package/corpus/templates/tasks/.agents/skills/secrets/SKILL.md +47 -0
- package/corpus/templates/tasks/AGENTS.md +2 -1
- package/corpus/templates/tasks/README.md +3 -1
- package/corpus/templates/tasks/app/components/layout/Sidebar.tsx +5 -18
- package/corpus/templates/tasks/app/root.tsx +19 -3
- package/corpus/templates/tasks/app/routes/_index.tsx +28 -14
- package/corpus/templates/tasks/app/routes/home.tsx +24 -0
- package/corpus/templates/tasks/public/manifest.json +1 -1
- package/corpus/templates/tasks/server/plugins/auth.ts +1 -0
- package/dist/a2a/client.d.ts +4 -0
- package/dist/a2a/client.js +15 -2
- package/dist/action.d.ts +3 -1
- package/dist/agent/engine/ai-sdk-engine.js +13 -9
- package/dist/agent/engine/anthropic-engine.js +2 -1
- package/dist/agent/engine/builder-engine.js +23 -5
- package/dist/agent/engine/limit-provider-tools.d.ts +3 -0
- package/dist/agent/engine/limit-provider-tools.js +23 -0
- package/dist/agent/engine/openai-compatible-endpoint.d.ts +2 -0
- package/dist/agent/engine/openai-compatible-endpoint.js +4 -0
- package/dist/agent/engine/output-tokens.d.ts +12 -6
- package/dist/agent/engine/output-tokens.js +42 -16
- package/dist/agent/engine/registry.d.ts +1 -1
- package/dist/agent/engine/registry.js +69 -16
- package/dist/agent/production-agent.js +107 -13
- package/dist/agent/run-manager.d.ts +9 -0
- package/dist/agent/run-manager.js +35 -6
- package/dist/agent/thread-data-builder.d.ts +6 -1
- package/dist/agent/thread-data-builder.js +20 -5
- package/dist/agent/types.d.ts +2 -0
- package/dist/app-config/agent.d.ts +4 -0
- package/dist/app-config/agent.js +44 -0
- package/dist/app-config/integrations.d.ts +1 -0
- package/dist/app-config/integrations.js +8 -0
- package/dist/app-config/migration.d.ts +1 -0
- package/dist/app-config/migration.js +4 -0
- package/dist/app-config/observability.d.ts +4 -1
- package/dist/app-config/observability.js +25 -1
- package/dist/app-config/schema.d.ts +9 -0
- package/dist/app-config/store.js +1 -0
- package/dist/client/AgentAskPopover.d.ts +2 -1
- package/dist/client/AgentAskPopover.js +2 -2
- package/dist/client/AgentPanel.d.ts +35 -10
- package/dist/client/AgentPanel.js +136 -119
- package/dist/client/AssistantChat.d.ts +9 -2
- package/dist/client/AssistantChat.js +161 -36
- package/dist/client/ConnectBuilderCard.js +3 -1
- package/dist/client/DefaultSpinner.d.ts +13 -1
- package/dist/client/DefaultSpinner.js +52 -46
- package/dist/client/FeedbackButton.d.ts +12 -0
- package/dist/client/FeedbackButton.js +62 -28
- package/dist/client/MultiTabAssistantChat.js +30 -11
- package/dist/client/NewWorkspaceAppFlow.js +5 -3
- package/dist/client/agent-chat/index.d.ts +1 -0
- package/dist/client/agent-chat/index.js +1 -0
- package/dist/client/agent-chat-adapter.js +16 -1
- package/dist/client/agent-chat.d.ts +9 -0
- package/dist/client/agent-chat.js +6 -3
- package/dist/client/agent-page/AgentJobsTab.d.ts +2 -1
- package/dist/client/agent-page/AgentJobsTab.js +8 -5
- package/dist/client/agent-page/AgentTabsPage.js +2 -2
- package/dist/client/analytics.d.ts +2 -0
- package/dist/client/analytics.js +86 -15
- package/dist/client/app-providers.js +13 -1
- package/dist/client/auth/AuthPage.d.ts +87 -0
- package/dist/client/auth/AuthPage.js +1847 -0
- package/dist/client/auth/ResetPasswordPage.d.ts +9 -0
- package/dist/client/auth/ResetPasswordPage.js +119 -0
- package/dist/client/auth/entry.d.ts +1 -0
- package/dist/client/auth/entry.js +15 -0
- package/dist/client/chat/message-components.d.ts +53 -0
- package/dist/client/chat/message-components.js +181 -11
- package/dist/client/chat/run-recovery.d.ts +4 -1
- package/dist/client/chat/run-recovery.js +30 -12
- package/dist/client/chat/tool-call-display.d.ts +4 -2
- package/dist/client/chat/tool-call-display.js +16 -11
- package/dist/client/chat-first.js +8 -2
- package/dist/client/chat-model-groups.js +11 -1
- package/dist/client/collab/index.d.ts +1 -1
- package/dist/client/components/CodeRequiredDialog.js +22 -35
- package/dist/client/components/icons/AgentNativeIcon.d.ts +3 -3
- package/dist/client/components/icons/AgentNativeIcon.js +4 -4
- package/dist/client/components/ui/message-scroller.js +1 -1
- package/dist/client/composer/runtime-adapters.js +2 -0
- package/dist/client/feedback-context.d.ts +1 -0
- package/dist/client/feedback-context.js +3 -2
- package/dist/client/host-bridge.d.ts +1 -0
- package/dist/client/index.d.ts +2 -2
- package/dist/client/index.js +1 -1
- package/dist/client/integrations/IntegrationsPanel.d.ts +2 -1
- package/dist/client/integrations/IntegrationsPanel.js +3 -3
- package/dist/client/observability/ThumbsFeedback.js +73 -10
- package/dist/client/onboarding/FirstRunOnboarding.js +24 -15
- package/dist/client/onboarding/OnboardingPanel.js +5 -3
- package/dist/client/onboarding/first-run-startup-gate.js +7 -1
- package/dist/client/resources/McpIntegrationDialog.d.ts +2 -1
- package/dist/client/resources/McpIntegrationDialog.js +10 -2
- package/dist/client/session-replay.js +10 -0
- package/dist/client/settings/BuilderConnectPopover.d.ts +25 -0
- package/dist/client/settings/BuilderConnectPopover.js +55 -0
- package/dist/client/settings/SettingsPanel.js +21 -7
- package/dist/client/settings/SettingsTabsPage.d.ts +1 -1
- package/dist/client/settings/SettingsTabsPage.js +42 -25
- package/dist/client/settings/VoiceTranscriptionSection.js +16 -22
- package/dist/client/settings/index.d.ts +1 -0
- package/dist/client/settings/index.js +1 -0
- package/dist/client/settings/useBuilderStatus.d.ts +7 -0
- package/dist/client/settings/useBuilderStatus.js +77 -21
- package/dist/client/setup-connections/BuilderConnectCard.js +2 -1
- package/dist/client/setup-connections/useBuilderConnectCardController.d.ts +3 -1
- package/dist/client/setup-connections/useBuilderConnectCardController.js +4 -2
- package/dist/client/sse-event-processor.js +8 -0
- package/dist/client/terminal/AgentTerminal.js +6 -7
- package/dist/client/transcription/BuilderTranscriptionCta.js +17 -69
- package/dist/client/ui/index.d.ts +1 -0
- package/dist/client/ui/index.js +1 -0
- package/dist/client/use-chat-models.js +5 -4
- package/dist/client/webmcp.d.ts +4 -0
- package/dist/client/webmcp.js +51 -4
- package/dist/collab/client.d.ts +13 -0
- package/dist/collab/client.js +96 -21
- package/dist/dashboard-storage/index.d.ts +1 -1
- package/dist/dashboard-storage/schema.d.ts +19 -0
- package/dist/dashboard-storage/schema.js +1 -0
- package/dist/dashboard-storage/store.d.ts +9 -0
- package/dist/dashboard-storage/store.js +93 -3
- package/dist/deploy/build.d.ts +19 -3
- package/dist/deploy/build.js +262 -10
- package/dist/index.browser.d.ts +1 -1
- package/dist/index.browser.js +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/ingestion/media.js +7 -2
- package/dist/integrations/config-store.js +2 -4
- package/dist/integrations/google-docs-poller.d.ts +1 -1
- package/dist/integrations/google-docs-poller.js +100 -24
- package/dist/integrations/plugin.js +45 -15
- package/dist/integrations/webhook-handler.js +2 -1
- package/dist/jobs/background-automation-runner.js +17 -1
- package/dist/localization/core-messages/ar-SA.js +19 -0
- package/dist/localization/core-messages/de-DE.js +19 -0
- package/dist/localization/core-messages/en-US.d.ts +19 -0
- package/dist/localization/core-messages/en-US.js +19 -0
- package/dist/localization/core-messages/es-ES.js +19 -0
- package/dist/localization/core-messages/fr-FR.js +19 -0
- package/dist/localization/core-messages/hi-IN.js +19 -0
- package/dist/localization/core-messages/ja-JP.js +19 -0
- package/dist/localization/core-messages/ko-KR.js +19 -0
- package/dist/localization/core-messages/pt-BR.js +19 -0
- package/dist/localization/core-messages/zh-CN.js +19 -0
- package/dist/localization/core-messages/zh-TW.js +19 -0
- package/dist/localization/core-messages.d.ts +19 -0
- package/dist/localization/default-messages.d.ts +11 -0
- package/dist/localization/default-messages.js +11 -0
- package/dist/mcp/analytics.d.ts +103 -0
- package/dist/mcp/analytics.js +204 -0
- package/dist/mcp/build-server.d.ts +7 -0
- package/dist/mcp/build-server.js +132 -35
- package/dist/mcp/screen-memory-stdio.d.ts +7 -7
- package/dist/mcp/server.js +37 -8
- package/dist/mcp/stdio.js +1 -0
- package/dist/mcp-client/errors.js +30 -10
- package/dist/mcp-client/oauth-routes.d.ts +7 -2
- package/dist/mcp-client/oauth-routes.js +12 -3
- package/dist/mcp-client/routes.js +2 -1
- package/dist/oauth-tokens/store.js +6 -3
- package/dist/observability/routes.d.ts +5 -5
- package/dist/observability/routes.js +8 -2
- package/dist/observability/store.d.ts +1 -1
- package/dist/observability/store.js +18 -3
- package/dist/observability/types.d.ts +1 -0
- package/dist/onboarding/plugin.js +16 -4
- package/dist/progress/routes.d.ts +1 -1
- package/dist/provider-api/actions/custom-provider-registration.d.ts +16 -16
- package/dist/provider-api/actions/provider-api.d.ts +12 -12
- package/dist/resources/handlers.d.ts +2 -2
- package/dist/secrets/routes.d.ts +9 -9
- package/dist/server/action-routes.d.ts +1 -6
- package/dist/server/action-routes.js +61 -18
- package/dist/server/agent-chat/plugin-options.d.ts +8 -1
- package/dist/server/agent-chat-plugin.d.ts +3 -0
- package/dist/server/agent-chat-plugin.js +49 -4
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/agent-run-context.d.ts +1 -0
- package/dist/server/agent-run-context.js +6 -0
- package/dist/server/analytics.d.ts +3 -2
- package/dist/server/analytics.js +18 -7
- package/dist/server/app-url.d.ts +5 -2
- package/dist/server/app-url.js +4 -3
- package/dist/server/auth.d.ts +25 -0
- package/dist/server/auth.js +168 -21
- package/dist/server/better-auth-instance.js +18 -4
- package/dist/server/better-auth-migrations.d.ts +14 -0
- package/dist/server/better-auth-migrations.js +5 -1
- package/dist/server/builder-api-auth.js +30 -6
- package/dist/server/builder-browser.d.ts +10 -0
- package/dist/server/builder-browser.js +22 -5
- package/dist/server/builder-design-systems.d.ts +11 -0
- package/dist/server/builder-design-systems.js +52 -3
- package/dist/server/builder-oauth.d.ts +13 -6
- package/dist/server/builder-oauth.js +121 -63
- package/dist/server/capture-error.js +3 -0
- package/dist/server/cookie-namespace.d.ts +1 -0
- package/dist/server/cookie-namespace.js +3 -0
- package/dist/server/core-routes-plugin.d.ts +25 -9
- package/dist/server/core-routes-plugin.js +180 -76
- package/dist/server/credential-provider.js +22 -12
- package/dist/server/email.d.ts +4 -0
- package/dist/server/email.js +13 -5
- package/dist/server/framework-request-handler.js +6 -3
- package/dist/server/google-credential-check.d.ts +7 -3
- package/dist/server/google-credential-check.js +71 -0
- package/dist/server/google-oauth-credentials.d.ts +4 -3
- package/dist/server/google-oauth-credentials.js +7 -8
- package/dist/server/google-oauth.d.ts +9 -4
- package/dist/server/google-oauth.js +14 -93
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.js +1 -1
- package/dist/server/jwks-secret-rotation.d.ts +29 -0
- package/dist/server/jwks-secret-rotation.js +150 -0
- package/dist/server/onboarding-html.d.ts +2 -14
- package/dist/server/onboarding-html.js +254 -2519
- package/dist/server/origin-allowlist.d.ts +15 -0
- package/dist/server/origin-allowlist.js +93 -0
- package/dist/server/release-migrations.js +48 -0
- package/dist/server/request-context.d.ts +2 -0
- package/dist/server/request-context.js +7 -2
- package/dist/server/self-dispatch.js +5 -0
- package/dist/server/sentry.js +5 -0
- package/dist/server/ssr-handler.js +5 -0
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/dist/server/workspace-provider-oauth.d.ts +9 -0
- package/dist/server/workspace-provider-oauth.js +96 -31
- package/dist/shared/index.d.ts +2 -0
- package/dist/shared/index.js +2 -0
- package/dist/shared/loading-labels.d.ts +1 -0
- package/dist/shared/loading-labels.js +55 -0
- package/dist/shared/qa-test-email.d.ts +1 -0
- package/dist/shared/qa-test-email.js +42 -0
- package/dist/shared/route-warmup-config.js +2 -2
- package/dist/shared/sign-in-journey.js +1 -1
- package/dist/shared/ssr-auth-redirect.d.ts +8 -0
- package/dist/shared/ssr-auth-redirect.js +56 -0
- package/dist/shared/test-traffic.d.ts +8 -0
- package/dist/shared/test-traffic.js +11 -0
- package/dist/styles/agent-native.css +50 -14
- package/dist/styles/blocks.css +0 -6
- package/dist/templates/chat/.agents/skills/frontend-design/SKILL.md +4 -0
- package/dist/templates/chat/.agents/skills/secrets/SKILL.md +47 -0
- package/dist/templates/chat/AGENTS.md +5 -4
- package/dist/templates/chat/app/components/layout/Header.tsx +1 -1
- package/dist/templates/chat/app/components/layout/Layout.tsx +5 -4
- package/dist/templates/chat/app/components/layout/Sidebar.tsx +16 -25
- package/dist/templates/chat/app/hooks/use-navigation-state.ts +5 -5
- package/dist/templates/chat/app/root.tsx +16 -3
- package/dist/templates/chat/app/routes/_index.tsx +17 -74
- package/dist/templates/chat/app/routes/chat.$threadId.tsx +1 -1
- package/dist/templates/chat/app/routes/home.tsx +94 -0
- package/dist/templates/chat/netlify.toml +2 -1
- package/dist/templates/chat/public/manifest.json +1 -1
- package/dist/templates/chat/server/plugins/auth.ts +1 -0
- package/dist/templates/default/.agents/skills/frontend-design/SKILL.md +4 -0
- package/dist/templates/default/.agents/skills/secrets/SKILL.md +47 -0
- package/dist/templates/default/AGENTS.md +10 -6
- package/dist/templates/default/DEVELOPING.md +8 -1
- package/dist/templates/default/app/hooks/use-navigation-state.ts +1 -1
- package/dist/templates/default/app/root.tsx +10 -3
- package/dist/templates/default/app/routes/_index.tsx +10 -86
- package/dist/templates/default/app/routes/home.tsx +94 -0
- package/dist/templates/default/app/routes/settings.tsx +1 -1
- package/dist/templates/default/public/manifest.json +1 -1
- package/dist/templates/default/server/plugins/auth.ts +5 -0
- package/dist/templates/headless/.agents/skills/secrets/SKILL.md +47 -0
- package/dist/templates/workspace-core/.agents/skills/frontend-design/SKILL.md +4 -0
- package/dist/templates/workspace-core/.agents/skills/secrets/SKILL.md +47 -0
- package/dist/templates/workspace-root/.env.example +3 -2
- package/dist/terminal/pty-server.d.ts +2 -0
- package/dist/terminal/pty-server.js +22 -5
- package/dist/tracking/registry.d.ts +1 -0
- package/dist/tracking/registry.js +12 -0
- package/dist/usage/store.d.ts +1 -0
- package/dist/usage/store.js +16 -7
- package/dist/vite/client.d.ts +1 -1
- package/dist/vite/client.js +59 -0
- package/dist/workspace-connections/index.d.ts +1 -1
- package/dist/workspace-connections/index.js +1 -1
- package/dist/workspace-connections/store.d.ts +1 -0
- package/dist/workspace-connections/store.js +4 -0
- package/docs/content/aws-amplify.mdx +179 -0
- package/docs/content/client-agent-chat.mdx +1 -1
- package/docs/content/deploy-an-app.mdx +2 -1
- package/docs/content/deployment.mdx +14 -3
- package/docs/content/environment-variables.mdx +1 -0
- package/docs/content/template-forms-agent.mdx +65 -0
- package/docs/content/template-forms-developers.mdx +220 -65
- package/docs/content/template-forms-features.mdx +154 -0
- package/docs/content/template-forms-integrations.mdx +40 -0
- package/docs/content/template-forms.mdx +49 -36
- package/docs/content/template-mail-developers.mdx +3 -3
- package/docs/content/toolkit-settings.mdx +3 -3
- package/docs/content/webmcp.mdx +31 -12
- package/package.json +3 -3
- package/src/templates/chat/.agents/skills/frontend-design/SKILL.md +4 -0
- package/src/templates/chat/.agents/skills/secrets/SKILL.md +47 -0
- package/src/templates/chat/AGENTS.md +5 -4
- package/src/templates/chat/app/components/layout/Header.tsx +1 -1
- package/src/templates/chat/app/components/layout/Layout.tsx +5 -4
- package/src/templates/chat/app/components/layout/Sidebar.tsx +16 -25
- package/src/templates/chat/app/hooks/use-navigation-state.ts +5 -5
- package/src/templates/chat/app/root.tsx +16 -3
- package/src/templates/chat/app/routes/_index.tsx +17 -74
- package/src/templates/chat/app/routes/chat.$threadId.tsx +1 -1
- package/src/templates/chat/app/routes/home.tsx +94 -0
- package/src/templates/chat/netlify.toml +2 -1
- package/src/templates/chat/public/manifest.json +1 -1
- package/src/templates/chat/server/plugins/auth.ts +1 -0
- package/src/templates/default/.agents/skills/frontend-design/SKILL.md +4 -0
- package/src/templates/default/.agents/skills/secrets/SKILL.md +47 -0
- package/src/templates/default/AGENTS.md +10 -6
- package/src/templates/default/DEVELOPING.md +8 -1
- package/src/templates/default/app/hooks/use-navigation-state.ts +1 -1
- package/src/templates/default/app/root.tsx +10 -3
- package/src/templates/default/app/routes/_index.tsx +10 -86
- package/src/templates/default/app/routes/home.tsx +94 -0
- package/src/templates/default/app/routes/settings.tsx +1 -1
- package/src/templates/default/public/manifest.json +1 -1
- package/src/templates/default/server/plugins/auth.ts +5 -0
- package/src/templates/headless/.agents/skills/secrets/SKILL.md +47 -0
- package/src/templates/workspace-core/.agents/skills/frontend-design/SKILL.md +4 -0
- package/src/templates/workspace-core/.agents/skills/secrets/SKILL.md +47 -0
- package/src/templates/workspace-root/.env.example +3 -2
- package/corpus/templates/factory/actions/approve-factory-item.ts +0 -244
- package/corpus/templates/factory/app/components/factory/FactorySourceSettingsGroup.tsx +0 -33
- package/corpus/templates/factory/server/routes/_agent-native/factory/builder-callback.post.ts +0 -116
- package/corpus/templates/factory/server/triage/ai-services-git.ts +0 -205
- package/corpus/templates/factory/server/triage/builder-executor.ts +0 -123
- package/docs/content/template-forms-building-publishing.mdx +0 -135
- package/docs/content/template-forms-responses.mdx +0 -120
- /package/corpus/templates/clips/{server/lib → shared}/upload-interruption.ts +0 -0
|
@@ -6,16 +6,19 @@
|
|
|
6
6
|
*
|
|
7
7
|
* After first account exists, this page acts as a normal login page.
|
|
8
8
|
*/
|
|
9
|
+
import { createElement } from "react";
|
|
10
|
+
import { renderToString } from "react-dom/server";
|
|
9
11
|
import { getAppConfig } from "../app-config/index.js";
|
|
12
|
+
import { AuthPage, } from "../client/auth/AuthPage.js";
|
|
13
|
+
import { ResetPasswordPage } from "../client/auth/ResetPasswordPage.js";
|
|
10
14
|
import { getLocaleInitScript } from "../localization/server.js";
|
|
11
15
|
import { DEFAULT_LOCALE, LOCALE_METADATA, LOCALE_STORAGE_KEY, SUPPORTED_LOCALES, localeDisplayName, } from "../localization/shared.js";
|
|
12
16
|
import { NATIVE_AUTH_COPY } from "../shared/auth-copy.js";
|
|
13
17
|
import { docsUrl } from "../shared/docs-url.js";
|
|
14
18
|
import { BETA_FORCE_QUERY_PARAM, BETA_FORCE_SESSION_STORAGE_KEY, BETA_OPT_OUT_DURATION_MS, BETA_OPT_OUT_QUERY_PARAM, BETA_OPT_OUT_STORAGE_KEY, ENVIRONMENT_BETA_HOSTS, } from "../shared/environment-lanes.js";
|
|
15
19
|
import { PASSWORD_MAX_LENGTH, PASSWORD_MIN_LENGTH, } from "../shared/password-policy.js";
|
|
16
|
-
import { signInJourneyInlineScript } from "../shared/sign-in-journey.js";
|
|
17
20
|
import { AGENT_NATIVE_SOCIAL_IMAGE_ALT, AGENT_NATIVE_SOCIAL_IMAGE_HEIGHT, AGENT_NATIVE_SOCIAL_IMAGE_PATH, AGENT_NATIVE_SOCIAL_IMAGE_TYPE, AGENT_NATIVE_SOCIAL_IMAGE_WIDTH, withAgentNativeSocialImageCacheBuster, } from "../shared/social-meta.js";
|
|
18
|
-
import { normalizeAppBasePath } from "./app-base-path.js";
|
|
21
|
+
import { getAppBasePathFromViteEnv, normalizeAppBasePath, } from "./app-base-path.js";
|
|
19
22
|
import { AUTH_MARKETING_LOCALE_COPY, } from "./auth-marketing-locales.js";
|
|
20
23
|
import { BUILT_IN_AUTH_MARKETING, resolveBuiltInAuthMarketing, resolveBuiltInAuthMarketingSlug, } from "./auth-marketing.js";
|
|
21
24
|
import { resolveGoogleAuthMode, } from "./google-auth-mode.js";
|
|
@@ -64,9 +67,9 @@ function workspaceBasePathFromRequest(requestPath) {
|
|
|
64
67
|
}
|
|
65
68
|
return normalizeAppBasePath(`/${firstSegment}`);
|
|
66
69
|
}
|
|
67
|
-
function withAppBasePath(path) {
|
|
70
|
+
function withAppBasePath(path, explicitBasePath) {
|
|
68
71
|
const cleanPath = path.startsWith("/") ? path : `/${path}`;
|
|
69
|
-
const basePath =
|
|
72
|
+
const basePath = explicitBasePath ?? getAppBasePathFromViteEnv();
|
|
70
73
|
return `${basePath}${cleanPath}`;
|
|
71
74
|
}
|
|
72
75
|
const AGENT_NATIVE_TERMS_URL = "https://www.agent-native.com/terms";
|
|
@@ -877,7 +880,6 @@ const AUTH_LOCALE_COPY = {
|
|
|
877
880
|
googlePopupHelp: "اسمح بالنوافذ المنبثقة لهذا الموقع ثم حاول مرة أخرى",
|
|
878
881
|
},
|
|
879
882
|
};
|
|
880
|
-
const defaultAuthCopy = AUTH_LOCALE_COPY[DEFAULT_LOCALE];
|
|
881
883
|
function resolveBuiltInMarketingSlug(marketing, opts = {}) {
|
|
882
884
|
if (!marketing)
|
|
883
885
|
return undefined;
|
|
@@ -918,14 +920,47 @@ function isAgentNativeHostedHost(host) {
|
|
|
918
920
|
const hostname = normalizeRequestHostname(host);
|
|
919
921
|
return (hostname === "agent-native.com" || hostname.endsWith(".agent-native.com"));
|
|
920
922
|
}
|
|
923
|
+
function initialAuthView(opts, authMode, googleOnly) {
|
|
924
|
+
if (googleOnly)
|
|
925
|
+
return "googleOnly";
|
|
926
|
+
if (authMode === "magic-link")
|
|
927
|
+
return "magicLink";
|
|
928
|
+
try {
|
|
929
|
+
const url = new URL(opts.requestPath ?? "/", "https://agent-native.local");
|
|
930
|
+
if (url.searchParams.has("verified") ||
|
|
931
|
+
url.searchParams.get("error") === "verification_link_invalid") {
|
|
932
|
+
return "login";
|
|
933
|
+
}
|
|
934
|
+
const requestedView = url.searchParams.get("tab");
|
|
935
|
+
if (requestedView === "login" || requestedView === "signup") {
|
|
936
|
+
return requestedView;
|
|
937
|
+
}
|
|
938
|
+
const pathname = url.pathname.replace(/\/+$/, "") || "/";
|
|
939
|
+
if (pathname.endsWith("/login"))
|
|
940
|
+
return "login";
|
|
941
|
+
if (pathname.endsWith("/signup"))
|
|
942
|
+
return "signup";
|
|
943
|
+
}
|
|
944
|
+
catch (error) {
|
|
945
|
+
// coercion-ok: malformed paths use the public signup state; no session data is inferred.
|
|
946
|
+
void error;
|
|
947
|
+
}
|
|
948
|
+
return "signup";
|
|
949
|
+
}
|
|
950
|
+
function serializeAuthPageData(value) {
|
|
951
|
+
return JSON.stringify(value)
|
|
952
|
+
.replaceAll("&", "\\u0026")
|
|
953
|
+
.replaceAll("<", "\\u003c")
|
|
954
|
+
.replaceAll(">", "\\u003e")
|
|
955
|
+
.replaceAll("\u2028", "\\u2028")
|
|
956
|
+
.replaceAll("\u2029", "\\u2029");
|
|
957
|
+
}
|
|
921
958
|
export function getOnboardingHtml(opts = {}) {
|
|
922
959
|
const showGoogle = hasGoogleOAuth();
|
|
923
960
|
const googleOnly = !!opts.googleOnly;
|
|
924
961
|
const authMode = opts.authMode ?? "password";
|
|
925
|
-
const magicLinkMode = authMode === "magic-link";
|
|
926
962
|
const simplifiedAuth = opts.initialPrompt === true;
|
|
927
|
-
const
|
|
928
|
-
const configuredAppBasePath = normalizeAppBasePath(process.env.VITE_APP_BASE_PATH || process.env.APP_BASE_PATH);
|
|
963
|
+
const configuredAppBasePath = getAppBasePathFromViteEnv();
|
|
929
964
|
const appBasePath = configuredAppBasePath || workspaceBasePathFromRequest(opts.requestPath);
|
|
930
965
|
const workspaceRuntime = isWorkspaceRuntime();
|
|
931
966
|
const trackingApp = getAppConfig().app.slug ??
|
|
@@ -957,13 +992,6 @@ export function getOnboardingHtml(opts = {}) {
|
|
|
957
992
|
requestHost: opts.requestHost,
|
|
958
993
|
requestPath: opts.requestPath,
|
|
959
994
|
});
|
|
960
|
-
const defaultMarketingCopy = marketing
|
|
961
|
-
? {
|
|
962
|
-
tagline: marketing.tagline,
|
|
963
|
-
description: marketing.description,
|
|
964
|
-
features: marketing.features,
|
|
965
|
-
}
|
|
966
|
-
: undefined;
|
|
967
995
|
const localizedMarketingCopy = {};
|
|
968
996
|
if (marketingSlug) {
|
|
969
997
|
for (const [locale, copyBySlug] of Object.entries(AUTH_MARKETING_LOCALE_COPY)) {
|
|
@@ -979,65 +1007,11 @@ export function getOnboardingHtml(opts = {}) {
|
|
|
979
1007
|
command: marketing.signupLocalModeNote.command.trim(),
|
|
980
1008
|
}
|
|
981
1009
|
: undefined;
|
|
982
|
-
const brandMarkSrc = withAppBasePath("/agent-native-icon-dark.svg");
|
|
1010
|
+
const brandMarkSrc = withAppBasePath("/agent-native-icon-dark.svg", appBasePath);
|
|
983
1011
|
const socialImageUrl = withAgentNativeSocialImageCacheBuster(opts.requestOrigin
|
|
984
|
-
? `${opts.requestOrigin}${withAppBasePath(AGENT_NATIVE_SOCIAL_IMAGE_PATH)}`
|
|
985
|
-
: withAppBasePath(AGENT_NATIVE_SOCIAL_IMAGE_PATH));
|
|
986
|
-
const
|
|
987
|
-
.replace(/&/g, "&")
|
|
988
|
-
.replace(/</g, "<")
|
|
989
|
-
.replace(/>/g, ">")
|
|
990
|
-
.replace(/"/g, """);
|
|
991
|
-
const t = (key) => defaultAuthCopy[key];
|
|
992
|
-
const i18nAttr = (key) => key ? ` data-i18n="${key}"` : "";
|
|
993
|
-
const googleUnavailableHtml = googleOnly && !showGoogle
|
|
994
|
-
? `<p class="google-error show" id="google-err" role="status"${i18nAttr("googleNotConfigured")}>${esc(t("googleNotConfigured"))}</p>`
|
|
995
|
-
: "";
|
|
996
|
-
const i18nAriaAttr = (key) => key ? ` data-i18n-aria-label="${key}"` : "";
|
|
997
|
-
const i18nPlaceholderAttr = (key) => key ? ` data-i18n-placeholder="${key}"` : "";
|
|
998
|
-
const i18nDataAttr = (attr, key) => (key ? ` data-i18n-${attr}="${key}"` : "");
|
|
999
|
-
const i18nText = (key) => `<span${i18nAttr(key)}>${esc(t(key))}</span>`;
|
|
1000
|
-
const localizedValue = (value, key) => (value === undefined ? i18nText(key) : esc(value));
|
|
1001
|
-
const localizedAnchorLabel = (value, key) => value === undefined ? `${i18nAttr(key)}>${esc(t(key))}` : `>${esc(value)}`;
|
|
1002
|
-
const localeMenuItemsHtml = [
|
|
1003
|
-
` <button type="button" class="locale-menu-item" role="menuitemradio" aria-checked="false" data-locale-value="system">
|
|
1004
|
-
<span class="locale-menu-check" aria-hidden="true">✓</span>
|
|
1005
|
-
<span data-system-language>${esc(t("systemLanguage"))}</span>
|
|
1006
|
-
</button>`,
|
|
1007
|
-
...SUPPORTED_LOCALES.map((locale) => {
|
|
1008
|
-
const label = localeDisplayName(locale);
|
|
1009
|
-
return ` <button type="button" class="locale-menu-item" role="menuitemradio" aria-checked="false" data-locale-value="${esc(locale)}">
|
|
1010
|
-
<span class="locale-menu-check" aria-hidden="true">✓</span>
|
|
1011
|
-
<span>${esc(label)}</span>
|
|
1012
|
-
</button>`;
|
|
1013
|
-
}),
|
|
1014
|
-
].join("\n");
|
|
1015
|
-
const localePickerHtml = `
|
|
1016
|
-
<div class="locale-picker">
|
|
1017
|
-
<button type="button" class="locale-trigger" id="auth-locale-trigger" aria-haspopup="menu" aria-expanded="false" aria-controls="auth-locale-menu" aria-label="${esc(t("languageLabel"))}" title="${esc(t("languageLabel"))}"${i18nAriaAttr("languageLabel")} data-i18n-title="languageLabel">
|
|
1018
|
-
<svg viewBox="0 0 24 24" aria-hidden="true">
|
|
1019
|
-
<path d="M4 5h7" />
|
|
1020
|
-
<path d="M7.5 4v1" />
|
|
1021
|
-
<path d="M9.5 5c-.8 4.4-2.6 7.2-5.5 9" />
|
|
1022
|
-
<path d="M5 9c1.2 2.1 3.2 3.8 6 5" />
|
|
1023
|
-
<path d="M13 20l4-9 4 9" />
|
|
1024
|
-
<path d="M14.5 17h5" />
|
|
1025
|
-
</svg>
|
|
1026
|
-
</button>
|
|
1027
|
-
<div class="locale-menu" id="auth-locale-menu" role="menu" aria-labelledby="auth-locale-trigger" hidden>
|
|
1028
|
-
${localeMenuItemsHtml}
|
|
1029
|
-
</div>
|
|
1030
|
-
</div>`;
|
|
1031
|
-
const environmentBadgeHtml = `
|
|
1032
|
-
<div class="environment-switcher" id="environment-switcher" hidden>
|
|
1033
|
-
<button type="button" class="environment-badge" id="environment-badge" aria-expanded="false" aria-controls="environment-popover">beta</button>
|
|
1034
|
-
<div class="environment-popover" id="environment-popover" role="dialog" aria-labelledby="environment-popover-title" hidden>
|
|
1035
|
-
<div class="environment-popover-title" id="environment-popover-title">You're on Agent-Native Beta</div>
|
|
1036
|
-
<div class="environment-popover-copy">Choose where you want to continue.</div>
|
|
1037
|
-
<a class="environment-production-link" id="environment-production-link" href="">Switch to production</a>
|
|
1038
|
-
<button type="button" class="environment-hide-badge" id="environment-hide-badge">Hide badge</button>
|
|
1039
|
-
</div>
|
|
1040
|
-
</div>`;
|
|
1012
|
+
? `${opts.requestOrigin}${withAppBasePath(AGENT_NATIVE_SOCIAL_IMAGE_PATH, appBasePath)}`
|
|
1013
|
+
: withAppBasePath(AGENT_NATIVE_SOCIAL_IMAGE_PATH, appBasePath));
|
|
1014
|
+
const t = (key) => EN_AUTH_COPY[key];
|
|
1041
1015
|
const hostedSignupLegalNotice = opts.signupLegalNotice === undefined &&
|
|
1042
1016
|
isAgentNativeHostedHost(opts.requestHost)
|
|
1043
1017
|
? {
|
|
@@ -1048,59 +1022,13 @@ ${localeMenuItemsHtml}
|
|
|
1048
1022
|
const signupLegalNotice = opts.signupLegalNotice === false
|
|
1049
1023
|
? undefined
|
|
1050
1024
|
: (opts.signupLegalNotice ?? hostedSignupLegalNotice);
|
|
1051
|
-
const
|
|
1052
|
-
|
|
1053
|
-
: "";
|
|
1054
|
-
const magicLinkSuccessHtml = magicLinkMode
|
|
1055
|
-
? ` <div class="magic-link-success" id="magic-link-success" aria-live="polite" hidden>
|
|
1056
|
-
<p class="magic-link-success-copy"><span${i18nAttr("magicLinkSentCopy")}>${esc(t("magicLinkSentCopy"))}</span> <strong id="magic-link-success-email"></strong>.</p>
|
|
1057
|
-
<button type="button" class="link-button magic-link-back" id="magic-link-back"${i18nAttr("back")}>${esc(t("back"))}</button>
|
|
1058
|
-
</div>
|
|
1059
|
-
`
|
|
1060
|
-
: "";
|
|
1061
|
-
const signupLocalModeNoteHtml = signupLocalModeNote
|
|
1062
|
-
? ` <div class="signup-local-mode-note" id="signup-local-mode-note" data-command="${esc(signupLocalModeNote.command)}">
|
|
1063
|
-
<p>${esc(signupLocalModeNote.text)}</p>
|
|
1064
|
-
<code>${esc(signupLocalModeNote.command)}</code>
|
|
1065
|
-
<button type="button" class="copy-run-local" id="copy-signup-local-mode" onclick="__anCopySignupLocalModeCommand()"${i18nAttr("copyCommand")}>${esc(t("copyCommand"))}</button>
|
|
1066
|
-
</div>`
|
|
1067
|
-
: "";
|
|
1068
|
-
const identitySsoHtml = identitySsoLoginButtonHtml();
|
|
1069
|
-
const embeddedAuthCss = identitySsoHtml
|
|
1025
|
+
const identitySsoEnabled = Boolean(identitySsoLoginButtonHtml());
|
|
1026
|
+
const embeddedAuthCss = identitySsoEnabled
|
|
1070
1027
|
? ' html[data-agent-native-embedded="1"] #identity-sso-btn { display: none !important; }\n'
|
|
1071
1028
|
: "";
|
|
1072
|
-
const
|
|
1073
|
-
<div class="local-dev-signin" id="local-dev-signin" hidden>
|
|
1074
|
-
<button type="button" class="btn-local-dev btn-primary" id="local-dev-btn" title="${esc(t("localDevDescription"))}"${i18nAttr("localDevButton")} data-i18n-title="localDevDescription" aria-describedby="local-dev-description">${esc(t("localDevButton"))}</button>
|
|
1075
|
-
<p class="local-dev-description" id="local-dev-description">
|
|
1076
|
-
<span${i18nAttr("localDevDescription")}>${esc(t("localDevDescription"))}</span>
|
|
1077
|
-
<a class="local-dev-help" id="local-dev-help" href="${docsUrl("authentication", { hash: "local-development-sign-in" })}" target="_blank" rel="noreferrer" aria-label="${esc(t("localDevHelp"))}" title="${esc(t("localDevHelp"))}" data-i18n-title="localDevHelp"${i18nAriaAttr("localDevHelp")}><span class="local-dev-help-glyph" aria-hidden="true">?</span></a>
|
|
1078
|
-
</p>
|
|
1079
|
-
<button type="button" class="local-dev-full-options" id="local-dev-full-options" hidden${i18nAttr("localDevFullOptions")}>${esc(t("localDevFullOptions"))}</button>
|
|
1080
|
-
<p class="msg error" id="local-dev-msg" role="status" aria-live="polite"></p>
|
|
1081
|
-
</div>`;
|
|
1082
|
-
const identitySsoMagicLinkSelector = identitySsoHtml
|
|
1029
|
+
const identitySsoMagicLinkSelector = identitySsoEnabled
|
|
1083
1030
|
? " .card.magic-link-complete #identity-sso-btn,\n"
|
|
1084
1031
|
: "";
|
|
1085
|
-
const identitySsoScript = identitySsoHtml
|
|
1086
|
-
? `
|
|
1087
|
-
function __anIdentitySsoUrl() {
|
|
1088
|
-
var params = new URLSearchParams();
|
|
1089
|
-
params.set('return', __anResumeHref());
|
|
1090
|
-
return __anPath('/_agent-native/identity/login') + '?' + params.toString();
|
|
1091
|
-
}
|
|
1092
|
-
function __anStartIdentitySso(event) {
|
|
1093
|
-
if (event && event.preventDefault) event.preventDefault();
|
|
1094
|
-
window.location.href = __anIdentitySsoUrl();
|
|
1095
|
-
return false;
|
|
1096
|
-
}
|
|
1097
|
-
(function __anPrepareIdentitySsoButton() {
|
|
1098
|
-
var identity = document.getElementById('identity-sso-btn');
|
|
1099
|
-
if (!identity) return;
|
|
1100
|
-
identity.setAttribute('href', __anIdentitySsoUrl());
|
|
1101
|
-
identity.addEventListener('click', __anStartIdentitySso);
|
|
1102
|
-
})();`
|
|
1103
|
-
: "";
|
|
1104
1032
|
const marketingStyles = hasMarketing
|
|
1105
1033
|
? `
|
|
1106
1034
|
body.has-marketing { padding: 0; position: relative; overflow-x: hidden; }
|
|
@@ -1237,306 +1165,59 @@ ${localeMenuItemsHtml}
|
|
|
1237
1165
|
}
|
|
1238
1166
|
`
|
|
1239
1167
|
: "";
|
|
1240
|
-
const
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
:
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
' m+=line(p4,p1,st);d=length(st-p1);s=(.005/(d*d));s*=S(1.,.7,d);pulse=sin((fract(p1.x)+fract(p1.y)+t)*5.)*.4+.6;pulse=pow(pulse,20.);sparkle+=s*pulse;',
|
|
1294
|
-
' m+=line(p4,p2,st);d=length(st-p2);s=(.005/(d*d));s*=S(1.,.7,d);pulse=sin((fract(p2.x)+fract(p2.y)+t)*5.)*.4+.6;pulse=pow(pulse,20.);sparkle+=s*pulse;',
|
|
1295
|
-
' m+=line(p4,p3,st);d=length(st-p3);s=(.005/(d*d));s*=S(1.,.7,d);pulse=sin((fract(p3.x)+fract(p3.y)+t)*5.)*.4+.6;pulse=pow(pulse,20.);sparkle+=s*pulse;',
|
|
1296
|
-
' m+=line(p4,p4,st);d=length(st-p4);s=(.005/(d*d));s*=S(1.,.7,d);pulse=sin((fract(p4.x)+fract(p4.y)+t)*5.)*.4+.6;pulse=pow(pulse,20.);sparkle+=s*pulse;',
|
|
1297
|
-
' m+=line(p4,p5,st);d=length(st-p5);s=(.005/(d*d));s*=S(1.,.7,d);pulse=sin((fract(p5.x)+fract(p5.y)+t)*5.)*.4+.6;pulse=pow(pulse,20.);sparkle+=s*pulse;',
|
|
1298
|
-
' m+=line(p4,p6,st);d=length(st-p6);s=(.005/(d*d));s*=S(1.,.7,d);pulse=sin((fract(p6.x)+fract(p6.y)+t)*5.)*.4+.6;pulse=pow(pulse,20.);sparkle+=s*pulse;',
|
|
1299
|
-
' m+=line(p4,p7,st);d=length(st-p7);s=(.005/(d*d));s*=S(1.,.7,d);pulse=sin((fract(p7.x)+fract(p7.y)+t)*5.)*.4+.6;pulse=pow(pulse,20.);sparkle+=s*pulse;',
|
|
1300
|
-
' m+=line(p4,p8,st);d=length(st-p8);s=(.005/(d*d));s*=S(1.,.7,d);pulse=sin((fract(p8.x)+fract(p8.y)+t)*5.)*.4+.6;pulse=pow(pulse,20.);sparkle+=s*pulse;',
|
|
1301
|
-
' m+=line(p1,p3,st);m+=line(p1,p5,st);m+=line(p7,p5,st);m+=line(p7,p3,st);',
|
|
1302
|
-
' float sPhase=(sin(t+n)+sin(t*.1))*.25+.5;sPhase+=pow(sin(t*.1)*.5+.5,50.)*5.;m+=sparkle*sPhase;',
|
|
1303
|
-
' return m;',
|
|
1304
|
-
'}',
|
|
1305
|
-
'void mainImage(out vec4 fragColor,in vec2 fragCoord){',
|
|
1306
|
-
' vec2 uv=(fragCoord-iResolution.xy*.5)/iResolution.y;',
|
|
1307
|
-
' float t=iTime*.03;float s=sin(t);float c=cos(t);mat2 rot=mat2(c,-s,s,c);vec2 st=uv*rot;vec2 pointerUv=(uPointer.xy-iResolution.xy*.5)/iResolution.y;',
|
|
1308
|
-
' float m=0.;',
|
|
1309
|
-
' for(float i=0.;i<1.;i+=1./NUM_LAYERS){float z=fract(t+i);float size=mix(15.,1.,z);float fade=S(0.,.6,z)*S(1.,.8,z);vec2 pointerSt=pointerUv*rot*size;vec2 layerSt=st*size;float warp=1.-smoothstep(.15,2.7,length(layerSt-pointerSt));warp=warp*warp*(3.-2.*warp)*uPointer.z;layerSt-=(pointerSt-layerSt)*warp*.035;m+=fade*NetLayer(layerSt,i,iTime*0.3,pointerSt,uPointer.z);}',
|
|
1310
|
-
' float cursorLift=1.-smoothstep(.04,.48,length(uv-pointerUv));cursorLift=cursorLift*cursorLift*(3.-2.*cursorLift)*uPointer.z;m*=1.+cursorLift*1.6;',
|
|
1311
|
-
' vec3 col=vec3(0.35)*m;col*=1.-dot(uv,uv);',
|
|
1312
|
-
' float tt=min(iTime,5.0);col*=S(0.,20.,tt);',
|
|
1313
|
-
' col=clamp(col,0.,1.);fragColor=vec4(col,1.);',
|
|
1314
|
-
'}',
|
|
1315
|
-
'void main(){mainImage(gl_FragColor,gl_FragCoord.xy);}'
|
|
1316
|
-
].join('\\n'));
|
|
1317
|
-
gl.compileShader(fs);
|
|
1318
|
-
|
|
1319
|
-
var prog = gl.createProgram();
|
|
1320
|
-
gl.attachShader(prog, vs);
|
|
1321
|
-
gl.attachShader(prog, fs);
|
|
1322
|
-
gl.linkProgram(prog);
|
|
1323
|
-
gl.useProgram(prog);
|
|
1324
|
-
|
|
1325
|
-
var buf = gl.createBuffer();
|
|
1326
|
-
gl.bindBuffer(gl.ARRAY_BUFFER, buf);
|
|
1327
|
-
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1,-1,1,-1,-1,1,-1,1,1,-1,1,1]), gl.STATIC_DRAW);
|
|
1328
|
-
var pos = gl.getAttribLocation(prog, 'position');
|
|
1329
|
-
gl.enableVertexAttribArray(pos);
|
|
1330
|
-
gl.vertexAttribPointer(pos, 2, gl.FLOAT, false, 0, 0);
|
|
1331
|
-
|
|
1332
|
-
var uTime = gl.getUniformLocation(prog, 'iTime');
|
|
1333
|
-
var uRes = gl.getUniformLocation(prog, 'iResolution');
|
|
1334
|
-
var uPointer = gl.getUniformLocation(prog, 'uPointer');
|
|
1335
|
-
var reducedMotionQuery = window.matchMedia ? window.matchMedia('(prefers-reduced-motion: reduce)') : null;
|
|
1336
|
-
var reducedMotion = reducedMotionQuery ? reducedMotionQuery.matches : false;
|
|
1337
|
-
var pointerDpr = 1, hasPointer = false;
|
|
1338
|
-
var pointerX = 0, pointerY = 0, pointerStrength = 0;
|
|
1339
|
-
var targetX = 0, targetY = 0, targetStrength = 0;
|
|
1340
|
-
|
|
1341
|
-
function resize() {
|
|
1342
|
-
var w = window.innerWidth, h = window.innerHeight;
|
|
1343
|
-
pointerDpr = Math.min(window.devicePixelRatio, 1.5);
|
|
1344
|
-
canvas.width = w * pointerDpr; canvas.height = h * pointerDpr;
|
|
1345
|
-
gl.viewport(0, 0, canvas.width, canvas.height);
|
|
1346
|
-
if (!hasPointer) {
|
|
1347
|
-
pointerX = targetX = canvas.width * 0.5;
|
|
1348
|
-
pointerY = targetY = canvas.height * 0.5;
|
|
1349
|
-
}
|
|
1350
|
-
}
|
|
1351
|
-
function onPointerMove(event) {
|
|
1352
|
-
var rect = canvas.getBoundingClientRect();
|
|
1353
|
-
var x = event.clientX - rect.left;
|
|
1354
|
-
var y = event.clientY - rect.top;
|
|
1355
|
-
hasPointer = true;
|
|
1356
|
-
targetX = x * pointerDpr;
|
|
1357
|
-
targetY = (rect.height - y) * pointerDpr;
|
|
1358
|
-
targetStrength = x >= 0 && x <= rect.width && y >= 0 && y <= rect.height ? 1 : 0;
|
|
1359
|
-
}
|
|
1360
|
-
function fadePointer() {
|
|
1361
|
-
targetStrength = 0;
|
|
1362
|
-
}
|
|
1363
|
-
function easePointer(allowPointer) {
|
|
1364
|
-
if (!allowPointer) {
|
|
1365
|
-
pointerStrength = 0;
|
|
1366
|
-
return;
|
|
1367
|
-
}
|
|
1368
|
-
pointerX += (targetX - pointerX) * 0.22;
|
|
1369
|
-
pointerY += (targetY - pointerY) * 0.22;
|
|
1370
|
-
pointerStrength += (targetStrength - pointerStrength) * 0.14;
|
|
1371
|
-
if (pointerStrength < 0.001 && targetStrength === 0) pointerStrength = 0;
|
|
1372
|
-
}
|
|
1373
|
-
resize();
|
|
1374
|
-
window.addEventListener('resize', resize);
|
|
1375
|
-
window.addEventListener('pointermove', onPointerMove, { passive: true });
|
|
1376
|
-
window.addEventListener('mousemove', onPointerMove, { passive: true });
|
|
1377
|
-
document.addEventListener('pointerleave', fadePointer, { passive: true });
|
|
1378
|
-
window.addEventListener('blur', fadePointer);
|
|
1379
|
-
|
|
1380
|
-
var start = performance.now(), last = 0, raf = 0, reducedMotionStaticTime = 20;
|
|
1381
|
-
function draw(timeSeconds, allowPointer) {
|
|
1382
|
-
easePointer(allowPointer !== false && !reducedMotion);
|
|
1383
|
-
gl.uniform1f(uTime, timeSeconds);
|
|
1384
|
-
gl.uniform2f(uRes, canvas.width, canvas.height);
|
|
1385
|
-
gl.uniform3f(uPointer, pointerX, pointerY, pointerStrength);
|
|
1386
|
-
gl.drawArrays(gl.TRIANGLES, 0, 6);
|
|
1387
|
-
}
|
|
1388
|
-
function render(now) {
|
|
1389
|
-
if (reducedMotion) {
|
|
1390
|
-
raf = 0;
|
|
1391
|
-
return;
|
|
1392
|
-
}
|
|
1393
|
-
raf = requestAnimationFrame(render);
|
|
1394
|
-
if (now - last < 33) return;
|
|
1395
|
-
last = now;
|
|
1396
|
-
draw((now - start) * 0.001);
|
|
1397
|
-
}
|
|
1398
|
-
function startAnimation() {
|
|
1399
|
-
if (!raf) raf = requestAnimationFrame(render);
|
|
1400
|
-
}
|
|
1401
|
-
function stopAnimation() {
|
|
1402
|
-
if (raf) {
|
|
1403
|
-
cancelAnimationFrame(raf);
|
|
1404
|
-
raf = 0;
|
|
1405
|
-
}
|
|
1406
|
-
}
|
|
1407
|
-
function onReducedMotionChange() {
|
|
1408
|
-
reducedMotion = reducedMotionQuery ? reducedMotionQuery.matches : false;
|
|
1409
|
-
if (reducedMotion) {
|
|
1410
|
-
stopAnimation();
|
|
1411
|
-
last = 0;
|
|
1412
|
-
draw(reducedMotionStaticTime, false);
|
|
1413
|
-
} else {
|
|
1414
|
-
startAnimation();
|
|
1415
|
-
}
|
|
1416
|
-
}
|
|
1417
|
-
draw(reducedMotion ? reducedMotionStaticTime : 0, !reducedMotion);
|
|
1418
|
-
if (reducedMotionQuery) {
|
|
1419
|
-
if (reducedMotionQuery.addEventListener) {
|
|
1420
|
-
reducedMotionQuery.addEventListener('change', onReducedMotionChange);
|
|
1421
|
-
} else {
|
|
1422
|
-
reducedMotionQuery.addListener(onReducedMotionChange);
|
|
1423
|
-
}
|
|
1424
|
-
}
|
|
1425
|
-
if (!reducedMotion) startAnimation();
|
|
1426
|
-
})();`
|
|
1427
|
-
: "";
|
|
1428
|
-
const environmentBadgeScript = `
|
|
1429
|
-
(function __anInitEnvironmentBadge() {
|
|
1430
|
-
var switcher = document.getElementById('environment-switcher');
|
|
1431
|
-
var button = document.getElementById('environment-badge');
|
|
1432
|
-
var popover = document.getElementById('environment-popover');
|
|
1433
|
-
var productionLink = document.getElementById('environment-production-link');
|
|
1434
|
-
var hideButton = document.getElementById('environment-hide-badge');
|
|
1435
|
-
if (!switcher || !button || !popover || !productionLink || !hideButton) return;
|
|
1436
|
-
if (window.parent !== window) return;
|
|
1437
|
-
|
|
1438
|
-
try {
|
|
1439
|
-
var forceUrl = new URL(window.location.href);
|
|
1440
|
-
if (forceUrl.searchParams.get(${JSON.stringify(BETA_FORCE_QUERY_PARAM)}) === 'true') {
|
|
1441
|
-
window.sessionStorage.setItem(${JSON.stringify(BETA_FORCE_SESSION_STORAGE_KEY)}, '1');
|
|
1442
|
-
}
|
|
1443
|
-
} catch (error) {
|
|
1444
|
-
void error;
|
|
1445
|
-
}
|
|
1446
|
-
|
|
1447
|
-
// Persist the beta opt-out before authentication replaces this cached shell.
|
|
1448
|
-
try {
|
|
1449
|
-
var optOutUrl = new URL(window.location.href);
|
|
1450
|
-
var optOutValue = optOutUrl.searchParams.get(${JSON.stringify(BETA_OPT_OUT_QUERY_PARAM)});
|
|
1451
|
-
if (optOutValue !== null) {
|
|
1452
|
-
var optOutExpiry = Number(optOutValue);
|
|
1453
|
-
var optOutIsActive = Number.isFinite(optOutExpiry) && optOutExpiry > Date.now();
|
|
1454
|
-
var optOutStorageReady = false;
|
|
1455
|
-
try {
|
|
1456
|
-
if (optOutIsActive) {
|
|
1457
|
-
window.localStorage.setItem(
|
|
1458
|
-
${JSON.stringify(BETA_OPT_OUT_STORAGE_KEY)},
|
|
1459
|
-
String(optOutExpiry),
|
|
1460
|
-
);
|
|
1461
|
-
}
|
|
1462
|
-
optOutStorageReady = true;
|
|
1463
|
-
} catch (error) {
|
|
1464
|
-
void error;
|
|
1465
|
-
}
|
|
1466
|
-
if (optOutStorageReady) {
|
|
1467
|
-
optOutUrl.searchParams.delete(${JSON.stringify(BETA_OPT_OUT_QUERY_PARAM)});
|
|
1468
|
-
window.history.replaceState(null, '', optOutUrl.toString());
|
|
1469
|
-
}
|
|
1470
|
-
}
|
|
1471
|
-
} catch (error) {
|
|
1472
|
-
void error;
|
|
1473
|
-
}
|
|
1474
|
-
|
|
1475
|
-
var betaHosts = ${JSON.stringify(ENVIRONMENT_BETA_HOSTS)};
|
|
1476
|
-
var hostname = (window.location.hostname || '').toLowerCase().replace(/\\.$/, '');
|
|
1477
|
-
var productionHost = hostname.indexOf('beta.') === 0 ? hostname.slice(5) : '';
|
|
1478
|
-
if (!productionHost || betaHosts[productionHost] !== hostname) return;
|
|
1479
|
-
|
|
1480
|
-
try {
|
|
1481
|
-
var productionUrl = new URL(window.location.href);
|
|
1482
|
-
productionUrl.protocol = 'https:';
|
|
1483
|
-
productionUrl.hostname = productionHost;
|
|
1484
|
-
productionUrl.port = '';
|
|
1485
|
-
productionUrl.searchParams.set(
|
|
1486
|
-
${JSON.stringify(BETA_OPT_OUT_QUERY_PARAM)},
|
|
1487
|
-
String(Date.now() + ${BETA_OPT_OUT_DURATION_MS}),
|
|
1488
|
-
);
|
|
1489
|
-
productionLink.href = productionUrl.toString();
|
|
1490
|
-
} catch (error) {
|
|
1491
|
-
void error;
|
|
1492
|
-
return;
|
|
1493
|
-
}
|
|
1494
|
-
|
|
1495
|
-
function setOpen(open) {
|
|
1496
|
-
popover.hidden = !open;
|
|
1497
|
-
button.setAttribute('aria-expanded', String(open));
|
|
1498
|
-
}
|
|
1499
|
-
|
|
1500
|
-
switcher.hidden = false;
|
|
1501
|
-
button.addEventListener('click', function() {
|
|
1502
|
-
setOpen(popover.hidden);
|
|
1503
|
-
});
|
|
1504
|
-
document.addEventListener('click', function(event) {
|
|
1505
|
-
if (!switcher.contains(event.target)) setOpen(false);
|
|
1506
|
-
});
|
|
1507
|
-
document.addEventListener('keydown', function(event) {
|
|
1508
|
-
if (event.key === 'Escape') setOpen(false);
|
|
1509
|
-
});
|
|
1510
|
-
hideButton.addEventListener('click', function() {
|
|
1511
|
-
setOpen(false);
|
|
1512
|
-
switcher.hidden = true;
|
|
1513
|
-
});
|
|
1514
|
-
})();`;
|
|
1515
|
-
return `<!DOCTYPE html>
|
|
1516
|
-
<html lang="${DEFAULT_LOCALE}" dir="ltr">
|
|
1517
|
-
<head>
|
|
1518
|
-
<meta charset="UTF-8">
|
|
1519
|
-
<script data-agent-native-locale-init>${localeInitScript}</script>
|
|
1520
|
-
<script data-agent-native-embedded-init>${embeddedAuthInitScript}</script>
|
|
1521
|
-
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
|
|
1522
|
-
<title>${hasMarketing ? esc(marketing.appName) + " — " + esc(t("pageTitleSignIn")) : esc(t("pageTitleWelcome"))}</title>
|
|
1523
|
-
<link rel="icon" type="image/svg+xml" href="${withAppBasePath("/favicon.svg")}">
|
|
1524
|
-
<link rel="apple-touch-icon" href="${withAppBasePath("/icon-180.svg")}">
|
|
1525
|
-
${hasMarketing
|
|
1526
|
-
? `<meta name="description" content="${esc(marketing.tagline)}">
|
|
1527
|
-
<meta property="og:title" content="${esc(marketing.appName)}">
|
|
1528
|
-
<meta property="og:description" content="${esc(marketing.tagline)}">
|
|
1529
|
-
<meta property="og:image" content="${esc(socialImageUrl)}">
|
|
1530
|
-
<meta property="og:image:secure_url" content="${esc(socialImageUrl)}">
|
|
1531
|
-
<meta property="og:image:type" content="${AGENT_NATIVE_SOCIAL_IMAGE_TYPE}">
|
|
1532
|
-
<meta property="og:image:width" content="${AGENT_NATIVE_SOCIAL_IMAGE_WIDTH}">
|
|
1533
|
-
<meta property="og:image:height" content="${AGENT_NATIVE_SOCIAL_IMAGE_HEIGHT}">
|
|
1534
|
-
<meta property="og:image:alt" content="${AGENT_NATIVE_SOCIAL_IMAGE_ALT}">
|
|
1535
|
-
<meta name="twitter:card" content="summary_large_image">
|
|
1536
|
-
<meta name="twitter:image" content="${esc(socialImageUrl)}">
|
|
1537
|
-
<meta name="twitter:image:alt" content="${AGENT_NATIVE_SOCIAL_IMAGE_ALT}">`
|
|
1538
|
-
: ""}
|
|
1539
|
-
<style>
|
|
1168
|
+
const authMarketingLocales = Object.fromEntries(Object.entries(localizedMarketingCopy).map(([locale, copy]) => [
|
|
1169
|
+
locale,
|
|
1170
|
+
{
|
|
1171
|
+
appName: marketing?.appName ?? "",
|
|
1172
|
+
tagline: copy.tagline ?? marketing?.tagline ?? "",
|
|
1173
|
+
description: copy.description ?? marketing?.description,
|
|
1174
|
+
features: copy.features ?? marketing?.features,
|
|
1175
|
+
},
|
|
1176
|
+
]));
|
|
1177
|
+
const authPageProps = {
|
|
1178
|
+
authMode,
|
|
1179
|
+
googleOnly,
|
|
1180
|
+
initialPrompt: simplifiedAuth,
|
|
1181
|
+
initialView: initialAuthView(opts, authMode, googleOnly),
|
|
1182
|
+
appBasePath,
|
|
1183
|
+
workspaceRuntime,
|
|
1184
|
+
trackingApp,
|
|
1185
|
+
defaultLocale: DEFAULT_LOCALE,
|
|
1186
|
+
localeStorageKey: LOCALE_STORAGE_KEY,
|
|
1187
|
+
locales: AUTH_LOCALE_COPY,
|
|
1188
|
+
localeMetadata: LOCALE_METADATA,
|
|
1189
|
+
localeOptions: SUPPORTED_LOCALES.map((locale) => ({
|
|
1190
|
+
value: locale,
|
|
1191
|
+
label: localeDisplayName(locale),
|
|
1192
|
+
})),
|
|
1193
|
+
marketing: hasMarketing && marketing ? marketing : undefined,
|
|
1194
|
+
marketingLocales: authMarketingLocales,
|
|
1195
|
+
brandMarkSrc,
|
|
1196
|
+
githubUrl: "https://github.com/BuilderIO/agent-native",
|
|
1197
|
+
showGoogle,
|
|
1198
|
+
signupLegalNotice,
|
|
1199
|
+
signupLocalModeNote,
|
|
1200
|
+
connectionLabel: getConnectionLabel(),
|
|
1201
|
+
docsAuthUrl: docsUrl("authentication", {
|
|
1202
|
+
hash: "local-development-sign-in",
|
|
1203
|
+
}),
|
|
1204
|
+
identitySsoEnabled,
|
|
1205
|
+
publicOAuthOrigin,
|
|
1206
|
+
workspaceGatewayReturnOrigin,
|
|
1207
|
+
googleAuthMode,
|
|
1208
|
+
builderPreviewLocalDevEnabled,
|
|
1209
|
+
environmentBetaHosts: ENVIRONMENT_BETA_HOSTS,
|
|
1210
|
+
betaForceQueryParam: BETA_FORCE_QUERY_PARAM,
|
|
1211
|
+
betaForceSessionStorageKey: BETA_FORCE_SESSION_STORAGE_KEY,
|
|
1212
|
+
betaOptOutQueryParam: BETA_OPT_OUT_QUERY_PARAM,
|
|
1213
|
+
betaOptOutStorageKey: BETA_OPT_OUT_STORAGE_KEY,
|
|
1214
|
+
betaOptOutDurationMs: BETA_OPT_OUT_DURATION_MS,
|
|
1215
|
+
passwordMinLength: PASSWORD_MIN_LENGTH,
|
|
1216
|
+
passwordMaxLength: PASSWORD_MAX_LENGTH,
|
|
1217
|
+
passwordMaxCopy: `Choose a password with no more than ${PASSWORD_MAX_LENGTH} characters.`,
|
|
1218
|
+
};
|
|
1219
|
+
const authPageData = serializeAuthPageData(authPageProps);
|
|
1220
|
+
const authDocumentStyles = `\n
|
|
1540
1221
|
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
|
1541
1222
|
.sr-only {
|
|
1542
1223
|
position: absolute;
|
|
@@ -2148,1997 +1829,126 @@ ${marketingStyles}
|
|
|
2148
1829
|
body.simplified-auth .card { border-color: transparent; box-shadow: none; }
|
|
2149
1830
|
body.simplified-auth .local-note { display: none !important; }
|
|
2150
1831
|
${embeddedAuthCss}
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
${
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
: ""
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
}
|
|
2264
|
-
|
|
2265
|
-
}
|
|
2266
|
-
return '';
|
|
2267
|
-
}
|
|
2268
|
-
function __anPath(path) {
|
|
2269
|
-
return __anBasePath() + path;
|
|
2270
|
-
}
|
|
2271
|
-
${signInJourneyInlineScript()}
|
|
2272
|
-
var __anJourney = __anCreateSignInJourney(__anBasePath());
|
|
2273
|
-
/**
|
|
2274
|
-
* Where this document sends the visitor once a session exists. One
|
|
2275
|
-
* function, one answer — the page used to have two ("__anGetReturnPath"
|
|
2276
|
-
* and "__anGetSignedInReturnPath") that disagreed about whether the
|
|
2277
|
-
* sign-in page itself was an acceptable destination, which is how
|
|
2278
|
-
* verification emails ended up linking back to a login form.
|
|
2279
|
-
*/
|
|
2280
|
-
function __anResumeHref() {
|
|
2281
|
-
return __anJourney.journeyForLocation(window.location).resumeHref;
|
|
2282
|
-
}
|
|
2283
|
-
var __AN_AUTH_DEFAULT_LOCALE = ${JSON.stringify(DEFAULT_LOCALE)};
|
|
2284
|
-
var __AN_AUTH_SUPPORTED_LOCALES = ${JSON.stringify(SUPPORTED_LOCALES)};
|
|
2285
|
-
var __AN_AUTH_LOCALE_STORAGE_KEY = ${JSON.stringify(LOCALE_STORAGE_KEY)};
|
|
2286
|
-
var __AN_AUTH_LOCALE_METADATA = ${JSON.stringify(LOCALE_METADATA)};
|
|
2287
|
-
var __AN_AUTH_LOCALES = ${JSON.stringify(AUTH_LOCALE_COPY)};
|
|
2288
|
-
var __AN_AUTH_MARKETING_APP_NAME = ${JSON.stringify(marketing?.appName ?? "")};
|
|
2289
|
-
var __AN_AUTH_HAS_MARKETING = ${JSON.stringify(hasMarketing)};
|
|
2290
|
-
var __AN_AUTH_MARKETING_SLUG = ${JSON.stringify(marketingSlug ?? "")};
|
|
2291
|
-
var __AN_AUTH_MARKETING_DEFAULT = ${JSON.stringify(defaultMarketingCopy ?? {})};
|
|
2292
|
-
var __AN_AUTH_MARKETING_LOCALES = ${JSON.stringify(localizedMarketingCopy)};
|
|
2293
|
-
var __anAuthLocale = __AN_AUTH_DEFAULT_LOCALE;
|
|
2294
|
-
var __anAuthLocalePreference = 'system';
|
|
2295
|
-
var __AN_AUTH_MODE = ${JSON.stringify(authMode)};
|
|
2296
|
-
var __anAuthView = ${JSON.stringify(googleOnly ? "googleOnly" : "signup")};
|
|
2297
|
-
var __AN_AUTH_APP = ${JSON.stringify(trackingApp)};
|
|
2298
|
-
function __anTrackAuth(name, properties) {
|
|
2299
|
-
try {
|
|
2300
|
-
var config = window.__AGENT_NATIVE_CONFIG__ || {};
|
|
2301
|
-
if (!config.agentNativeAnalyticsPublicKey) return;
|
|
2302
|
-
var anonymousId = '';
|
|
2303
|
-
// coercion-ok: privacy-restricted storage means this public event cannot be attributed
|
|
2304
|
-
try { anonymousId = localStorage.getItem('agent-native.anonymous_id') || ''; } catch (e) {}
|
|
2305
|
-
if (!anonymousId) return;
|
|
2306
|
-
var sessionId = '';
|
|
2307
|
-
// coercion-ok: privacy-restricted storage means this public event has no session id
|
|
2308
|
-
try { sessionId = sessionStorage.getItem('agent-native.session_id') || ''; } catch (e) {}
|
|
2309
|
-
var body = JSON.stringify({
|
|
2310
|
-
publicKey: config.agentNativeAnalyticsPublicKey,
|
|
2311
|
-
event: name,
|
|
2312
|
-
properties: Object.assign({ app: __AN_AUTH_APP }, properties || {}),
|
|
2313
|
-
anonymousId: anonymousId,
|
|
2314
|
-
sessionId: sessionId || undefined,
|
|
2315
|
-
timestamp: new Date().toISOString()
|
|
2316
|
-
});
|
|
2317
|
-
var endpoint = config.agentNativeAnalyticsEndpoint || 'https://analytics.agent-native.com/track';
|
|
2318
|
-
if (navigator.sendBeacon && navigator.sendBeacon(endpoint, body)) return;
|
|
2319
|
-
fetch(endpoint, {
|
|
2320
|
-
method: 'POST',
|
|
2321
|
-
body: body,
|
|
2322
|
-
keepalive: true,
|
|
2323
|
-
headers: { 'Content-Type': 'text/plain;charset=UTF-8' }
|
|
2324
|
-
// coercion-ok: analytics delivery is best effort and cannot block auth
|
|
2325
|
-
}).catch(function() {});
|
|
2326
|
-
// coercion-ok: analytics delivery is best effort and cannot block auth
|
|
2327
|
-
} catch (e) {}
|
|
2328
|
-
}
|
|
2329
|
-
function __anAuthLocaleIsSupported(value) {
|
|
2330
|
-
return __AN_AUTH_SUPPORTED_LOCALES.indexOf(value) !== -1;
|
|
2331
|
-
}
|
|
2332
|
-
function __anNormalizeAuthLocale(value) {
|
|
2333
|
-
if (typeof value !== 'string' || !value) return null;
|
|
2334
|
-
if (__anAuthLocaleIsSupported(value)) return value;
|
|
2335
|
-
try {
|
|
2336
|
-
var canonical = Intl.getCanonicalLocales(value)[0];
|
|
2337
|
-
if (__anAuthLocaleIsSupported(canonical)) return canonical;
|
|
2338
|
-
var language = canonical && canonical.split('-')[0].toLowerCase();
|
|
2339
|
-
for (var i = 0; i < __AN_AUTH_SUPPORTED_LOCALES.length; i++) {
|
|
2340
|
-
var locale = __AN_AUTH_SUPPORTED_LOCALES[i];
|
|
2341
|
-
if (locale.split('-')[0].toLowerCase() === language) return locale;
|
|
2342
|
-
}
|
|
2343
|
-
} catch(e) {}
|
|
2344
|
-
return null;
|
|
2345
|
-
}
|
|
2346
|
-
function __anNormalizeAuthLocalePreference(value) {
|
|
2347
|
-
if (value === 'system') return 'system';
|
|
2348
|
-
return __anNormalizeAuthLocale(value);
|
|
2349
|
-
}
|
|
2350
|
-
function __anReadAuthLocalePreference() {
|
|
2351
|
-
try {
|
|
2352
|
-
return __anNormalizeAuthLocalePreference(localStorage.getItem(__AN_AUTH_LOCALE_STORAGE_KEY)) || 'system';
|
|
2353
|
-
} catch(e) {
|
|
2354
|
-
return 'system';
|
|
2355
|
-
}
|
|
2356
|
-
}
|
|
2357
|
-
function __anWriteAuthLocalePreference(preference) {
|
|
2358
|
-
try {
|
|
2359
|
-
localStorage.setItem(__AN_AUTH_LOCALE_STORAGE_KEY, preference);
|
|
2360
|
-
} catch(e) {}
|
|
2361
|
-
}
|
|
2362
|
-
function __anBrowserAuthLocales() {
|
|
2363
|
-
try {
|
|
2364
|
-
if (navigator.languages && navigator.languages.length) return navigator.languages;
|
|
2365
|
-
if (navigator.language) return [navigator.language];
|
|
2366
|
-
} catch(e) {}
|
|
2367
|
-
return [];
|
|
2368
|
-
}
|
|
2369
|
-
function __anResolveAuthSystemLocale() {
|
|
2370
|
-
var locales = __anBrowserAuthLocales();
|
|
2371
|
-
for (var i = 0; i < locales.length; i++) {
|
|
2372
|
-
var match = __anNormalizeAuthLocale(locales[i]);
|
|
2373
|
-
if (match) return match;
|
|
2374
|
-
}
|
|
2375
|
-
return __AN_AUTH_DEFAULT_LOCALE;
|
|
2376
|
-
}
|
|
2377
|
-
function __anResolveAuthLocale(preference) {
|
|
2378
|
-
var normalizedPreference = __anNormalizeAuthLocalePreference(preference) || 'system';
|
|
2379
|
-
return normalizedPreference === 'system'
|
|
2380
|
-
? __anResolveAuthSystemLocale()
|
|
2381
|
-
: normalizedPreference;
|
|
2382
|
-
}
|
|
2383
|
-
function __anApplyAuthSystemLanguage() {
|
|
2384
|
-
var systemLanguage = document.querySelector('[data-system-language]');
|
|
2385
|
-
if (!systemLanguage) return;
|
|
2386
|
-
var systemLocale = __anResolveAuthSystemLocale();
|
|
2387
|
-
var localized = __AN_AUTH_LOCALES[systemLocale] || __AN_AUTH_LOCALES[__AN_AUTH_DEFAULT_LOCALE] || {};
|
|
2388
|
-
systemLanguage.textContent = localized.systemLanguage || 'System';
|
|
2389
|
-
}
|
|
2390
|
-
function __anT(key) {
|
|
2391
|
-
var localized = __AN_AUTH_LOCALES[__anAuthLocale] || __AN_AUTH_LOCALES[__AN_AUTH_DEFAULT_LOCALE] || {};
|
|
2392
|
-
var fallback = __AN_AUTH_LOCALES[__AN_AUTH_DEFAULT_LOCALE] || {};
|
|
2393
|
-
return localized[key] || fallback[key] || key;
|
|
2394
|
-
}
|
|
2395
|
-
function __anAuthErrorText(data, fallback) {
|
|
2396
|
-
var candidate = data && (data.error || data.message);
|
|
2397
|
-
if (typeof candidate !== 'string' || !candidate.trim()) return fallback;
|
|
2398
|
-
var message = candidate.trim();
|
|
2399
|
-
if (/failed query|\bselect\b.*\bfrom\b|\binsert\b.*\binto\b|\bupdate\b.*\bset\b|\bdelete\b.*\bfrom\b|\bsql\b|database|relation .* does not exist|column .* does not exist|syntax error|constraint|connection refused|econn|timeout/i.test(message)) {
|
|
2400
|
-
return fallback;
|
|
2401
|
-
}
|
|
2402
|
-
return message;
|
|
2403
|
-
}
|
|
2404
|
-
function __anBindPasswordValidation(input) {
|
|
2405
|
-
if (!input) return;
|
|
2406
|
-
input.addEventListener('invalid', function() {
|
|
2407
|
-
if (input.validity && input.validity.tooShort) {
|
|
2408
|
-
input.setCustomValidity(__anT('passwordMinPlaceholder'));
|
|
2409
|
-
} else if (input.validity && input.validity.tooLong) {
|
|
2410
|
-
input.setCustomValidity('Choose a password with no more than ${PASSWORD_MAX_LENGTH} characters.');
|
|
2411
|
-
}
|
|
2412
|
-
});
|
|
2413
|
-
input.addEventListener('input', function() {
|
|
2414
|
-
input.setCustomValidity('');
|
|
2415
|
-
});
|
|
2416
|
-
}
|
|
2417
|
-
function __anSetAuthI18nKey(node, key) {
|
|
2418
|
-
if (!node || !key) return;
|
|
2419
|
-
node.setAttribute('data-i18n', key);
|
|
2420
|
-
node.textContent = __anT(key);
|
|
2421
|
-
}
|
|
2422
|
-
function __anAuthHeadingKeys(view) {
|
|
2423
|
-
if (view === 'login') return { heading: 'welcomeBackTitle', subtitle: 'signInSubtitle' };
|
|
2424
|
-
if (view === 'forgot') return { heading: 'resetPasswordTitle', subtitle: 'resetPasswordSubtitle' };
|
|
2425
|
-
if (view === 'verification') return { heading: 'checkEmailTitle', subtitle: 'finishAccountSubtitle' };
|
|
2426
|
-
if (view === 'googleOnly') return { heading: 'signInTitle', subtitle: 'googleOnlySubtitle' };
|
|
2427
|
-
if (view === 'magicLinkSent') return { heading: 'magicLinkSent', subtitle: 'magicLinkSentCopy' };
|
|
2428
|
-
if (view === 'magicLink') return { heading: 'magicLinkTitle', subtitle: 'magicLinkSubtitle' };
|
|
2429
|
-
return { heading: 'welcomeTitle', subtitle: 'createAccountSubtitle' };
|
|
2430
|
-
}
|
|
2431
|
-
function __anRefreshAuthViewCopy() {
|
|
2432
|
-
var keys = __anAuthHeadingKeys(__anAuthView);
|
|
2433
|
-
__anSetAuthI18nKey(document.getElementById('heading'), keys.heading);
|
|
2434
|
-
__anSetAuthI18nKey(document.getElementById('subtitle'), keys.subtitle);
|
|
2435
|
-
}
|
|
2436
|
-
function __anSetAuthView(view) {
|
|
2437
|
-
__anAuthView = view || 'signup';
|
|
2438
|
-
__anRefreshAuthViewCopy();
|
|
2439
|
-
}
|
|
2440
|
-
function __anMarketingCopy() {
|
|
2441
|
-
if (!__AN_AUTH_MARKETING_SLUG) return __AN_AUTH_MARKETING_DEFAULT || {};
|
|
2442
|
-
var localeMarketing = __AN_AUTH_MARKETING_LOCALES[__anAuthLocale] || {};
|
|
2443
|
-
return {
|
|
2444
|
-
tagline: localeMarketing.tagline || __AN_AUTH_MARKETING_DEFAULT.tagline,
|
|
2445
|
-
description: localeMarketing.description || __AN_AUTH_MARKETING_DEFAULT.description,
|
|
2446
|
-
features: localeMarketing.features || __AN_AUTH_MARKETING_DEFAULT.features || []
|
|
2447
|
-
};
|
|
2448
|
-
}
|
|
2449
|
-
function __anApplyAuthMarketingCopy() {
|
|
2450
|
-
var copy = __anMarketingCopy();
|
|
2451
|
-
var tagline = document.querySelector('[data-marketing-field="tagline"]');
|
|
2452
|
-
if (tagline && copy.tagline) tagline.textContent = copy.tagline;
|
|
2453
|
-
var description = document.querySelector('[data-marketing-field="description"]');
|
|
2454
|
-
if (description && copy.description) description.textContent = copy.description;
|
|
2455
|
-
document.querySelectorAll('[data-marketing-feature-index]').forEach(function(node) {
|
|
2456
|
-
var index = Number(node.getAttribute('data-marketing-feature-index'));
|
|
2457
|
-
var feature = copy.features && copy.features[index];
|
|
2458
|
-
if (feature) node.textContent = feature;
|
|
2459
|
-
});
|
|
2460
|
-
}
|
|
2461
|
-
function __anApplyAuthLocale(preference) {
|
|
2462
|
-
__anAuthLocalePreference = __anNormalizeAuthLocalePreference(preference) || __anReadAuthLocalePreference();
|
|
2463
|
-
__anAuthLocale = __anResolveAuthLocale(__anAuthLocalePreference);
|
|
2464
|
-
var root = document.documentElement;
|
|
2465
|
-
var meta = __AN_AUTH_LOCALE_METADATA[__anAuthLocale] || {};
|
|
2466
|
-
root.setAttribute('lang', __anAuthLocale);
|
|
2467
|
-
root.setAttribute('dir', meta.dir || 'ltr');
|
|
2468
|
-
root.setAttribute('data-locale', __anAuthLocale);
|
|
2469
|
-
document.querySelectorAll('[data-i18n]').forEach(function(node) {
|
|
2470
|
-
node.textContent = __anT(node.getAttribute('data-i18n'));
|
|
2471
|
-
});
|
|
2472
|
-
document.querySelectorAll('[data-i18n-placeholder]').forEach(function(node) {
|
|
2473
|
-
node.setAttribute('placeholder', __anT(node.getAttribute('data-i18n-placeholder')));
|
|
2474
|
-
});
|
|
2475
|
-
document.querySelectorAll('[data-i18n-aria-label]').forEach(function(node) {
|
|
2476
|
-
node.setAttribute('aria-label', __anT(node.getAttribute('data-i18n-aria-label')));
|
|
2477
|
-
});
|
|
2478
|
-
document.querySelectorAll('[data-i18n-title]').forEach(function(node) {
|
|
2479
|
-
node.setAttribute('title', __anT(node.getAttribute('data-i18n-title')));
|
|
2480
|
-
});
|
|
2481
|
-
document.querySelectorAll('[data-i18n-data-upgrade-copy]').forEach(function(node) {
|
|
2482
|
-
node.setAttribute('data-upgrade-copy', __anT(node.getAttribute('data-i18n-data-upgrade-copy')));
|
|
2483
|
-
});
|
|
2484
|
-
document.querySelectorAll('[data-locale-value]').forEach(function(node) {
|
|
2485
|
-
var checked = node.getAttribute('data-locale-value') === __anAuthLocalePreference;
|
|
2486
|
-
node.setAttribute('aria-checked', checked ? 'true' : 'false');
|
|
2487
|
-
});
|
|
2488
|
-
document.title = __AN_AUTH_HAS_MARKETING && __AN_AUTH_MARKETING_APP_NAME
|
|
2489
|
-
? __AN_AUTH_MARKETING_APP_NAME + ' — ' + __anT('pageTitleSignIn')
|
|
2490
|
-
: __anT('pageTitleWelcome');
|
|
2491
|
-
__anApplyAuthSystemLanguage();
|
|
2492
|
-
__anApplyAuthMarketingCopy();
|
|
2493
|
-
__anRefreshAuthViewCopy();
|
|
2494
|
-
}
|
|
2495
|
-
function __anSetAuthLocaleMenuOpen(open) {
|
|
2496
|
-
var trigger = document.getElementById('auth-locale-trigger');
|
|
2497
|
-
var menu = document.getElementById('auth-locale-menu');
|
|
2498
|
-
if (!trigger || !menu) return;
|
|
2499
|
-
if (open) {
|
|
2500
|
-
menu.removeAttribute('hidden');
|
|
2501
|
-
} else {
|
|
2502
|
-
menu.setAttribute('hidden', '');
|
|
2503
|
-
}
|
|
2504
|
-
trigger.setAttribute('aria-expanded', open ? 'true' : 'false');
|
|
2505
|
-
}
|
|
2506
|
-
(function __anInitAuthLocalePicker() {
|
|
2507
|
-
var trigger = document.getElementById('auth-locale-trigger');
|
|
2508
|
-
var menu = document.getElementById('auth-locale-menu');
|
|
2509
|
-
var preference = __anReadAuthLocalePreference();
|
|
2510
|
-
__anApplyAuthLocale(preference);
|
|
2511
|
-
if (!trigger || !menu) return;
|
|
2512
|
-
trigger.addEventListener('click', function(event) {
|
|
2513
|
-
event.preventDefault();
|
|
2514
|
-
__anSetAuthLocaleMenuOpen(menu.hasAttribute('hidden'));
|
|
2515
|
-
});
|
|
2516
|
-
menu.querySelectorAll('[data-locale-value]').forEach(function(item) {
|
|
2517
|
-
item.addEventListener('click', function() {
|
|
2518
|
-
var next = __anNormalizeAuthLocalePreference(item.getAttribute('data-locale-value')) || 'system';
|
|
2519
|
-
__anWriteAuthLocalePreference(next);
|
|
2520
|
-
__anApplyAuthLocale(next);
|
|
2521
|
-
__anSetAuthLocaleMenuOpen(false);
|
|
2522
|
-
trigger.focus();
|
|
2523
|
-
});
|
|
2524
|
-
});
|
|
2525
|
-
document.addEventListener('click', function(event) {
|
|
2526
|
-
var picker = document.querySelector('.locale-picker');
|
|
2527
|
-
if (picker && picker.contains(event.target)) return;
|
|
2528
|
-
__anSetAuthLocaleMenuOpen(false);
|
|
2529
|
-
});
|
|
2530
|
-
document.addEventListener('keydown', function(event) {
|
|
2531
|
-
if (event.key === 'Escape') __anSetAuthLocaleMenuOpen(false);
|
|
2532
|
-
});
|
|
2533
|
-
})();
|
|
2534
|
-
var __AN_PUBLIC_OAUTH_ORIGIN = ${JSON.stringify(publicOAuthOrigin)};
|
|
2535
|
-
var __AN_WORKSPACE_GATEWAY_RETURN_ORIGIN = ${JSON.stringify(workspaceGatewayReturnOrigin)};
|
|
2536
|
-
var __AN_GOOGLE_AUTH_MODE = ${JSON.stringify(googleAuthMode)};
|
|
2537
|
-
var __AN_BUILDER_PREVIEW_LOCAL_DEV_ENABLED = ${JSON.stringify(builderPreviewLocalDevEnabled)};
|
|
2538
|
-
function __anConfiguredOAuthOrigin() {
|
|
2539
|
-
if (!__AN_PUBLIC_OAUTH_ORIGIN) return '';
|
|
2540
|
-
try {
|
|
2541
|
-
var origin = new URL(__AN_PUBLIC_OAUTH_ORIGIN).origin;
|
|
2542
|
-
return origin && origin !== window.location.origin ? origin : '';
|
|
2543
|
-
} catch(e) {
|
|
2544
|
-
return '';
|
|
2545
|
-
}
|
|
2546
|
-
}
|
|
2547
|
-
function __anAuthPath(path) {
|
|
2548
|
-
var origin = __anIsBuilderPreview() ? __anConfiguredOAuthOrigin() : '';
|
|
2549
|
-
return origin ? origin + path : __anPath(path);
|
|
2550
|
-
}
|
|
2551
|
-
function __anGoogleAuthUrlPath() {
|
|
2552
|
-
return __anIsBuilderPreview()
|
|
2553
|
-
? __anAuthPath('/_agent-native/google/auth-url')
|
|
2554
|
-
: __anPath('/_agent-native/google/auth-url');
|
|
2555
|
-
}
|
|
2556
|
-
function __anBuilderPreviewReturnOrigin() {
|
|
2557
|
-
var candidates = [window.location.href, document.referrer || ''];
|
|
2558
|
-
try {
|
|
2559
|
-
if (window.location.ancestorOrigins) {
|
|
2560
|
-
for (var j = 0; j < window.location.ancestorOrigins.length; j++) {
|
|
2561
|
-
candidates.push(window.location.ancestorOrigins[j]);
|
|
2562
|
-
}
|
|
2563
|
-
}
|
|
2564
|
-
} catch(e) {}
|
|
2565
|
-
for (var i = 0; i < candidates.length; i++) {
|
|
2566
|
-
try {
|
|
2567
|
-
var url = new URL(candidates[i]);
|
|
2568
|
-
var host = url.hostname.toLowerCase();
|
|
2569
|
-
var isPreviewHost =
|
|
2570
|
-
host === 'builderio.xyz' || host.slice(-14) === '.builderio.xyz' ||
|
|
2571
|
-
host === 'builderio.dev' || host.slice(-14) === '.builderio.dev' ||
|
|
2572
|
-
host === 'builder.codes' || host.slice(-14) === '.builder.codes' ||
|
|
2573
|
-
host === 'builder.my' || host.slice(-11) === '.builder.my';
|
|
2574
|
-
if (url.protocol === 'https:' && isPreviewHost) return url.origin;
|
|
2575
|
-
} catch(e) {}
|
|
2576
|
-
}
|
|
2577
|
-
return '';
|
|
2578
|
-
}
|
|
2579
|
-
function __anWorkspaceGatewayReturnOrigin() {
|
|
2580
|
-
var previewOrigin = __anBuilderPreviewReturnOrigin();
|
|
2581
|
-
if (previewOrigin) return previewOrigin;
|
|
2582
|
-
if (__AN_WORKSPACE_GATEWAY_RETURN_ORIGIN) return __AN_WORKSPACE_GATEWAY_RETURN_ORIGIN;
|
|
2583
|
-
return __anIsBuilderDesktop() ? 'http://127.0.0.1:8080' : '';
|
|
2584
|
-
}
|
|
2585
|
-
function __anNormalizeWorkspaceReturnPath(ret) {
|
|
2586
|
-
try {
|
|
2587
|
-
var url = new URL(ret || '/', window.location.origin);
|
|
2588
|
-
var path = url.pathname || '/';
|
|
2589
|
-
if (path === '/dispatch/dispatch') {
|
|
2590
|
-
path = '/dispatch';
|
|
2591
|
-
} else if (path.indexOf('/dispatch/') === 0) {
|
|
2592
|
-
var rest = path.slice('/dispatch/'.length);
|
|
2593
|
-
var first = rest.split('/')[0];
|
|
2594
|
-
var dispatchRoutes = {
|
|
2595
|
-
overview: true, apps: true, metrics: true, vault: true,
|
|
2596
|
-
integrations: true, messaging: true, workspace: true,
|
|
2597
|
-
agents: true, destinations: true, identities: true,
|
|
2598
|
-
approvals: true, audit: true, team: true, 'thread-debug': true,
|
|
2599
|
-
'new-app': true
|
|
2600
|
-
};
|
|
2601
|
-
if (first === 'dispatch') {
|
|
2602
|
-
path = '/dispatch' + rest.slice(first.length);
|
|
2603
|
-
} else if (first && !dispatchRoutes[first]) {
|
|
2604
|
-
path = '/' + rest;
|
|
2605
|
-
}
|
|
2606
|
-
}
|
|
2607
|
-
return path + url.search + url.hash;
|
|
2608
|
-
} catch(e) {
|
|
2609
|
-
return ret || '/';
|
|
2610
|
-
}
|
|
2611
|
-
}
|
|
2612
|
-
function __anOAuthReturnTarget(ret) {
|
|
2613
|
-
var path = __anNormalizeWorkspaceReturnPath(ret);
|
|
2614
|
-
var origin = __anWorkspaceGatewayReturnOrigin();
|
|
2615
|
-
return origin ? origin + path : path;
|
|
2616
|
-
}
|
|
2617
|
-
function __anSessionBridgeUrl(ret, sessionToken) {
|
|
2618
|
-
try {
|
|
2619
|
-
var url = new URL(ret || window.location.pathname + window.location.search, window.location.origin);
|
|
2620
|
-
url.searchParams.set('_session', sessionToken);
|
|
2621
|
-
return url.pathname + url.search + url.hash;
|
|
2622
|
-
} catch(e) {
|
|
2623
|
-
var sep = (ret || '/').indexOf('?') === -1 ? '?' : '&';
|
|
2624
|
-
return (ret || '/') + sep + '_session=' + encodeURIComponent(sessionToken);
|
|
2625
|
-
}
|
|
2626
|
-
}
|
|
2627
|
-
function __anFinishOAuthExchange(ret, flowId, sessionToken) {
|
|
2628
|
-
__anStopOAuthPopupWatch();
|
|
2629
|
-
__anStopNativeOAuthAbandonment();
|
|
2630
|
-
__anGoogleSignInInFlight = false;
|
|
2631
|
-
__anClearGoogleSignInFlow();
|
|
2632
|
-
__anMagicLinkInFlight = false;
|
|
2633
|
-
if (__anIsBuilderPreview()) {
|
|
2634
|
-
if (sessionToken) {
|
|
2635
|
-
__anSetOAuthDebug('OAuth exchange redeemed; applying session bridge to embedded app', flowId);
|
|
2636
|
-
window.location.replace(__anSessionBridgeUrl(ret, sessionToken));
|
|
2637
|
-
return;
|
|
2638
|
-
}
|
|
2639
|
-
__anSetOAuthDebug('OAuth exchange redeemed; reloading the embedded app', flowId);
|
|
2640
|
-
window.location.reload();
|
|
2641
|
-
return;
|
|
2642
|
-
}
|
|
2643
|
-
__anSetOAuthDebug('OAuth exchange redeemed; returning to the app', flowId);
|
|
2644
|
-
__anRedirectToSignedInApp(ret);
|
|
2645
|
-
}
|
|
2646
|
-
function __anRedirectToSignedInApp(ret) {
|
|
2647
|
-
window.location.replace(ret || __anResumeHref());
|
|
2648
|
-
}
|
|
2649
|
-
function __anMaybeRedirectSignedIn(ret) {
|
|
2650
|
-
return fetch(__anPath('/_agent-native/auth/session'), {
|
|
2651
|
-
headers: { 'Accept': 'application/json' },
|
|
2652
|
-
credentials: 'include',
|
|
2653
|
-
cache: 'no-store',
|
|
2654
|
-
}).then(function(res) {
|
|
2655
|
-
if (!res.ok) return null;
|
|
2656
|
-
return res.json().catch(function() { return null; });
|
|
2657
|
-
}).then(function(data) {
|
|
2658
|
-
if (data && data.email && !data.error) {
|
|
2659
|
-
__anRedirectToSignedInApp(ret);
|
|
2660
|
-
return true;
|
|
2661
|
-
}
|
|
2662
|
-
return false;
|
|
2663
|
-
}).catch(function() {
|
|
2664
|
-
return false;
|
|
2665
|
-
});
|
|
2666
|
-
}
|
|
2667
|
-
function __anIsLoopbackHostname() {
|
|
2668
|
-
var hostname = (window.location.hostname || '').toLowerCase();
|
|
2669
|
-
return hostname === 'localhost' || hostname === '::1' || hostname === '127.0.0.1' || hostname.indexOf('127.') === 0;
|
|
2670
|
-
}
|
|
2671
|
-
function __anIsBuilderPreviewHost() {
|
|
2672
|
-
var hostname = (window.location.hostname || '').toLowerCase();
|
|
2673
|
-
return hostname.endsWith('.builderio.xyz') || hostname.endsWith('.builderio.dev') || hostname.endsWith('.builder.codes') || hostname.endsWith('.builder.my');
|
|
2674
|
-
}
|
|
2675
|
-
function __anCanUseLocalDevSignin() {
|
|
2676
|
-
return __anIsLoopbackHostname() || (__AN_BUILDER_PREVIEW_LOCAL_DEV_ENABLED && __anIsBuilderPreviewHost());
|
|
2677
|
-
}
|
|
2678
|
-
function __anShouldStartWithLocalDev() {
|
|
2679
|
-
if (!__anCanUseLocalDevSignin()) return false;
|
|
2680
|
-
var params = new URLSearchParams(window.location.search);
|
|
2681
|
-
var explicitTab = params.get('tab');
|
|
2682
|
-
var verifiedRedirect = typeof __anIsVerifiedRedirectSuccess === 'function' && __anIsVerifiedRedirectSuccess();
|
|
2683
|
-
return explicitTab !== 'login' && explicitTab !== 'signup' && !verifiedRedirect;
|
|
2684
|
-
}
|
|
2685
|
-
function __anSetFullAuthOptionsVisible(visible) {
|
|
2686
|
-
var options = document.getElementById('full-auth-options');
|
|
2687
|
-
var toggle = document.getElementById('local-dev-full-options');
|
|
2688
|
-
if (!options) return;
|
|
2689
|
-
if (visible) {
|
|
2690
|
-
options.removeAttribute('hidden');
|
|
2691
|
-
if (toggle) toggle.setAttribute('hidden', '');
|
|
2692
|
-
} else {
|
|
2693
|
-
options.setAttribute('hidden', '');
|
|
2694
|
-
if (toggle) toggle.removeAttribute('hidden');
|
|
2695
|
-
}
|
|
2696
|
-
}
|
|
2697
|
-
(function __anPrepareLocalDevButton() {
|
|
2698
|
-
var container = document.getElementById('local-dev-signin');
|
|
2699
|
-
var button = document.getElementById('local-dev-btn');
|
|
2700
|
-
var fullOptionsButton = document.getElementById('local-dev-full-options');
|
|
2701
|
-
if (!container || !button || !__anCanUseLocalDevSignin()) return;
|
|
2702
|
-
function __anShowLocalDevSignin() {
|
|
2703
|
-
container.hidden = false;
|
|
2704
|
-
var startWithLocalDev = __anShouldStartWithLocalDev();
|
|
2705
|
-
__anSetFullAuthOptionsVisible(!startWithLocalDev);
|
|
2706
|
-
if (startWithLocalDev) button.focus();
|
|
2707
|
-
if (fullOptionsButton) fullOptionsButton.addEventListener('click', function() {
|
|
2708
|
-
__anSetFullAuthOptionsVisible(true);
|
|
2709
|
-
var firstInput = document.querySelector('#full-auth-options input, #full-auth-options button, #full-auth-options a');
|
|
2710
|
-
if (firstInput) firstInput.focus();
|
|
2711
|
-
});
|
|
2712
|
-
button.addEventListener('click', function() {
|
|
2713
|
-
button.disabled = true;
|
|
2714
|
-
button.textContent = __anT('localDevSigningIn');
|
|
2715
|
-
fetch(__anPath('/_agent-native/auth/local-dev'), {
|
|
2716
|
-
method: 'POST',
|
|
2717
|
-
credentials: 'include',
|
|
2718
|
-
headers: { 'Accept': 'application/json' },
|
|
2719
|
-
}).then(function(response) {
|
|
2720
|
-
if (!response.ok) throw new Error('local-dev-auth-failed');
|
|
2721
|
-
}).then(function() {
|
|
2722
|
-
__anRedirectToSignedInApp(__anResumeHref());
|
|
2723
|
-
}).catch(function() {
|
|
2724
|
-
container.hidden = true;
|
|
2725
|
-
__anSetFullAuthOptionsVisible(true);
|
|
2726
|
-
});
|
|
2727
|
-
});
|
|
2728
|
-
}
|
|
2729
|
-
fetch(__anPath('/_agent-native/auth/local-dev'), {
|
|
2730
|
-
method: 'GET',
|
|
2731
|
-
credentials: 'include',
|
|
2732
|
-
cache: 'no-store',
|
|
2733
|
-
headers: { 'Accept': 'application/json' },
|
|
2734
|
-
}).then(function(response) {
|
|
2735
|
-
if (!response.ok) return null;
|
|
2736
|
-
return response.json().then(function(data) {
|
|
2737
|
-
return data;
|
|
2738
|
-
}, function() {
|
|
2739
|
-
return null;
|
|
2740
|
-
});
|
|
2741
|
-
}, function() {
|
|
2742
|
-
return null;
|
|
2743
|
-
}).then(function(data) {
|
|
2744
|
-
if (data && data.available === true) {
|
|
2745
|
-
__anShowLocalDevSignin();
|
|
2746
|
-
} else {
|
|
2747
|
-
__anSetFullAuthOptionsVisible(true);
|
|
2748
|
-
}
|
|
2749
|
-
});
|
|
2750
|
-
})();
|
|
2751
|
-
${identitySsoScript}
|
|
2752
|
-
(function __anRedirectIfAlreadySignedIn() {
|
|
2753
|
-
__anMaybeRedirectSignedIn();
|
|
2754
|
-
})();
|
|
2755
|
-
function __anSafeAttributionValue(value) {
|
|
2756
|
-
return typeof value === 'string' ? value.trim().slice(0, 120) : '';
|
|
2757
|
-
}
|
|
2758
|
-
function __anGenerateAnalyticsAnonymousId() {
|
|
2759
|
-
try {
|
|
2760
|
-
if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') return crypto.randomUUID();
|
|
2761
|
-
} catch(e) {}
|
|
2762
|
-
return Date.now().toString(36) + Math.random().toString(36).slice(2) + Math.random().toString(36).slice(2);
|
|
2763
|
-
}
|
|
2764
|
-
function __anSyncAnalyticsAnonymousId() {
|
|
2765
|
-
try {
|
|
2766
|
-
var anonymousId = '';
|
|
2767
|
-
try { anonymousId = localStorage.getItem('agent-native.anonymous_id') || ''; } catch(e) {}
|
|
2768
|
-
if (!/^[A-Za-z0-9_-]{1,128}$/.test(anonymousId)) {
|
|
2769
|
-
anonymousId = __anGenerateAnalyticsAnonymousId();
|
|
2770
|
-
try { localStorage.setItem('agent-native.anonymous_id', anonymousId); } catch(e) {}
|
|
2771
|
-
}
|
|
2772
|
-
document.cookie = 'an_aid=' + encodeURIComponent(anonymousId) + '; path=/; max-age=2592000; SameSite=Lax';
|
|
2773
|
-
} catch(e) {}
|
|
2774
|
-
}
|
|
2775
|
-
function __anFirstTouchCookiePresent() {
|
|
2776
|
-
try {
|
|
2777
|
-
return document.cookie.split(';').some(function(part) {
|
|
2778
|
-
return part.trim().indexOf('an_ft=') === 0;
|
|
2779
|
-
});
|
|
2780
|
-
} catch(e) {
|
|
2781
|
-
return false;
|
|
2782
|
-
}
|
|
2783
|
-
}
|
|
2784
|
-
function __anWriteFirstTouchCookie(json) {
|
|
2785
|
-
try {
|
|
2786
|
-
document.cookie = 'an_ft=' + encodeURIComponent(json) + '; path=/; max-age=2592000; SameSite=Lax';
|
|
2787
|
-
} catch(e) {}
|
|
2788
|
-
}
|
|
2789
|
-
function __anExternalReferrerHost(referrer) {
|
|
2790
|
-
try {
|
|
2791
|
-
var url = new URL(referrer);
|
|
2792
|
-
if (url.host.toLowerCase() === window.location.host.toLowerCase()) return '';
|
|
2793
|
-
return __anSafeAttributionValue(url.host);
|
|
2794
|
-
} catch(e) {
|
|
2795
|
-
return '';
|
|
2796
|
-
}
|
|
2797
|
-
}
|
|
2798
|
-
function __anCaptureSignupAttribution() {
|
|
2799
|
-
try {
|
|
2800
|
-
var stored = '';
|
|
2801
|
-
try { stored = localStorage.getItem('an_attribution') || ''; } catch(e) {}
|
|
2802
|
-
if (stored) {
|
|
2803
|
-
if (!__anFirstTouchCookiePresent()) __anWriteFirstTouchCookie(stored);
|
|
2804
|
-
return;
|
|
2805
|
-
}
|
|
2806
|
-
if (__anFirstTouchCookiePresent()) return;
|
|
2807
|
-
var params = new URLSearchParams(window.location.search || '');
|
|
2808
|
-
var ft = {};
|
|
2809
|
-
['ref', 'via', 'utm_source', 'utm_medium', 'utm_campaign', 'utm_content', 'utm_term'].forEach(function(key) {
|
|
2810
|
-
var value = __anSafeAttributionValue(params.get(key));
|
|
2811
|
-
if (value) ft[key] = value;
|
|
2812
|
-
});
|
|
2813
|
-
var returnPath = __anJourney.normalizeAppPath(params.get('return'));
|
|
2814
|
-
var landingPath = __anSafeAttributionValue(returnPath || window.location.pathname || '');
|
|
2815
|
-
if (landingPath) ft.landing_path = landingPath;
|
|
2816
|
-
var referrer = __anExternalReferrerHost(document.referrer || '');
|
|
2817
|
-
if (referrer) ft.landing_referrer = referrer;
|
|
2818
|
-
ft.landed_at = new Date().toISOString();
|
|
2819
|
-
var json = JSON.stringify(ft);
|
|
2820
|
-
try { localStorage.setItem('an_attribution', json); } catch(e) {}
|
|
2821
|
-
__anWriteFirstTouchCookie(json);
|
|
2822
|
-
} catch(e) {}
|
|
2823
|
-
}
|
|
2824
|
-
__anSyncAnalyticsAnonymousId();
|
|
2825
|
-
__anCaptureSignupAttribution();
|
|
2826
|
-
var __anBuilderPreviewSeen = false;
|
|
2827
|
-
function __anRememberBuilderPreview() {
|
|
2828
|
-
__anBuilderPreviewSeen = true;
|
|
2829
|
-
try { sessionStorage.setItem('__an_builder_preview_seen', '1'); } catch(e) {}
|
|
2830
|
-
}
|
|
2831
|
-
function __anHasBuilderPreviewSignal() {
|
|
2832
|
-
try {
|
|
2833
|
-
var params = new URLSearchParams(window.location.search);
|
|
2834
|
-
if (params.has('builder.preview') || params.has('builder.frameEditing') || params.has('__builder_editing__')) return true;
|
|
2835
|
-
} catch(e) {}
|
|
2836
|
-
return false;
|
|
2837
|
-
}
|
|
2838
|
-
function __anIsBuilderPreview() {
|
|
2839
|
-
if (__anBuilderPreviewSeen) return true;
|
|
2840
|
-
if (__anHasBuilderPreviewSignal()) {
|
|
2841
|
-
__anRememberBuilderPreview();
|
|
2842
|
-
return true;
|
|
2843
|
-
}
|
|
2844
|
-
try {
|
|
2845
|
-
if (sessionStorage.getItem('__an_builder_preview_seen') === '1') {
|
|
2846
|
-
__anBuilderPreviewSeen = true;
|
|
2847
|
-
return true;
|
|
2848
|
-
}
|
|
2849
|
-
} catch(e) {}
|
|
2850
|
-
try {
|
|
2851
|
-
var ref = document.referrer || '';
|
|
2852
|
-
var fromBuilder = ref.indexOf('builder.io') !== -1 || ref.indexOf('builder.my') !== -1 || ref.indexOf('builderio.xyz') !== -1 || ref.indexOf('builderio.dev') !== -1 || ref.indexOf('builder.codes') !== -1;
|
|
2853
|
-
if (fromBuilder) __anRememberBuilderPreview();
|
|
2854
|
-
return fromBuilder;
|
|
2855
|
-
} catch(e) {
|
|
2856
|
-
return false;
|
|
2857
|
-
}
|
|
2858
|
-
}
|
|
2859
|
-
__anIsBuilderPreview();
|
|
2860
|
-
function __anIsBuilderDesktop() {
|
|
2861
|
-
try {
|
|
2862
|
-
var ua = navigator.userAgent || '';
|
|
2863
|
-
return ua.indexOf('Electron') !== -1 && ua.indexOf('AgentNativeDesktop') === -1;
|
|
2864
|
-
} catch(e) {
|
|
2865
|
-
return false;
|
|
2866
|
-
}
|
|
2867
|
-
}
|
|
2868
|
-
function __anIsAgentNativeDesktop() {
|
|
2869
|
-
try {
|
|
2870
|
-
return (navigator.userAgent || '').indexOf('AgentNativeDesktop') !== -1;
|
|
2871
|
-
} catch(e) {
|
|
2872
|
-
return false;
|
|
2873
|
-
}
|
|
2874
|
-
}
|
|
2875
|
-
function __anIsInFrame() {
|
|
2876
|
-
try {
|
|
2877
|
-
return window.self !== window.top;
|
|
2878
|
-
} catch(e) {
|
|
2879
|
-
return true;
|
|
2880
|
-
}
|
|
2881
|
-
}
|
|
2882
|
-
function __anIsElectron() {
|
|
2883
|
-
try {
|
|
2884
|
-
return (navigator.userAgent || '').indexOf('Electron') !== -1;
|
|
2885
|
-
} catch(e) {
|
|
2886
|
-
return false;
|
|
2887
|
-
}
|
|
2888
|
-
}
|
|
2889
|
-
function __anResolveAuthFlow() {
|
|
2890
|
-
if (__anIsBuilderPreview()) return __anIsInFrame() ? 'popup' : 'redirect';
|
|
2891
|
-
// Per-session override for ad-hoc testing outside Builder: append
|
|
2892
|
-
// ?authMode=popup or ?authMode=redirect to the sign-in URL.
|
|
2893
|
-
var qp = new URLSearchParams(window.location.search).get('authMode');
|
|
2894
|
-
if (qp === 'popup' || qp === 'redirect') return qp;
|
|
2895
|
-
var mode = __AN_GOOGLE_AUTH_MODE || 'auto';
|
|
2896
|
-
if (mode === 'popup') return 'popup';
|
|
2897
|
-
if (mode === 'redirect') return 'redirect';
|
|
2898
|
-
return __anIsAgentNativeDesktop() ? 'redirect' : 'popup';
|
|
2899
|
-
}
|
|
2900
|
-
var __anOAuthPollTimer = null;
|
|
2901
|
-
var __anOAuthPopupWatchTimer = null;
|
|
2902
|
-
var __anOAuthPopupCloseGraceTimer = null;
|
|
2903
|
-
var __anOAuthPopupCloseGraceMs = 5000;
|
|
2904
|
-
var __anNativeOAuthFlowId = null;
|
|
2905
|
-
var __anNativeOAuthRequestPending = false;
|
|
2906
|
-
var __anNativeOAuthReturnObserved = false;
|
|
2907
|
-
var __anNativeOAuthAbandonGraceTimer = null;
|
|
2908
|
-
var __anNativeOAuthAbandonGraceMs = 5000;
|
|
2909
|
-
var __anOAuthPollCount = 0;
|
|
2910
|
-
var __anGoogleSignInInFlight = false;
|
|
2911
|
-
var __anGoogleSignInFlowId = null;
|
|
2912
|
-
var __anGoogleSignInRecoveryFlowId = null;
|
|
2913
|
-
var __anMagicLinkInFlight = false;
|
|
2914
|
-
var __anGoogleRecoverBound = false;
|
|
2915
|
-
function __anNewOAuthFlowId() {
|
|
2916
|
-
try {
|
|
2917
|
-
if (window.crypto && typeof window.crypto.randomUUID === 'function') {
|
|
2918
|
-
return window.crypto.randomUUID();
|
|
2919
|
-
}
|
|
2920
|
-
} catch(e) {}
|
|
2921
|
-
return 'builder-' + Date.now().toString(36) + '-' + Math.random().toString(36).slice(2);
|
|
2922
|
-
}
|
|
2923
|
-
function __anNewOAuthVerifier() {
|
|
2924
|
-
try {
|
|
2925
|
-
if (window.crypto && typeof window.crypto.randomUUID === 'function') {
|
|
2926
|
-
return window.crypto.randomUUID() + window.crypto.randomUUID();
|
|
2927
|
-
}
|
|
2928
|
-
if (window.crypto && typeof window.crypto.getRandomValues === 'function') {
|
|
2929
|
-
var bytes = new Uint8Array(32);
|
|
2930
|
-
window.crypto.getRandomValues(bytes);
|
|
2931
|
-
var binary = '';
|
|
2932
|
-
for (var i = 0; i < bytes.length; i++) binary += String.fromCharCode(bytes[i]);
|
|
2933
|
-
return btoa(binary).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '');
|
|
2934
|
-
}
|
|
2935
|
-
} catch(e) { // coercion-ok: callers reject the empty verifier fallback.
|
|
2936
|
-
}
|
|
2937
|
-
return '';
|
|
2938
|
-
}
|
|
2939
|
-
function __anFlowDebugId(flowId) {
|
|
2940
|
-
return flowId ? String(flowId).slice(-10) : '';
|
|
2941
|
-
}
|
|
2942
|
-
function __anSetOAuthDebug(message, flowId) {
|
|
2943
|
-
var text = message + (flowId ? ' (flow ' + __anFlowDebugId(flowId) + ')' : '');
|
|
2944
|
-
try {
|
|
2945
|
-
console.info('[agent-native][google-oauth] ' + text);
|
|
2946
|
-
} catch(e) {}
|
|
2947
|
-
// Only surface the debug overlay when explicitly opted in via #oauth-debug
|
|
2948
|
-
// hash or ?oauth_debug=1 query — otherwise it leaks raw flow IDs and
|
|
2949
|
-
// diagnostic strings into the user-facing sign-in screen.
|
|
2950
|
-
var showDebugOverlay = false;
|
|
2951
|
-
try {
|
|
2952
|
-
var loc = window.location || {};
|
|
2953
|
-
showDebugOverlay =
|
|
2954
|
-
(typeof loc.hash === 'string' && loc.hash.indexOf('oauth-debug') !== -1) ||
|
|
2955
|
-
(typeof loc.search === 'string' && loc.search.indexOf('oauth_debug=1') !== -1);
|
|
2956
|
-
} catch(e) {}
|
|
2957
|
-
var debug = document.getElementById('google-debug');
|
|
2958
|
-
if (debug) {
|
|
2959
|
-
debug.textContent = text;
|
|
2960
|
-
if (showDebugOverlay) debug.classList.add('show');
|
|
2961
|
-
}
|
|
2962
|
-
}
|
|
2963
|
-
function __anStopOAuthExchangePolling() {
|
|
2964
|
-
if (__anOAuthPollTimer) {
|
|
2965
|
-
clearInterval(__anOAuthPollTimer);
|
|
2966
|
-
__anOAuthPollTimer = null;
|
|
2967
|
-
}
|
|
2968
|
-
}
|
|
2969
|
-
function __anStopOAuthPopupWatch() {
|
|
2970
|
-
if (__anOAuthPopupWatchTimer) {
|
|
2971
|
-
clearInterval(__anOAuthPopupWatchTimer);
|
|
2972
|
-
__anOAuthPopupWatchTimer = null;
|
|
2973
|
-
}
|
|
2974
|
-
if (__anOAuthPopupCloseGraceTimer) {
|
|
2975
|
-
clearTimeout(__anOAuthPopupCloseGraceTimer);
|
|
2976
|
-
__anOAuthPopupCloseGraceTimer = null;
|
|
2977
|
-
}
|
|
2978
|
-
}
|
|
2979
|
-
function __anStopNativeOAuthAbandonment() {
|
|
2980
|
-
__anCancelNativeOAuthAbandonment();
|
|
2981
|
-
__anNativeOAuthFlowId = null;
|
|
2982
|
-
__anNativeOAuthRequestPending = false;
|
|
2983
|
-
}
|
|
2984
|
-
function __anCancelNativeOAuthAbandonment() {
|
|
2985
|
-
if (__anNativeOAuthAbandonGraceTimer) {
|
|
2986
|
-
clearTimeout(__anNativeOAuthAbandonGraceTimer);
|
|
2987
|
-
__anNativeOAuthAbandonGraceTimer = null;
|
|
2988
|
-
}
|
|
2989
|
-
__anNativeOAuthReturnObserved = false;
|
|
2990
|
-
}
|
|
2991
|
-
function __anBeginNativeOAuth(flowId) {
|
|
2992
|
-
__anStopNativeOAuthAbandonment();
|
|
2993
|
-
__anNativeOAuthFlowId = flowId;
|
|
2994
|
-
__anNativeOAuthRequestPending = true;
|
|
2995
|
-
__anNativeOAuthReturnObserved = false;
|
|
2996
|
-
}
|
|
2997
|
-
function __anMarkNativeOAuthPolling(flowId) {
|
|
2998
|
-
if (__anNativeOAuthFlowId !== flowId) return;
|
|
2999
|
-
__anNativeOAuthRequestPending = false;
|
|
3000
|
-
}
|
|
3001
|
-
function __anIsCurrentNativeOAuth(flowId) {
|
|
3002
|
-
return __anNativeOAuthFlowId === flowId && __anIsCurrentGoogleSignInFlow(flowId);
|
|
3003
|
-
}
|
|
3004
|
-
function __anFinalizeNativeOAuthAbandonment(flowId) {
|
|
3005
|
-
if (!__anIsCurrentNativeOAuth(flowId) || !__anOAuthPollTimer) return;
|
|
3006
|
-
if (document.visibilityState === 'hidden') {
|
|
3007
|
-
__anCancelNativeOAuthAbandonment();
|
|
3008
|
-
return;
|
|
3009
|
-
}
|
|
3010
|
-
__anStopNativeOAuthAbandonment();
|
|
3011
|
-
if (__anInvalidateGoogleSignInFlow(flowId)) {
|
|
3012
|
-
__anStopOAuthExchangePolling();
|
|
3013
|
-
__anRecoverGoogleSignInAfterReturn(flowId);
|
|
3014
|
-
}
|
|
3015
|
-
}
|
|
3016
|
-
function __anScheduleNativeOAuthAbandonment(flowId) {
|
|
3017
|
-
// Returning focus is the only signal that the system-browser ceremony was
|
|
3018
|
-
// abandoned. Preserve the exchange poll briefly for a late deep-link.
|
|
3019
|
-
if (
|
|
3020
|
-
!__anIsCurrentNativeOAuth(flowId) ||
|
|
3021
|
-
__anNativeOAuthRequestPending ||
|
|
3022
|
-
!__anNativeOAuthReturnObserved ||
|
|
3023
|
-
!__anOAuthPollTimer ||
|
|
3024
|
-
__anNativeOAuthAbandonGraceTimer
|
|
3025
|
-
) return;
|
|
3026
|
-
__anNativeOAuthAbandonGraceTimer = setTimeout(function() {
|
|
3027
|
-
__anNativeOAuthAbandonGraceTimer = null;
|
|
3028
|
-
__anFinalizeNativeOAuthAbandonment(flowId);
|
|
3029
|
-
}, __anNativeOAuthAbandonGraceMs);
|
|
3030
|
-
}
|
|
3031
|
-
function __anBeginGoogleSignInFlow(flowId) {
|
|
3032
|
-
__anGoogleSignInFlowId = flowId;
|
|
3033
|
-
__anGoogleSignInRecoveryFlowId = null;
|
|
3034
|
-
__anGoogleSignInInFlight = true;
|
|
3035
|
-
}
|
|
3036
|
-
function __anIsCurrentGoogleSignInFlow(flowId) {
|
|
3037
|
-
return __anGoogleSignInInFlight && __anGoogleSignInFlowId === flowId;
|
|
3038
|
-
}
|
|
3039
|
-
function __anClearGoogleSignInFlow() {
|
|
3040
|
-
__anGoogleSignInFlowId = null;
|
|
3041
|
-
__anGoogleSignInRecoveryFlowId = null;
|
|
3042
|
-
}
|
|
3043
|
-
function __anInvalidateGoogleSignInFlow(flowId) {
|
|
3044
|
-
if (!__anIsCurrentGoogleSignInFlow(flowId)) return false;
|
|
3045
|
-
__anGoogleSignInFlowId = null;
|
|
3046
|
-
__anGoogleSignInRecoveryFlowId = flowId;
|
|
3047
|
-
return true;
|
|
3048
|
-
}
|
|
3049
|
-
function __anCanRecoverGoogleSignInFlow(flowId, expectedFlowId) {
|
|
3050
|
-
// Focus can return while either the system-browser exchange or the popup
|
|
3051
|
-
// exchange is still active. Let that exchange finish before recovering.
|
|
3052
|
-
if (!flowId && (__anNativeOAuthFlowId || __anOAuthPollTimer || __anOAuthPopupWatchTimer)) return false;
|
|
3053
|
-
if (flowId) {
|
|
3054
|
-
return __anGoogleSignInInFlight &&
|
|
3055
|
-
!__anGoogleSignInFlowId &&
|
|
3056
|
-
__anGoogleSignInRecoveryFlowId === flowId;
|
|
3057
|
-
}
|
|
3058
|
-
return __anGoogleSignInInFlight && __anGoogleSignInFlowId === expectedFlowId;
|
|
3059
|
-
}
|
|
3060
|
-
function __anFinalizeOAuthPopupClose(flowId) {
|
|
3061
|
-
if (!__anIsCurrentGoogleSignInFlow(flowId)) return;
|
|
3062
|
-
__anOAuthPopupCloseGraceTimer = null;
|
|
3063
|
-
if (__anInvalidateGoogleSignInFlow(flowId)) {
|
|
3064
|
-
__anStopOAuthExchangePolling();
|
|
3065
|
-
__anRecoverGoogleSignInAfterReturn(flowId);
|
|
3066
|
-
}
|
|
3067
|
-
}
|
|
3068
|
-
function __anHandleOAuthPopupClosed(flowId) {
|
|
3069
|
-
__anStopOAuthPopupWatch();
|
|
3070
|
-
// The success callback closes its tab 250ms after staging the token, but
|
|
3071
|
-
// the opener polls once per second. Let an active exchange win that race.
|
|
3072
|
-
if (__anOAuthPollTimer) {
|
|
3073
|
-
__anOAuthPopupCloseGraceTimer = setTimeout(function() {
|
|
3074
|
-
__anFinalizeOAuthPopupClose(flowId);
|
|
3075
|
-
}, __anOAuthPopupCloseGraceMs);
|
|
3076
|
-
return;
|
|
3077
|
-
}
|
|
3078
|
-
__anFinalizeOAuthPopupClose(flowId);
|
|
3079
|
-
}
|
|
3080
|
-
function __anWatchOAuthPopupClose(popup, flowId) {
|
|
3081
|
-
__anStopOAuthPopupWatch();
|
|
3082
|
-
__anOAuthPopupWatchTimer = setInterval(function() {
|
|
3083
|
-
if (!__anIsCurrentGoogleSignInFlow(flowId)) {
|
|
3084
|
-
__anStopOAuthPopupWatch();
|
|
3085
|
-
return;
|
|
3086
|
-
}
|
|
3087
|
-
var closed = false;
|
|
3088
|
-
try {
|
|
3089
|
-
closed = popup.closed === true;
|
|
3090
|
-
} catch(e) {
|
|
3091
|
-
__anHandleOAuthPopupClosed(flowId);
|
|
3092
|
-
return;
|
|
3093
|
-
}
|
|
3094
|
-
if (!closed) return;
|
|
3095
|
-
__anHandleOAuthPopupClosed(flowId);
|
|
3096
|
-
}, 500);
|
|
3097
|
-
}
|
|
3098
|
-
function __anShowAuthExchangeError(err, btn, message, kind) {
|
|
3099
|
-
__anStopOAuthExchangePolling();
|
|
3100
|
-
__anStopOAuthPopupWatch();
|
|
3101
|
-
__anStopNativeOAuthAbandonment();
|
|
3102
|
-
err.textContent = message;
|
|
3103
|
-
err.classList.add('show', 'error');
|
|
3104
|
-
btn.disabled = false;
|
|
3105
|
-
if (kind === 'magic-link') {
|
|
3106
|
-
__anMagicLinkInFlight = false;
|
|
3107
|
-
showMagicLinkForm();
|
|
3108
|
-
} else {
|
|
3109
|
-
__anGoogleSignInInFlight = false;
|
|
3110
|
-
__anClearGoogleSignInFlow();
|
|
3111
|
-
}
|
|
3112
|
-
}
|
|
3113
|
-
function __anShowOAuthError(err, btn, message) {
|
|
3114
|
-
__anShowAuthExchangeError(err, btn, message, 'google');
|
|
3115
|
-
}
|
|
3116
|
-
function __anRecoverGoogleSignInAfterReturn(flowId) {
|
|
3117
|
-
// The user left for the Google sign-in window and came back. If the flow
|
|
3118
|
-
// never completed (e.g. they closed the window to switch profiles), the
|
|
3119
|
-
// button is stuck disabled with no error path firing for up to 5 minutes.
|
|
3120
|
-
// Re-enable it so they can retry. Wait briefly first so a genuinely
|
|
3121
|
-
// in-flight exchange can still finish and navigate without a flicker.
|
|
3122
|
-
if (!flowId && __anNativeOAuthFlowId) {
|
|
3123
|
-
__anNativeOAuthReturnObserved = true;
|
|
3124
|
-
__anScheduleNativeOAuthAbandonment(__anNativeOAuthFlowId);
|
|
3125
|
-
return;
|
|
3126
|
-
}
|
|
3127
|
-
var expectedFlowId = flowId || __anGoogleSignInFlowId;
|
|
3128
|
-
if (!__anCanRecoverGoogleSignInFlow(flowId, expectedFlowId)) return;
|
|
3129
|
-
setTimeout(function() {
|
|
3130
|
-
if (!__anCanRecoverGoogleSignInFlow(flowId, expectedFlowId)) return;
|
|
3131
|
-
__anMaybeRedirectSignedIn(__anResumeHref()).then(function(redirected) {
|
|
3132
|
-
if (!__anCanRecoverGoogleSignInFlow(flowId, expectedFlowId)) return;
|
|
3133
|
-
if (redirected) return;
|
|
3134
|
-
var btn = document.getElementById('google-btn');
|
|
3135
|
-
if (!btn || !btn.disabled) return;
|
|
3136
|
-
// Keep the desktop-exchange poll alive. Agent-Native Desktop opens
|
|
3137
|
-
// Google in the system browser, so focus can return before the
|
|
3138
|
-
// callback has stored the session token.
|
|
3139
|
-
btn.disabled = false;
|
|
3140
|
-
__anGoogleSignInInFlight = false;
|
|
3141
|
-
__anClearGoogleSignInFlow();
|
|
3142
|
-
});
|
|
3143
|
-
}, 1200);
|
|
3144
|
-
}
|
|
3145
|
-
function __anBindGoogleRecover() {
|
|
3146
|
-
if (__anGoogleRecoverBound) return;
|
|
3147
|
-
__anGoogleRecoverBound = true;
|
|
3148
|
-
window.addEventListener('focus', function() {
|
|
3149
|
-
__anRecoverGoogleSignInAfterReturn();
|
|
3150
|
-
});
|
|
3151
|
-
window.addEventListener('blur', function() {
|
|
3152
|
-
__anCancelNativeOAuthAbandonment();
|
|
3153
|
-
});
|
|
3154
|
-
document.addEventListener('visibilitychange', function() {
|
|
3155
|
-
if (document.visibilityState === 'visible') {
|
|
3156
|
-
__anRecoverGoogleSignInAfterReturn();
|
|
3157
|
-
} else {
|
|
3158
|
-
__anCancelNativeOAuthAbandonment();
|
|
3159
|
-
}
|
|
3160
|
-
});
|
|
3161
|
-
}
|
|
3162
|
-
function __anHandlePopupOAuthFailure(ret, btn, err, flowId, redirectReason, builderFrameMessage) {
|
|
3163
|
-
if (__anIsBuilderPreview() && __anIsInFrame()) {
|
|
3164
|
-
__anShowOAuthError(err, btn, builderFrameMessage + ' ' + __anT('googlePopupHelp') + ' (flow ' + __anFlowDebugId(flowId) + ').');
|
|
3165
|
-
return;
|
|
3166
|
-
}
|
|
3167
|
-
__anStartRedirectOAuth(ret, btn, err, flowId, redirectReason);
|
|
3168
|
-
}
|
|
3169
|
-
function __anStartRedirectOAuth(ret, btn, err, flowId, reason) {
|
|
3170
|
-
var params = new URLSearchParams();
|
|
3171
|
-
var oauthReturn = __anIsBuilderPreview() ? __anOAuthReturnTarget(ret) : ret;
|
|
3172
|
-
if (oauthReturn) params.set('return', oauthReturn);
|
|
3173
|
-
params.set('redirect', '1');
|
|
3174
|
-
__anSetOAuthDebug(reason || 'Opening Google sign-in redirect', flowId);
|
|
3175
|
-
try {
|
|
3176
|
-
__anOpenOAuthUrl(__anGoogleAuthUrlPath() + '?' + params.toString());
|
|
3177
|
-
} catch(e) {
|
|
3178
|
-
__anShowOAuthError(err, btn, __anT('failedToConnect'));
|
|
3179
|
-
}
|
|
3180
|
-
}
|
|
3181
|
-
function __anWaitForOAuthExchange(flowId, ret, btn, err, kind, verifier) {
|
|
3182
|
-
var started = Date.now();
|
|
3183
|
-
var timeoutMs = 5 * 60 * 1000;
|
|
3184
|
-
var isMagicLink = kind === 'magic-link';
|
|
3185
|
-
__anOAuthPollCount = 0;
|
|
3186
|
-
async function check() {
|
|
3187
|
-
if (!isMagicLink && !__anIsCurrentGoogleSignInFlow(flowId)) return;
|
|
3188
|
-
__anOAuthPollCount++;
|
|
3189
|
-
try {
|
|
3190
|
-
var exchangeParams = '?flow_id=' + encodeURIComponent(flowId);
|
|
3191
|
-
var exchangeOptions = { credentials: 'include' };
|
|
3192
|
-
if (verifier) {
|
|
3193
|
-
exchangeOptions.headers = { 'X-Agent-Native-Desktop-Verifier': verifier };
|
|
3194
|
-
}
|
|
3195
|
-
var res = await fetch(__anPath('/_agent-native/auth/desktop-exchange') + exchangeParams, exchangeOptions);
|
|
3196
|
-
var data = await res.json().catch(function() { return {}; });
|
|
3197
|
-
if (!isMagicLink && !__anIsCurrentGoogleSignInFlow(flowId)) return;
|
|
3198
|
-
if (data && (data.email || data.token)) {
|
|
3199
|
-
if (__anOAuthPollTimer) clearInterval(__anOAuthPollTimer);
|
|
3200
|
-
__anOAuthPollTimer = null;
|
|
3201
|
-
__anFinishOAuthExchange(ret, flowId, data.token);
|
|
3202
|
-
return;
|
|
3203
|
-
}
|
|
3204
|
-
if (data && data.error) {
|
|
3205
|
-
__anSetOAuthDebug('OAuth exchange returned an error: ' + (data.message || data.error), flowId);
|
|
3206
|
-
__anShowAuthExchangeError(
|
|
3207
|
-
err,
|
|
3208
|
-
btn,
|
|
3209
|
-
__anAuthErrorText(data, isMagicLink ? __anT('magicLinkFailed') : __anT('googleNotConfigured')),
|
|
3210
|
-
isMagicLink ? 'magic-link' : 'google',
|
|
3211
|
-
);
|
|
3212
|
-
return;
|
|
3213
|
-
}
|
|
3214
|
-
if (data && data.pending && (__anOAuthPollCount === 1 || __anOAuthPollCount % 5 === 0)) {
|
|
3215
|
-
__anSetOAuthDebug('Waiting for the Google callback; polling attempt ' + __anOAuthPollCount, flowId);
|
|
3216
|
-
}
|
|
3217
|
-
} catch(e) {
|
|
3218
|
-
if (__anOAuthPollCount === 1 || __anOAuthPollCount % 5 === 0) {
|
|
3219
|
-
__anSetOAuthDebug('Could not reach the OAuth exchange endpoint: ' + (e && e.message ? e.message : 'network error'), flowId);
|
|
3220
|
-
}
|
|
3221
|
-
}
|
|
3222
|
-
if (Date.now() - started > timeoutMs) {
|
|
3223
|
-
__anShowAuthExchangeError(
|
|
3224
|
-
err,
|
|
3225
|
-
btn,
|
|
3226
|
-
isMagicLink
|
|
3227
|
-
? __anT('magicLinkFailed')
|
|
3228
|
-
: __anT('googleNeverFinished') + ' Flow ' + __anFlowDebugId(flowId) + '.',
|
|
3229
|
-
isMagicLink ? 'magic-link' : 'google',
|
|
3230
|
-
);
|
|
3231
|
-
}
|
|
3232
|
-
}
|
|
3233
|
-
__anStopOAuthExchangePolling();
|
|
3234
|
-
__anOAuthPollTimer = setInterval(check, 1000);
|
|
3235
|
-
setTimeout(check, 500);
|
|
3236
|
-
}
|
|
3237
|
-
async function __anRequestDesktopOAuthUrl(flowId, verifier, oauthReturn) {
|
|
3238
|
-
var params = new URLSearchParams();
|
|
3239
|
-
if (oauthReturn) params.set('return', oauthReturn);
|
|
3240
|
-
params.set('desktop', '1');
|
|
3241
|
-
params.set('flow_id', flowId);
|
|
3242
|
-
var res = await fetch(__anGoogleAuthUrlPath() + '?' + params.toString(), {
|
|
3243
|
-
method: 'POST',
|
|
3244
|
-
credentials: 'include',
|
|
3245
|
-
headers: {
|
|
3246
|
-
'Accept': 'application/json',
|
|
3247
|
-
'X-Agent-Native-Desktop-Verifier': verifier
|
|
3248
|
-
}
|
|
3249
|
-
});
|
|
3250
|
-
var data;
|
|
3251
|
-
try {
|
|
3252
|
-
data = await res.json();
|
|
3253
|
-
} catch(e) {
|
|
3254
|
-
throw new Error(__anT('failedToConnect'));
|
|
3255
|
-
}
|
|
3256
|
-
if (!res.ok || !data || typeof data.url !== 'string' || !data.url) {
|
|
3257
|
-
throw new Error(__anAuthErrorText(data, __anT('failedToConnect')));
|
|
3258
|
-
}
|
|
3259
|
-
return data.url;
|
|
3260
|
-
}
|
|
3261
|
-
function __anStartPopupOAuth(ret, btn, err, flowId) {
|
|
3262
|
-
var verifier = __anNewOAuthVerifier();
|
|
3263
|
-
if (!verifier) {
|
|
3264
|
-
__anShowOAuthError(err, btn, __anT('failedToConnect'));
|
|
3265
|
-
return;
|
|
3266
|
-
}
|
|
3267
|
-
var oauthReturn = __anIsBuilderPreview() ? __anOAuthReturnTarget(ret) : ret;
|
|
3268
|
-
try { sessionStorage.setItem('__an_signin', '1'); } catch(e) {}
|
|
3269
|
-
__anSetOAuthDebug('Opening Google sign-in popup', flowId);
|
|
3270
|
-
var popup;
|
|
3271
|
-
try {
|
|
3272
|
-
popup = window.open('', '_blank', 'width=640,height=760');
|
|
3273
|
-
if (!popup) {
|
|
3274
|
-
__anHandlePopupOAuthFailure(ret, btn, err, flowId, 'Google popup was blocked; falling back to redirect', 'Google popup was blocked.');
|
|
3275
|
-
return;
|
|
3276
|
-
}
|
|
3277
|
-
try { popup.opener = null; } catch(e) {}
|
|
3278
|
-
__anWatchOAuthPopupClose(popup, flowId);
|
|
3279
|
-
} catch(e) {
|
|
3280
|
-
__anHandlePopupOAuthFailure(ret, btn, err, flowId, 'Could not open Google popup; falling back to redirect', 'Could not open Google popup.');
|
|
3281
|
-
return;
|
|
3282
|
-
}
|
|
3283
|
-
__anRequestDesktopOAuthUrl(flowId, verifier, oauthReturn).then(function(url) {
|
|
3284
|
-
if (!__anIsCurrentGoogleSignInFlow(flowId)) return;
|
|
3285
|
-
try {
|
|
3286
|
-
popup.location.href = url;
|
|
3287
|
-
__anSetOAuthDebug('Google popup opened; waiting for callback', flowId);
|
|
3288
|
-
__anWaitForOAuthExchange(flowId, ret, btn, err, 'google', verifier);
|
|
3289
|
-
} catch(e) {
|
|
3290
|
-
throw e;
|
|
3291
|
-
}
|
|
3292
|
-
}).catch(function(e) {
|
|
3293
|
-
if (!__anIsCurrentGoogleSignInFlow(flowId)) return;
|
|
3294
|
-
try { popup.close(); } catch(closeErr) {}
|
|
3295
|
-
__anShowOAuthError(err, btn, e && e.message ? e.message : __anT('failedToConnect'));
|
|
3296
|
-
});
|
|
3297
|
-
}
|
|
3298
|
-
function __anStartNativeDesktopOAuth(ret, btn, err, flowId) {
|
|
3299
|
-
var verifier = __anNewOAuthVerifier();
|
|
3300
|
-
if (!verifier) {
|
|
3301
|
-
__anShowOAuthError(err, btn, __anT('failedToConnect'));
|
|
3302
|
-
return;
|
|
3303
|
-
}
|
|
3304
|
-
var oauthReturn = ret;
|
|
3305
|
-
__anBeginNativeOAuth(flowId);
|
|
3306
|
-
__anSetOAuthDebug('Preparing Google sign-in in system browser', flowId);
|
|
3307
|
-
__anRequestDesktopOAuthUrl(flowId, verifier, oauthReturn).then(function(url) {
|
|
3308
|
-
if (!__anIsCurrentGoogleSignInFlow(flowId)) return;
|
|
3309
|
-
__anMarkNativeOAuthPolling(flowId);
|
|
3310
|
-
__anSetOAuthDebug('Opening Google sign-in in system browser', flowId);
|
|
3311
|
-
__anOpenOAuthUrl(url);
|
|
3312
|
-
__anWaitForOAuthExchange(flowId, ret, btn, err, 'google', verifier);
|
|
3313
|
-
__anScheduleNativeOAuthAbandonment(flowId);
|
|
3314
|
-
}).catch(function(e) {
|
|
3315
|
-
if (!__anIsCurrentGoogleSignInFlow(flowId)) return;
|
|
3316
|
-
__anShowOAuthError(err, btn, e && e.message ? e.message : __anT('failedToConnect'));
|
|
3317
|
-
});
|
|
3318
|
-
}
|
|
3319
|
-
function __anOpenOAuthUrl(url) {
|
|
3320
|
-
try { sessionStorage.setItem('__an_signin', '1'); } catch(e) {}
|
|
3321
|
-
window.location.href = url;
|
|
3322
|
-
}
|
|
3323
|
-
(function revealLocalNote() {
|
|
3324
|
-
var h = location.hostname;
|
|
3325
|
-
if (h === 'localhost' || h === '127.0.0.1' || h === '::1' || h.endsWith('.local')) {
|
|
3326
|
-
var n = document.getElementById('local-note');
|
|
3327
|
-
if (n) n.classList.add('show');
|
|
3328
|
-
}
|
|
3329
|
-
})();
|
|
3330
|
-
(function revealUpgradeNote() {
|
|
3331
|
-
var shouldShow = false;
|
|
3332
|
-
try {
|
|
3333
|
-
var params = new URLSearchParams(location.search);
|
|
3334
|
-
shouldShow = params.get('signin') === '1' || params.get('upgrade-from-local') === '1';
|
|
3335
|
-
} catch(e) {}
|
|
3336
|
-
if (!shouldShow) {
|
|
3337
|
-
try { shouldShow = localStorage.getItem('an_migrate_from_local') === '1'; } catch(e) {}
|
|
3338
|
-
}
|
|
3339
|
-
if (!shouldShow) return;
|
|
3340
|
-
var n = document.getElementById('upgrade-note');
|
|
3341
|
-
if (!n) return;
|
|
3342
|
-
n.textContent = n.getAttribute('data-upgrade-copy') || __anT('migrateLocalFallback');
|
|
3343
|
-
n.classList.add('show');
|
|
3344
|
-
})();
|
|
3345
|
-
${googleOnly
|
|
3346
|
-
? ""
|
|
3347
|
-
: ` var TAB_STORAGE_KEY = 'an.onboarding.tab';
|
|
3348
|
-
var tabs = document.querySelectorAll('.tab');
|
|
3349
|
-
var forms = document.querySelectorAll('.form');
|
|
3350
|
-
var pendingSignupEmail = '';
|
|
3351
|
-
var pendingSignupPassword = '';
|
|
3352
|
-
var verificationCheckInFlight = false;
|
|
3353
|
-
var RESEND_VERIFICATION_COOLDOWN_SECONDS = 60;
|
|
3354
|
-
var resendVerificationCooldownUntil = 0;
|
|
3355
|
-
var resendVerificationCooldownTimer = null;
|
|
3356
|
-
var PENDING_SIGNUP_EMAIL_STORAGE_KEY = 'an.onboarding.pendingSignupEmail';
|
|
3357
|
-
// The verification link can open in a new tab, so in-memory pending state
|
|
3358
|
-
// cannot be the only source of the account email. Keep only the address,
|
|
3359
|
-
// never the password, for the manual-login fallback.
|
|
3360
|
-
function pendingSignupEmailStorageKey() {
|
|
3361
|
-
return PENDING_SIGNUP_EMAIL_STORAGE_KEY + ':' + (__anBasePath() || '/');
|
|
3362
|
-
}
|
|
3363
|
-
function rememberPendingSignupEmail(email) {
|
|
3364
|
-
try {
|
|
3365
|
-
if (email) localStorage.setItem(pendingSignupEmailStorageKey(), email);
|
|
3366
|
-
else localStorage.removeItem(pendingSignupEmailStorageKey());
|
|
3367
|
-
// coercion-ok: localStorage is optional; the in-memory and form fallbacks remain available.
|
|
3368
|
-
} catch (e) {}
|
|
3369
|
-
}
|
|
3370
|
-
function readRememberedPendingSignupEmail() {
|
|
3371
|
-
try {
|
|
3372
|
-
var email = localStorage.getItem(pendingSignupEmailStorageKey()) || '';
|
|
3373
|
-
return __anIsValidAuthEmail(email) ? __anNormalizeAuthEmail(email) : '';
|
|
3374
|
-
// coercion-ok: localStorage is optional; callers fall back to the in-memory or form value.
|
|
3375
|
-
} catch (e) {
|
|
3376
|
-
return '';
|
|
3377
|
-
}
|
|
3378
|
-
}
|
|
3379
|
-
function clearRememberedPendingSignupEmail() {
|
|
3380
|
-
rememberPendingSignupEmail('');
|
|
3381
|
-
}
|
|
3382
|
-
function hideMagicLinkSuccess() {
|
|
3383
|
-
var card = document.querySelector('.card');
|
|
3384
|
-
if (card) card.classList.remove('magic-link-complete');
|
|
3385
|
-
var success = document.getElementById('magic-link-success');
|
|
3386
|
-
if (success) {
|
|
3387
|
-
success.classList.remove('is-visible');
|
|
3388
|
-
success.setAttribute('hidden', '');
|
|
3389
|
-
}
|
|
3390
|
-
}
|
|
3391
|
-
function showMagicLinkSuccess(email) {
|
|
3392
|
-
var card = document.querySelector('.card');
|
|
3393
|
-
if (card) card.classList.add('magic-link-complete');
|
|
3394
|
-
var success = document.getElementById('magic-link-success');
|
|
3395
|
-
var successEmail = document.getElementById('magic-link-success-email');
|
|
3396
|
-
if (successEmail && typeof email === 'string') successEmail.textContent = email;
|
|
3397
|
-
if (success) {
|
|
3398
|
-
success.removeAttribute('hidden');
|
|
3399
|
-
success.classList.add('is-visible');
|
|
3400
|
-
}
|
|
3401
|
-
forms.forEach(function(x) { x.classList.remove('active'); });
|
|
3402
|
-
var authTabs = document.getElementById('auth-tabs');
|
|
3403
|
-
if (authTabs) authTabs.hidden = true;
|
|
3404
|
-
__anSetAuthView('magicLinkSent');
|
|
3405
|
-
}
|
|
3406
|
-
function showMagicLinkForm() {
|
|
3407
|
-
__anStopOAuthExchangePolling();
|
|
3408
|
-
__anMagicLinkInFlight = false;
|
|
3409
|
-
var form = document.getElementById('magic-link-form');
|
|
3410
|
-
if (!form) return;
|
|
3411
|
-
hideMagicLinkSuccess();
|
|
3412
|
-
forms.forEach(function(x) { x.classList.remove('active'); });
|
|
3413
|
-
form.classList.add('active');
|
|
3414
|
-
var authTabs = document.getElementById('auth-tabs');
|
|
3415
|
-
if (authTabs) authTabs.hidden = true;
|
|
3416
|
-
updateMagicLinkSubmitState();
|
|
3417
|
-
__anSetAuthView('magicLink');
|
|
3418
|
-
}
|
|
3419
|
-
function updateMagicLinkSubmitState() {
|
|
3420
|
-
var emailInput = document.getElementById('m-email');
|
|
3421
|
-
var button = document.getElementById('magic-link-submit');
|
|
3422
|
-
if (!emailInput || !button) return;
|
|
3423
|
-
var isValid = __anIsValidAuthEmail(emailInput.value);
|
|
3424
|
-
button.disabled = !isValid;
|
|
3425
|
-
var googleButton = document.getElementById('google-btn');
|
|
3426
|
-
if (googleButton) googleButton.classList.toggle('magic-link-secondary', isValid);
|
|
3427
|
-
}
|
|
3428
|
-
function setActiveTab(name, opts) {
|
|
3429
|
-
if (name !== 'signup' && name !== 'login') return;
|
|
3430
|
-
var form = document.getElementById(name + '-form');
|
|
3431
|
-
if (!form) return;
|
|
3432
|
-
var card = document.querySelector('.card');
|
|
3433
|
-
if (card) card.classList.remove('verifying');
|
|
3434
|
-
var authTabs = document.getElementById('auth-tabs');
|
|
3435
|
-
if (authTabs) authTabs.hidden = false;
|
|
3436
|
-
tabs.forEach(function(x) { x.classList.remove('active'); });
|
|
3437
|
-
forms.forEach(function(x) { x.classList.remove('active'); });
|
|
3438
|
-
var btn = document.querySelector('.tab[data-tab="' + name + '"]');
|
|
3439
|
-
if (btn) btn.classList.add('active');
|
|
3440
|
-
form.classList.add('active');
|
|
3441
|
-
__anSetAuthView(name);
|
|
3442
|
-
if (opts && opts.persist) {
|
|
3443
|
-
try { localStorage.setItem(TAB_STORAGE_KEY, name); } catch (e) {}
|
|
3444
|
-
}
|
|
3445
|
-
}
|
|
3446
|
-
function showVerificationStep(email, password) {
|
|
3447
|
-
pendingSignupEmail = email || '';
|
|
3448
|
-
pendingSignupPassword = password || '';
|
|
3449
|
-
rememberPendingSignupEmail(pendingSignupEmail);
|
|
3450
|
-
tabs.forEach(function(x) { x.classList.remove('active'); });
|
|
3451
|
-
forms.forEach(function(x) { x.classList.remove('active'); });
|
|
3452
|
-
var card = document.querySelector('.card');
|
|
3453
|
-
if (card) card.classList.add('verifying');
|
|
3454
|
-
var step = document.getElementById('verification-step');
|
|
3455
|
-
if (step) step.classList.add('active');
|
|
3456
|
-
var emailNode = document.getElementById('verify-email');
|
|
3457
|
-
if (emailNode) emailNode.textContent = pendingSignupEmail;
|
|
3458
|
-
__anSetAuthView('verification');
|
|
3459
|
-
var msg = document.getElementById('verify-msg');
|
|
3460
|
-
if (msg) {
|
|
3461
|
-
msg.classList.remove('show', 'error', 'success');
|
|
3462
|
-
msg.textContent = '';
|
|
3463
|
-
}
|
|
3464
|
-
try { localStorage.setItem(TAB_STORAGE_KEY, 'signup'); } catch (e) {}
|
|
3465
|
-
}
|
|
3466
|
-
function getVerificationMessageNode() {
|
|
3467
|
-
var verifyStep = document.getElementById('verification-step');
|
|
3468
|
-
if (verifyStep && verifyStep.classList.contains('active')) {
|
|
3469
|
-
return document.getElementById('verify-msg');
|
|
3470
|
-
}
|
|
3471
|
-
return document.getElementById('l-msg') || document.getElementById('verify-msg');
|
|
3472
|
-
}
|
|
3473
|
-
function isVerificationStepActive() {
|
|
3474
|
-
var verifyStep = document.getElementById('verification-step');
|
|
3475
|
-
return !!(verifyStep && verifyStep.classList.contains('active'));
|
|
3476
|
-
}
|
|
3477
|
-
function getPendingSignupEmail() {
|
|
3478
|
-
var signupEmail = document.getElementById('s-email');
|
|
3479
|
-
var loginEmail = document.getElementById('l-email');
|
|
3480
|
-
return (pendingSignupEmail || readRememberedPendingSignupEmail() || (signupEmail && signupEmail.value) || (loginEmail && loginEmail.value) || '').trim();
|
|
3481
|
-
}
|
|
3482
|
-
function getPendingSignupPassword() {
|
|
3483
|
-
var signupPassword = document.getElementById('s-pass');
|
|
3484
|
-
return pendingSignupPassword || (signupPassword && signupPassword.value) || '';
|
|
3485
|
-
}
|
|
3486
|
-
function __anNormalizeAuthEmail(value) {
|
|
3487
|
-
return String(value || '').trim().toLowerCase();
|
|
3488
|
-
}
|
|
3489
|
-
function __anIsValidAuthEmail(value) {
|
|
3490
|
-
return /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(__anNormalizeAuthEmail(value));
|
|
3491
|
-
}
|
|
3492
|
-
function __anIsVerifiedRedirectSuccess() {
|
|
3493
|
-
try {
|
|
3494
|
-
var params = new URLSearchParams(location.search);
|
|
3495
|
-
return params.has('verified') && !params.has('error');
|
|
3496
|
-
} catch (e) {
|
|
3497
|
-
return false;
|
|
3498
|
-
}
|
|
3499
|
-
}
|
|
3500
|
-
function __anVerificationRedirectError() {
|
|
3501
|
-
try {
|
|
3502
|
-
var params = new URLSearchParams(location.search);
|
|
3503
|
-
return params.get('error') === 'verification_link_invalid'
|
|
3504
|
-
? __anT('verificationLinkInvalid')
|
|
3505
|
-
: '';
|
|
3506
|
-
} catch (e) { // coercion-ok: malformed query has no verification error to render
|
|
3507
|
-
return '';
|
|
3508
|
-
}
|
|
3509
|
-
}
|
|
3510
|
-
function __anShowEmailValidationError(input, msg) {
|
|
3511
|
-
if (msg) {
|
|
3512
|
-
msg.textContent = __anT('invalidEmail');
|
|
3513
|
-
msg.classList.add('show', 'error');
|
|
3514
|
-
}
|
|
3515
|
-
if (input && typeof input.focus === 'function') input.focus();
|
|
3516
|
-
}
|
|
3517
|
-
function movePendingSignupToLogin(message) {
|
|
3518
|
-
var email = getPendingSignupEmail();
|
|
3519
|
-
setActiveTab('login', { persist: true });
|
|
3520
|
-
var loginEmail = document.getElementById('l-email');
|
|
3521
|
-
var loginPassword = document.getElementById('l-pass');
|
|
3522
|
-
var msg = document.getElementById('l-msg');
|
|
3523
|
-
if (loginEmail && email) loginEmail.value = email;
|
|
3524
|
-
if (msg) {
|
|
3525
|
-
msg.textContent = message || __anT('signInToContinue');
|
|
3526
|
-
msg.classList.remove('error');
|
|
3527
|
-
msg.classList.add('show', 'success');
|
|
3528
|
-
}
|
|
3529
|
-
setTimeout(function() { if (loginPassword) loginPassword.focus(); }, 0);
|
|
3530
|
-
}
|
|
3531
|
-
async function signInWithPendingSignup() {
|
|
3532
|
-
var email = getPendingSignupEmail();
|
|
3533
|
-
var password = getPendingSignupPassword();
|
|
3534
|
-
if (!email || !password) {
|
|
3535
|
-
return { ok: false, needsManualSignIn: true };
|
|
3536
|
-
}
|
|
3537
|
-
var res = await fetch(__anPath('/_agent-native/auth/login'), {
|
|
3538
|
-
method: 'POST',
|
|
3539
|
-
headers: { 'Content-Type': 'application/json' },
|
|
3540
|
-
body: JSON.stringify({ email: email, password: password }),
|
|
3541
|
-
});
|
|
3542
|
-
if (res.ok) {
|
|
3543
|
-
clearRememberedPendingSignupEmail();
|
|
3544
|
-
__anRedirectToSignedInApp();
|
|
3545
|
-
return { ok: true };
|
|
3546
|
-
}
|
|
3547
|
-
var data = await res.json().catch(function(error) {
|
|
3548
|
-
console.warn('[auth] Could not parse sign-in response', error);
|
|
3549
|
-
return null;
|
|
3550
|
-
});
|
|
3551
|
-
var error = __anAuthErrorText(data, __anT('finishSignInFailed'));
|
|
3552
|
-
return {
|
|
3553
|
-
ok: false,
|
|
3554
|
-
error: error,
|
|
3555
|
-
isWaitingForVerification: /not verified|verification/i.test(error),
|
|
3556
|
-
};
|
|
3557
|
-
}
|
|
3558
|
-
async function checkVerificationSession(fallbackText, opts) {
|
|
3559
|
-
opts = opts || {};
|
|
3560
|
-
if (verificationCheckInFlight) return;
|
|
3561
|
-
verificationCheckInFlight = true;
|
|
3562
|
-
var msg = getVerificationMessageNode();
|
|
3563
|
-
var continueBtn = document.getElementById('verify-continue');
|
|
3564
|
-
if (continueBtn && !opts.silent) {
|
|
3565
|
-
continueBtn.disabled = true;
|
|
3566
|
-
continueBtn.textContent = __anT('checking');
|
|
3567
|
-
}
|
|
3568
|
-
if (msg && !opts.silent) {
|
|
3569
|
-
msg.textContent = __anT('checkingVerification');
|
|
3570
|
-
msg.classList.remove('error');
|
|
3571
|
-
msg.classList.add('show', 'success');
|
|
3572
|
-
}
|
|
3573
|
-
try {
|
|
3574
|
-
var res = await fetch(__anPath('/_agent-native/auth/session'), {
|
|
3575
|
-
headers: { 'Accept': 'application/json' },
|
|
3576
|
-
});
|
|
3577
|
-
var data = await res.json().catch(function() { return {}; });
|
|
3578
|
-
if (res.ok && data && data.email && !data.error) {
|
|
3579
|
-
clearRememberedPendingSignupEmail();
|
|
3580
|
-
__anRedirectToSignedInApp();
|
|
3581
|
-
return;
|
|
3582
|
-
}
|
|
3583
|
-
var loginResult = await signInWithPendingSignup();
|
|
3584
|
-
if (loginResult.ok) return;
|
|
3585
|
-
if (loginResult.needsManualSignIn) {
|
|
3586
|
-
if (!opts.silent) {
|
|
3587
|
-
movePendingSignupToLogin(fallbackText || __anT('enterPasswordAfterVerification'));
|
|
3588
|
-
}
|
|
3589
|
-
return;
|
|
3590
|
-
}
|
|
3591
|
-
if (loginResult.error && !loginResult.isWaitingForVerification) {
|
|
3592
|
-
if (!opts.silent) {
|
|
3593
|
-
movePendingSignupToLogin(__anT('finishSignInManually'));
|
|
3594
|
-
}
|
|
3595
|
-
return;
|
|
3596
|
-
}
|
|
3597
|
-
if (msg && !opts.silent) {
|
|
3598
|
-
msg.textContent = fallbackText || __anT('stillWaitingVerification');
|
|
3599
|
-
msg.classList.remove('success');
|
|
3600
|
-
msg.classList.add('show', 'error');
|
|
3601
|
-
}
|
|
3602
|
-
} catch (err) {
|
|
3603
|
-
if (msg && !opts.silent) {
|
|
3604
|
-
msg.textContent = __anT('checkVerificationFailed');
|
|
3605
|
-
msg.classList.remove('success');
|
|
3606
|
-
msg.classList.add('show', 'error');
|
|
3607
|
-
}
|
|
3608
|
-
} finally {
|
|
3609
|
-
verificationCheckInFlight = false;
|
|
3610
|
-
if (continueBtn && !opts.silent) {
|
|
3611
|
-
continueBtn.disabled = false;
|
|
3612
|
-
continueBtn.textContent = __anT('continue');
|
|
3613
|
-
}
|
|
3614
|
-
}
|
|
3615
|
-
}
|
|
3616
|
-
function maybeCompleteVerificationAfterReturn() {
|
|
3617
|
-
if (!isVerificationStepActive()) return;
|
|
3618
|
-
checkVerificationSession(null, { silent: true });
|
|
3619
|
-
}
|
|
3620
|
-
function updateResendVerificationCooldown() {
|
|
3621
|
-
var btn = document.getElementById('resend-verification');
|
|
3622
|
-
if (!btn) return;
|
|
3623
|
-
var remaining = Math.ceil((resendVerificationCooldownUntil - Date.now()) / 1000);
|
|
3624
|
-
if (remaining > 0) {
|
|
3625
|
-
btn.disabled = true;
|
|
3626
|
-
btn.textContent = __anT('resendEmail') + ' (' + remaining + 's)';
|
|
3627
|
-
return;
|
|
3628
|
-
}
|
|
3629
|
-
if (resendVerificationCooldownTimer) {
|
|
3630
|
-
clearInterval(resendVerificationCooldownTimer);
|
|
3631
|
-
resendVerificationCooldownTimer = null;
|
|
3632
|
-
}
|
|
3633
|
-
resendVerificationCooldownUntil = 0;
|
|
3634
|
-
btn.disabled = false;
|
|
3635
|
-
btn.textContent = __anT('resendEmail');
|
|
3636
|
-
}
|
|
3637
|
-
function startResendVerificationCooldown(seconds) {
|
|
3638
|
-
resendVerificationCooldownUntil = Date.now() + seconds * 1000;
|
|
3639
|
-
updateResendVerificationCooldown();
|
|
3640
|
-
if (resendVerificationCooldownTimer) clearInterval(resendVerificationCooldownTimer);
|
|
3641
|
-
resendVerificationCooldownTimer = setInterval(updateResendVerificationCooldown, 1000);
|
|
3642
|
-
}
|
|
3643
|
-
async function resendVerificationEmail() {
|
|
3644
|
-
var btn = document.getElementById('resend-verification');
|
|
3645
|
-
var msg = document.getElementById('verify-msg');
|
|
3646
|
-
var email = getPendingSignupEmail();
|
|
3647
|
-
if (!email) return;
|
|
3648
|
-
if (resendVerificationCooldownUntil > Date.now()) {
|
|
3649
|
-
updateResendVerificationCooldown();
|
|
3650
|
-
return;
|
|
3651
|
-
}
|
|
3652
|
-
var original = btn ? btn.textContent : '';
|
|
3653
|
-
if (btn) {
|
|
3654
|
-
btn.disabled = true;
|
|
3655
|
-
btn.textContent = __anT('sending');
|
|
3656
|
-
}
|
|
3657
|
-
if (msg) msg.classList.remove('show', 'error', 'success');
|
|
3658
|
-
try {
|
|
3659
|
-
var res = await fetch(__anPath('/_agent-native/auth/ba/send-verification-email'), {
|
|
3660
|
-
method: 'POST',
|
|
3661
|
-
headers: { 'Content-Type': 'application/json' },
|
|
3662
|
-
body: JSON.stringify({ email: email, callbackURL: __anResumeHref() }),
|
|
3663
|
-
});
|
|
3664
|
-
if (res.ok) {
|
|
3665
|
-
if (msg) {
|
|
3666
|
-
msg.textContent = __anT('sentVerification');
|
|
3667
|
-
msg.classList.add('show', 'success');
|
|
3668
|
-
}
|
|
3669
|
-
startResendVerificationCooldown(RESEND_VERIFICATION_COOLDOWN_SECONDS);
|
|
3670
|
-
return;
|
|
3671
|
-
}
|
|
3672
|
-
var data = await res.json().catch(function() { return {}; });
|
|
3673
|
-
if (msg) {
|
|
3674
|
-
msg.textContent = __anAuthErrorText(data, __anT('resendVerificationFailed'));
|
|
3675
|
-
msg.classList.add('show', 'error');
|
|
3676
|
-
}
|
|
3677
|
-
if (btn) {
|
|
3678
|
-
btn.disabled = false;
|
|
3679
|
-
btn.textContent = original;
|
|
3680
|
-
}
|
|
3681
|
-
} catch (err) {
|
|
3682
|
-
if (msg) {
|
|
3683
|
-
msg.textContent = __anT('networkErrorRetry');
|
|
3684
|
-
msg.classList.add('show', 'error');
|
|
3685
|
-
}
|
|
3686
|
-
if (btn) {
|
|
3687
|
-
btn.disabled = false;
|
|
3688
|
-
btn.textContent = original;
|
|
3689
|
-
}
|
|
3690
|
-
}
|
|
3691
|
-
}
|
|
3692
|
-
(function initActiveTab() {
|
|
3693
|
-
var initial = __AN_AUTH_MODE === 'magic-link' ? 'magicLink' : 'signup';
|
|
3694
|
-
var verificationError = __anVerificationRedirectError();
|
|
3695
|
-
try {
|
|
3696
|
-
var params = new URLSearchParams(location.search);
|
|
3697
|
-
var qp = params.get('tab');
|
|
3698
|
-
var path = location.pathname;
|
|
3699
|
-
while (path.length > 1 && path.charAt(path.length - 1) === '/') path = path.slice(0, -1);
|
|
3700
|
-
if (qp === 'login' || qp === 'signup') {
|
|
3701
|
-
initial = qp;
|
|
3702
|
-
} else if (__anIsVerifiedRedirectSuccess()) {
|
|
3703
|
-
initial = 'login';
|
|
3704
|
-
} else if (verificationError) {
|
|
3705
|
-
initial = 'login';
|
|
3706
|
-
} else if (path === '/login' || path.endsWith('/login')) {
|
|
3707
|
-
initial = 'login';
|
|
3708
|
-
} else if (path === '/signup' || path.endsWith('/signup')) {
|
|
3709
|
-
initial = 'signup';
|
|
3710
|
-
} else if (__AN_AUTH_MODE !== 'magic-link') {
|
|
3711
|
-
var stored = localStorage.getItem(TAB_STORAGE_KEY);
|
|
3712
|
-
if (stored === 'login' || stored === 'signup') initial = stored;
|
|
3713
|
-
}
|
|
3714
|
-
} catch (e) {}
|
|
3715
|
-
if (initial === 'magicLink') showMagicLinkForm();
|
|
3716
|
-
else setActiveTab(initial, { persist: false });
|
|
3717
|
-
if (verificationError) {
|
|
3718
|
-
var verificationMsg = document.getElementById('l-msg');
|
|
3719
|
-
if (verificationMsg) {
|
|
3720
|
-
verificationMsg.textContent = verificationError;
|
|
3721
|
-
verificationMsg.classList.add('show', 'error');
|
|
3722
|
-
}
|
|
3723
|
-
}
|
|
3724
|
-
try {
|
|
3725
|
-
if (__anIsVerifiedRedirectSuccess()) {
|
|
3726
|
-
var rememberedEmail = readRememberedPendingSignupEmail();
|
|
3727
|
-
var loginEmail = document.getElementById('l-email');
|
|
3728
|
-
if (loginEmail && rememberedEmail) loginEmail.value = rememberedEmail;
|
|
3729
|
-
var msg = document.getElementById('l-msg');
|
|
3730
|
-
if (msg) {
|
|
3731
|
-
msg.textContent = __anT('emailVerifiedFinishing');
|
|
3732
|
-
msg.classList.remove('error');
|
|
3733
|
-
msg.classList.add('show', 'success');
|
|
3734
|
-
}
|
|
3735
|
-
checkVerificationSession(__anT('emailVerifiedSignIn'));
|
|
3736
|
-
}
|
|
3737
|
-
} catch (e) {}
|
|
3738
|
-
})();
|
|
3739
|
-
tabs.forEach(function(t) { t.addEventListener('click', function() {
|
|
3740
|
-
setActiveTab(t.dataset.tab, { persist: true });
|
|
3741
|
-
}); });
|
|
3742
|
-
|
|
3743
|
-
var usePasswordLink = document.getElementById('use-password-link');
|
|
3744
|
-
if (usePasswordLink) usePasswordLink.addEventListener('click', function(e) {
|
|
3745
|
-
e.preventDefault();
|
|
3746
|
-
setActiveTab('login', { persist: false });
|
|
3747
|
-
var magicEmail = document.getElementById('m-email');
|
|
3748
|
-
var loginEmail = document.getElementById('l-email');
|
|
3749
|
-
if (magicEmail && loginEmail && magicEmail.value) loginEmail.value = magicEmail.value;
|
|
3750
|
-
});
|
|
3751
|
-
var backToMagicLink = document.getElementById('back-to-magic-link');
|
|
3752
|
-
if (backToMagicLink) backToMagicLink.addEventListener('click', function(e) {
|
|
3753
|
-
e.preventDefault();
|
|
3754
|
-
showMagicLinkForm();
|
|
3755
|
-
});
|
|
3756
|
-
var magicLinkBack = document.getElementById('magic-link-back');
|
|
3757
|
-
if (magicLinkBack) magicLinkBack.addEventListener('click', function(e) {
|
|
3758
|
-
e.preventDefault();
|
|
3759
|
-
var magicLinkEmailInput = document.getElementById('m-email');
|
|
3760
|
-
if (magicLinkEmailInput) magicLinkEmailInput.value = '';
|
|
3761
|
-
showMagicLinkForm();
|
|
3762
|
-
if (magicLinkEmailInput) magicLinkEmailInput.focus();
|
|
3763
|
-
});
|
|
3764
|
-
|
|
3765
|
-
var magicLinkForm = document.getElementById('magic-link-form');
|
|
3766
|
-
__anBindPasswordValidation(document.getElementById('s-pass'));
|
|
3767
|
-
__anBindPasswordValidation(document.getElementById('s-pass2'));
|
|
3768
|
-
var magicLinkEmail = document.getElementById('m-email');
|
|
3769
|
-
if (magicLinkEmail) {
|
|
3770
|
-
magicLinkEmail.addEventListener('input', updateMagicLinkSubmitState);
|
|
3771
|
-
magicLinkEmail.addEventListener('change', updateMagicLinkSubmitState);
|
|
3772
|
-
updateMagicLinkSubmitState();
|
|
3773
|
-
}
|
|
3774
|
-
if (magicLinkForm) magicLinkForm.addEventListener('submit', async function(e) {
|
|
3775
|
-
e.preventDefault();
|
|
3776
|
-
var btn = magicLinkForm.querySelector('button[type="submit"]');
|
|
3777
|
-
var msg = document.getElementById('m-msg');
|
|
3778
|
-
var emailInput = document.getElementById('m-email');
|
|
3779
|
-
var email = __anNormalizeAuthEmail(emailInput && emailInput.value);
|
|
3780
|
-
var isDesktopMagicLink = __anIsAgentNativeDesktop();
|
|
3781
|
-
msg.classList.remove('show', 'error', 'success');
|
|
3782
|
-
if (!__anIsValidAuthEmail(email)) {
|
|
3783
|
-
__anShowEmailValidationError(emailInput, msg);
|
|
3784
|
-
return;
|
|
3785
|
-
}
|
|
3786
|
-
__anTrackAuth('auth.signup_clicked', { surface: 'signup', method: 'magic_link', auth_view: __anAuthView });
|
|
3787
|
-
var originalLabel = btn.textContent;
|
|
3788
|
-
btn.disabled = true;
|
|
3789
|
-
__anMagicLinkInFlight = isDesktopMagicLink;
|
|
3790
|
-
btn.textContent = __anT('sending');
|
|
3791
|
-
try {
|
|
3792
|
-
var res = await fetch(__anPath('/_agent-native/auth/magic-link'), {
|
|
3793
|
-
method: 'POST',
|
|
3794
|
-
headers: { 'Content-Type': 'application/json' },
|
|
3795
|
-
body: JSON.stringify({
|
|
3796
|
-
email: email,
|
|
3797
|
-
callbackURL: isDesktopMagicLink
|
|
3798
|
-
? __anPath('/_agent-native/auth/magic-link/desktop-callback')
|
|
3799
|
-
: __anResumeHref(),
|
|
3800
|
-
}),
|
|
3801
|
-
});
|
|
3802
|
-
var data = await res.json().catch(function(error) {
|
|
3803
|
-
console.warn('[auth] Could not parse magic-link response', error);
|
|
3804
|
-
return null;
|
|
3805
|
-
});
|
|
3806
|
-
if (res.ok) {
|
|
3807
|
-
btn.disabled = false;
|
|
3808
|
-
btn.textContent = originalLabel;
|
|
3809
|
-
showMagicLinkSuccess(email);
|
|
3810
|
-
if (isDesktopMagicLink) {
|
|
3811
|
-
var magicFlowId = data && typeof data.flowId === 'string' ? data.flowId : '';
|
|
3812
|
-
var magicVerifier = data && typeof data.verifier === 'string' ? data.verifier : '';
|
|
3813
|
-
if (!magicFlowId || !magicVerifier) {
|
|
3814
|
-
throw new Error('The sign-in flow was not initialized.');
|
|
3815
|
-
}
|
|
3816
|
-
__anWaitForOAuthExchange(magicFlowId, __anResumeHref(), btn, msg, 'magic-link', magicVerifier);
|
|
3817
|
-
}
|
|
3818
|
-
return;
|
|
3819
|
-
}
|
|
3820
|
-
__anMagicLinkInFlight = false;
|
|
3821
|
-
msg.textContent = __anAuthErrorText(data, __anT('magicLinkFailed'));
|
|
3822
|
-
msg.classList.add('show', 'error');
|
|
3823
|
-
btn.disabled = false;
|
|
3824
|
-
btn.textContent = originalLabel;
|
|
3825
|
-
} catch (err) {
|
|
3826
|
-
__anMagicLinkInFlight = false;
|
|
3827
|
-
msg.textContent = __anT('networkErrorDashRetry');
|
|
3828
|
-
msg.classList.add('show', 'error');
|
|
3829
|
-
btn.disabled = false;
|
|
3830
|
-
btn.textContent = originalLabel;
|
|
3831
|
-
}
|
|
3832
|
-
});
|
|
3833
|
-
|
|
3834
|
-
document.getElementById('signup-form').addEventListener('submit', async function(e) {
|
|
3835
|
-
e.preventDefault();
|
|
3836
|
-
var form = e.currentTarget;
|
|
3837
|
-
var btn = form.querySelector('button[type="submit"]');
|
|
3838
|
-
var msg = document.getElementById('s-msg');
|
|
3839
|
-
msg.classList.remove('show', 'error', 'success');
|
|
3840
|
-
var pass = document.getElementById('s-pass').value;
|
|
3841
|
-
var pass2 = document.getElementById('s-pass2').value;
|
|
3842
|
-
if (pass !== pass2) {
|
|
3843
|
-
msg.textContent = __anT('passwordsMismatch');
|
|
3844
|
-
msg.classList.add('show', 'error');
|
|
3845
|
-
return;
|
|
3846
|
-
}
|
|
3847
|
-
var originalLabel = btn.textContent;
|
|
3848
|
-
btn.disabled = true;
|
|
3849
|
-
btn.textContent = __anT('creatingAccount');
|
|
3850
|
-
try {
|
|
3851
|
-
var emailInput = document.getElementById('s-email');
|
|
3852
|
-
var email = __anNormalizeAuthEmail(emailInput && emailInput.value);
|
|
3853
|
-
if (!__anIsValidAuthEmail(email)) {
|
|
3854
|
-
btn.disabled = false;
|
|
3855
|
-
btn.textContent = originalLabel;
|
|
3856
|
-
__anShowEmailValidationError(emailInput, msg);
|
|
3857
|
-
return;
|
|
3858
|
-
}
|
|
3859
|
-
__anTrackAuth('auth.signup_clicked', { surface: 'signup', method: 'password', auth_view: __anAuthView });
|
|
3860
|
-
var res = await fetch(__anPath('/_agent-native/auth/register'), {
|
|
3861
|
-
method: 'POST',
|
|
3862
|
-
headers: { 'Content-Type': 'application/json' },
|
|
3863
|
-
body: JSON.stringify({
|
|
3864
|
-
email: email,
|
|
3865
|
-
password: pass,
|
|
3866
|
-
callbackURL: __anResumeHref(),
|
|
3867
|
-
}),
|
|
3868
|
-
});
|
|
3869
|
-
var data = await res.json().catch(function() { return {}; });
|
|
3870
|
-
if (res.ok) {
|
|
3871
|
-
// If email verification is required, the server won't return a session.
|
|
3872
|
-
// Try logging in — if it fails (unverified), show a "check your email" message.
|
|
3873
|
-
var loginRes = await fetch(__anPath('/_agent-native/auth/login'), {
|
|
3874
|
-
method: 'POST',
|
|
3875
|
-
headers: { 'Content-Type': 'application/json' },
|
|
3876
|
-
body: JSON.stringify({ email: email, password: pass }),
|
|
3877
|
-
});
|
|
3878
|
-
if (loginRes.ok) {
|
|
3879
|
-
clearRememberedPendingSignupEmail();
|
|
3880
|
-
msg.textContent = __anT('accountCreatedSigningIn');
|
|
3881
|
-
msg.classList.add('show', 'success');
|
|
3882
|
-
__anRedirectToSignedInApp();
|
|
3883
|
-
return;
|
|
3884
|
-
}
|
|
3885
|
-
var loginData;
|
|
3886
|
-
try {
|
|
3887
|
-
loginData = await loginRes.json();
|
|
3888
|
-
} catch (error) {
|
|
3889
|
-
console.warn('[auth] Could not parse sign-in response', error);
|
|
3890
|
-
}
|
|
3891
|
-
var loginError = __anAuthErrorText(loginData, __anT('registrationFailed'));
|
|
3892
|
-
if (loginRes.status === 403 && /not verified|verification/i.test(loginError)) {
|
|
3893
|
-
btn.disabled = false;
|
|
3894
|
-
btn.textContent = originalLabel;
|
|
3895
|
-
showVerificationStep(email, pass);
|
|
3896
|
-
return;
|
|
3897
|
-
}
|
|
3898
|
-
msg.textContent = loginError;
|
|
3899
|
-
msg.classList.add('show', 'error');
|
|
3900
|
-
btn.disabled = false;
|
|
3901
|
-
btn.textContent = originalLabel;
|
|
3902
|
-
return;
|
|
3903
|
-
}
|
|
3904
|
-
msg.textContent = __anAuthErrorText(data, __anT('registrationFailed'));
|
|
3905
|
-
msg.classList.add('show', 'error');
|
|
3906
|
-
btn.disabled = false;
|
|
3907
|
-
btn.textContent = originalLabel;
|
|
3908
|
-
} catch (err) {
|
|
3909
|
-
msg.textContent = __anT('networkErrorDashRetry');
|
|
3910
|
-
msg.classList.add('show', 'error');
|
|
3911
|
-
btn.disabled = false;
|
|
3912
|
-
btn.textContent = originalLabel;
|
|
3913
|
-
}
|
|
3914
|
-
});
|
|
3915
|
-
|
|
3916
|
-
var verifyContinue = document.getElementById('verify-continue');
|
|
3917
|
-
if (verifyContinue) verifyContinue.addEventListener('click', function(e) {
|
|
3918
|
-
e.preventDefault();
|
|
3919
|
-
checkVerificationSession();
|
|
3920
|
-
});
|
|
3921
|
-
window.addEventListener('focus', maybeCompleteVerificationAfterReturn);
|
|
3922
|
-
document.addEventListener('visibilitychange', function() {
|
|
3923
|
-
if (document.visibilityState === 'visible') maybeCompleteVerificationAfterReturn();
|
|
3924
|
-
});
|
|
3925
|
-
var resendBtn = document.getElementById('resend-verification');
|
|
3926
|
-
if (resendBtn) resendBtn.addEventListener('click', function(e) {
|
|
3927
|
-
e.preventDefault();
|
|
3928
|
-
resendVerificationEmail();
|
|
3929
|
-
});
|
|
3930
|
-
var backToSignup = document.getElementById('back-to-signup');
|
|
3931
|
-
if (backToSignup) backToSignup.addEventListener('click', function(e) {
|
|
3932
|
-
e.preventDefault();
|
|
3933
|
-
clearRememberedPendingSignupEmail();
|
|
3934
|
-
setActiveTab('signup', { persist: true });
|
|
3935
|
-
var email = document.getElementById('s-email');
|
|
3936
|
-
setTimeout(function() { if (email) email.focus(); }, 0);
|
|
3937
|
-
});
|
|
3938
|
-
|
|
3939
|
-
var forgotLink = document.getElementById('forgot-link');
|
|
3940
|
-
var backToLogin = document.getElementById('back-to-login');
|
|
3941
|
-
if (forgotLink) forgotLink.addEventListener('click', function(e) {
|
|
3942
|
-
e.preventDefault();
|
|
3943
|
-
document.getElementById('login-form').classList.remove('active');
|
|
3944
|
-
document.getElementById('forgot-form').classList.add('active');
|
|
3945
|
-
__anSetAuthView('forgot');
|
|
3946
|
-
var fEmail = document.getElementById('f-email');
|
|
3947
|
-
var lEmail = document.getElementById('l-email');
|
|
3948
|
-
if (lEmail && lEmail.value) fEmail.value = lEmail.value;
|
|
3949
|
-
setTimeout(function() { fEmail.focus(); }, 0);
|
|
3950
|
-
});
|
|
3951
|
-
if (backToLogin) backToLogin.addEventListener('click', function(e) {
|
|
3952
|
-
e.preventDefault();
|
|
3953
|
-
document.getElementById('forgot-form').classList.remove('active');
|
|
3954
|
-
document.getElementById('login-form').classList.add('active');
|
|
3955
|
-
__anSetAuthView('login');
|
|
3956
|
-
});
|
|
3957
|
-
|
|
3958
|
-
var forgotForm = document.getElementById('forgot-form');
|
|
3959
|
-
if (forgotForm) forgotForm.addEventListener('submit', async function(e) {
|
|
3960
|
-
e.preventDefault();
|
|
3961
|
-
var btn = e.currentTarget.querySelector('button[type="submit"]');
|
|
3962
|
-
var msg = document.getElementById('f-msg');
|
|
3963
|
-
msg.classList.remove('show', 'error', 'success');
|
|
3964
|
-
var original = btn.textContent;
|
|
3965
|
-
btn.disabled = true;
|
|
3966
|
-
btn.textContent = __anT('sending');
|
|
3967
|
-
try {
|
|
3968
|
-
var emailInput = document.getElementById('f-email');
|
|
3969
|
-
var email = __anNormalizeAuthEmail(emailInput && emailInput.value);
|
|
3970
|
-
if (!__anIsValidAuthEmail(email)) {
|
|
3971
|
-
btn.disabled = false;
|
|
3972
|
-
btn.textContent = original;
|
|
3973
|
-
__anShowEmailValidationError(emailInput, msg);
|
|
3974
|
-
return;
|
|
3975
|
-
}
|
|
3976
|
-
var res = await fetch(__anPath('/_agent-native/auth/ba/request-password-reset'), {
|
|
3977
|
-
method: 'POST',
|
|
3978
|
-
headers: { 'Content-Type': 'application/json' },
|
|
3979
|
-
body: JSON.stringify({ email: email }),
|
|
3980
|
-
});
|
|
3981
|
-
if (res.ok) {
|
|
3982
|
-
msg.textContent = __anT('resetEmailSent');
|
|
3983
|
-
msg.classList.add('show', 'success');
|
|
3984
|
-
btn.textContent = __anT('sent');
|
|
3985
|
-
return;
|
|
3986
|
-
}
|
|
3987
|
-
var data = await res.json().catch(function() { return {}; });
|
|
3988
|
-
msg.textContent = __anAuthErrorText(data, __anT('resetEmailFailed'));
|
|
3989
|
-
msg.classList.add('show', 'error');
|
|
3990
|
-
btn.disabled = false;
|
|
3991
|
-
btn.textContent = original;
|
|
3992
|
-
} catch (err) {
|
|
3993
|
-
msg.textContent = __anT('networkErrorDashRetry');
|
|
3994
|
-
msg.classList.add('show', 'error');
|
|
3995
|
-
btn.disabled = false;
|
|
3996
|
-
btn.textContent = original;
|
|
3997
|
-
}
|
|
3998
|
-
});
|
|
3999
|
-
|
|
4000
|
-
document.getElementById('login-form').addEventListener('submit', async function(e) {
|
|
4001
|
-
e.preventDefault();
|
|
4002
|
-
var form = e.currentTarget;
|
|
4003
|
-
var btn = form.querySelector('button[type="submit"]');
|
|
4004
|
-
var msg = document.getElementById('l-msg');
|
|
4005
|
-
msg.classList.remove('show', 'success');
|
|
4006
|
-
msg.classList.add('error');
|
|
4007
|
-
var originalLabel = btn.textContent;
|
|
4008
|
-
btn.disabled = true;
|
|
4009
|
-
btn.textContent = __anT('signingIn');
|
|
4010
|
-
try {
|
|
4011
|
-
var emailInput = document.getElementById('l-email');
|
|
4012
|
-
var email = __anNormalizeAuthEmail(emailInput && emailInput.value);
|
|
4013
|
-
if (!__anIsValidAuthEmail(email)) {
|
|
4014
|
-
btn.disabled = false;
|
|
4015
|
-
btn.textContent = originalLabel;
|
|
4016
|
-
__anShowEmailValidationError(emailInput, msg);
|
|
4017
|
-
return;
|
|
4018
|
-
}
|
|
4019
|
-
var res = await fetch(__anPath('/_agent-native/auth/login'), {
|
|
4020
|
-
method: 'POST',
|
|
4021
|
-
headers: { 'Content-Type': 'application/json' },
|
|
4022
|
-
body: JSON.stringify({
|
|
4023
|
-
email: email,
|
|
4024
|
-
password: document.getElementById('l-pass').value,
|
|
4025
|
-
}),
|
|
4026
|
-
});
|
|
4027
|
-
if (res.ok) {
|
|
4028
|
-
clearRememberedPendingSignupEmail();
|
|
4029
|
-
__anRedirectToSignedInApp();
|
|
4030
|
-
return;
|
|
4031
|
-
}
|
|
4032
|
-
var data = await res.json().catch(function() { return {}; });
|
|
4033
|
-
msg.textContent = __anAuthErrorText(data, __anT('invalidLogin'));
|
|
4034
|
-
msg.classList.add('show');
|
|
4035
|
-
btn.disabled = false;
|
|
4036
|
-
btn.textContent = originalLabel;
|
|
4037
|
-
} catch (err) {
|
|
4038
|
-
msg.textContent = __anT('networkErrorDashRetry');
|
|
4039
|
-
msg.classList.add('show');
|
|
4040
|
-
btn.disabled = false;
|
|
4041
|
-
btn.textContent = originalLabel;
|
|
4042
|
-
}
|
|
4043
|
-
});
|
|
4044
|
-
`}
|
|
4045
|
-
${renderGoogleButton
|
|
4046
|
-
? `
|
|
4047
|
-
async function signInWithGoogle() {
|
|
4048
|
-
__anTrackAuth(__anAuthView === 'login' ? 'auth.login_clicked' : 'auth.signup_clicked', { surface: __anAuthView === 'login' ? 'login' : 'signup', method: 'google', auth_view: __anAuthView });
|
|
4049
|
-
var btn = document.getElementById('google-btn');
|
|
4050
|
-
var err = document.getElementById('google-err');
|
|
4051
|
-
var ret = __anResumeHref();
|
|
4052
|
-
var flowId = __anNewOAuthFlowId();
|
|
4053
|
-
btn.disabled = true;
|
|
4054
|
-
__anBeginGoogleSignInFlow(flowId);
|
|
4055
|
-
__anBindGoogleRecover();
|
|
4056
|
-
err.classList.remove('show');
|
|
4057
|
-
if (__anResolveAuthFlow() === 'popup') {
|
|
4058
|
-
__anStartPopupOAuth(ret, btn, err, flowId);
|
|
4059
|
-
return;
|
|
4060
|
-
}
|
|
4061
|
-
if (__anIsAgentNativeDesktop()) {
|
|
4062
|
-
__anStartNativeDesktopOAuth(ret, btn, err, flowId);
|
|
4063
|
-
return;
|
|
4064
|
-
}
|
|
4065
|
-
if (__anIsBuilderPreview()) {
|
|
4066
|
-
__anStartRedirectOAuth(ret, btn, err, flowId, 'Opening Google sign-in redirect from Builder preview');
|
|
4067
|
-
return;
|
|
4068
|
-
}
|
|
4069
|
-
try {
|
|
4070
|
-
var authUrl = __anGoogleAuthUrlPath() + '?return=' + encodeURIComponent(ret);
|
|
4071
|
-
var res = await fetch(authUrl);
|
|
4072
|
-
var data = await res.json();
|
|
4073
|
-
if (!__anIsCurrentGoogleSignInFlow(flowId)) return;
|
|
4074
|
-
if (data.url) {
|
|
4075
|
-
__anOpenOAuthUrl(data.url);
|
|
4076
|
-
} else {
|
|
4077
|
-
err.textContent = __anAuthErrorText(data, __anT('googleNotConfigured'));
|
|
4078
|
-
err.classList.add('show');
|
|
4079
|
-
btn.disabled = false;
|
|
4080
|
-
__anGoogleSignInInFlight = false;
|
|
4081
|
-
__anClearGoogleSignInFlow();
|
|
4082
|
-
}
|
|
4083
|
-
} catch (e) {
|
|
4084
|
-
err.textContent = __anT('failedToConnect');
|
|
4085
|
-
err.classList.add('show');
|
|
4086
|
-
btn.disabled = false;
|
|
4087
|
-
__anGoogleSignInInFlight = false;
|
|
4088
|
-
__anClearGoogleSignInFlow();
|
|
4089
|
-
}
|
|
4090
|
-
}`
|
|
4091
|
-
: ""}
|
|
4092
|
-
${starfieldScript}
|
|
4093
|
-
${signupLocalModeNote
|
|
4094
|
-
? `
|
|
4095
|
-
function __anCopyCommandFromPanel(panelId, buttonId) {
|
|
4096
|
-
var panel = document.getElementById(panelId);
|
|
4097
|
-
var button = document.getElementById(buttonId);
|
|
4098
|
-
if (!panel || !button) return;
|
|
4099
|
-
var command = panel.getAttribute('data-command') || '';
|
|
4100
|
-
var original = button.textContent || __anT('copyCommand');
|
|
4101
|
-
function markCopied() {
|
|
4102
|
-
button.textContent = __anT('copied');
|
|
4103
|
-
setTimeout(function() { button.textContent = original; }, 1600);
|
|
4104
|
-
}
|
|
4105
|
-
if (navigator.clipboard && navigator.clipboard.writeText) {
|
|
4106
|
-
navigator.clipboard.writeText(command).then(markCopied).catch(function() {});
|
|
4107
|
-
}
|
|
4108
|
-
}
|
|
4109
|
-
function __anCopySignupLocalModeCommand() {
|
|
4110
|
-
__anCopyCommandFromPanel('signup-local-mode-note', 'copy-signup-local-mode');
|
|
4111
|
-
}
|
|
4112
|
-
`
|
|
4113
|
-
: ""}
|
|
4114
|
-
if (__anAuthView === 'signup' || __anAuthView === 'magicLink' || __anAuthView === 'googleOnly') {
|
|
4115
|
-
__anTrackAuth('auth.signup_viewed', {
|
|
4116
|
-
surface: 'signup',
|
|
4117
|
-
auth_mode: __AN_AUTH_MODE,
|
|
4118
|
-
auth_view: __anAuthView
|
|
4119
|
-
});
|
|
4120
|
-
}
|
|
4121
|
-
</script>
|
|
4122
|
-
</body>
|
|
4123
|
-
</html>`;
|
|
1832
|
+
`;
|
|
1833
|
+
const authPageLayoutStyles = `
|
|
1834
|
+
.auth-root { width: 100%; }
|
|
1835
|
+
.auth-marketing-home { width: 100%; padding: 0; position: relative; overflow-x: hidden; }
|
|
1836
|
+
.auth-marketing-shell { padding: 0; }
|
|
1837
|
+
.auth-marketing-home .split { width: 100%; }
|
|
1838
|
+
.auth-marketing-home .marketing-panel { min-width: 0; }
|
|
1839
|
+
.auth-marketing-home .form-panel { min-width: 0; }
|
|
1840
|
+
.auth-marketing-home [data-agent-native-starfield] { position: fixed; inset: 0; width: 100%; height: 100%; }
|
|
1841
|
+
@media (max-width: 900px) {
|
|
1842
|
+
.auth-marketing-home .auth-marketing-shell { display: block; }
|
|
1843
|
+
}
|
|
1844
|
+
`;
|
|
1845
|
+
const authClientScriptPath = `${appBasePath}/assets/auth-client.js`;
|
|
1846
|
+
const title = hasMarketing
|
|
1847
|
+
? `${marketing.appName} — ${t("pageTitleSignIn")}`
|
|
1848
|
+
: t("pageTitleWelcome");
|
|
1849
|
+
const authDocumentMarkup = renderToString(createElement("html", { lang: DEFAULT_LOCALE, dir: "ltr" }, createElement("head", null, createElement("meta", { charSet: "UTF-8" }), createElement("script", {
|
|
1850
|
+
"data-agent-native-locale-init": "",
|
|
1851
|
+
dangerouslySetInnerHTML: { __html: localeInitScript },
|
|
1852
|
+
}), createElement("script", {
|
|
1853
|
+
"data-agent-native-embedded-init": "",
|
|
1854
|
+
dangerouslySetInnerHTML: { __html: embeddedAuthInitScript },
|
|
1855
|
+
}), createElement("meta", {
|
|
1856
|
+
name: "viewport",
|
|
1857
|
+
content: "width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no",
|
|
1858
|
+
}), createElement("title", null, title), createElement("link", {
|
|
1859
|
+
rel: "icon",
|
|
1860
|
+
type: "image/svg+xml",
|
|
1861
|
+
href: withAppBasePath("/favicon.svg", appBasePath),
|
|
1862
|
+
}), createElement("link", {
|
|
1863
|
+
rel: "apple-touch-icon",
|
|
1864
|
+
href: withAppBasePath("/icon-180.svg", appBasePath),
|
|
1865
|
+
}), hasMarketing
|
|
1866
|
+
? [
|
|
1867
|
+
createElement("meta", {
|
|
1868
|
+
key: "description",
|
|
1869
|
+
name: "description",
|
|
1870
|
+
content: marketing.tagline,
|
|
1871
|
+
}),
|
|
1872
|
+
createElement("meta", {
|
|
1873
|
+
key: "og-title",
|
|
1874
|
+
property: "og:title",
|
|
1875
|
+
content: marketing.appName,
|
|
1876
|
+
}),
|
|
1877
|
+
createElement("meta", {
|
|
1878
|
+
key: "og-description",
|
|
1879
|
+
property: "og:description",
|
|
1880
|
+
content: marketing.tagline,
|
|
1881
|
+
}),
|
|
1882
|
+
createElement("meta", {
|
|
1883
|
+
key: "og-image",
|
|
1884
|
+
property: "og:image",
|
|
1885
|
+
content: socialImageUrl,
|
|
1886
|
+
}),
|
|
1887
|
+
createElement("meta", {
|
|
1888
|
+
key: "og-image-secure",
|
|
1889
|
+
property: "og:image:secure_url",
|
|
1890
|
+
content: socialImageUrl,
|
|
1891
|
+
}),
|
|
1892
|
+
createElement("meta", {
|
|
1893
|
+
key: "og-image-type",
|
|
1894
|
+
property: "og:image:type",
|
|
1895
|
+
content: AGENT_NATIVE_SOCIAL_IMAGE_TYPE,
|
|
1896
|
+
}),
|
|
1897
|
+
createElement("meta", {
|
|
1898
|
+
key: "og-image-width",
|
|
1899
|
+
property: "og:image:width",
|
|
1900
|
+
content: AGENT_NATIVE_SOCIAL_IMAGE_WIDTH,
|
|
1901
|
+
}),
|
|
1902
|
+
createElement("meta", {
|
|
1903
|
+
key: "og-image-height",
|
|
1904
|
+
property: "og:image:height",
|
|
1905
|
+
content: AGENT_NATIVE_SOCIAL_IMAGE_HEIGHT,
|
|
1906
|
+
}),
|
|
1907
|
+
createElement("meta", {
|
|
1908
|
+
key: "og-image-alt",
|
|
1909
|
+
property: "og:image:alt",
|
|
1910
|
+
content: AGENT_NATIVE_SOCIAL_IMAGE_ALT,
|
|
1911
|
+
}),
|
|
1912
|
+
createElement("meta", {
|
|
1913
|
+
key: "twitter-card",
|
|
1914
|
+
name: "twitter:card",
|
|
1915
|
+
content: "summary_large_image",
|
|
1916
|
+
}),
|
|
1917
|
+
createElement("meta", {
|
|
1918
|
+
key: "twitter-image",
|
|
1919
|
+
name: "twitter:image",
|
|
1920
|
+
content: socialImageUrl,
|
|
1921
|
+
}),
|
|
1922
|
+
createElement("meta", {
|
|
1923
|
+
key: "twitter-image-alt",
|
|
1924
|
+
name: "twitter:image:alt",
|
|
1925
|
+
content: AGENT_NATIVE_SOCIAL_IMAGE_ALT,
|
|
1926
|
+
}),
|
|
1927
|
+
]
|
|
1928
|
+
: null, createElement("style", {
|
|
1929
|
+
dangerouslySetInnerHTML: {
|
|
1930
|
+
__html: authDocumentStyles + authPageLayoutStyles,
|
|
1931
|
+
},
|
|
1932
|
+
}), createElement("script", {
|
|
1933
|
+
type: "module",
|
|
1934
|
+
src: authClientScriptPath,
|
|
1935
|
+
})), createElement("body", {
|
|
1936
|
+
className: simplifiedAuth
|
|
1937
|
+
? "simplified-auth"
|
|
1938
|
+
: hasMarketing
|
|
1939
|
+
? "has-marketing"
|
|
1940
|
+
: undefined,
|
|
1941
|
+
}, createElement("div", { id: "agent-native-auth-root", className: "auth-root" }, createElement(AuthPage, authPageProps)), createElement("script", {
|
|
1942
|
+
type: "application/json",
|
|
1943
|
+
id: "agent-native-auth-data",
|
|
1944
|
+
dangerouslySetInnerHTML: { __html: authPageData },
|
|
1945
|
+
}))));
|
|
1946
|
+
return `<!DOCTYPE html>${authDocumentMarkup}`;
|
|
4124
1947
|
}
|
|
4125
1948
|
/** @deprecated Use getOnboardingHtml() instead */
|
|
4126
1949
|
export const ONBOARDING_HTML = getOnboardingHtml();
|
|
4127
|
-
|
|
4128
|
-
|
|
4129
|
-
* their reset email. Posts `{ newPassword, token }` to Better Auth's
|
|
4130
|
-
* `/reset-password` endpoint, then redirects to the login page.
|
|
4131
|
-
*/
|
|
4132
|
-
export function getResetPasswordHtml() {
|
|
4133
|
-
return `<!DOCTYPE html>
|
|
4134
|
-
<html lang="en">
|
|
4135
|
-
<head>
|
|
4136
|
-
<meta charset="UTF-8">
|
|
4137
|
-
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
|
|
4138
|
-
<title>Reset password</title>
|
|
4139
|
-
<link rel="icon" type="image/svg+xml" href="${withAppBasePath("/favicon.svg")}">
|
|
4140
|
-
<link rel="apple-touch-icon" href="${withAppBasePath("/icon-180.svg")}">
|
|
4141
|
-
<style>
|
|
1950
|
+
const RESET_PASSWORD_STYLES = `
|
|
1951
|
+
/* guard:allow-raw-color - standalone reset page has no app theme token layer */
|
|
4142
1952
|
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
|
4143
1953
|
body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; background: #0a0a0a; color: #e5e5e5; display: flex; align-items: center; justify-content: center; min-height: 100vh; padding: 1rem; }
|
|
4144
1954
|
.card { width: 100%; max-width: 400px; padding: 2rem; background: #141414; border: 1px solid rgba(255,255,255,0.08); border-radius: 12px; }
|
|
@@ -4157,113 +1967,38 @@ export function getResetPasswordHtml() {
|
|
|
4157
1967
|
.msg.show { display: block; }
|
|
4158
1968
|
.back { display: inline-block; margin-top: 1rem; font-size: 0.75rem; color: #888; text-decoration: none; }
|
|
4159
1969
|
.back:hover { color: #bbb; }
|
|
4160
|
-
|
|
4161
|
-
|
|
4162
|
-
|
|
4163
|
-
|
|
4164
|
-
|
|
4165
|
-
|
|
4166
|
-
|
|
4167
|
-
|
|
4168
|
-
|
|
4169
|
-
|
|
4170
|
-
|
|
4171
|
-
|
|
4172
|
-
|
|
4173
|
-
|
|
4174
|
-
|
|
4175
|
-
|
|
4176
|
-
|
|
4177
|
-
|
|
4178
|
-
|
|
4179
|
-
|
|
4180
|
-
|
|
4181
|
-
|
|
4182
|
-
|
|
4183
|
-
|
|
4184
|
-
|
|
4185
|
-
|
|
4186
|
-
|
|
4187
|
-
|
|
4188
|
-
|
|
4189
|
-
|
|
4190
|
-
|
|
4191
|
-
|
|
4192
|
-
|
|
4193
|
-
|
|
4194
|
-
var message = candidate.trim();
|
|
4195
|
-
if (/failed query|\bselect\b.*\bfrom\b|\binsert\b.*\binto\b|\bupdate\b.*\bset\b|\bdelete\b.*\bfrom\b|\bsql\b|database|relation .* does not exist|column .* does not exist|syntax error|constraint|connection refused|econn|timeout/i.test(message)) {
|
|
4196
|
-
return fallback;
|
|
4197
|
-
}
|
|
4198
|
-
if (/password.*(?:at least|minimum|min(?:imum)?|too short)/i.test(message)) {
|
|
4199
|
-
return 'Choose a password with at least ${PASSWORD_MIN_LENGTH} characters.';
|
|
4200
|
-
}
|
|
4201
|
-
if (/password.*(?:at most|maximum|max(?:imum)?|too long)/i.test(message)) {
|
|
4202
|
-
return 'Choose a password with no more than ${PASSWORD_MAX_LENGTH} characters.';
|
|
4203
|
-
}
|
|
4204
|
-
return message;
|
|
4205
|
-
}
|
|
4206
|
-
function bindPasswordValidation(input) {
|
|
4207
|
-
if (!input) return;
|
|
4208
|
-
input.addEventListener('invalid', function() {
|
|
4209
|
-
if (input.validity && input.validity.tooShort) {
|
|
4210
|
-
input.setCustomValidity('Choose a password with at least ${PASSWORD_MIN_LENGTH} characters.');
|
|
4211
|
-
} else if (input.validity && input.validity.tooLong) {
|
|
4212
|
-
input.setCustomValidity('Choose a password with no more than ${PASSWORD_MAX_LENGTH} characters.');
|
|
4213
|
-
}
|
|
4214
|
-
});
|
|
4215
|
-
input.addEventListener('input', function() {
|
|
4216
|
-
input.setCustomValidity('');
|
|
4217
|
-
});
|
|
4218
|
-
}
|
|
4219
|
-
bindPasswordValidation(document.getElementById('p1'));
|
|
4220
|
-
bindPasswordValidation(document.getElementById('p2'));
|
|
4221
|
-
if (!token) {
|
|
4222
|
-
msg.textContent = 'This password reset link is missing or invalid. Request a new one.';
|
|
4223
|
-
msg.classList.add('show', 'error');
|
|
4224
|
-
resetForm.style.display = 'none';
|
|
4225
|
-
return;
|
|
4226
|
-
}
|
|
4227
|
-
resetForm.addEventListener('submit', async function(e) {
|
|
4228
|
-
e.preventDefault();
|
|
4229
|
-
var btn = e.currentTarget.querySelector('button[type="submit"]');
|
|
4230
|
-
var p1 = document.getElementById('p1').value;
|
|
4231
|
-
var p2 = document.getElementById('p2').value;
|
|
4232
|
-
msg.classList.remove('show', 'error', 'success');
|
|
4233
|
-
if (p1 !== p2) {
|
|
4234
|
-
msg.textContent = 'Passwords do not match.';
|
|
4235
|
-
msg.classList.add('show', 'error');
|
|
4236
|
-
return;
|
|
4237
|
-
}
|
|
4238
|
-
var original = btn.textContent;
|
|
4239
|
-
btn.disabled = true;
|
|
4240
|
-
btn.textContent = 'Saving…';
|
|
4241
|
-
try {
|
|
4242
|
-
var res = await fetch(basePath + '/_agent-native/auth/ba/reset-password', {
|
|
4243
|
-
method: 'POST',
|
|
4244
|
-
headers: { 'Content-Type': 'application/json' },
|
|
4245
|
-
body: JSON.stringify({ newPassword: p1, token: token }),
|
|
4246
|
-
});
|
|
4247
|
-
if (res.ok) {
|
|
4248
|
-
msg.textContent = 'Password updated — redirecting to sign in…';
|
|
4249
|
-
msg.classList.add('show', 'success');
|
|
4250
|
-
setTimeout(function() { window.location.href = homeHref; }, 1200);
|
|
4251
|
-
return;
|
|
4252
|
-
}
|
|
4253
|
-
var data = await res.json().catch(function() { return {}; });
|
|
4254
|
-
msg.textContent = resetErrorText(data, "We couldn't update your password. The link may have expired; request a new one.");
|
|
4255
|
-
msg.classList.add('show', 'error');
|
|
4256
|
-
btn.disabled = false;
|
|
4257
|
-
btn.textContent = original;
|
|
4258
|
-
} catch (err) {
|
|
4259
|
-
msg.textContent = "We couldn't reach the server. Check your connection and try again.";
|
|
4260
|
-
msg.classList.add('show', 'error');
|
|
4261
|
-
btn.disabled = false;
|
|
4262
|
-
btn.textContent = original;
|
|
4263
|
-
}
|
|
4264
|
-
});
|
|
4265
|
-
})();
|
|
4266
|
-
</script>
|
|
4267
|
-
</body>
|
|
4268
|
-
</html>`;
|
|
1970
|
+
`;
|
|
1971
|
+
/** React document for the password reset page linked from auth email. */
|
|
1972
|
+
export function getResetPasswordHtml(requestPath) {
|
|
1973
|
+
const configuredAppBasePath = getAppBasePathFromViteEnv();
|
|
1974
|
+
const appBasePath = configuredAppBasePath || workspaceBasePathFromRequest(requestPath);
|
|
1975
|
+
const resetPageProps = {
|
|
1976
|
+
pageType: "reset-password",
|
|
1977
|
+
appBasePath,
|
|
1978
|
+
passwordMinLength: PASSWORD_MIN_LENGTH,
|
|
1979
|
+
passwordMaxLength: PASSWORD_MAX_LENGTH,
|
|
1980
|
+
};
|
|
1981
|
+
const resetDocumentMarkup = renderToString(createElement("html", { lang: "en", dir: "ltr" }, createElement("head", null, createElement("meta", { charSet: "UTF-8" }), createElement("meta", {
|
|
1982
|
+
name: "viewport",
|
|
1983
|
+
content: "width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no",
|
|
1984
|
+
}), createElement("title", null, "Reset password"), createElement("link", {
|
|
1985
|
+
rel: "icon",
|
|
1986
|
+
type: "image/svg+xml",
|
|
1987
|
+
href: withAppBasePath("/favicon.svg", appBasePath),
|
|
1988
|
+
}), createElement("link", {
|
|
1989
|
+
rel: "apple-touch-icon",
|
|
1990
|
+
href: withAppBasePath("/icon-180.svg", appBasePath),
|
|
1991
|
+
}), createElement("style", {
|
|
1992
|
+
dangerouslySetInnerHTML: { __html: RESET_PASSWORD_STYLES },
|
|
1993
|
+
}), createElement("script", {
|
|
1994
|
+
type: "module",
|
|
1995
|
+
src: `${appBasePath}/assets/auth-client.js`,
|
|
1996
|
+
})), createElement("body", null, createElement("div", { id: "agent-native-auth-root" }, createElement(ResetPasswordPage, resetPageProps)), createElement("script", {
|
|
1997
|
+
type: "application/json",
|
|
1998
|
+
id: "agent-native-auth-data",
|
|
1999
|
+
dangerouslySetInnerHTML: {
|
|
2000
|
+
__html: serializeAuthPageData(resetPageProps),
|
|
2001
|
+
},
|
|
2002
|
+
}))));
|
|
2003
|
+
return `<!DOCTYPE html>${resetDocumentMarkup}`;
|
|
4269
2004
|
}
|