@agent-native/core 0.141.6 → 0.144.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/agent-native.eject.json +9 -0
- package/corpus/README.md +1 -1
- package/corpus/templates/analytics/.agents/skills/dashboard-management/SKILL.md +3 -14
- package/corpus/templates/analytics/.agents/skills/data-querying/SKILL.md +11 -6
- package/corpus/templates/analytics/.agents/skills/prometheus/SKILL.md +5 -5
- package/corpus/templates/analytics/.agents/skills/provider-api/SKILL.md +19 -0
- package/corpus/templates/analytics/.agents/skills/turn-into-app/SKILL.md +296 -0
- package/corpus/templates/analytics/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
- package/corpus/templates/analytics/.agents/skills/turn-into-skill/SKILL.md +112 -0
- package/corpus/templates/analytics/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
- package/corpus/templates/analytics/AGENTS.md +37 -40
- package/corpus/templates/analytics/actions/compose-dashboard.ts +1 -1
- package/corpus/templates/analytics/actions/ensure-native-v2-dashboards.ts +1 -1
- package/corpus/templates/analytics/actions/list-dashboard-usage-stats.ts +17 -22
- package/corpus/templates/analytics/actions/migrate-first-party-analytics-to-bigquery.ts +135 -0
- package/corpus/templates/analytics/actions/navigate.ts +5 -6
- package/corpus/templates/analytics/actions/provider-api-register.ts +50 -0
- package/corpus/templates/analytics/actions/query-agent-native-analytics.ts +46 -13
- package/corpus/templates/analytics/actions/test-custom-api-connection.ts +106 -0
- package/corpus/templates/analytics/actions/update-dashboard.ts +0 -1
- package/corpus/templates/analytics/actions/view-screen.ts +0 -20
- package/corpus/templates/analytics/app/components/CustomApiCard.tsx +430 -0
- package/corpus/templates/analytics/app/components/layout/Header.tsx +0 -1
- package/corpus/templates/analytics/app/hooks/use-navigation-state.ts +5 -5
- package/corpus/templates/analytics/app/i18n-data.ts +682 -90
- package/corpus/templates/analytics/app/lib/native-mcp-exclusions.ts +6 -0
- package/corpus/templates/analytics/app/lib/sql-query.ts +33 -6
- package/corpus/templates/analytics/app/pages/Agents.tsx +0 -3
- package/corpus/templates/analytics/app/pages/DataSources.tsx +4 -0
- package/corpus/templates/analytics/app/pages/Settings.tsx +22 -43
- package/corpus/templates/analytics/app/pages/settings/settings-search.ts +23 -20
- package/corpus/templates/analytics/app/routes/extensions._index.tsx +1 -1
- package/corpus/templates/analytics/app/routes/settings.$.tsx +1 -0
- package/corpus/templates/analytics/app/routes/team.tsx +1 -1
- package/corpus/templates/analytics/changelog/2026-08-05-settings-no-longer-includes-an-unnecessary-about-section.md +6 -0
- package/corpus/templates/analytics/changelog/2026-08-06-analytics-dashboards-load-reliably-during-background-data-sw.md +6 -0
- package/corpus/templates/analytics/changelog/2026-08-06-analytics-dashboards-remain-responsive-while-historical-data.md +6 -0
- package/corpus/templates/analytics/changelog/2026-08-06-analytics-query-results-now-render-as-a-table-with-csv-downl.md +6 -0
- package/corpus/templates/analytics/changelog/2026-08-06-connect-public-https-custom-apis-and-hand-tested-endpoints-t.md +6 -0
- package/corpus/templates/analytics/changelog/2026-08-06-durable-agent-worker-memory.md +6 -0
- package/corpus/templates/analytics/changelog/2026-08-06-live-dashboard-panels-use-the-shared-query-timeout.md +6 -0
- package/corpus/templates/analytics/changelog/2026-08-06-on-demand-billing-is-available-as-a-native-dashboard-with-ta.md +6 -0
- package/corpus/templates/analytics/changelog/2026-08-06-visible-dashboard-names-are-unique.md +6 -0
- package/corpus/templates/analytics/docs/schemas/first-party-analytics.md +1 -1
- package/corpus/templates/analytics/netlify.toml +7 -0
- package/corpus/templates/analytics/scripts/emit-netlify-dashboard-report-cron.ts +4 -0
- package/corpus/templates/analytics/scripts/first-party-analytics-bigquery.sql +104 -0
- package/corpus/templates/analytics/server/db/index.ts +27 -0
- package/corpus/templates/analytics/server/db/schema.ts +10 -0
- package/corpus/templates/analytics/server/lib/agent-chat-plan-mode.ts +0 -2
- package/corpus/templates/analytics/server/lib/dashboards-store.ts +227 -60
- package/corpus/templates/analytics/server/lib/first-party-analytics-backend.ts +1147 -0
- package/corpus/templates/analytics/server/lib/first-party-analytics-health.ts +34 -15
- package/corpus/templates/analytics/server/lib/first-party-analytics.ts +57 -4
- package/corpus/templates/analytics/server/lib/native-v2-dashboards.ts +227 -1
- package/corpus/templates/analytics/server/lib/real-data-actions.ts +1 -3
- package/corpus/templates/analytics/server/plugins/agent-chat.ts +7 -4
- package/corpus/templates/analytics/server/plugins/analytics-rollup-backfill-jobs.ts +1 -0
- package/corpus/templates/analytics/server/plugins/db.ts +52 -18
- package/corpus/templates/assets/.agents/skills/asset-generation/SKILL.md +36 -8
- package/corpus/templates/assets/.agents/skills/image-generation/SKILL.md +16 -1
- package/corpus/templates/assets/.agents/skills/library-management/SKILL.md +16 -1
- package/corpus/templates/assets/.agents/skills/turn-into-app/SKILL.md +296 -0
- package/corpus/templates/assets/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
- package/corpus/templates/assets/.agents/skills/turn-into-skill/SKILL.md +112 -0
- package/corpus/templates/assets/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
- package/corpus/templates/assets/AGENTS.md +1 -0
- package/corpus/templates/assets/actions/_helpers.ts +12 -0
- package/corpus/templates/assets/actions/generate-image.ts +9 -3
- package/corpus/templates/assets/actions/import-style-from-url.ts +115 -0
- package/corpus/templates/assets/app/hooks/use-navigation-state.ts +3 -1
- package/corpus/templates/assets/app/routes/extensions._index.tsx +1 -1
- package/corpus/templates/assets/app/routes/settings.$.tsx +1 -0
- package/corpus/templates/assets/app/routes/settings.tsx +5 -0
- package/corpus/templates/assets/app/routes/team.tsx +1 -1
- package/corpus/templates/assets/changelog/2026-08-05-brand-kits-can-import-a-website-s-hydrated-visual-language-a.md +6 -0
- package/corpus/templates/assets/changelog/2026-08-05-generated-images-now-hand-off-embeddable-previews-to-other-w.md +6 -0
- package/corpus/templates/assets/server/lib/generation.ts +58 -0
- package/corpus/templates/assets/shared/api.ts +12 -0
- package/corpus/templates/brain/.agents/skills/turn-into-app/SKILL.md +296 -0
- package/corpus/templates/brain/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
- package/corpus/templates/brain/.agents/skills/turn-into-skill/SKILL.md +112 -0
- package/corpus/templates/brain/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
- package/corpus/templates/brain/actions/list-connection-providers.ts +24 -3
- package/corpus/templates/brain/app/lib/dispatch-links.ts +44 -0
- package/corpus/templates/brain/app/routes/extensions._index.tsx +1 -1
- package/corpus/templates/brain/app/routes/sources.tsx +15 -7
- package/corpus/templates/brain/app/routes/team.tsx +1 -1
- package/corpus/templates/brain/app/routes.ts +1 -1
- package/corpus/templates/brain/changelog/2026-08-06-brain-provider-setup-links-open-dispatch-correctly-in-standa.md +6 -0
- package/corpus/templates/brain/server/plugins/agent-chat.ts +1 -0
- package/corpus/templates/calendar/.agents/skills/event-management/SKILL.md +26 -0
- package/corpus/templates/calendar/.agents/skills/turn-into-app/SKILL.md +296 -0
- package/corpus/templates/calendar/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
- package/corpus/templates/calendar/.agents/skills/turn-into-skill/SKILL.md +112 -0
- package/corpus/templates/calendar/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
- package/corpus/templates/calendar/AGENTS.md +11 -32
- package/corpus/templates/calendar/actions/update-event.ts +107 -1
- package/corpus/templates/calendar/app/components/calendar/EventCalendarSelect.tsx +83 -0
- package/corpus/templates/calendar/app/components/calendar/EventDetailPanel.tsx +57 -0
- package/corpus/templates/calendar/app/components/calendar/EventDetailPopover.tsx +59 -73
- package/corpus/templates/calendar/app/components/layout/AppLayout.tsx +3 -1
- package/corpus/templates/calendar/app/hooks/use-events.ts +4 -1
- package/corpus/templates/calendar/app/i18n-data.ts +20 -0
- package/corpus/templates/calendar/app/routes/_app.extensions._index.tsx +1 -1
- package/corpus/templates/calendar/app/routes/_app.settings.$.tsx +1 -0
- package/corpus/templates/calendar/app/routes/_app.team.tsx +1 -1
- package/corpus/templates/calendar/changelog/2026-08-06-delegated-requests-continue-in-the-background.md +6 -0
- package/corpus/templates/calendar/changelog/2026-08-06-existing-events-can-move-between-connected-google-account-ca.md +6 -0
- package/corpus/templates/calendar/server/lib/google-calendar.ts +101 -0
- package/corpus/templates/calendar/server/plugins/agent-chat.ts +7 -1
- package/corpus/templates/chat/.agents/skills/turn-into-app/SKILL.md +296 -0
- package/corpus/templates/chat/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
- package/corpus/templates/chat/.agents/skills/turn-into-skill/SKILL.md +112 -0
- package/corpus/templates/chat/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
- package/corpus/templates/chat/app/components/layout/Layout.tsx +1 -1
- package/corpus/templates/chat/app/hooks/use-navigation-state.ts +1 -1
- package/corpus/templates/chat/app/root.tsx +1 -1
- package/corpus/templates/chat/app/routes/agent.tsx +7 -7
- package/corpus/templates/chat/app/routes/extensions._index.tsx +1 -1
- package/corpus/templates/chat/app/routes/settings.$.tsx +1 -0
- package/corpus/templates/chat/app/routes/team.tsx +1 -1
- package/corpus/templates/clips/.agents/skills/turn-into-app/SKILL.md +296 -0
- package/corpus/templates/clips/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
- package/corpus/templates/clips/.agents/skills/turn-into-skill/SKILL.md +112 -0
- package/corpus/templates/clips/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
- package/corpus/templates/clips/app/components/editor/editor-layout.tsx +9 -24
- package/corpus/templates/clips/app/components/editor/timeline-geometry.ts +15 -0
- package/corpus/templates/clips/app/components/editor/waveform.tsx +4 -17
- package/corpus/templates/clips/app/components/library/library-layout.tsx +1 -1
- package/corpus/templates/clips/app/components/player/delete-recording-menu.tsx +14 -3
- package/corpus/templates/clips/app/components/player/transcript-panel.tsx +1 -1
- package/corpus/templates/clips/app/components/recorder/storage-setup-card.tsx +1 -1
- package/corpus/templates/clips/app/routes/_app.extensions._index.tsx +1 -1
- package/corpus/templates/clips/app/routes/_app.settings.$.tsx +1 -0
- package/corpus/templates/clips/app/routes/r.$recordingId.tsx +28 -38
- package/corpus/templates/clips/app/routes/share.$shareId.tsx +21 -27
- package/corpus/templates/clips/changelog/2026-08-06-clips-recovers-from-stalled-recording-setup-without-requirin.md +6 -0
- package/corpus/templates/clips/changelog/2026-08-06-clips-starts-faster-after-a-deploy-or-idle-period-startup-no.md +6 -0
- package/corpus/templates/clips/changelog/2026-08-06-deleting-a-recording-returns-cleanly-to-the-library-and-fit-.md +6 -0
- package/corpus/templates/clips/changelog/2026-08-06-hide-clip-insights-from-viewers-without-analytics-access.md +6 -0
- package/corpus/templates/clips/desktop/src/app.tsx +48 -20
- package/corpus/templates/clips/desktop/src/lib/recorder.ts +275 -74
- package/corpus/templates/clips/desktop/src/lib/recording-start-guard.ts +84 -0
- package/corpus/templates/clips/desktop/src/overlays/toolbar.tsx +14 -4
- package/corpus/templates/clips/server/plugins/db.ts +214 -26
- package/corpus/templates/content/.agents/skills/turn-into-app/SKILL.md +296 -0
- package/corpus/templates/content/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
- package/corpus/templates/content/.agents/skills/turn-into-skill/SKILL.md +112 -0
- package/corpus/templates/content/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
- package/corpus/templates/content/app/routes/_app.extensions._index.tsx +1 -1
- package/corpus/templates/content/app/routes/_app.settings.$.tsx +1 -0
- package/corpus/templates/content/app/routes/_app.team.tsx +1 -1
- package/corpus/templates/content/e2e/global-setup.ts +1 -1
- package/corpus/templates/crm/.agents/skills/turn-into-app/SKILL.md +296 -0
- package/corpus/templates/crm/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
- package/corpus/templates/crm/.agents/skills/turn-into-skill/SKILL.md +112 -0
- package/corpus/templates/crm/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
- package/corpus/templates/crm/changelog/2026-08-06-crm-starts-faster-after-a-deploy-or-idle-period-one-time-dat.md +6 -0
- package/corpus/templates/crm/server/plugins/db.ts +11 -8
- package/corpus/templates/design/.agents/skills/design-generation/SKILL.md +36 -1
- package/corpus/templates/design/.agents/skills/design-systems/SKILL.md +6 -1
- package/corpus/templates/design/.agents/skills/turn-into-app/SKILL.md +296 -0
- package/corpus/templates/design/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
- package/corpus/templates/design/.agents/skills/turn-into-skill/SKILL.md +112 -0
- package/corpus/templates/design/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
- package/corpus/templates/design/actions/analyze-brand-assets.ts +7 -7
- package/corpus/templates/design/actions/import-from-url.ts +6 -5
- package/corpus/templates/design/app/components/design/LayersPanel.tsx +27 -18
- package/corpus/templates/design/app/pages/DesignSystemSetup.tsx +2 -2
- package/corpus/templates/design/app/pages/Index.tsx +6 -2
- package/corpus/templates/design/app/routes/extensions._index.tsx +1 -1
- package/corpus/templates/design/app/routes/settings.$.tsx +1 -0
- package/corpus/templates/design/app/routes/team.tsx +1 -1
- package/corpus/templates/design/changelog/2026-08-05-deleting-a-design-from-the-home-page-no-longer-leaves-the-ap.md +6 -0
- package/corpus/templates/design/changelog/2026-08-05-renaming-a-layer-now-focuses-its-name-field-automatically.md +6 -0
- package/corpus/templates/design/changelog/2026-08-05-website-url-imports-now-capture-hydrated-browser-computed-de.md +6 -0
- package/corpus/templates/design/e2e/global-setup.ts +1 -1
- package/corpus/templates/design/server/plugins/agent-chat.ts +2 -0
- package/corpus/templates/dispatch/.agents/skills/turn-into-app/SKILL.md +296 -0
- package/corpus/templates/dispatch/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
- package/corpus/templates/dispatch/.agents/skills/turn-into-skill/SKILL.md +112 -0
- package/corpus/templates/dispatch/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
- package/corpus/templates/dispatch/app/hooks/use-navigation-state.ts +1 -1
- package/corpus/templates/dispatch/app/routes/settings.$.tsx +1 -0
- package/corpus/templates/dispatch/app/routes/team.tsx +1 -1
- package/corpus/templates/dispatch/changelog/2026-08-06-ready-workspace-apps-stay-one-click-away-in-a-compact-dispat.md +6 -0
- package/corpus/templates/dispatch/changelog/2026-08-06-shared-vault-values-and-management-are-now-restricted-to-wor.md +6 -0
- package/corpus/templates/factory/.agents/skills/turn-into-app/SKILL.md +296 -0
- package/corpus/templates/factory/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
- package/corpus/templates/factory/.agents/skills/turn-into-skill/SKILL.md +112 -0
- package/corpus/templates/factory/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
- package/corpus/templates/factory/app/hooks/use-navigation-state.ts +1 -1
- package/corpus/templates/factory/app/routes/extensions._index.tsx +1 -1
- package/corpus/templates/factory/app/routes/settings.$.tsx +1 -0
- package/corpus/templates/factory/app/routes/team.tsx +1 -1
- package/corpus/templates/forms/.agents/skills/turn-into-app/SKILL.md +296 -0
- package/corpus/templates/forms/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
- package/corpus/templates/forms/.agents/skills/turn-into-skill/SKILL.md +112 -0
- package/corpus/templates/forms/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
- package/corpus/templates/forms/app/routes/_app.extensions._index.tsx +1 -1
- package/corpus/templates/forms/app/routes/_app.settings.$.tsx +1 -0
- package/corpus/templates/forms/app/routes/_app.team.tsx +1 -1
- package/corpus/templates/forms/changelog/2026-08-06-delegated-requests-continue-in-the-background.md +6 -0
- package/corpus/templates/forms/server/plugins/agent-chat.ts +4 -0
- package/corpus/templates/forms/shared/navigation.ts +1 -1
- package/corpus/templates/macros/.agents/skills/turn-into-app/SKILL.md +296 -0
- package/corpus/templates/macros/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
- package/corpus/templates/macros/.agents/skills/turn-into-skill/SKILL.md +112 -0
- package/corpus/templates/macros/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
- package/corpus/templates/macros/app/routes/extensions._index.tsx +1 -1
- package/corpus/templates/macros/app/routes/settings.$.tsx +1 -0
- package/corpus/templates/macros/app/routes/team.tsx +1 -1
- package/corpus/templates/mail/.agents/skills/turn-into-app/SKILL.md +296 -0
- package/corpus/templates/mail/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
- package/corpus/templates/mail/.agents/skills/turn-into-skill/SKILL.md +112 -0
- package/corpus/templates/mail/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
- package/corpus/templates/mail/app/routes/extensions._index.tsx +1 -1
- package/corpus/templates/mail/app/routes/settings.$.tsx +1 -0
- package/corpus/templates/mail/changelog/2026-08-06-delegated-requests-continue-in-the-background.md +6 -0
- package/corpus/templates/mail/server/plugins/agent-chat.ts +6 -0
- package/corpus/templates/plan/.agents/skills/turn-into-app/SKILL.md +296 -0
- package/corpus/templates/plan/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
- package/corpus/templates/plan/.agents/skills/turn-into-skill/SKILL.md +112 -0
- package/corpus/templates/plan/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
- package/corpus/templates/plan/app/hooks/use-navigation-state.ts +1 -1
- package/corpus/templates/plan/app/routes/extensions._index.tsx +1 -1
- package/corpus/templates/plan/app/routes/settings.$.tsx +1 -0
- package/corpus/templates/plan/app/routes/team.tsx +1 -1
- package/corpus/templates/slides/.agents/skills/create-deck/SKILL.md +48 -5
- package/corpus/templates/slides/.agents/skills/design-systems/SKILL.md +40 -2
- package/corpus/templates/slides/.agents/skills/image-generation-via-a2a/SKILL.md +6 -0
- package/corpus/templates/slides/.agents/skills/slide-editing/SKILL.md +15 -2
- package/corpus/templates/slides/.agents/skills/slide-images/SKILL.md +29 -24
- package/corpus/templates/slides/.agents/skills/turn-into-app/SKILL.md +296 -0
- package/corpus/templates/slides/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
- package/corpus/templates/slides/.agents/skills/turn-into-skill/SKILL.md +112 -0
- package/corpus/templates/slides/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
- package/corpus/templates/slides/AGENTS.md +7 -9
- package/corpus/templates/slides/_gitignore +1 -0
- package/corpus/templates/slides/actions/analyze-brand-assets.ts +7 -7
- package/corpus/templates/slides/actions/export-pptx.ts +402 -36
- package/corpus/templates/slides/actions/import-file.ts +46 -85
- package/corpus/templates/slides/actions/import-from-url.ts +6 -6
- package/corpus/templates/slides/actions/import-google-slides-reference.ts +271 -12
- package/corpus/templates/slides/actions/import-pptx.ts +85 -60
- package/corpus/templates/slides/app/components/deck/DeckCard.tsx +10 -13
- package/corpus/templates/slides/app/components/design-system/DesignSystemSetup.tsx +1 -1
- package/corpus/templates/slides/app/components/editor/AddSlidePopover.tsx +5 -1
- package/corpus/templates/slides/app/components/editor/EditorToolbar.tsx +25 -12
- package/corpus/templates/slides/app/components/editor/ExportMenu.tsx +112 -57
- package/corpus/templates/slides/app/components/editor/GoogleDriveConnectionCta.tsx +202 -0
- package/corpus/templates/slides/app/components/editor/GoogleSlidesReferenceImport.tsx +26 -14
- package/corpus/templates/slides/app/components/editor/PromptDialog.tsx +176 -0
- package/corpus/templates/slides/app/components/editor/SlideEditor.tsx +182 -141
- package/corpus/templates/slides/app/components/editor/canvas-interactions/index.ts +1 -0
- package/corpus/templates/slides/app/components/editor/canvas-interactions/slides-canvas-adapter.ts +18 -0
- package/corpus/templates/slides/app/components/editor/slide-text-targets.ts +85 -0
- package/corpus/templates/slides/app/components/layout/Layout.tsx +3 -0
- package/corpus/templates/slides/app/components/onboarding/FirstDeckOnboardingFlow.tsx +13 -3
- package/corpus/templates/slides/app/components/presentation/PresentationView.tsx +27 -1
- package/corpus/templates/slides/app/context/DeckContext.tsx +71 -20
- package/corpus/templates/slides/app/global.css +6 -0
- package/corpus/templates/slides/app/i18n/en-US.ts +1 -0
- package/corpus/templates/slides/app/lib/create-deck-generation.ts +10 -6
- package/corpus/templates/slides/app/lib/deck-preview-frame.ts +15 -0
- package/corpus/templates/slides/app/lib/deck-share-links.ts +9 -0
- package/corpus/templates/slides/app/lib/export-pptx-client.ts +89 -0
- package/corpus/templates/slides/app/lib/slide-animation-elements.ts +3 -0
- package/corpus/templates/slides/app/pages/DeckEditor.tsx +17 -0
- package/corpus/templates/slides/app/pages/Index.tsx +107 -6
- package/corpus/templates/slides/app/routes/extensions._index.tsx +1 -1
- package/corpus/templates/slides/app/routes/settings.$.tsx +1 -0
- package/corpus/templates/slides/app/routes/team.tsx +1 -1
- package/corpus/templates/slides/changelog/2026-08-05-failed-deck-creation-and-reference-uploads-now-recover-clean.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-05-slides-recover-completed-generation-results-after-a-sync-hic.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-05-website-url-imports-now-capture-hydrated-browser-computed-st.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-06-clicking-the-gray-canvas-around-a-slide-clears-its-selection.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-06-deck-thumbnails-keep-a-consistent-listing-frame-across-aspec.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-06-deep-linked-decks-open-directly-instead-of-being-interrupted.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-06-google-slides-exports-now-show-clear-import-steps-when-direc.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-06-import-pdf-google-slides-and-powerpoint-decks-directly-from-.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-06-imported-powerpoint-exports-keep-text-and-images-editable-an.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-06-presentation-prompts-continue-adding-rendered-slides-until-t.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-06-public-decks-now-share-read-only-presentation-links-by-defau.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-06-slides-offers-a-direct-connect-google-button-when-a-drive-co.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-06-slides-preserve-uploaded-pdf-layouts-accept-larger-reference.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-06-styled-words-stay-part-of-their-text-box-instead-of-becoming.md +6 -0
- package/corpus/templates/slides/server/handlers/google-docs-auth.ts +7 -20
- package/corpus/templates/slides/server/handlers/import/html-converter.ts +236 -13
- package/corpus/templates/slides/server/handlers/import/pptx-assets.ts +67 -0
- package/corpus/templates/slides/server/handlers/import/pptx-parser.ts +2 -0
- package/corpus/templates/slides/server/handlers/uploads.ts +7 -3
- package/corpus/templates/slides/server/lib/chat-attachments.ts +6 -3
- package/corpus/templates/slides/server/lib/emails.ts +7 -2
- package/corpus/templates/slides/server/lib/google-docs-error.ts +50 -0
- package/corpus/templates/slides/server/lib/google-docs-oauth.ts +1 -0
- package/corpus/templates/slides/server/lib/import-asset-storage.ts +127 -0
- package/corpus/templates/slides/server/plugins/agent-chat.ts +4 -3
- package/corpus/templates/slides/server/routes/api/import-assets/[token].get.ts +70 -0
- package/corpus/templates/slides/shared/upload-types.ts +3 -0
- package/corpus/templates/tasks/.agents/skills/turn-into-app/SKILL.md +296 -0
- package/corpus/templates/tasks/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
- package/corpus/templates/tasks/.agents/skills/turn-into-skill/SKILL.md +112 -0
- package/corpus/templates/tasks/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
- package/corpus/templates/tasks/app/components/layout/Header.tsx +3 -1
- package/corpus/templates/tasks/app/routes/extensions._index.tsx +1 -1
- package/corpus/templates/tasks/app/routes/settings.$.tsx +1 -0
- package/dist/agent/engine/ai-sdk-engine.js +49 -3
- package/dist/agent/production-agent.d.ts +18 -0
- package/dist/agent/production-agent.js +80 -1
- package/dist/agent/types.d.ts +7 -0
- package/dist/cli/agent-plugin.d.ts +112 -0
- package/dist/cli/agent-plugin.js +1081 -0
- package/dist/cli/app-skill.js +39 -1
- package/dist/cli/code-agent-executor.d.ts +3 -0
- package/dist/cli/code-agent-executor.js +51 -13
- package/dist/cli/index.js +13 -0
- package/dist/cli/templates-meta.js +1 -1
- package/dist/client/AgentPanel.d.ts +3 -1
- package/dist/client/AgentPanel.js +9 -2
- package/dist/client/AssistantChat.d.ts +8 -0
- package/dist/client/AssistantChat.js +23 -8
- package/dist/client/NewWorkspaceAppFlow.js +1 -0
- package/dist/client/agent-chat-adapter.d.ts +1 -1
- package/dist/client/agent-chat-adapter.js +153 -7
- package/dist/client/agent-page/AgentWorkspaceContent.d.ts +1 -1
- package/dist/client/agent-page/AgentWorkspaceContent.js +13 -13
- package/dist/client/assistant-ui-recovery.d.ts +2 -1
- package/dist/client/assistant-ui-recovery.js +7 -3
- package/dist/client/chat/run-recovery.js +5 -1
- package/dist/client/embed-auth.js +6 -2
- package/dist/client/error-format.js +12 -0
- package/dist/client/integrations/IntegrationsPanel.js +40 -6
- package/dist/client/onboarding/FirstRunOnboarding.js +11 -4
- package/dist/client/org/OrgSwitcher.js +2 -2
- package/dist/client/org/TeamPage.js +92 -72
- package/dist/client/require-session.d.ts +1 -1
- package/dist/client/require-session.js +4 -4
- package/dist/client/resources/McpConnectionSuggestion.d.ts +1 -0
- package/dist/client/resources/McpConnectionSuggestion.js +27 -10
- package/dist/client/resources/McpIntegrationDialog.js +77 -45
- package/dist/client/resources/mcp-integration-catalog.d.ts +13 -1
- package/dist/client/resources/mcp-integration-catalog.js +255 -2
- package/dist/client/resources/mcp-integration-logos.js +18 -2
- package/dist/client/resources/use-mcp-servers.d.ts +5 -0
- package/dist/client/resources/use-mcp-servers.js +36 -0
- package/dist/client/settings/AccountSettingsCard.js +42 -36
- package/dist/client/settings/AutomationsSection.js +1 -1
- package/dist/client/settings/DemoModeSection.d.ts +3 -1
- package/dist/client/settings/DemoModeSection.js +4 -1
- package/dist/client/settings/ExtensionsSettingsContent.js +1 -1
- package/dist/client/settings/SchedulingTimezoneField.d.ts +3 -1
- package/dist/client/settings/SchedulingTimezoneField.js +9 -5
- package/dist/client/settings/SettingsPanel.d.ts +4 -1
- package/dist/client/settings/SettingsPanel.js +21 -21
- package/dist/client/settings/SettingsTabsPage.d.ts +2 -2
- package/dist/client/settings/SettingsTabsPage.js +98 -45
- package/dist/client/settings/VoiceTranscriptionSection.js +6 -1
- package/dist/client/settings/useSettingsPanelController.js +47 -8
- package/dist/collab/routes.d.ts +1 -1
- package/dist/db/client.d.ts +9 -0
- package/dist/db/client.js +51 -16
- package/dist/db/create-get-db.js +2 -2
- package/dist/db/ddl-guard.d.ts +11 -10
- package/dist/db/ddl-guard.js +40 -12
- package/dist/deploy/build.d.ts +2 -0
- package/dist/deploy/build.js +97 -4
- package/dist/deploy/workspace-deploy.js +0 -2
- package/dist/guards/no-env-credentials.js +9 -0
- package/dist/ingestion/index.d.ts +1 -1
- package/dist/ingestion/pptx.d.ts +68 -0
- package/dist/ingestion/pptx.js +660 -213
- package/dist/ingestion/website.d.ts +30 -0
- package/dist/integrations/plugin.js +9 -6
- package/dist/localization/default-messages.d.ts +59 -0
- package/dist/localization/default-messages.js +62 -2
- package/dist/mcp/screen-memory-stdio.d.ts +7 -7
- package/dist/mcp-client/oauth-routes.d.ts +2 -0
- package/dist/mcp-client/oauth-routes.js +74 -7
- package/dist/mcp-client/routes.d.ts +1 -0
- package/dist/mcp-client/routes.js +49 -0
- package/dist/navigation/index.js +16 -5
- package/dist/notifications/routes.d.ts +1 -1
- package/dist/observability/routes.d.ts +3 -3
- package/dist/onboarding/app-profile.js +11 -0
- package/dist/progress/routes.d.ts +1 -1
- package/dist/provider-api/actions/custom-provider-registration.d.ts +13 -13
- package/dist/provider-api/actions/provider-api.d.ts +11 -11
- package/dist/resources/store.js +15 -1
- package/dist/scripts/call-agent.js +45 -4
- package/dist/secrets/routes.d.ts +6 -6
- package/dist/server/agent-chat/action-filters-a2a.d.ts +1 -1
- package/dist/server/agent-chat/action-filters-a2a.js +36 -1
- package/dist/server/agent-chat-plugin.js +29 -8
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/auth.js +55 -17
- package/dist/server/better-auth-instance.js +5 -3
- package/dist/server/core-routes-plugin.d.ts +8 -1
- package/dist/server/core-routes-plugin.js +28 -3
- package/dist/server/credential-provider.d.ts +3 -3
- package/dist/server/credential-provider.js +90 -4
- package/dist/server/identity-sso.js +2 -1
- package/dist/server/onboarding-html.d.ts +2 -0
- package/dist/server/onboarding-html.js +171 -62
- package/dist/server/realtime-token.d.ts +1 -1
- package/dist/server/self-dispatch.d.ts +5 -4
- package/dist/server/self-dispatch.js +25 -14
- package/dist/server/ssr-handler.d.ts +1 -1
- package/dist/server/ssr-handler.js +1 -1
- package/dist/server/workspace-provider-oauth.js +1 -1
- package/dist/setup-connections/onboarding.js +1 -1
- package/dist/shared/cache-control.d.ts +26 -2
- package/dist/shared/cache-control.js +43 -2
- package/dist/shared/index.d.ts +1 -1
- package/dist/shared/index.js +1 -1
- package/dist/shared/password-policy.d.ts +3 -0
- package/dist/shared/password-policy.js +3 -0
- package/dist/shared/sign-in-journey.d.ts +5 -2
- package/dist/shared/sign-in-journey.js +10 -4
- package/dist/sharing/actions/set-resource-visibility.js +16 -4
- package/dist/sharing/registry.d.ts +14 -0
- package/dist/styles/agent-native.css +6 -0
- package/dist/templates/chat/.agents/skills/turn-into-app/SKILL.md +296 -0
- package/dist/templates/chat/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
- package/dist/templates/chat/.agents/skills/turn-into-skill/SKILL.md +112 -0
- package/dist/templates/chat/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
- package/dist/templates/chat/app/components/layout/Layout.tsx +1 -1
- package/dist/templates/chat/app/hooks/use-navigation-state.ts +1 -1
- package/dist/templates/chat/app/root.tsx +1 -1
- package/dist/templates/chat/app/routes/agent.tsx +7 -7
- package/dist/templates/chat/app/routes/extensions._index.tsx +1 -1
- package/dist/templates/chat/app/routes/settings.$.tsx +1 -0
- package/dist/templates/chat/app/routes/team.tsx +1 -1
- package/dist/templates/default/.agents/skills/turn-into-app/SKILL.md +296 -0
- package/dist/templates/default/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
- package/dist/templates/default/.agents/skills/turn-into-skill/SKILL.md +112 -0
- package/dist/templates/default/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
- package/dist/templates/headless/.agents/skills/turn-into-app/SKILL.md +296 -0
- package/dist/templates/headless/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
- package/dist/templates/headless/.agents/skills/turn-into-skill/SKILL.md +112 -0
- package/dist/templates/headless/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
- package/dist/templates/workspace-core/.agents/skills/adding-workspace-apps/SKILL.md +6 -0
- package/dist/templates/workspace-core/.agents/skills/address-feedback/SKILL.md +37 -6
- package/dist/templates/workspace-core/.agents/skills/authentication/SKILL.md +4 -2
- package/dist/templates/workspace-core/.agents/skills/performance/SKILL.md +51 -0
- package/dist/templates/workspace-core/.agents/skills/turn-into-app/SKILL.md +296 -0
- package/dist/templates/workspace-core/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
- package/dist/templates/workspace-core/.agents/skills/turn-into-skill/SKILL.md +112 -0
- package/dist/templates/workspace-core/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
- package/dist/templates/workspace-root/AGENTS.md +7 -0
- package/dist/user-profile/actions/change-password.js +8 -3
- package/dist/user-profile/actions/set-password.js +5 -1
- package/dist/vite/action-types-plugin.js +59 -0
- package/docs/content/authentication.mdx +4 -5
- package/docs/content/skills-guide.mdx +13 -0
- package/docs/content/template-analytics-developers.mdx +1 -1
- package/docs/content/template-calendar-developers.mdx +1 -1
- package/docs/content/template-chat-developers.mdx +2 -2
- package/docs/content/template-content-developers.mdx +1 -1
- package/docs/content/template-mail-developers.mdx +1 -1
- package/docs/content/template-plan-developers.mdx +1 -1
- package/docs/content/toolkit-command-navigation.mdx +6 -6
- package/docs/content/toolkit-org-team.mdx +1 -1
- package/docs/content/toolkit-settings.mdx +8 -8
- package/docs/content/toolkit-setup-connections.mdx +1 -1
- package/package.json +6 -2
- package/src/templates/chat/.agents/skills/turn-into-app/SKILL.md +296 -0
- package/src/templates/chat/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
- package/src/templates/chat/.agents/skills/turn-into-skill/SKILL.md +112 -0
- package/src/templates/chat/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
- package/src/templates/chat/app/components/layout/Layout.tsx +1 -1
- package/src/templates/chat/app/hooks/use-navigation-state.ts +1 -1
- package/src/templates/chat/app/root.tsx +1 -1
- package/src/templates/chat/app/routes/agent.tsx +7 -7
- package/src/templates/chat/app/routes/extensions._index.tsx +1 -1
- package/src/templates/chat/app/routes/settings.$.tsx +1 -0
- package/src/templates/chat/app/routes/team.tsx +1 -1
- package/src/templates/default/.agents/skills/turn-into-app/SKILL.md +296 -0
- package/src/templates/default/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
- package/src/templates/default/.agents/skills/turn-into-skill/SKILL.md +112 -0
- package/src/templates/default/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
- package/src/templates/headless/.agents/skills/turn-into-app/SKILL.md +296 -0
- package/src/templates/headless/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
- package/src/templates/headless/.agents/skills/turn-into-skill/SKILL.md +112 -0
- package/src/templates/headless/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
- package/src/templates/workspace-core/.agents/skills/adding-workspace-apps/SKILL.md +6 -0
- package/src/templates/workspace-core/.agents/skills/address-feedback/SKILL.md +37 -6
- package/src/templates/workspace-core/.agents/skills/authentication/SKILL.md +4 -2
- package/src/templates/workspace-core/.agents/skills/performance/SKILL.md +51 -0
- package/src/templates/workspace-core/.agents/skills/turn-into-app/SKILL.md +296 -0
- package/src/templates/workspace-core/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
- package/src/templates/workspace-core/.agents/skills/turn-into-skill/SKILL.md +112 -0
- package/src/templates/workspace-core/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
- package/src/templates/workspace-root/AGENTS.md +7 -0
- package/corpus/templates/analytics/.agents/skills/dashboard-management/references/template-catalog-and-demo.md +0 -62
- package/corpus/templates/analytics/actions/install-dashboard-template.ts +0 -369
- package/corpus/templates/analytics/actions/list-dashboard-templates.ts +0 -47
- package/corpus/templates/analytics/actions/list-native-v2-dashboard-templates.ts +0 -34
- package/corpus/templates/analytics/app/routes/catalog.tsx +0 -240
- package/src/templates/default/actions/navigate.spec.ts +0 -53
|
@@ -131,8 +131,30 @@ export const BACKGROUND_FOLLOW_IDLE_TIMEOUT_MS = 210_000;
|
|
|
131
131
|
// every poll tick and the follow loop never exits (prod: 26 chained runs over
|
|
132
132
|
// 22 minutes, all error:stale_run, user watching a spinner). These bound the
|
|
133
133
|
// whole turn instead, and an identical repeated failure counts as no progress.
|
|
134
|
-
|
|
135
|
-
|
|
134
|
+
//
|
|
135
|
+
// CLIENT-ABOVE-SERVER INVARIANT (asserted in agent-chat-adapter.spec.ts).
|
|
136
|
+
// These are a backstop for a server that has gone silent in a way the idle
|
|
137
|
+
// timeout misses — NOT the primary limit. They must stay ABOVE the server's
|
|
138
|
+
// own ceilings so the server, which can actually tell progress from looping,
|
|
139
|
+
// always terminates a turn first and writes a truthful terminal reason:
|
|
140
|
+
// BACKGROUND_SOFT_TIMEOUT_CEILING_MS (13 min, run-manager.ts) — one chunk
|
|
141
|
+
// MAX_TURN_WALL_CLOCK_MS (90 min, production-agent.ts) — one turn
|
|
142
|
+
// MAX_BACKGROUND_RUN_CONTINUATIONS (20, production-agent.ts)
|
|
143
|
+
//
|
|
144
|
+
// They were originally set to 10 min / 6 runs, which put the whole-turn client
|
|
145
|
+
// budget BELOW the 13-minute ceiling of a single legal chunk. Any turn needing
|
|
146
|
+
// a second full-length chunk was killed by the client while the server was
|
|
147
|
+
// healthy and had 80 minutes left — measured in prod as turns dying at 11-25
|
|
148
|
+
// minutes with `last_progress_at` tracking the abort, i.e. still streaming
|
|
149
|
+
// tokens and completing tools when the client gave up. That is the top
|
|
150
|
+
// non-auth cause of "the chat just stopped" reports.
|
|
151
|
+
//
|
|
152
|
+
// Killing a turn that is NOT progressing is already covered twice over, by
|
|
153
|
+
// mechanisms that read progress rather than a clock: the 210s idle timeout
|
|
154
|
+
// above, and MAX_REPEATED_BACKGROUND_TERMINAL_REASONS below. Do not re-tighten
|
|
155
|
+
// these two to catch a stuck turn — fix the progress signal instead.
|
|
156
|
+
export const MAX_FOLLOWED_BACKGROUND_RUNS = 24;
|
|
157
|
+
export const MAX_BACKGROUND_FOLLOW_WALL_TIME_MS = 95 * 60_000;
|
|
136
158
|
const MAX_REPEATED_BACKGROUND_TERMINAL_REASONS = 3;
|
|
137
159
|
// A re-observed terminal run whose outcome would be an ERROR (never a
|
|
138
160
|
// genuine "done" success) gets a short extra grace window before the follow
|
|
@@ -958,6 +980,65 @@ class AgentStartupTimeoutError extends Error {
|
|
|
958
980
|
this.timeoutMs = timeoutMs;
|
|
959
981
|
}
|
|
960
982
|
}
|
|
983
|
+
/**
|
|
984
|
+
* Keep the server's error contract intact across the fetch boundary. In
|
|
985
|
+
* particular, a POST response with `retryable: false` must not be fed into the
|
|
986
|
+
* generic reconnect/continuation path: replaying a mutation after the server
|
|
987
|
+
* has started processing it can duplicate work. The previous code discarded
|
|
988
|
+
* this metadata and exposed the raw JSON body to the user instead.
|
|
989
|
+
*/
|
|
990
|
+
class AgentChatHttpError extends Error {
|
|
991
|
+
errorCode;
|
|
992
|
+
details;
|
|
993
|
+
retryable;
|
|
994
|
+
upgradeUrl;
|
|
995
|
+
constructor(error) {
|
|
996
|
+
super(error.message);
|
|
997
|
+
this.name = "AgentChatHttpError";
|
|
998
|
+
this.errorCode = error.errorCode;
|
|
999
|
+
this.details = error.details;
|
|
1000
|
+
this.retryable = error.retryable;
|
|
1001
|
+
this.upgradeUrl = error.upgradeUrl;
|
|
1002
|
+
}
|
|
1003
|
+
}
|
|
1004
|
+
function parseStructuredAgentChatError(body) {
|
|
1005
|
+
if (!body.trim())
|
|
1006
|
+
return null;
|
|
1007
|
+
try {
|
|
1008
|
+
const parsed = JSON.parse(body);
|
|
1009
|
+
if (!parsed || typeof parsed !== "object")
|
|
1010
|
+
return null;
|
|
1011
|
+
const message = typeof parsed.error === "string"
|
|
1012
|
+
? parsed.error
|
|
1013
|
+
: typeof parsed.message === "string"
|
|
1014
|
+
? parsed.message
|
|
1015
|
+
: "";
|
|
1016
|
+
if (!message)
|
|
1017
|
+
return null;
|
|
1018
|
+
return {
|
|
1019
|
+
message,
|
|
1020
|
+
...(typeof parsed.code === "string"
|
|
1021
|
+
? { errorCode: parsed.code }
|
|
1022
|
+
: typeof parsed.errorCode === "string"
|
|
1023
|
+
? { errorCode: parsed.errorCode }
|
|
1024
|
+
: {}),
|
|
1025
|
+
...(typeof parsed.details === "string"
|
|
1026
|
+
? { details: parsed.details }
|
|
1027
|
+
: {}),
|
|
1028
|
+
...(typeof parsed.retryable === "boolean"
|
|
1029
|
+
? { retryable: parsed.retryable }
|
|
1030
|
+
: {}),
|
|
1031
|
+
...(typeof parsed.upgradeUrl === "string"
|
|
1032
|
+
? { upgradeUrl: parsed.upgradeUrl }
|
|
1033
|
+
: {}),
|
|
1034
|
+
};
|
|
1035
|
+
}
|
|
1036
|
+
catch (error) {
|
|
1037
|
+
if (error instanceof SyntaxError)
|
|
1038
|
+
return null;
|
|
1039
|
+
throw error;
|
|
1040
|
+
}
|
|
1041
|
+
}
|
|
961
1042
|
async function fetchWithStartupTimeout(input, init, timeoutMs, abortSignal) {
|
|
962
1043
|
if (abortSignal.aborted) {
|
|
963
1044
|
throw new DOMException("The operation was aborted.", "AbortError");
|
|
@@ -2185,7 +2266,12 @@ export function createAgentChatAdapter(options) {
|
|
|
2185
2266
|
if (Date.now() - followStartedAt >=
|
|
2186
2267
|
MAX_BACKGROUND_FOLLOW_WALL_TIME_MS) {
|
|
2187
2268
|
yield* stopBackgroundTurnBeforeReporting({
|
|
2188
|
-
|
|
2269
|
+
// Says only what this backstop actually knows. It fires on a
|
|
2270
|
+
// clock, so it cannot tell a looping turn from one that was
|
|
2271
|
+
// still working — the old copy asserted "kept restarting
|
|
2272
|
+
// without finishing", which prod runs contradicted: they were
|
|
2273
|
+
// streaming tokens right up to the abort.
|
|
2274
|
+
message: `This turn ran for ${Math.round(MAX_BACKGROUND_FOLLOW_WALL_TIME_MS / 60_000)} minutes without finishing, so it was stopped. Your chat context is preserved — retrying, or splitting this into smaller requests, usually gets through.`,
|
|
2189
2275
|
errorCode: "background_follow_time_budget_exhausted",
|
|
2190
2276
|
details: `followed_runs: ${followedRunIds.size}`,
|
|
2191
2277
|
});
|
|
@@ -2716,7 +2802,7 @@ export function createAgentChatAdapter(options) {
|
|
|
2716
2802
|
const body = await res.text();
|
|
2717
2803
|
const parsed = JSON.parse(body);
|
|
2718
2804
|
if (parsed.error) {
|
|
2719
|
-
throw new Error(parsed.error);
|
|
2805
|
+
throw new Error(String(parsed.error));
|
|
2720
2806
|
}
|
|
2721
2807
|
}
|
|
2722
2808
|
catch (e) {
|
|
@@ -2850,6 +2936,7 @@ export function createAgentChatAdapter(options) {
|
|
|
2850
2936
|
let errorText = `Server error: ${res.status}`;
|
|
2851
2937
|
try {
|
|
2852
2938
|
const body = await res.text();
|
|
2939
|
+
const structuredError = parseStructuredAgentChatError(body);
|
|
2853
2940
|
if (isAuthErrorMessage(body)) {
|
|
2854
2941
|
if (await tryRecoverAuthOnce()) {
|
|
2855
2942
|
continue;
|
|
@@ -2893,11 +2980,25 @@ export function createAgentChatAdapter(options) {
|
|
|
2893
2980
|
"Agent chat endpoint not found. Make sure the agent-chat plugin is loaded in server/plugins/.";
|
|
2894
2981
|
}
|
|
2895
2982
|
else if (body) {
|
|
2896
|
-
|
|
2897
|
-
|
|
2983
|
+
// A non-retryable structured response is a terminal server
|
|
2984
|
+
// outcome. Preserve its code and stop before the generic
|
|
2985
|
+
// connection recovery below can POST the same turn again.
|
|
2986
|
+
if (structuredError &&
|
|
2987
|
+
(structuredError.retryable === false ||
|
|
2988
|
+
structuredError.errorCode === "database_unavailable")) {
|
|
2989
|
+
throw new AgentChatHttpError(structuredError);
|
|
2990
|
+
}
|
|
2991
|
+
errorText = structuredError
|
|
2992
|
+
? structuredError.message
|
|
2993
|
+
: body.length > 200
|
|
2994
|
+
? body.slice(0, 200) + "..."
|
|
2995
|
+
: body;
|
|
2898
2996
|
}
|
|
2899
2997
|
}
|
|
2900
|
-
catch {
|
|
2998
|
+
catch (error) {
|
|
2999
|
+
if (error instanceof AgentChatHttpError)
|
|
3000
|
+
throw error;
|
|
3001
|
+
}
|
|
2901
3002
|
throw new Error(errorText);
|
|
2902
3003
|
}
|
|
2903
3004
|
if (!res.body) {
|
|
@@ -3068,6 +3169,51 @@ export function createAgentChatAdapter(options) {
|
|
|
3068
3169
|
return;
|
|
3069
3170
|
continue;
|
|
3070
3171
|
}
|
|
3172
|
+
if (err instanceof AgentChatHttpError) {
|
|
3173
|
+
const normalized = normalizeChatError(err.message, err.errorCode);
|
|
3174
|
+
const details = [err.details, normalized.details]
|
|
3175
|
+
.filter(Boolean)
|
|
3176
|
+
.join("\n\n");
|
|
3177
|
+
const runError = {
|
|
3178
|
+
message: normalized.message,
|
|
3179
|
+
...(details ? { details } : {}),
|
|
3180
|
+
...(err.errorCode ? { errorCode: err.errorCode } : {}),
|
|
3181
|
+
recoverable: err.retryable === true,
|
|
3182
|
+
...(runId ? { runId } : {}),
|
|
3183
|
+
};
|
|
3184
|
+
captureChatClientError(err, "server-error", {
|
|
3185
|
+
...(err.errorCode ? { errorCode: err.errorCode } : {}),
|
|
3186
|
+
retryable: err.retryable ?? false,
|
|
3187
|
+
});
|
|
3188
|
+
if (typeof window !== "undefined") {
|
|
3189
|
+
window.dispatchEvent(new CustomEvent("agent-chat:run-error", {
|
|
3190
|
+
detail: {
|
|
3191
|
+
...runError,
|
|
3192
|
+
...(err.upgradeUrl ? { upgradeUrl: err.upgradeUrl } : {}),
|
|
3193
|
+
tabId,
|
|
3194
|
+
},
|
|
3195
|
+
}));
|
|
3196
|
+
}
|
|
3197
|
+
settleInterruptedToolCalls(content, undefined, {
|
|
3198
|
+
includeActivity: true,
|
|
3199
|
+
});
|
|
3200
|
+
content.push({
|
|
3201
|
+
type: "text",
|
|
3202
|
+
text: `Something went wrong: ${normalized.message}`,
|
|
3203
|
+
});
|
|
3204
|
+
yield {
|
|
3205
|
+
content: [...content],
|
|
3206
|
+
status: {
|
|
3207
|
+
type: "incomplete",
|
|
3208
|
+
reason: "error",
|
|
3209
|
+
},
|
|
3210
|
+
metadata: {
|
|
3211
|
+
custom: { ...(runId ? { runId } : {}), runError },
|
|
3212
|
+
},
|
|
3213
|
+
};
|
|
3214
|
+
clearActiveRun();
|
|
3215
|
+
return;
|
|
3216
|
+
}
|
|
3071
3217
|
const errMsg = err instanceof Error ? err.message : "Something went wrong.";
|
|
3072
3218
|
const isAuthError = isAuthErrorMessage(errMsg);
|
|
3073
3219
|
// Don't try to reconnect for auth/client errors — show error directly
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type ReactNode } from "react";
|
|
2
|
-
export type AgentWorkspaceTab = "overview" | "resources" | "automations" | "agents"
|
|
2
|
+
export type AgentWorkspaceTab = "overview" | "resources" | "automations" | "agents";
|
|
3
3
|
export declare function AgentWorkspaceContent({ overview, className, activeTab, }: {
|
|
4
4
|
overview: ReactNode;
|
|
5
5
|
activeTab: AgentWorkspaceTab;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { IconBook2, IconBolt, IconChecklist, IconFolder, IconHierarchy2, IconHistory, IconNotes,
|
|
2
|
+
import { IconBook2, IconBolt, IconChecklist, IconFolder, IconHierarchy2, IconHistory, IconNotes, IconTopologyRing2, } from "@tabler/icons-react";
|
|
3
3
|
import { lazy, Suspense, useEffect, useState } from "react";
|
|
4
4
|
import { AgentsSection } from "../settings/AgentsSection.js";
|
|
5
5
|
import { cn } from "../utils.js";
|
|
@@ -21,7 +21,6 @@ const HUB_TABS = [
|
|
|
21
21
|
{ id: "resources", label: "Resources", icon: IconFolder },
|
|
22
22
|
{ id: "automations", label: "Automations", icon: IconBolt },
|
|
23
23
|
{ id: "agents", label: "Connected agents", icon: IconTopologyRing2 },
|
|
24
|
-
{ id: "access", label: "Access", icon: IconShieldLock },
|
|
25
24
|
];
|
|
26
25
|
const RESOURCE_IDS = new Set(RESOURCE_TABS.map((tab) => tab.id));
|
|
27
26
|
function normalizeHash(value) {
|
|
@@ -31,9 +30,15 @@ function initialHubState() {
|
|
|
31
30
|
if (typeof window === "undefined") {
|
|
32
31
|
return { tab: "overview", resource: "files" };
|
|
33
32
|
}
|
|
33
|
+
const pathParts = window.location.pathname.split("/").filter(Boolean);
|
|
34
|
+
const settingsIndex = pathParts.indexOf("settings");
|
|
35
|
+
const settingsPath = settingsIndex === -1 ? [] : pathParts.slice(settingsIndex + 1);
|
|
36
|
+
const routeParts = settingsPath[0] === "agent" ? settingsPath : ["agent", ...settingsPath];
|
|
34
37
|
const hash = normalizeHash(window.location.hash);
|
|
35
|
-
const
|
|
36
|
-
const
|
|
38
|
+
const hashParts = hash.split(":");
|
|
39
|
+
const pathScoped = settingsPath[0] === "agent";
|
|
40
|
+
const scoped = pathScoped || hashParts[0] === "agent";
|
|
41
|
+
const parts = pathScoped ? routeParts : hashParts;
|
|
37
42
|
const requested = scoped ? parts[1] : hash;
|
|
38
43
|
const resource = scoped && RESOURCE_IDS.has(parts[2])
|
|
39
44
|
? parts[2]
|
|
@@ -54,8 +59,6 @@ function initialHubState() {
|
|
|
54
59
|
requested === "remote-agents") {
|
|
55
60
|
return { tab: "agents", resource };
|
|
56
61
|
}
|
|
57
|
-
if (requested === "access")
|
|
58
|
-
return { tab: "access", resource };
|
|
59
62
|
return { tab: "overview", resource };
|
|
60
63
|
}
|
|
61
64
|
function ResourceContent({ resource }) {
|
|
@@ -65,8 +68,8 @@ function ResourceContent({ resource }) {
|
|
|
65
68
|
const selected = tab.id === resource;
|
|
66
69
|
return (_jsxs("button", { type: "button", onClick: () => {
|
|
67
70
|
if (typeof window !== "undefined") {
|
|
68
|
-
window.history.pushState(null, "",
|
|
69
|
-
window.dispatchEvent(new Event("
|
|
71
|
+
window.history.pushState(null, "", `/settings/agent/resources/${tab.id}${window.location.search}`);
|
|
72
|
+
window.dispatchEvent(new Event("popstate"));
|
|
70
73
|
}
|
|
71
74
|
}, className: cn("inline-flex shrink-0 items-center gap-1.5 rounded-md px-2.5 py-1.5 text-xs font-medium transition-colors", selected
|
|
72
75
|
? "bg-accent text-foreground"
|
|
@@ -75,9 +78,6 @@ function ResourceContent({ resource }) {
|
|
|
75
78
|
? "Add context the agent can use across conversations."
|
|
76
79
|
: "Manage the resources that shape how the agent works." })] }), _jsx(Suspense, { fallback: _jsx("div", { className: "h-48 animate-pulse rounded-xl border border-border bg-muted/20" }), children: _jsx(ResourcesPanel, { showMcpServers: false, resourceFilter: resource, resourceTreeVariant: "collection", scope: "personal" }, resource) })] }));
|
|
77
80
|
}
|
|
78
|
-
function AccessContent() {
|
|
79
|
-
return (_jsx("div", { children: _jsx("div", { className: "rounded-xl border border-border/70 bg-card text-card-foreground", children: _jsx("div", { className: "px-5 py-5 sm:px-6", children: _jsxs("div", { className: "flex items-start gap-3", children: [_jsx("span", { className: "flex size-9 shrink-0 items-center justify-center rounded-lg border border-border bg-background text-muted-foreground", children: _jsx(IconShieldLock, { className: "size-4" }) }), _jsxs("div", { className: "min-w-0", children: [_jsx("p", { className: "text-sm font-medium text-foreground", children: "Agent access" }), _jsx("p", { className: "mt-1 text-sm leading-5 text-muted-foreground", children: "Use the agent card and MCP endpoints from connected clients." })] })] }) }) }) }));
|
|
80
|
-
}
|
|
81
81
|
export function AgentWorkspaceContent({ overview, className, activeTab, }) {
|
|
82
82
|
const [{ resource }, setState] = useState(initialHubState);
|
|
83
83
|
useEffect(() => {
|
|
@@ -98,8 +98,8 @@ export function AgentWorkspaceContent({ overview, className, activeTab, }) {
|
|
|
98
98
|
? "Schedule and manage agent tasks."
|
|
99
99
|
: activeTab === "agents"
|
|
100
100
|
? "Connect agents to delegate work from chat."
|
|
101
|
-
: "
|
|
102
|
-
return (_jsxs("div", { className: cn("w-full space-y-6", className), children: [_jsxs("header", { className: "space-y-1", children: [_jsx("h1", { className: "text-2xl font-semibold tracking-tight text-foreground", children: activeTab === "overview" ? "Agent" : page?.label }), _jsx("p", { className: "text-sm leading-5 text-muted-foreground", children: pageDescription })] }), activeTab === "overview" && overview, activeTab === "resources" && _jsx(ResourceContent, { resource: resource }), activeTab === "automations" && (_jsx(Suspense, { fallback: _jsx("div", { className: "h-48 animate-pulse rounded-xl border border-border bg-muted/20" }), children: _jsx(AgentJobsTab, { scope: "user", canManageOrg: true, hideHeader: true }) })), activeTab === "agents" && _jsx(AgentsSection, {})
|
|
101
|
+
: "Configure how your agent works, what it knows, and what it can do.";
|
|
102
|
+
return (_jsxs("div", { className: cn("w-full space-y-6", className), children: [_jsxs("header", { className: "space-y-1", children: [_jsx("h1", { className: "text-2xl font-semibold tracking-tight text-foreground", children: activeTab === "overview" ? "Agent" : page?.label }), _jsx("p", { className: "text-sm leading-5 text-muted-foreground", children: pageDescription })] }), activeTab === "overview" && overview, activeTab === "resources" && _jsx(ResourceContent, { resource: resource }), activeTab === "automations" && (_jsx(Suspense, { fallback: _jsx("div", { className: "h-48 animate-pulse rounded-xl border border-border bg-muted/20" }), children: _jsx(AgentJobsTab, { scope: "user", canManageOrg: true, hideHeader: true }) })), activeTab === "agents" && _jsx(AgentsSection, {})] }));
|
|
103
103
|
}
|
|
104
104
|
export function agentWorkspaceTabHash(tab) {
|
|
105
105
|
return `agent:${tab}`;
|
|
@@ -8,6 +8,7 @@ type AssistantUiStaleIndexErrorBoundaryProps = {
|
|
|
8
8
|
/** Remount children when the recovery scope changes. */
|
|
9
9
|
remountOnResetKey?: boolean;
|
|
10
10
|
componentName?: string;
|
|
11
|
+
fallback?: React.ReactNode;
|
|
11
12
|
children: React.ReactNode;
|
|
12
13
|
};
|
|
13
14
|
type AssistantUiStaleIndexErrorBoundaryState = {
|
|
@@ -26,7 +27,7 @@ export declare class AssistantUiStaleIndexErrorBoundary extends React.Component<
|
|
|
26
27
|
componentDidCatch(error: unknown, info: React.ErrorInfo): void;
|
|
27
28
|
componentDidUpdate(prevProps: AssistantUiStaleIndexErrorBoundaryProps, prevState: AssistantUiStaleIndexErrorBoundaryState): void;
|
|
28
29
|
componentWillUnmount(): void;
|
|
29
|
-
render(): React.JSX.Element | null;
|
|
30
|
+
render(): string | number | bigint | boolean | React.JSX.Element | Iterable<React.ReactNode> | Promise<string | number | bigint | boolean | Iterable<React.ReactNode> | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | React.ReactPortal | null | undefined> | null;
|
|
30
31
|
}
|
|
31
32
|
export declare function AssistantMessageListErrorBoundary({ resetKey, children, }: {
|
|
32
33
|
resetKey: string;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { IconLoader2 } from "@tabler/icons-react";
|
|
2
3
|
import React from "react";
|
|
3
4
|
import { captureError } from "./analytics.js";
|
|
4
5
|
export function assistantUiRecoverableRenderErrorKind(error) {
|
|
@@ -114,7 +115,7 @@ export class AssistantUiStaleIndexErrorBoundary extends React.Component {
|
|
|
114
115
|
this.state.recovery.retryCount > MAX_ASSISTANT_UI_RECOVERABLE_RETRIES) {
|
|
115
116
|
throw this.state.error;
|
|
116
117
|
}
|
|
117
|
-
return null;
|
|
118
|
+
return this.props.fallback ?? null;
|
|
118
119
|
}
|
|
119
120
|
const fragmentKey = this.props.remountOnResetKey === false
|
|
120
121
|
? String(this.state.retryToken)
|
|
@@ -123,5 +124,8 @@ export class AssistantUiStaleIndexErrorBoundary extends React.Component {
|
|
|
123
124
|
}
|
|
124
125
|
}
|
|
125
126
|
export function AssistantMessageListErrorBoundary({ resetKey, children, }) {
|
|
126
|
-
return (_jsx(AssistantUiStaleIndexErrorBoundary, { resetKey: resetKey, remountOnResetKey: false, componentName: "AssistantMessageList", children: children }));
|
|
127
|
+
return (_jsx(AssistantUiStaleIndexErrorBoundary, { resetKey: resetKey, remountOnResetKey: false, componentName: "AssistantMessageList", fallback: _jsx(AssistantUiRecoverableRenderFallback, {}), children: children }));
|
|
128
|
+
}
|
|
129
|
+
function AssistantUiRecoverableRenderFallback() {
|
|
130
|
+
return (_jsxs("div", { "aria-label": "Updating chat", className: "flex min-h-8 items-center justify-center text-muted-foreground", role: "status", children: [_jsx(IconLoader2, { className: "size-3.5 animate-spin", "aria-hidden": "true" }), _jsx("span", { className: "sr-only", children: "Updating chat..." })] }));
|
|
127
131
|
}
|
|
@@ -227,7 +227,11 @@ export function RunErrorRecoveryCard({ info, onContinue, onRetry, onFork, onDism
|
|
|
227
227
|
const canRecover = info.recoverable === true;
|
|
228
228
|
const shouldShowBuilderReconnect = isBuilderReconnectRunError(info);
|
|
229
229
|
const isProviderAuthError = isProviderAuthenticationError([info.message, info.details].filter(Boolean).join("\n"), info.errorCode);
|
|
230
|
-
|
|
230
|
+
// Blocked on something the reader goes and fixes elsewhere, then comes back
|
|
231
|
+
// to. Without a retry the card is a dead end and its own copy ("then retry")
|
|
232
|
+
// points at a button that isn't there.
|
|
233
|
+
const isUnblockableExternally = info.errorCode === "email_verification_required";
|
|
234
|
+
const canRetry = canRecover || isProviderAuthError || isUnblockableExternally;
|
|
231
235
|
const builderReconnectResolved = shouldShowBuilderReconnect &&
|
|
232
236
|
builderReconnect.hasFetchedStatus &&
|
|
233
237
|
builderReconnect.configured;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { EMBED_MODE_QUERY_PARAM, EMBED_START_PATH, EMBED_TARGET_HEADER, EMBED_TARGET_QUERY_PARAM, EMBED_TOKEN_QUERY_PARAM, MCP_APP_CHAT_BRIDGE_QUERY_PARAM, } from "../shared/embed-auth.js";
|
|
2
|
+
import { SIGN_IN_ENTRY_PATH, SIGN_IN_LEGACY_ENTRY_PATH, } from "../shared/sign-in-journey.js";
|
|
2
3
|
let installed = false;
|
|
3
4
|
let memoryToken = null;
|
|
4
5
|
let mcpChatBridgeActive = false;
|
|
@@ -322,9 +323,12 @@ function shouldGuardAuthFailure(method, url) {
|
|
|
322
323
|
if (url.pathname === EMBED_START_PATH)
|
|
323
324
|
return false;
|
|
324
325
|
// Suffix, not equality: an app mounted under a base path serves
|
|
325
|
-
// `/<app>/
|
|
326
|
-
|
|
326
|
+
// `/<app>/sign-in` (or the legacy framework path), which an exact match
|
|
327
|
+
// would miss.
|
|
328
|
+
if (url.pathname.endsWith(SIGN_IN_ENTRY_PATH) ||
|
|
329
|
+
url.pathname.endsWith(SIGN_IN_LEGACY_ENTRY_PATH)) {
|
|
327
330
|
return false;
|
|
331
|
+
}
|
|
328
332
|
return true;
|
|
329
333
|
}
|
|
330
334
|
function activeAuthFailure(record) {
|
|
@@ -100,6 +100,18 @@ export function normalizeChatError(errorMessage, errorCode) {
|
|
|
100
100
|
details: text,
|
|
101
101
|
};
|
|
102
102
|
}
|
|
103
|
+
// Reaches us as a bare gateway 403 with no upgradeUrl, so before this case
|
|
104
|
+
// it fell all the way through to the raw upstream sentence under a generic
|
|
105
|
+
// "The agent hit an error" headline, with no retry and no action — a dead
|
|
106
|
+
// end. It was the single largest cause of turns ending without an answer in
|
|
107
|
+
// one app, and reads to the user as the chat being broken rather than as
|
|
108
|
+
// something one person can fix in a minute.
|
|
109
|
+
if (code === "email_verification_required") {
|
|
110
|
+
return {
|
|
111
|
+
message: "AI is paused until an email address in this workspace is verified. Check the inbox for the verification link, then retry.",
|
|
112
|
+
details: text,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
103
115
|
// A model/parameter combination this provider will never accept. Retrying is
|
|
104
116
|
// pointless and the raw sentence names an API surface the reader has no way
|
|
105
117
|
// to act on, so say what they can actually change.
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { IconPlus, IconBrandSlack, IconBrandTelegram, IconBrandWhatsapp, IconBrandGoogleDrive, IconTerminal2, IconBuildingSkyscraper, IconCopy, IconCheck, IconChevronLeft, IconChevronRight, IconExternalLink, IconCircleCheck, IconInfoCircle, IconSearch, IconServer, } from "@tabler/icons-react";
|
|
2
|
+
import { IconPlus, IconBrandSlack, IconBrandTelegram, IconBrandWhatsapp, IconBrandGoogleDrive, IconTerminal2, IconBuildingSkyscraper, IconCopy, IconCheck, IconChevronLeft, IconChevronRight, IconExternalLink, IconCircleCheck, IconInfoCircle, IconSearch, IconServer, IconLoader2, IconRefresh, } from "@tabler/icons-react";
|
|
3
3
|
import { useState, useCallback, useEffect, useMemo } from "react";
|
|
4
4
|
import { agentNativePath } from "../api-path.js";
|
|
5
5
|
import { Tooltip, TooltipContent, TooltipTrigger, } from "../components/ui/tooltip.js";
|
|
6
6
|
import { useT } from "../i18n.js";
|
|
7
7
|
import { getDefaultMcpIntegrations, } from "../resources/mcp-integration-catalog.js";
|
|
8
8
|
import { McpIntegrationDialog } from "../resources/McpIntegrationDialog.js";
|
|
9
|
-
import { useCreateMcpServer, useDeleteMcpServer, useMcpServers, } from "../resources/use-mcp-servers.js";
|
|
9
|
+
import { useCreateMcpServer, useDeleteMcpServer, useMcpServers, useReconnectMcpServer, } from "../resources/use-mcp-servers.js";
|
|
10
10
|
import { useIntegrationStatus, } from "./useIntegrationStatus.js";
|
|
11
11
|
import { isNonPublicWebhookUrl } from "./webhook-url.js";
|
|
12
12
|
const PLATFORMS = [
|
|
@@ -257,12 +257,19 @@ function McpLogo({ integration }) {
|
|
|
257
257
|
const [failed, setFailed] = useState(false);
|
|
258
258
|
return (_jsx("span", { className: "flex size-9 shrink-0 items-center justify-center overflow-hidden rounded-lg border border-border/70 bg-background text-xs font-semibold text-muted-foreground", children: failed ? (integration.name.slice(0, 1)) : (_jsx("img", { src: integration.logoUrl, alt: "", loading: "lazy", decoding: "async", className: "size-7 object-contain", onError: () => setFailed(true) })) }));
|
|
259
259
|
}
|
|
260
|
-
function McpServerStatus({ server }) {
|
|
260
|
+
function McpServerStatus({ server, onReconnect, reconnecting = false, reconnectError, }) {
|
|
261
|
+
const t = useT();
|
|
261
262
|
if (server.status.state === "connected") {
|
|
262
263
|
return (_jsxs("span", { className: "inline-flex items-center gap-1.5 text-xs text-emerald-600 dark:text-emerald-400", children: [_jsx("span", { className: "size-1.5 rounded-full bg-emerald-500" }), "Connected \u00B7 ", server.status.toolCount, " tool", server.status.toolCount === 1 ? "" : "s"] }));
|
|
263
264
|
}
|
|
264
265
|
if (server.status.state === "error") {
|
|
265
|
-
return (_jsxs("
|
|
266
|
+
return (_jsxs("div", { className: "flex min-w-0 flex-1 flex-col gap-2 sm:flex-row sm:items-start sm:justify-between", children: [_jsxs("div", { className: "min-w-0", children: [_jsxs("div", { className: "inline-flex items-center gap-1.5 text-xs text-destructive", children: [_jsx("span", { className: "size-1.5 rounded-full bg-destructive" }), t("mcpIntegrations.connectionError")] }), _jsx("p", { className: "mt-1 max-w-3xl break-words text-xs leading-5 text-destructive/85", children: t("mcpIntegrations.connectionErrorReason", {
|
|
267
|
+
reason: server.status.error,
|
|
268
|
+
}) }), reconnectError && (_jsx("p", { className: "mt-1 break-words text-xs leading-5 text-destructive", children: t("mcpIntegrations.reconnectFailed", {
|
|
269
|
+
error: reconnectError,
|
|
270
|
+
}) }))] }), onReconnect && (_jsxs("button", { type: "button", onClick: onReconnect, disabled: reconnecting, className: "inline-flex shrink-0 items-center gap-1.5 rounded-md border border-border bg-background px-2.5 py-1.5 text-xs font-medium text-foreground transition-colors hover:bg-accent disabled:cursor-wait disabled:opacity-60", children: [reconnecting ? (_jsx(IconLoader2, { className: "size-3.5 animate-spin" })) : (_jsx(IconRefresh, { className: "size-3.5" })), reconnecting
|
|
271
|
+
? t("mcpIntegrations.reconnecting")
|
|
272
|
+
: t("mcpIntegrations.reconnect")] }))] }));
|
|
266
273
|
}
|
|
267
274
|
return (_jsxs("span", { className: "inline-flex items-center gap-1.5 text-xs text-muted-foreground", children: [_jsx("span", { className: "size-1.5 rounded-full bg-muted-foreground/50" }), "Status unknown"] }));
|
|
268
275
|
}
|
|
@@ -273,10 +280,13 @@ function McpIntegrationsSection({ query }) {
|
|
|
273
280
|
const serversQuery = useMcpServers();
|
|
274
281
|
const createServer = useCreateMcpServer();
|
|
275
282
|
const deleteServer = useDeleteMcpServer();
|
|
283
|
+
const reconnectServer = useReconnectMcpServer();
|
|
276
284
|
const [dialogOpen, setDialogOpen] = useState(false);
|
|
277
285
|
const [initialIntegrationId, setInitialIntegrationId] = useState(null);
|
|
278
286
|
const [deleteTarget, setDeleteTarget] = useState(null);
|
|
279
287
|
const [deleteError, setDeleteError] = useState(null);
|
|
288
|
+
const [reconnectingKey, setReconnectingKey] = useState(null);
|
|
289
|
+
const [reconnectError, setReconnectError] = useState(null);
|
|
280
290
|
const catalog = useMemo(() => getDefaultMcpIntegrations(), []);
|
|
281
291
|
const normalizedQuery = query.trim().toLowerCase();
|
|
282
292
|
const filteredCatalog = useMemo(() => {
|
|
@@ -318,14 +328,38 @@ function McpIntegrationsSection({ query }) {
|
|
|
318
328
|
: "Could not remove agent integration.");
|
|
319
329
|
}
|
|
320
330
|
}, [deleteServer, deleteTarget]);
|
|
331
|
+
const reconnect = useCallback(async (server) => {
|
|
332
|
+
const key = `${server.scope}:${server.id}`;
|
|
333
|
+
setReconnectingKey(key);
|
|
334
|
+
setReconnectError(null);
|
|
335
|
+
try {
|
|
336
|
+
await reconnectServer.mutateAsync({
|
|
337
|
+
id: server.id,
|
|
338
|
+
scope: server.scope,
|
|
339
|
+
});
|
|
340
|
+
}
|
|
341
|
+
catch (error) {
|
|
342
|
+
setReconnectError({
|
|
343
|
+
key,
|
|
344
|
+
message: error instanceof Error ? error.message : String(error),
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
finally {
|
|
348
|
+
setReconnectingKey(null);
|
|
349
|
+
}
|
|
350
|
+
}, [reconnectServer]);
|
|
321
351
|
return (_jsxs("section", { "data-testid": "mcp-integrations", className: "space-y-5", children: [_jsxs("div", { className: "flex flex-col gap-3 sm:flex-row sm:items-end sm:justify-between", children: [_jsxs("div", { children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(IconServer, { className: "size-4 text-muted-foreground" }), _jsx("h2", { className: "text-sm font-semibold text-foreground", children: "Agent integrations" })] }), _jsx("p", { className: "mt-1 text-xs leading-5 text-muted-foreground", children: "Give your agent tools and context from the services you use." })] }), _jsxs("button", { type: "button", onClick: () => openCatalog(), className: "inline-flex w-fit items-center gap-1.5 rounded-md bg-primary px-3 py-1.5 text-xs font-medium text-primary-foreground transition-colors hover:bg-primary/90", children: [_jsx(IconPlus, { className: "size-3.5" }), "Add integration"] })] }), deleteError && (_jsx("p", { className: "border-y border-destructive/20 bg-destructive/5 py-3 text-xs text-destructive", children: deleteError })), serversQuery.isError ? (_jsx("p", { className: "border-y border-destructive/20 bg-destructive/5 py-3 text-xs text-destructive", children: "Could not load connected agent integrations. The catalog is still available." })) : serversQuery.isLoading ? (_jsxs("div", { className: "space-y-3 rounded-xl border border-border/70 bg-card px-4 py-4", children: [_jsx("div", { className: "h-5 w-1/2 animate-pulse rounded bg-muted" }), _jsx("div", { className: "h-5 w-3/4 animate-pulse rounded bg-muted" })] })) : servers.length > 0 && !normalizedQuery ? (_jsxs("section", { className: "space-y-2", children: [_jsx("h3", { className: "text-sm font-semibold text-foreground", children: "Installed" }), _jsx("div", { className: "overflow-hidden rounded-xl border border-border/70 bg-card text-card-foreground", children: _jsx("div", { className: "divide-y divide-border/60 px-4", children: servers.map((server) => {
|
|
322
352
|
const key = `${server.scope}:${server.id}`;
|
|
323
353
|
const canRemove = server.scope === "user" ||
|
|
324
354
|
serversQuery.data?.role === "owner" ||
|
|
325
355
|
serversQuery.data?.role === "admin";
|
|
326
|
-
return (_jsxs("div", { className: "flex items-
|
|
356
|
+
return (_jsxs("div", { className: "flex items-start gap-3 py-3.5", children: [_jsx("span", { className: "mt-0.5 flex size-9 shrink-0 items-center justify-center rounded-lg border border-border/70 bg-background text-muted-foreground", children: _jsx(IconServer, { className: "size-4" }) }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [_jsx("span", { className: "truncate text-sm font-medium text-foreground", children: server.name }), _jsx("span", { className: "text-[11px] text-muted-foreground", children: server.scope === "user"
|
|
327
357
|
? "Personal"
|
|
328
|
-
: "Organization" })] }), _jsx(McpServerStatus, { server: server
|
|
358
|
+
: "Organization" })] }), _jsx(McpServerStatus, { server: server, onReconnect: server.status.state === "error"
|
|
359
|
+
? () => void reconnect(server)
|
|
360
|
+
: undefined, reconnecting: reconnectingKey === key, reconnectError: reconnectError?.key === key
|
|
361
|
+
? reconnectError.message
|
|
362
|
+
: undefined })] }), canRemove && (_jsx("button", { type: "button", onClick: () => void removeServer(server), disabled: deleteServer.isPending, className: "shrink-0 rounded-md border border-border px-2.5 py-1.5 text-xs font-medium text-foreground transition-colors hover:bg-accent disabled:opacity-50", children: deleteTarget === key ? "Confirm" : "Remove" }))] }, key));
|
|
329
363
|
}) }) })] })) : null, filteredCatalog.length > 0 && (_jsxs("div", { children: [_jsxs("div", { className: "mb-1 flex items-center justify-between gap-3", children: [_jsx("h3", { className: "text-sm font-semibold text-foreground", children: "Available integrations" }), _jsxs("span", { className: "text-xs text-muted-foreground", children: [filteredCatalog.length, " integrations"] })] }), _jsx("div", { className: "grid gap-x-8 overflow-hidden rounded-xl border border-border/70 bg-card px-4 sm:grid-cols-2", children: filteredCatalog.map((integration) => (_jsx(McpCatalogItem, { integration: integration, connected: connectedUrls.has(compareMcpUrl(integration.url)), onConnect: openCatalog }, integration.id))) })] })), filteredCatalog.length === 0 && normalizedQuery && (_jsxs("p", { className: "border-y border-border/60 py-4 text-xs text-muted-foreground", children: ["No agent integrations match \u201C", query, "\u201D."] })), _jsx(McpIntegrationDialog, { open: dialogOpen, onOpenChange: setDialogOpen, initialIntegrationId: initialIntegrationId, defaultScope: "user", canCreateOrgMcp: canCreateOrgMcp, hasOrg: hasOrg, onCreateMcpServer: (args) => createServer.mutateAsync(args) })] }));
|
|
330
364
|
}
|
|
331
365
|
export function IntegrationsPanel() {
|
|
@@ -4,7 +4,7 @@ import { IconArrowRight, IconBrandGithub, IconCheck, IconExternalLink, IconInfoC
|
|
|
4
4
|
import React, { useMemo, useState } from "react";
|
|
5
5
|
import { appPath } from "../api-path.js";
|
|
6
6
|
import { Tooltip, TooltipContent, TooltipTrigger, } from "../components/ui/tooltip.js";
|
|
7
|
-
import { buildMcpOAuthStartUrl, filterMcpIntegrations, getDefaultMcpIntegrations, navigateToMcpOAuthStart, } from "../resources/mcp-integration-catalog.js";
|
|
7
|
+
import { buildMcpOAuthStartUrl, filterMcpIntegrations, getDefaultMcpIntegrations, navigateToMcpOAuthStart, shouldOfferMcpIntegrationOrganizationScope, } from "../resources/mcp-integration-catalog.js";
|
|
8
8
|
import { McpIntegrationDialog } from "../resources/McpIntegrationDialog.js";
|
|
9
9
|
import { formatMcpServerError, useCreateMcpServer, useMcpServers, } from "../resources/use-mcp-servers.js";
|
|
10
10
|
import { useBuilderConnectFlow } from "../settings/useBuilderStatus.js";
|
|
@@ -112,6 +112,10 @@ export function FirstRunOnboarding({ skipIntegrations = shouldSkipFirstRunIntegr
|
|
|
112
112
|
connectingIntegrationId === integration.id) {
|
|
113
113
|
return;
|
|
114
114
|
}
|
|
115
|
+
if (shouldOfferMcpIntegrationOrganizationScope(integration, hasOrg, canCreateOrgMcp)) {
|
|
116
|
+
setIntegrationDialogId(integration.id);
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
115
119
|
if (integration.authMode === "none" &&
|
|
116
120
|
integration.connectionMode === "direct") {
|
|
117
121
|
setConnectingIntegrationId(integration.id);
|
|
@@ -165,7 +169,7 @@ export function FirstRunOnboarding({ skipIntegrations = shouldSkipFirstRunIntegr
|
|
|
165
169
|
return (_jsx(OnboardingShell, { profile: profile, screen: "intro", children: _jsxs("div", { className: "mx-auto flex w-full max-w-lg flex-col items-center text-center", children: [_jsxs("h1", { className: "text-3xl font-semibold tracking-[-0.05em] sm:text-4xl", children: ["Free forever.", _jsx("br", {}), _jsx("span", { className: "text-primary", children: "Open source for life." })] }), _jsxs("div", { className: "mt-7 grid w-full gap-2 text-left sm:grid-cols-3", children: [_jsxs("div", { className: "rounded-lg border border-border bg-card px-3 py-3", children: [_jsx("p", { className: "text-xs font-medium", children: "Fully customizable" }), _jsx("p", { className: "mt-1 text-[11px] leading-4 text-muted-foreground", children: "Change the UI, code, and behavior." })] }), _jsxs("div", { className: "rounded-lg border border-border bg-card px-3 py-3", children: [_jsx("p", { className: "text-xs font-medium", children: "Bring your own keys" }), _jsx("p", { className: "mt-1 text-[11px] leading-4 text-muted-foreground", children: "Use your own providers and accounts." })] }), _jsxs("div", { className: "rounded-lg border border-border bg-card px-3 py-3", children: [_jsx("p", { className: "text-xs font-medium", children: "Build your own" }), _jsx("p", { className: "mt-1 text-[11px] leading-4 text-muted-foreground", children: "Mix and match toolkit pieces in your own apps." })] })] }), _jsxs("button", { type: "button", className: cn(primaryButtonClass, "mt-6"), onClick: () => setScreen("choice"), children: ["Continue", _jsx(IconArrowRight, { size: 15 })] }), _jsxs("a", { href: "https://github.com/builderio/agent-native", target: "_blank", rel: "noreferrer", className: "mt-3 inline-flex items-center gap-1.5 text-xs text-muted-foreground transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", children: [_jsx(IconBrandGithub, { size: 14 }), _jsx("span", { children: "View source" }), _jsx(IconExternalLink, { size: 13 })] })] }) }));
|
|
166
170
|
}
|
|
167
171
|
if (screen === "choice") {
|
|
168
|
-
return (_jsx(OnboardingShell, { profile: profile, screen: "choice", children: _jsxs("div", { className: "mx-auto flex w-full max-w-3xl flex-col gap-4", children: [_jsx("h1", { className: "text-center text-xl font-semibold tracking-[-0.04em] sm:text-2xl", children: "Choose your setup." }), _jsxs("div", { className: "grid gap-3 sm:grid-cols-2", children: [_jsxs("section", { className: "rounded-xl border border-primary/50 bg-primary/[0.06] p-4 shadow-sm", children: [_jsxs("div", { className: "flex items-start justify-between gap-3", children: [_jsxs("div", { children: [_jsx("h2", { className: "text-sm font-semibold", children: "Connect Builder.io free credits" }), _jsxs("p", { className: "mt-1 max-w-xs text-xs leading-5 text-muted-foreground", children: ["One click connects", " ", _jsx("a", { href: "https://www.builder.io/", target: "_blank", rel: "noreferrer", className: "text-foreground underline decoration-border underline-offset-2 hover:decoration-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", children: "Builder.io free credits" }), " ", "with the services this app needs."] })] }), _jsx(IconArrowRight, { className: "mt-0.5 text-primary", size: 17 })] }), _jsxs("div", { className: "mt-5 border-t border-primary/15 pt-3", children: [_jsx("p", { className: "text-[11px] font-medium text-muted-foreground", children: "Included with Builder.io free credits" }), _jsxs("div", { className: "mt-2 flex flex-wrap items-center gap-x-1.5 gap-y-1 text-[11px]", children: [builderCapabilities.map((capability, index) => (_jsxs(React.Fragment, { children: [index > 0 && (_jsx("span", { "aria-hidden": "true", className: "text-muted-foreground", children: "\u00B7" })), _jsx("span", { children: capability.label })] }, capability.id))), _jsx("span", { "aria-hidden": "true", className: "text-muted-foreground", children: "\u00B7" }), _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsxs("button", { type: "button", className: "text-primary underline-offset-2 hover:underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", "aria-label": `See ${BUILDER_MORE_SERVICES.length} more services included with Builder.io free credits`, children: ["+", BUILDER_MORE_SERVICES.length, " more"] }) }), _jsxs(TooltipContent, { side: "top", className: "max-w-sm text-xs", children: [_jsx("p", { className: "font-medium", children: "Also included with Builder.io free credits" }), _jsx("p", { className: "mt-1 leading-5", children: BUILDER_MORE_SERVICES.join(" · ") })] })] })] })] }), _jsxs("button", { type: "button", "data-testid": "first-run-connect-builder", className: cn(primaryButtonClass, "mt-5 w-full"), onClick: handleBuilder, children: ["Connect Builder.io free credits", _jsx(IconArrowRight, { size: 15 })] })] }), _jsxs("div", { role: "button", tabIndex: 0, "aria-label": "Use my own keys", "data-testid": "first-run-use-own-keys", className: "rounded-xl border border-border bg-card p-4 text-left transition-colors hover:border-foreground/30 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", onClick: () => setScreen("manual"), onKeyDown: (event) => {
|
|
172
|
+
return (_jsx(OnboardingShell, { profile: profile, screen: "choice", children: _jsxs("div", { className: "mx-auto flex w-full max-w-3xl flex-col gap-4", children: [_jsx("h1", { className: "text-center text-xl font-semibold tracking-[-0.04em] sm:text-2xl", children: "Choose your setup." }), _jsxs("div", { className: "grid gap-3 sm:grid-cols-2", children: [_jsxs("section", { className: "rounded-xl border border-primary/50 bg-primary/[0.06] p-4 shadow-sm", children: [_jsxs("div", { className: "flex items-start justify-between gap-3", children: [_jsxs("div", { children: [_jsx("h2", { className: "text-sm font-semibold", children: "Connect Builder.io free credits" }), _jsxs("p", { className: "mt-1 max-w-xs text-xs leading-5 text-muted-foreground", children: ["One click connects", " ", _jsx("a", { href: "https://www.builder.io/", target: "_blank", rel: "noreferrer", className: "text-foreground underline decoration-border underline-offset-2 hover:decoration-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", children: "Builder.io free credits" }), " ", "with the services this app needs."] })] }), _jsx(IconArrowRight, { className: "mt-0.5 text-primary", size: 17 })] }), _jsxs("div", { className: "mt-5 border-t border-primary/15 pt-3", children: [_jsx("p", { className: "text-[11px] font-medium text-muted-foreground", children: "Included with Builder.io free credits" }), _jsxs("div", { className: "mt-2 flex flex-wrap items-center gap-x-1.5 gap-y-1 text-[11px]", children: [builderCapabilities.map((capability, index) => (_jsxs(React.Fragment, { children: [index > 0 && (_jsx("span", { "aria-hidden": "true", className: "text-muted-foreground", children: "\u00B7" })), _jsxs("span", { className: "inline-flex items-center gap-0.5", children: [_jsx("span", { children: capability.label }), capability.id === "design-system-intelligence" && (_jsx(CapabilityInfoButton, { capability: capability, ariaLabel: `About ${capability.label}` }))] })] }, capability.id))), _jsx("span", { "aria-hidden": "true", className: "text-muted-foreground", children: "\u00B7" }), _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsxs("button", { type: "button", className: "text-primary underline-offset-2 hover:underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", "aria-label": `See ${BUILDER_MORE_SERVICES.length} more services included with Builder.io free credits`, children: ["+", BUILDER_MORE_SERVICES.length, " more"] }) }), _jsxs(TooltipContent, { side: "top", className: "max-w-sm text-xs", children: [_jsx("p", { className: "font-medium", children: "Also included with Builder.io free credits" }), _jsx("p", { className: "mt-1 leading-5", children: BUILDER_MORE_SERVICES.join(" · ") })] })] })] })] }), _jsxs("button", { type: "button", "data-testid": "first-run-connect-builder", className: cn(primaryButtonClass, "mt-5 w-full"), onClick: handleBuilder, children: ["Connect Builder.io free credits", _jsx(IconArrowRight, { size: 15 })] })] }), _jsxs("div", { role: "button", tabIndex: 0, "aria-label": "Use my own keys", "data-testid": "first-run-use-own-keys", className: "rounded-xl border border-border bg-card p-4 text-left transition-colors hover:border-foreground/30 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", onClick: () => setScreen("manual"), onKeyDown: (event) => {
|
|
169
173
|
if (event.key !== "Enter" && event.key !== " ")
|
|
170
174
|
return;
|
|
171
175
|
event.preventDefault();
|
|
@@ -179,7 +183,7 @@ export function FirstRunOnboarding({ skipIntegrations = shouldSkipFirstRunIntegr
|
|
|
179
183
|
return (_jsxs(OnboardingShell, { profile: profile, screen: "tools", footer: _jsxs("div", { "data-testid": "onboarding-tools-footer", className: "mx-auto flex w-full max-w-3xl flex-wrap items-center justify-end gap-2", children: [_jsx("button", { type: "button", className: secondaryButtonClass, onClick: handleFinish, children: "Skip for now" }), _jsxs("button", { type: "button", className: primaryButtonClass, onClick: handleFinish, children: ["Continue", _jsx(IconArrowRight, { size: 15 })] })] }), children: [_jsxs("div", { className: "mx-auto flex w-full max-w-4xl flex-col gap-5", children: [_jsxs("div", { className: "text-center", children: [_jsx("div", { className: "mx-auto flex size-11 items-center justify-center rounded-2xl bg-primary/10 text-primary", children: _jsx(IconPlugConnected, { size: 22 }) }), _jsx("h1", { className: "mt-5 text-2xl font-semibold tracking-[-0.05em] sm:text-3xl", children: "This app is an agent." }), _jsx("p", { className: "mt-3 text-sm leading-6 text-muted-foreground", children: "Search the catalog and connect what you need. The onboarding stays open while you add integrations." })] }), _jsxs("div", { className: "flex flex-col gap-4", children: [_jsxs("div", { className: "flex flex-col gap-3 border-b border-border pb-4", children: [_jsxs("div", { className: "flex items-center justify-between gap-3", children: [_jsx("p", { className: "text-sm font-medium text-foreground", children: "Agent integrations" }), _jsxs("span", { className: "text-xs text-muted-foreground", children: [mcpIntegrations.length, " of ", mcpCatalog.length] })] }), _jsxs("label", { className: "relative", children: [_jsx(IconSearch, { className: "pointer-events-none absolute start-3 top-1/2 h-3.5 w-3.5 -translate-y-1/2 text-muted-foreground" }), _jsx("input", { value: integrationQuery, onChange: (event) => setIntegrationQuery(event.target.value), className: "h-9 w-full rounded-md border border-border bg-background pe-3 ps-8 text-[13px] text-foreground outline-none placeholder:text-muted-foreground/50 focus:ring-1 focus:ring-ring", placeholder: "Search integrations", "aria-label": "Search integrations" })] }), connectError && (_jsx("p", { className: "text-xs leading-5 text-destructive", children: connectError }))] }), _jsx("div", { children: mcpIntegrations.length > 0 ? (_jsx("div", { className: "grid gap-x-8 sm:grid-cols-2", children: mcpIntegrations.map((integration) => (_jsx(McpIntegrationCard, { integration: integration, connected: connectedUrls.has(compareUrl(integration.url)), busy: connectingIntegrationId === integration.id, onConnect: connectIntegration }, integration.id))) })) : (_jsx("div", { className: "border-y border-dashed border-border px-4 py-8 text-center text-xs text-muted-foreground", children: "No integrations match." })) })] })] }), integrationDialogId && (_jsx(McpIntegrationDialog, { open: true, onOpenChange: (open) => {
|
|
180
184
|
if (!open)
|
|
181
185
|
setIntegrationDialogId(null);
|
|
182
|
-
}, initialIntegrationId: integrationDialogId, defaultScope:
|
|
186
|
+
}, initialIntegrationId: integrationDialogId, defaultScope: "user", canCreateOrgMcp: canCreateOrgMcp, hasOrg: hasOrg, onCreateMcpServer: createMcpServer.mutateAsync }))] }));
|
|
183
187
|
}
|
|
184
188
|
if (screen === "connecting") {
|
|
185
189
|
return (_jsx(OnboardingShell, { profile: profile, screen: "choice", children: _jsxs("div", { className: "mx-auto flex w-full max-w-md flex-col items-center text-center", children: [_jsx("div", { className: "flex size-10 items-center justify-center rounded-full bg-primary/10 text-primary", children: _jsx(IconLoader2, { className: "animate-spin", size: 19 }) }), _jsx("h1", { className: "mt-5 text-xl font-semibold tracking-[-0.04em]", children: "Connecting Builder.io free credits" }), _jsx("p", { className: "mt-2 text-sm text-muted-foreground", children: "Finish the one-click connection in the new window." }), _jsxs("div", { className: "mt-7 w-full rounded-xl border border-border bg-card p-4 text-left", children: [_jsxs("div", { className: "flex items-center justify-between gap-3", children: [_jsx(Skeleton, { className: "h-3 w-28" }), _jsx(Skeleton, { className: "h-5 w-16 rounded-full" })] }), _jsx(Skeleton, { className: "mt-4 h-8 w-full" }), _jsxs("div", { className: "mt-3 grid grid-cols-3 gap-2", children: [_jsx(Skeleton, { className: "h-7 w-full" }), _jsx(Skeleton, { className: "h-7 w-full" }), _jsx(Skeleton, { className: "h-7 w-full" })] })] }), connectFlow.error && (_jsxs("div", { className: "mt-4 flex flex-col items-center gap-2", children: [_jsx("p", { className: "text-xs text-destructive", children: connectFlow.error }), _jsx("button", { type: "button", className: secondaryButtonClass, onClick: () => setScreen("choice"), children: "Try again" })] }))] }) }));
|
|
@@ -231,7 +235,10 @@ function McpIntegrationCard({ integration, connected, busy, onConnect, }) {
|
|
|
231
235
|
} })] }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("h3", { className: "truncate text-sm font-medium text-foreground", children: integration.name }), connected ? (_jsx("span", { className: "rounded-full border border-border bg-muted px-2 py-0.5 text-[10px] font-medium text-muted-foreground", children: "Connected" })) : null] }), _jsx("p", { className: "mt-1 line-clamp-2 text-[11px] leading-4 text-muted-foreground", children: integration.description })] })] }), _jsxs("button", { type: "button", onClick: () => onConnect(integration), disabled: connected || busy, "aria-label": `${actionLabel} ${integration.name}`, className: "inline-flex min-h-8 shrink-0 items-center justify-center gap-1.5 rounded-md border border-border bg-background px-3 text-[11px] font-medium text-foreground transition-colors hover:bg-accent focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50", children: [busy ? _jsx(IconLoader2, { className: "animate-spin", size: 13 }) : null, connected ? "Connected" : actionLabel] })] }));
|
|
232
236
|
}
|
|
233
237
|
function CapabilityRow({ capability, compact, }) {
|
|
234
|
-
return (_jsxs("div", { className: cn("flex items-start justify-between gap-3", compact ? "py-2" : "py-3"), children: [_jsxs("div", { className: "min-w-0", children: [_jsxs("div", { className: "flex items-center gap-1.5", children: [_jsx("span", { className: cn("font-medium", compact ? "text-[11px]" : "text-sm"), children: capability.label }),
|
|
238
|
+
return (_jsxs("div", { className: cn("flex items-start justify-between gap-3", compact ? "py-2" : "py-3"), children: [_jsxs("div", { className: "min-w-0", children: [_jsxs("div", { className: "flex items-center gap-1.5", children: [_jsx("span", { className: cn("font-medium", compact ? "text-[11px]" : "text-sm"), children: capability.label }), _jsx(CapabilityInfoButton, { capability: capability, ariaLabel: `Why ${capability.label} is needed` })] }), _jsx("p", { className: "mt-1 text-[11px] leading-4 text-muted-foreground", children: capability.keySummary })] }), _jsx("span", { className: cn("shrink-0 text-[10px] uppercase tracking-[0.08em]", capability.required ? "text-primary" : "text-muted-foreground"), children: capability.required ? "Required" : "Optional" })] }));
|
|
239
|
+
}
|
|
240
|
+
function CapabilityInfoButton({ capability, ariaLabel, }) {
|
|
241
|
+
return (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { type: "button", "aria-label": ariaLabel, className: "inline-flex size-4 items-center justify-center rounded-full text-muted-foreground hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", onClick: (event) => event.stopPropagation(), onKeyDown: (event) => event.stopPropagation(), children: _jsx(IconInfoCircle, { size: 13 }) }) }), _jsx(TooltipContent, { side: "top", className: "max-w-xs text-xs", children: capability.why })] }));
|
|
235
242
|
}
|
|
236
243
|
const primaryButtonClass = "inline-flex min-h-9 items-center justify-center gap-2 rounded-lg bg-primary px-4 text-xs font-medium text-primary-foreground shadow-sm transition-opacity hover:opacity-90 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring";
|
|
237
244
|
const secondaryButtonClass = "inline-flex min-h-9 items-center justify-center gap-2 rounded-lg border border-border bg-background px-4 text-xs font-medium text-foreground transition-colors hover:bg-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring";
|
|
@@ -30,8 +30,8 @@ const SECTION_LABEL_CLASS = "px-2.5 pt-1 pb-0.5 text-[10px] uppercase tracking-w
|
|
|
30
30
|
const APP_SUBMENU_CONTENT_CLASS = "z-50 w-72 rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2";
|
|
31
31
|
const SWITCHER_BUTTON_CLASS = "flex w-full items-center gap-2 rounded-md border-0 bg-accent/50 px-2.5 py-1.5 text-xs font-medium text-muted-foreground hover:bg-accent/70 hover:text-foreground focus:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-60 cursor-pointer";
|
|
32
32
|
const COMPACT_SWITCHER_BUTTON_CLASS = "flex items-center justify-center rounded-md border-0 bg-accent/50 p-1.5 text-muted-foreground hover:bg-accent/70 hover:text-foreground focus:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-60 cursor-pointer";
|
|
33
|
-
const DEFAULT_ORGANIZATION_SETTINGS_PATH = "/settings
|
|
34
|
-
const DEFAULT_PROFILE_PATH = "/settings
|
|
33
|
+
const DEFAULT_ORGANIZATION_SETTINGS_PATH = "/settings/organization";
|
|
34
|
+
const DEFAULT_PROFILE_PATH = "/settings/account";
|
|
35
35
|
const DEFAULT_AGENT_PATH = "/agent";
|
|
36
36
|
const APP_ICON_MAP = {
|
|
37
37
|
Mail: IconMail,
|