@agent-native/core 0.79.17 → 0.79.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/corpus/README.md +2 -2
- package/corpus/core/CHANGELOG.md +14 -0
- package/corpus/core/docs/content/file-uploads.md +11 -4
- package/corpus/core/docs/content/locales/ar-SA/multi-app-workspace.md +3 -3
- package/corpus/core/docs/content/locales/de-DE/multi-app-workspace.md +3 -3
- package/corpus/core/docs/content/locales/es-ES/multi-app-workspace.md +3 -3
- package/corpus/core/docs/content/locales/fr-FR/multi-app-workspace.md +3 -3
- package/corpus/core/docs/content/locales/hi-IN/multi-app-workspace.md +3 -3
- package/corpus/core/docs/content/locales/ja-JP/multi-app-workspace.md +3 -3
- package/corpus/core/docs/content/locales/ko-KR/multi-app-workspace.md +3 -3
- package/corpus/core/docs/content/locales/pt-BR/multi-app-workspace.md +3 -3
- package/corpus/core/docs/content/locales/zh-CN/multi-app-workspace.md +3 -3
- package/corpus/core/docs/content/locales/zh-TW/multi-app-workspace.md +3 -3
- package/corpus/core/docs/content/multi-app-workspace.md +3 -3
- package/corpus/core/docs/content/template-clips.md +14 -5
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/agent/engine/builder-engine.ts +8 -3
- package/corpus/core/src/cli/mcp.ts +11 -6
- package/corpus/core/src/client/AssistantChat.tsx +6 -2
- package/corpus/core/src/client/chat/markdown-renderer.tsx +1 -0
- package/corpus/core/src/client/i18n.tsx +77 -65
- package/corpus/core/src/client/index.ts +7 -1
- package/corpus/core/src/client/org/OrgSwitcher.tsx +5 -5
- package/corpus/core/src/client/org/TeamPage.tsx +11 -3
- package/corpus/core/src/client/settings/SettingsTabsPage.tsx +216 -0
- package/corpus/core/src/client/settings/index.ts +5 -0
- package/corpus/core/src/file-upload/index.ts +1 -0
- package/corpus/core/src/file-upload/registry.ts +22 -6
- package/corpus/core/src/file-upload/types.ts +6 -1
- package/corpus/core/src/integrations/adapters/email.ts +26 -18
- package/corpus/core/src/integrations/adapters/slack.ts +8 -7
- package/corpus/core/src/integrations/adapters/telegram.ts +9 -11
- package/corpus/core/src/integrations/adapters/whatsapp.ts +12 -9
- package/corpus/core/src/integrations/plugin.ts +79 -13
- package/corpus/core/src/onboarding/default-steps.ts +6 -3
- package/corpus/core/src/onboarding/types.ts +1 -1
- package/corpus/core/src/org/handlers.ts +1 -1
- package/corpus/core/src/server/agent-chat-plugin.ts +4 -7
- package/corpus/core/src/server/better-auth-instance.ts +19 -62
- package/corpus/core/src/server/core-routes-plugin.ts +93 -180
- package/corpus/core/src/server/create-server.ts +55 -116
- package/corpus/core/src/server/email-actions.ts +3 -6
- package/corpus/core/src/server/email.ts +52 -17
- package/corpus/core/src/server/index.ts +2 -1
- package/corpus/core/src/server/scoped-key-storage.ts +223 -0
- package/corpus/core/src/shared/agent-env.ts +3 -3
- package/corpus/core/src/sharing/actions/share-resource.ts +1 -1
- package/corpus/core/src/styles/agent-native.css +47 -3
- package/corpus/core/src/templates/workspace-root/AGENTS.md +3 -2
- package/corpus/core/src/templates/workspace-root/README.md +1 -1
- package/corpus/core/src/templates/workspace-root/scripts/repair-workspace-org.ts +29 -90
- package/corpus/core/src/terminal/pty-server.ts +3 -38
- package/corpus/core/src/triggers/dispatcher.ts +1 -2
- package/corpus/templates/.retired/issues/package.json +7 -0
- package/corpus/templates/.retired/meeting-notes/package.json +7 -0
- package/corpus/templates/.retired/recruiting/package.json +7 -0
- package/corpus/templates/.retired/scheduling/package.json +7 -0
- package/corpus/templates/.retired/voice/package.json +7 -0
- package/corpus/templates/analytics/app/components/layout/Header.tsx +0 -1
- package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +1 -18
- package/corpus/templates/analytics/app/global.css +15 -0
- package/corpus/templates/analytics/app/i18n/zh-TW.ts +7 -1
- package/corpus/templates/analytics/app/i18n-data.ts +71 -2
- package/corpus/templates/analytics/app/pages/Ask.tsx +1 -1
- package/corpus/templates/analytics/app/pages/Settings.tsx +120 -73
- package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +0 -11
- package/corpus/templates/analytics/app/routes/catalog.tsx +33 -176
- package/corpus/templates/analytics/app/routes/team.tsx +3 -2
- package/corpus/templates/analytics/changelog/2026-06-26-dashboard-templates-are-tucked-into-settings-and-show-simple.md +6 -0
- package/corpus/templates/analytics/changelog/2026-06-26-the-ask-tab-uses-a-softer-dark-gray-canvas-while-sidebar-cha.md +6 -0
- package/corpus/templates/analytics/changelog/2026-06-26-the-sessions-page-shows-a-single-page-title-instead-of-repea.md +6 -0
- package/corpus/templates/analytics/server/lib/dashboard-catalog.ts +37 -28
- package/corpus/templates/assets/app/routes/settings.tsx +65 -43
- package/corpus/templates/assets/app/routes/team.tsx +2 -10
- package/corpus/templates/brain/app/routes/settings.tsx +390 -358
- package/corpus/templates/brain/app/routes/team.tsx +2 -8
- package/corpus/templates/calendar/actions/db-connect.ts +5 -29
- package/corpus/templates/calendar/app/components/CloudUpgrade.tsx +8 -51
- package/corpus/templates/calendar/app/components/calendar/GoogleConnectBanner.tsx +2 -1
- package/corpus/templates/calendar/app/components/calendar/GoogleSetupWizard.tsx +4 -2
- package/corpus/templates/calendar/app/components/layout/Sidebar.tsx +0 -2
- package/corpus/templates/calendar/app/pages/Settings.tsx +304 -271
- package/corpus/templates/calendar/app/routes/_app.team.tsx +2 -17
- package/corpus/templates/calendar/server/handlers/google-auth.ts +22 -9
- package/corpus/templates/calendar/server/lib/booking-emails.ts +1 -1
- package/corpus/templates/calendar/server/lib/event-guest-notifications.ts +1 -1
- package/corpus/templates/calendar/server/lib/google-calendar.ts +48 -28
- package/corpus/templates/chat/app/components/layout/Header.tsx +0 -1
- package/corpus/templates/chat/app/hooks/use-navigation-state.ts +4 -2
- package/corpus/templates/chat/app/routes/settings.tsx +54 -54
- package/corpus/templates/chat/app/routes/team.tsx +2 -10
- package/corpus/templates/clips/.agents/skills/ai-video-tools/SKILL.md +7 -2
- package/corpus/templates/clips/.agents/skills/recording/SKILL.md +1 -1
- package/corpus/templates/clips/.agents/skills/video-sharing/SKILL.md +7 -0
- package/corpus/templates/clips/AGENTS.md +8 -0
- package/corpus/templates/clips/actions/invite-member.ts +1 -1
- package/corpus/templates/clips/actions/request-transcript.ts +1 -1
- package/corpus/templates/clips/app/components/library/library-layout.tsx +325 -333
- package/corpus/templates/clips/app/components/player/delete-recording-menu.tsx +80 -40
- package/corpus/templates/clips/app/components/player/transcript-panel.tsx +2 -0
- package/corpus/templates/clips/app/routes/_app.settings._index.tsx +629 -643
- package/corpus/templates/clips/app/routes/r.$recordingId.tsx +263 -158
- package/corpus/templates/clips/app/routes/share.$shareId.tsx +10 -2
- package/corpus/templates/clips/changelog/2026-06-26-long-desktop-recordings-are-checkpointed-so-macos-finalizati.md +6 -0
- package/corpus/templates/clips/changelog/2026-06-26-non-mac-desktop-recordings-wait-for-upload-transcription.md +6 -0
- package/corpus/templates/clips/changelog/2026-06-26-recording-details-button-stays-at-the-far-right-on-small-screen.md +6 -0
- package/corpus/templates/clips/changelog/2026-06-26-s3-compatible-storage-keys-now-save-securely-from-clips-sett.md +6 -0
- package/corpus/templates/clips/changelog/2026-06-26-shared-clip-links-guide-agents-through-processing-transcripts.md +6 -0
- package/corpus/templates/clips/changelog/2026-06-26-the-agent-sidebar-now-slides-in-smoothly-without-duplicate-e.md +6 -0
- package/corpus/templates/clips/changelog/2026-06-26-the-clip-details-sidebar-now-collapses-into-a-slide-out-pane.md +6 -0
- package/corpus/templates/clips/desktop/src/lib/recorder.ts +55 -3
- package/corpus/templates/clips/desktop/src/lib/transcription-capture.ts +217 -5
- package/corpus/templates/clips/desktop/src-tauri/src/lib.rs +1 -0
- package/corpus/templates/clips/desktop/src-tauri/src/native_screen.rs +176 -5
- package/corpus/templates/clips/server/lib/public-agent-context.ts +31 -0
- package/corpus/templates/clips/server/lib/s3-upload-provider.ts +60 -14
- package/corpus/templates/clips/server/lib/video-storage.ts +37 -9
- package/corpus/templates/clips/server/routes/api/agent-transcript.json.get.ts +5 -0
- package/corpus/templates/content/app/components/layout/Header.tsx +0 -1
- package/corpus/templates/content/app/components/sidebar/NotionButton.tsx +1 -0
- package/corpus/templates/content/app/routes/_app.settings.tsx +54 -55
- package/corpus/templates/content/app/routes/_app.team.tsx +2 -28
- package/corpus/templates/content/server/lib/notion.ts +43 -11
- package/corpus/templates/content/server/routes/api/notion/auth-url.get.ts +2 -2
- package/corpus/templates/content/server/routes/api/notion/status.get.ts +3 -3
- package/corpus/templates/design/app/routes/settings.tsx +60 -38
- package/corpus/templates/design/app/routes/team.tsx +2 -10
- package/corpus/templates/dispatch/app/hooks/use-navigation-state.ts +2 -2
- package/corpus/templates/dispatch/app/routes/settings.tsx +70 -55
- package/corpus/templates/dispatch/app/routes/team.tsx +5 -1
- package/corpus/templates/forms/actions/db-connect.ts +7 -36
- package/corpus/templates/forms/actions/navigate.ts +2 -2
- package/corpus/templates/forms/app/components/CloudUpgrade.tsx +8 -47
- package/corpus/templates/forms/app/components/layout/Header.tsx +0 -1
- package/corpus/templates/forms/app/components/layout/Layout.tsx +42 -25
- package/corpus/templates/forms/app/components/layout/Sidebar.tsx +35 -76
- package/corpus/templates/forms/app/global.css +9 -25
- package/corpus/templates/forms/app/hooks/use-navigation-state.ts +4 -4
- package/corpus/templates/forms/app/i18n/ar-SA.ts +1 -0
- package/corpus/templates/forms/app/i18n/de-DE.ts +1 -0
- package/corpus/templates/forms/app/i18n/en-US.ts +1 -0
- package/corpus/templates/forms/app/i18n/es-ES.ts +1 -0
- package/corpus/templates/forms/app/i18n/fr-FR.ts +1 -0
- package/corpus/templates/forms/app/i18n/hi-IN.ts +1 -0
- package/corpus/templates/forms/app/i18n/ja-JP.ts +1 -0
- package/corpus/templates/forms/app/i18n/ko-KR.ts +1 -0
- package/corpus/templates/forms/app/i18n/pt-BR.ts +1 -0
- package/corpus/templates/forms/app/i18n/zh-CN.ts +1 -0
- package/corpus/templates/forms/app/i18n/zh-TW.ts +1 -0
- package/corpus/templates/forms/app/lib/route-prewarm.ts +9 -8
- package/corpus/templates/forms/app/pages/AskPage.tsx +70 -0
- package/corpus/templates/forms/app/pages/FormsListPage.tsx +74 -81
- package/corpus/templates/forms/app/root.tsx +1 -1
- package/corpus/templates/forms/app/routes/_app.ask.tsx +14 -0
- package/corpus/templates/forms/app/routes/_app.settings.tsx +54 -54
- package/corpus/templates/forms/app/routes/_app.team.tsx +2 -9
- package/corpus/templates/forms/app/routes/_index.tsx +21 -130
- package/corpus/templates/forms/changelog/2026-06-26-ask-forms-opens-as-a-standard-app-tab-with-a-simpler-sidebar.md +6 -0
- package/corpus/templates/forms/changelog/2026-06-26-forms-are-shown-in-a-tighter-row-list-with-a-denser-sidebar.md +6 -0
- package/corpus/templates/forms/shared/navigation.ts +4 -2
- package/corpus/templates/macros/app/routes/settings.tsx +54 -54
- package/corpus/templates/macros/app/routes/team.tsx +2 -10
- package/corpus/templates/mail/actions/helpers.ts +2 -2
- package/corpus/templates/mail/app/components/GoogleConnectBanner.tsx +2 -1
- package/corpus/templates/mail/app/pages/SettingsPage.tsx +5 -5
- package/corpus/templates/mail/app/routes/team.tsx +3 -2
- package/corpus/templates/mail/server/handlers/emails.ts +3 -2
- package/corpus/templates/mail/server/handlers/google-auth.ts +19 -12
- package/corpus/templates/mail/server/lib/automation-engine.ts +3 -2
- package/corpus/templates/mail/server/lib/email-state.ts +2 -3
- package/corpus/templates/mail/server/lib/google-auth.ts +28 -11
- package/corpus/templates/mail/server/lib/jobs.ts +3 -2
- package/corpus/templates/mail/server/onboarding.ts +9 -6
- package/corpus/templates/mail/server/routes/api/attachments.get.ts +3 -3
- package/corpus/templates/plan/actions/request-plan-access.ts +1 -1
- package/corpus/templates/plan/app/components/layout/Header.tsx +0 -1
- package/corpus/templates/plan/app/components/plan/CanvasArea.tsx +56 -4
- package/corpus/templates/plan/app/global.css +8 -3
- package/corpus/templates/plan/app/hooks/use-navigation-state.ts +4 -2
- package/corpus/templates/plan/app/lib/route-prewarm.ts +0 -4
- package/corpus/templates/plan/app/pages/PlansPage.tsx +1 -1
- package/corpus/templates/plan/app/routes/settings.tsx +75 -73
- package/corpus/templates/plan/app/routes/team.tsx +2 -8
- package/corpus/templates/plan/changelog/2026-06-26-canvas-grid-panning-now-stays-smooth-and-fills-the-workspace.md +6 -0
- package/corpus/templates/plan/server/lib/comment-notifications.ts +1 -1
- package/corpus/templates/slides/actions/check-image-gen.ts +2 -1
- package/corpus/templates/slides/actions/db-connect.ts +7 -45
- package/corpus/templates/slides/actions/edit-image.ts +6 -3
- package/corpus/templates/slides/actions/generate-image-api.ts +1 -1
- package/corpus/templates/slides/actions/generate-image.ts +2 -2
- package/corpus/templates/slides/actions/generate-slides-ai.ts +5 -3
- package/corpus/templates/slides/actions/image-gen-status.ts +4 -3
- package/corpus/templates/slides/actions/image-search.ts +6 -3
- package/corpus/templates/slides/actions/search-images.ts +6 -3
- package/corpus/templates/slides/app/components/CloudUpgrade.tsx +8 -51
- package/corpus/templates/slides/app/components/layout/Header.tsx +0 -1
- package/corpus/templates/slides/app/components/layout/Sidebar.tsx +0 -2
- package/corpus/templates/slides/app/routes/settings.tsx +54 -54
- package/corpus/templates/slides/app/routes/team.tsx +2 -12
- package/corpus/templates/slides/server/handlers/google-docs-auth.ts +9 -9
- package/corpus/templates/slides/server/handlers/image-gen.ts +5 -1
- package/corpus/templates/slides/server/handlers/image-providers/gemini.ts +9 -1
- package/corpus/templates/slides/server/handlers/image-providers/index.ts +18 -8
- package/corpus/templates/slides/server/handlers/image-providers/openai.ts +10 -4
- package/corpus/templates/slides/server/handlers/image-providers/types.ts +1 -0
- package/corpus/templates/slides/server/lib/google-docs-oauth.ts +59 -34
- package/corpus/templates/slides/server/register-secrets.ts +60 -0
- package/corpus/templates/videos/actions/db-connect.ts +7 -45
- package/corpus/templates/videos/app/components/CloudUpgrade.tsx +8 -51
- package/corpus/templates/videos/app/components/Sidebar.tsx +1 -9
- package/corpus/templates/videos/app/components/layout/Header.tsx +0 -1
- package/corpus/templates/videos/app/components/layout/NavSidebar.tsx +0 -3
- package/corpus/templates/videos/app/routes/settings.tsx +54 -54
- package/corpus/templates/videos/app/routes/team.tsx +2 -8
- package/dist/agent/engine/builder-engine.d.ts.map +1 -1
- package/dist/agent/engine/builder-engine.js +8 -3
- package/dist/agent/engine/builder-engine.js.map +1 -1
- package/dist/cli/mcp.d.ts.map +1 -1
- package/dist/cli/mcp.js +3 -4
- package/dist/cli/mcp.js.map +1 -1
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +6 -2
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/chat/markdown-renderer.d.ts.map +1 -1
- package/dist/client/chat/markdown-renderer.js +1 -0
- package/dist/client/chat/markdown-renderer.js.map +1 -1
- package/dist/client/i18n.d.ts.map +1 -1
- package/dist/client/i18n.js +20 -9
- package/dist/client/i18n.js.map +1 -1
- package/dist/client/index.d.ts +1 -1
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +1 -1
- package/dist/client/index.js.map +1 -1
- package/dist/client/org/OrgSwitcher.d.ts +3 -3
- package/dist/client/org/OrgSwitcher.js +2 -2
- package/dist/client/org/OrgSwitcher.js.map +1 -1
- package/dist/client/org/TeamPage.d.ts +6 -1
- package/dist/client/org/TeamPage.d.ts.map +1 -1
- package/dist/client/org/TeamPage.js +2 -2
- package/dist/client/org/TeamPage.js.map +1 -1
- package/dist/client/settings/SettingsTabsPage.d.ts +27 -0
- package/dist/client/settings/SettingsTabsPage.d.ts.map +1 -0
- package/dist/client/settings/SettingsTabsPage.js +108 -0
- package/dist/client/settings/SettingsTabsPage.js.map +1 -0
- package/dist/client/settings/index.d.ts +1 -0
- package/dist/client/settings/index.d.ts.map +1 -1
- package/dist/client/settings/index.js +1 -0
- package/dist/client/settings/index.js.map +1 -1
- package/dist/file-upload/index.d.ts +1 -1
- package/dist/file-upload/index.d.ts.map +1 -1
- package/dist/file-upload/index.js +1 -1
- package/dist/file-upload/index.js.map +1 -1
- package/dist/file-upload/registry.d.ts +1 -0
- package/dist/file-upload/registry.d.ts.map +1 -1
- package/dist/file-upload/registry.js +24 -6
- package/dist/file-upload/registry.js.map +1 -1
- package/dist/file-upload/types.d.ts +6 -1
- package/dist/file-upload/types.d.ts.map +1 -1
- package/dist/file-upload/types.js.map +1 -1
- package/dist/integrations/adapters/email.d.ts.map +1 -1
- package/dist/integrations/adapters/email.js +18 -18
- package/dist/integrations/adapters/email.js.map +1 -1
- package/dist/integrations/adapters/slack.d.ts.map +1 -1
- package/dist/integrations/adapters/slack.js +8 -7
- package/dist/integrations/adapters/slack.js.map +1 -1
- package/dist/integrations/adapters/telegram.d.ts.map +1 -1
- package/dist/integrations/adapters/telegram.js +9 -9
- package/dist/integrations/adapters/telegram.js.map +1 -1
- package/dist/integrations/adapters/whatsapp.d.ts.map +1 -1
- package/dist/integrations/adapters/whatsapp.js +10 -9
- package/dist/integrations/adapters/whatsapp.js.map +1 -1
- package/dist/integrations/plugin.d.ts.map +1 -1
- package/dist/integrations/plugin.js +47 -13
- package/dist/integrations/plugin.js.map +1 -1
- package/dist/notifications/routes.d.ts +3 -3
- package/dist/observability/routes.d.ts +6 -6
- package/dist/onboarding/default-steps.d.ts.map +1 -1
- package/dist/onboarding/default-steps.js +6 -5
- package/dist/onboarding/default-steps.js.map +1 -1
- package/dist/onboarding/types.d.ts +1 -1
- package/dist/onboarding/types.d.ts.map +1 -1
- package/dist/onboarding/types.js.map +1 -1
- package/dist/org/handlers.js +1 -1
- package/dist/org/handlers.js.map +1 -1
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +4 -6
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/agent-engine-api-key-route.d.ts +2 -2
- package/dist/server/better-auth-instance.d.ts.map +1 -1
- package/dist/server/better-auth-instance.js +17 -56
- package/dist/server/better-auth-instance.js.map +1 -1
- package/dist/server/core-routes-plugin.d.ts +1 -1
- package/dist/server/core-routes-plugin.d.ts.map +1 -1
- package/dist/server/core-routes-plugin.js +67 -153
- package/dist/server/core-routes-plugin.js.map +1 -1
- package/dist/server/create-server.d.ts +3 -9
- package/dist/server/create-server.d.ts.map +1 -1
- package/dist/server/create-server.js +37 -91
- package/dist/server/create-server.js.map +1 -1
- package/dist/server/email-actions.d.ts +2 -3
- package/dist/server/email-actions.d.ts.map +1 -1
- package/dist/server/email-actions.js +3 -6
- package/dist/server/email-actions.js.map +1 -1
- package/dist/server/email.d.ts +3 -3
- package/dist/server/email.d.ts.map +1 -1
- package/dist/server/email.js +40 -19
- package/dist/server/email.js.map +1 -1
- package/dist/server/index.d.ts +3 -3
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +3 -3
- package/dist/server/index.js.map +1 -1
- package/dist/server/scoped-key-storage.d.ts +22 -0
- package/dist/server/scoped-key-storage.d.ts.map +1 -0
- package/dist/server/scoped-key-storage.js +152 -0
- package/dist/server/scoped-key-storage.js.map +1 -0
- package/dist/shared/agent-env.d.ts +3 -3
- package/dist/shared/agent-env.d.ts.map +1 -1
- package/dist/shared/agent-env.js +3 -3
- package/dist/shared/agent-env.js.map +1 -1
- package/dist/sharing/actions/share-resource.js +1 -1
- package/dist/sharing/actions/share-resource.js.map +1 -1
- package/dist/styles/agent-native.css +47 -3
- package/dist/templates/workspace-root/AGENTS.md +3 -2
- package/dist/templates/workspace-root/README.md +1 -1
- package/dist/templates/workspace-root/scripts/repair-workspace-org.ts +29 -90
- package/dist/terminal/pty-server.d.ts.map +1 -1
- package/dist/terminal/pty-server.js +3 -36
- package/dist/terminal/pty-server.js.map +1 -1
- package/dist/triggers/dispatcher.js +1 -1
- package/dist/triggers/dispatcher.js.map +1 -1
- package/docs/content/file-uploads.md +11 -4
- package/docs/content/locales/ar-SA/multi-app-workspace.md +3 -3
- package/docs/content/locales/de-DE/multi-app-workspace.md +3 -3
- package/docs/content/locales/es-ES/multi-app-workspace.md +3 -3
- package/docs/content/locales/fr-FR/multi-app-workspace.md +3 -3
- package/docs/content/locales/hi-IN/multi-app-workspace.md +3 -3
- package/docs/content/locales/ja-JP/multi-app-workspace.md +3 -3
- package/docs/content/locales/ko-KR/multi-app-workspace.md +3 -3
- package/docs/content/locales/pt-BR/multi-app-workspace.md +3 -3
- package/docs/content/locales/zh-CN/multi-app-workspace.md +3 -3
- package/docs/content/locales/zh-TW/multi-app-workspace.md +3 -3
- package/docs/content/multi-app-workspace.md +3 -3
- package/docs/content/template-clips.md +14 -5
- package/package.json +1 -1
- package/src/templates/workspace-root/AGENTS.md +3 -2
- package/src/templates/workspace-root/README.md +1 -1
- package/src/templates/workspace-root/scripts/repair-workspace-org.ts +29 -90
- package/corpus/core/src/server/env-var-writes.ts +0 -16
- package/corpus/templates/analytics/app/pages/Team.tsx +0 -9
- package/corpus/templates/calendar/app/pages/Team.tsx +0 -12
- package/corpus/templates/mail/app/pages/Team.tsx +0 -17
- package/dist/server/env-var-writes.d.ts +0 -10
- package/dist/server/env-var-writes.d.ts.map +0 -1
- package/dist/server/env-var-writes.js +0 -18
- package/dist/server/env-var-writes.js.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as PopoverPrimitive from "@radix-ui/react-popover";
|
|
2
2
|
import { IconCheck, IconChevronDown, IconLanguage } from "@tabler/icons-react";
|
|
3
3
|
import i18next, { type i18n as I18nInstance } from "i18next";
|
|
4
4
|
import React, {
|
|
@@ -34,6 +34,7 @@ import {
|
|
|
34
34
|
} from "../localization/shared.js";
|
|
35
35
|
import { setClientAppState } from "./application-state.js";
|
|
36
36
|
import { callAction } from "./use-action.js";
|
|
37
|
+
import { cn } from "./utils.js";
|
|
37
38
|
|
|
38
39
|
export {
|
|
39
40
|
DEFAULT_LOCALE,
|
|
@@ -676,6 +677,7 @@ export function LanguagePicker({
|
|
|
676
677
|
variant?: "select" | "icon";
|
|
677
678
|
}) {
|
|
678
679
|
const { locale, preference, setPreference } = useLocale();
|
|
680
|
+
const [open, setOpen] = useState(false);
|
|
679
681
|
const copy =
|
|
680
682
|
LANGUAGE_PICKER_COPY[locale] ?? LANGUAGE_PICKER_COPY[DEFAULT_LOCALE];
|
|
681
683
|
const resolvedLabel = label ?? copy.label;
|
|
@@ -691,84 +693,94 @@ export function LanguagePicker({
|
|
|
691
693
|
: []),
|
|
692
694
|
...SUPPORTED_LOCALES.map((code) => ({
|
|
693
695
|
value: code,
|
|
694
|
-
label:
|
|
695
|
-
LOCALE_METADATA[code].nativeName === LOCALE_METADATA[code].englishName
|
|
696
|
-
? LOCALE_METADATA[code].nativeName
|
|
697
|
-
: `${LOCALE_METADATA[code].nativeName} (${LOCALE_METADATA[code].englishName})`,
|
|
696
|
+
label: `${LOCALE_METADATA[code].nativeName} (${code})`,
|
|
698
697
|
description: code,
|
|
699
698
|
})),
|
|
700
699
|
];
|
|
701
700
|
const selected = options.find((option) => option.value === preference);
|
|
701
|
+
const selectedLabel = selected?.label ?? preference;
|
|
702
|
+
const triggerLabel = `${resolvedLabel}: ${selectedLabel}`;
|
|
703
|
+
|
|
704
|
+
function handleOptionClick(value: LocalePreference) {
|
|
705
|
+
setOpen(false);
|
|
706
|
+
void setPreference(normalizeLocalizationPreference(value).locale);
|
|
707
|
+
}
|
|
702
708
|
|
|
703
709
|
return (
|
|
704
710
|
<div className={className}>
|
|
705
|
-
<
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
711
|
+
<PopoverPrimitive.Root open={open} onOpenChange={setOpen}>
|
|
712
|
+
<PopoverPrimitive.Trigger asChild>
|
|
713
|
+
<button
|
|
714
|
+
type="button"
|
|
715
|
+
aria-label={triggerLabel}
|
|
716
|
+
title={triggerLabel}
|
|
717
|
+
data-language-picker-trigger
|
|
718
|
+
className={cn(
|
|
719
|
+
"shrink-0 rounded-md border border-border bg-background text-foreground outline-none transition-colors hover:border-foreground/30 hover:bg-accent/40 hover:text-foreground focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 data-[state=open]:border-foreground/30 data-[state=open]:bg-accent/40",
|
|
720
|
+
variant === "icon"
|
|
721
|
+
? "flex h-8 w-8 items-center justify-center"
|
|
722
|
+
: "flex h-9 w-full items-center justify-between gap-2 px-3 text-start text-sm",
|
|
723
|
+
)}
|
|
724
|
+
>
|
|
725
|
+
<span className="flex min-w-0 items-center gap-2">
|
|
726
|
+
<IconLanguage className="h-4 w-4 shrink-0 text-muted-foreground" />
|
|
727
|
+
{variant === "select" ? (
|
|
728
|
+
<span className="truncate">{selectedLabel}</span>
|
|
729
|
+
) : (
|
|
730
|
+
<span className="sr-only">{triggerLabel}</span>
|
|
731
|
+
)}
|
|
732
|
+
</span>
|
|
722
733
|
{variant === "select" ? (
|
|
723
|
-
<
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
</SelectPrimitive.Value>
|
|
734
|
+
<IconChevronDown
|
|
735
|
+
className="h-3.5 w-3.5 shrink-0 text-muted-foreground"
|
|
736
|
+
aria-hidden="true"
|
|
737
|
+
/>
|
|
728
738
|
) : null}
|
|
729
|
-
</
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
) : null}
|
|
735
|
-
</SelectPrimitive.Trigger>
|
|
736
|
-
<SelectPrimitive.Portal>
|
|
737
|
-
<SelectPrimitive.Content
|
|
738
|
-
position="popper"
|
|
739
|
+
</button>
|
|
740
|
+
</PopoverPrimitive.Trigger>
|
|
741
|
+
<PopoverPrimitive.Portal>
|
|
742
|
+
<PopoverPrimitive.Content
|
|
743
|
+
align={variant === "icon" ? "end" : "start"}
|
|
739
744
|
sideOffset={6}
|
|
740
|
-
|
|
745
|
+
role="menu"
|
|
746
|
+
className={cn(
|
|
747
|
+
"z-[9999] max-h-[min(20rem,var(--radix-popover-content-available-height))] overflow-y-auto rounded-lg border border-border bg-popover p-1 text-popover-foreground shadow-lg outline-none will-change-[transform,opacity] 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-[state=closed]:duration-100 data-[state=open]:duration-150 data-[state=closed]:ease-in data-[state=open]:ease-out data-[side=bottom]:slide-in-from-top-1 data-[side=left]:slide-in-from-right-1 data-[side=right]:slide-in-from-left-1 data-[side=top]:slide-in-from-bottom-1",
|
|
741
748
|
variant === "icon"
|
|
742
|
-
? "
|
|
743
|
-
: "
|
|
744
|
-
}
|
|
749
|
+
? "min-w-56"
|
|
750
|
+
: "w-[min(20rem,calc(100vw-2rem))] min-w-[var(--radix-popover-trigger-width)]",
|
|
751
|
+
)}
|
|
745
752
|
>
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
753
|
+
{options.map((option) => {
|
|
754
|
+
const optionSelected = option.value === preference;
|
|
755
|
+
return (
|
|
756
|
+
<button
|
|
749
757
|
key={option.value}
|
|
750
|
-
|
|
751
|
-
|
|
758
|
+
type="button"
|
|
759
|
+
role="menuitemradio"
|
|
760
|
+
aria-checked={optionSelected}
|
|
761
|
+
title={option.description}
|
|
762
|
+
onClick={() => handleOptionClick(option.value)}
|
|
763
|
+
className={cn(
|
|
764
|
+
"flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-start text-sm outline-none transition-colors hover:bg-accent/60 hover:text-foreground focus-visible:bg-accent/60 focus-visible:text-foreground",
|
|
765
|
+
optionSelected
|
|
766
|
+
? "bg-accent/40 text-foreground"
|
|
767
|
+
: "text-muted-foreground",
|
|
768
|
+
)}
|
|
752
769
|
>
|
|
753
|
-
<
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
))}
|
|
768
|
-
</SelectPrimitive.Viewport>
|
|
769
|
-
</SelectPrimitive.Content>
|
|
770
|
-
</SelectPrimitive.Portal>
|
|
771
|
-
</SelectPrimitive.Root>
|
|
770
|
+
<IconCheck
|
|
771
|
+
className={cn(
|
|
772
|
+
"h-3.5 w-3.5 shrink-0",
|
|
773
|
+
optionSelected ? "opacity-100" : "opacity-0",
|
|
774
|
+
)}
|
|
775
|
+
aria-hidden="true"
|
|
776
|
+
/>
|
|
777
|
+
<span className="truncate">{option.label}</span>
|
|
778
|
+
</button>
|
|
779
|
+
);
|
|
780
|
+
})}
|
|
781
|
+
</PopoverPrimitive.Content>
|
|
782
|
+
</PopoverPrimitive.Portal>
|
|
783
|
+
</PopoverPrimitive.Root>
|
|
772
784
|
</div>
|
|
773
785
|
);
|
|
774
786
|
}
|
|
@@ -610,7 +610,13 @@ export {
|
|
|
610
610
|
type DataWidgetResultMetadata,
|
|
611
611
|
} from "./chat/widgets/data-widget-types.js";
|
|
612
612
|
export { AgentNativeIcon } from "./components/icons/AgentNativeIcon.js";
|
|
613
|
-
export {
|
|
613
|
+
export {
|
|
614
|
+
SettingsPanel,
|
|
615
|
+
SettingsTabsPage,
|
|
616
|
+
type SettingsPanelProps,
|
|
617
|
+
type SettingsTabItem,
|
|
618
|
+
type SettingsTabsPageProps,
|
|
619
|
+
} from "./settings/index.js";
|
|
614
620
|
export { useBuilderStatus } from "./settings/useBuilderStatus.js";
|
|
615
621
|
export {
|
|
616
622
|
openBuilderConnectPopup,
|
|
@@ -64,9 +64,9 @@ export interface OrgSwitcherProps {
|
|
|
64
64
|
reserveSpace?: boolean;
|
|
65
65
|
/**
|
|
66
66
|
* Path to navigate to when the user clicks "Organization settings".
|
|
67
|
-
* Defaults to
|
|
68
|
-
*
|
|
69
|
-
*
|
|
67
|
+
* Defaults to the standard Team tab inside Settings. Templates with an
|
|
68
|
+
* established org surface can pass their own path; pass `null` to only open
|
|
69
|
+
* the in-sidebar settings panel.
|
|
70
70
|
*/
|
|
71
71
|
settingsPath?: string | null;
|
|
72
72
|
}
|
|
@@ -97,7 +97,7 @@ const SECTION_LABEL_CLASS =
|
|
|
97
97
|
const APP_SUBMENU_CONTENT_CLASS =
|
|
98
98
|
"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";
|
|
99
99
|
|
|
100
|
-
const DEFAULT_ORGANIZATION_SETTINGS_PATH = "/team";
|
|
100
|
+
const DEFAULT_ORGANIZATION_SETTINGS_PATH = "/settings#team";
|
|
101
101
|
|
|
102
102
|
const APP_ICON_MAP: Record<string, typeof IconApps> = {
|
|
103
103
|
Mail: IconMail,
|
|
@@ -131,7 +131,7 @@ function appMenuIcon(app: OrgSwitcherAppLink): typeof IconApps {
|
|
|
131
131
|
}
|
|
132
132
|
|
|
133
133
|
function organizationSettingsPath(path: string): string {
|
|
134
|
-
return
|
|
134
|
+
return path.includes("#") ? path : `${path}#team`;
|
|
135
135
|
}
|
|
136
136
|
|
|
137
137
|
function AppMenuLink({
|
|
@@ -58,6 +58,11 @@ export interface TeamPageProps {
|
|
|
58
58
|
* Title shown at the top of the page. Defaults to "Team".
|
|
59
59
|
*/
|
|
60
60
|
title?: string;
|
|
61
|
+
/**
|
|
62
|
+
* Hide the page title when this is rendered inside another titled surface,
|
|
63
|
+
* such as the Settings > Team tab.
|
|
64
|
+
*/
|
|
65
|
+
showTitle?: boolean;
|
|
61
66
|
/**
|
|
62
67
|
* Description shown on the "Create an Organization" card. Defaults to
|
|
63
68
|
* "Set up a team to collaborate with your colleagues."
|
|
@@ -1260,6 +1265,7 @@ function A2ASecretSection({ secret }: { secret: string | null | undefined }) {
|
|
|
1260
1265
|
export function TeamPage({
|
|
1261
1266
|
layout,
|
|
1262
1267
|
title,
|
|
1268
|
+
showTitle = true,
|
|
1263
1269
|
createOrgDescription,
|
|
1264
1270
|
className,
|
|
1265
1271
|
}: TeamPageProps) {
|
|
@@ -1268,9 +1274,11 @@ export function TeamPage({
|
|
|
1268
1274
|
|
|
1269
1275
|
const content = (
|
|
1270
1276
|
<div className={`space-y-6 max-w-2xl ${className ?? ""}`}>
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1277
|
+
{showTitle ? (
|
|
1278
|
+
<h2 className="text-2xl font-bold tracking-tight">
|
|
1279
|
+
{title ?? t("org.team")}
|
|
1280
|
+
</h2>
|
|
1281
|
+
) : null}
|
|
1274
1282
|
|
|
1275
1283
|
{isLoading && (
|
|
1276
1284
|
<section className="rounded-lg border border-border bg-card p-6">
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
import { IconHistory, IconSettings, IconUsers } from "@tabler/icons-react";
|
|
2
|
+
import {
|
|
3
|
+
useEffect,
|
|
4
|
+
useMemo,
|
|
5
|
+
useState,
|
|
6
|
+
type ComponentType,
|
|
7
|
+
type ReactNode,
|
|
8
|
+
} from "react";
|
|
9
|
+
|
|
10
|
+
import { cn } from "../utils.js";
|
|
11
|
+
|
|
12
|
+
type SettingsTabIcon = ComponentType<{ className?: string }>;
|
|
13
|
+
|
|
14
|
+
export interface SettingsTabItem {
|
|
15
|
+
id: string;
|
|
16
|
+
label: string;
|
|
17
|
+
icon?: SettingsTabIcon;
|
|
18
|
+
content: ReactNode;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface SettingsTabsPageProps {
|
|
22
|
+
general: ReactNode;
|
|
23
|
+
team?: ReactNode;
|
|
24
|
+
whatsNew?: ReactNode;
|
|
25
|
+
extraTabs?: SettingsTabItem[];
|
|
26
|
+
generalLabel?: string;
|
|
27
|
+
teamLabel?: string;
|
|
28
|
+
whatsNewLabel?: string;
|
|
29
|
+
ariaLabel?: string;
|
|
30
|
+
defaultTab?: string;
|
|
31
|
+
className?: string;
|
|
32
|
+
navClassName?: string;
|
|
33
|
+
contentClassName?: string;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function normalizeTabId(value?: string | null): string | null {
|
|
37
|
+
const normalized = value
|
|
38
|
+
?.replace(/^#/, "")
|
|
39
|
+
.trim()
|
|
40
|
+
.toLowerCase()
|
|
41
|
+
.replace(/['"]/g, "")
|
|
42
|
+
.replace(/[\s_]+/g, "-");
|
|
43
|
+
if (!normalized) return null;
|
|
44
|
+
if (
|
|
45
|
+
normalized === "whats-new" ||
|
|
46
|
+
normalized === "what-s-new" ||
|
|
47
|
+
normalized === "changelog" ||
|
|
48
|
+
normalized === "updates"
|
|
49
|
+
) {
|
|
50
|
+
return "whats-new";
|
|
51
|
+
}
|
|
52
|
+
if (
|
|
53
|
+
normalized === "workspace" ||
|
|
54
|
+
normalized === "workspace-settings" ||
|
|
55
|
+
normalized === "organization" ||
|
|
56
|
+
normalized === "org"
|
|
57
|
+
) {
|
|
58
|
+
return "team";
|
|
59
|
+
}
|
|
60
|
+
return normalized;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function activeTabFromHash(
|
|
64
|
+
tabs: SettingsTabItem[],
|
|
65
|
+
defaultTab: string,
|
|
66
|
+
): string {
|
|
67
|
+
if (typeof window === "undefined") return defaultTab;
|
|
68
|
+
const fromHash = normalizeTabId(window.location.hash);
|
|
69
|
+
if (fromHash && tabs.some((tab) => tab.id === fromHash)) return fromHash;
|
|
70
|
+
return defaultTab;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function updateHashForTab(tabId: string) {
|
|
74
|
+
if (typeof window === "undefined") return;
|
|
75
|
+
const { pathname, search } = window.location;
|
|
76
|
+
const hash = tabId === "general" ? "" : `#${encodeURIComponent(tabId)}`;
|
|
77
|
+
window.history.pushState(null, "", `${pathname}${search}${hash}`);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export function SettingsTabsPage({
|
|
81
|
+
general,
|
|
82
|
+
team,
|
|
83
|
+
whatsNew,
|
|
84
|
+
extraTabs = [],
|
|
85
|
+
generalLabel = "General",
|
|
86
|
+
teamLabel = "Team",
|
|
87
|
+
whatsNewLabel = "What's new",
|
|
88
|
+
ariaLabel = "Settings sections",
|
|
89
|
+
defaultTab = "general",
|
|
90
|
+
className,
|
|
91
|
+
navClassName,
|
|
92
|
+
contentClassName,
|
|
93
|
+
}: SettingsTabsPageProps) {
|
|
94
|
+
const tabs = useMemo<SettingsTabItem[]>(() => {
|
|
95
|
+
const next: SettingsTabItem[] = [
|
|
96
|
+
{
|
|
97
|
+
id: "general",
|
|
98
|
+
label: generalLabel,
|
|
99
|
+
icon: IconSettings,
|
|
100
|
+
content: general,
|
|
101
|
+
},
|
|
102
|
+
];
|
|
103
|
+
if (team) {
|
|
104
|
+
next.push({
|
|
105
|
+
id: "team",
|
|
106
|
+
label: teamLabel,
|
|
107
|
+
icon: IconUsers,
|
|
108
|
+
content: team,
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
if (whatsNew) {
|
|
112
|
+
next.push({
|
|
113
|
+
id: "whats-new",
|
|
114
|
+
label: whatsNewLabel,
|
|
115
|
+
icon: IconHistory,
|
|
116
|
+
content: whatsNew,
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
next.push(...extraTabs);
|
|
120
|
+
return next;
|
|
121
|
+
}, [
|
|
122
|
+
extraTabs,
|
|
123
|
+
general,
|
|
124
|
+
generalLabel,
|
|
125
|
+
team,
|
|
126
|
+
teamLabel,
|
|
127
|
+
whatsNew,
|
|
128
|
+
whatsNewLabel,
|
|
129
|
+
]);
|
|
130
|
+
|
|
131
|
+
const fallbackTab = tabs.some((tab) => tab.id === defaultTab)
|
|
132
|
+
? defaultTab
|
|
133
|
+
: (tabs[0]?.id ?? "general");
|
|
134
|
+
const [activeTab, setActiveTab] = useState(() =>
|
|
135
|
+
activeTabFromHash(tabs, fallbackTab),
|
|
136
|
+
);
|
|
137
|
+
|
|
138
|
+
useEffect(() => {
|
|
139
|
+
if (tabs.some((tab) => tab.id === activeTab)) return;
|
|
140
|
+
setActiveTab(fallbackTab);
|
|
141
|
+
}, [activeTab, fallbackTab, tabs]);
|
|
142
|
+
|
|
143
|
+
useEffect(() => {
|
|
144
|
+
const handleHashChange = () => {
|
|
145
|
+
setActiveTab(activeTabFromHash(tabs, fallbackTab));
|
|
146
|
+
};
|
|
147
|
+
window.addEventListener("hashchange", handleHashChange);
|
|
148
|
+
return () => window.removeEventListener("hashchange", handleHashChange);
|
|
149
|
+
}, [fallbackTab, tabs]);
|
|
150
|
+
|
|
151
|
+
const selectedTab = tabs.find((tab) => tab.id === activeTab) ?? tabs[0];
|
|
152
|
+
|
|
153
|
+
return (
|
|
154
|
+
<div
|
|
155
|
+
className={cn(
|
|
156
|
+
"flex min-h-full w-full flex-col overflow-hidden bg-background sm:flex-row",
|
|
157
|
+
className,
|
|
158
|
+
)}
|
|
159
|
+
>
|
|
160
|
+
<nav
|
|
161
|
+
aria-label={ariaLabel}
|
|
162
|
+
role="tablist"
|
|
163
|
+
className={cn(
|
|
164
|
+
"flex shrink-0 gap-1 overflow-x-auto border-b border-border/50 bg-muted/30 p-2 sm:w-48 sm:flex-col sm:overflow-x-visible sm:border-b-0 sm:border-e",
|
|
165
|
+
navClassName,
|
|
166
|
+
)}
|
|
167
|
+
>
|
|
168
|
+
{tabs.map((tab) => {
|
|
169
|
+
const Icon = tab.icon;
|
|
170
|
+
const selected = tab.id === selectedTab?.id;
|
|
171
|
+
return (
|
|
172
|
+
<button
|
|
173
|
+
key={tab.id}
|
|
174
|
+
type="button"
|
|
175
|
+
role="tab"
|
|
176
|
+
aria-selected={selected}
|
|
177
|
+
aria-controls={`settings-tabpanel-${tab.id}`}
|
|
178
|
+
id={`settings-tab-${tab.id}`}
|
|
179
|
+
onClick={() => {
|
|
180
|
+
setActiveTab(tab.id);
|
|
181
|
+
updateHashForTab(tab.id);
|
|
182
|
+
}}
|
|
183
|
+
className={cn(
|
|
184
|
+
"flex min-h-9 shrink-0 items-center gap-2 rounded-md px-3 py-2 text-start text-sm font-medium transition-colors sm:w-full",
|
|
185
|
+
selected
|
|
186
|
+
? "bg-background text-foreground shadow-sm ring-1 ring-border/60"
|
|
187
|
+
: "text-muted-foreground hover:bg-accent/60 hover:text-foreground",
|
|
188
|
+
)}
|
|
189
|
+
>
|
|
190
|
+
{Icon ? (
|
|
191
|
+
<Icon
|
|
192
|
+
className={cn(
|
|
193
|
+
"size-4 shrink-0",
|
|
194
|
+
selected ? "text-foreground" : "text-muted-foreground",
|
|
195
|
+
)}
|
|
196
|
+
/>
|
|
197
|
+
) : null}
|
|
198
|
+
<span className="truncate">{tab.label}</span>
|
|
199
|
+
</button>
|
|
200
|
+
);
|
|
201
|
+
})}
|
|
202
|
+
</nav>
|
|
203
|
+
<div
|
|
204
|
+
id={`settings-tabpanel-${selectedTab?.id ?? "general"}`}
|
|
205
|
+
role="tabpanel"
|
|
206
|
+
aria-labelledby={`settings-tab-${selectedTab?.id ?? "general"}`}
|
|
207
|
+
className={cn(
|
|
208
|
+
"min-w-0 flex-1 overflow-y-auto p-4 sm:p-6",
|
|
209
|
+
contentClassName,
|
|
210
|
+
)}
|
|
211
|
+
>
|
|
212
|
+
{selectedTab?.content}
|
|
213
|
+
</div>
|
|
214
|
+
</div>
|
|
215
|
+
);
|
|
216
|
+
}
|
|
@@ -1,3 +1,8 @@
|
|
|
1
1
|
export { SettingsPanel, type SettingsPanelProps } from "./SettingsPanel.js";
|
|
2
|
+
export {
|
|
3
|
+
SettingsTabsPage,
|
|
4
|
+
type SettingsTabItem,
|
|
5
|
+
type SettingsTabsPageProps,
|
|
6
|
+
} from "./SettingsTabsPage.js";
|
|
2
7
|
export { useBuilderStatus } from "./useBuilderStatus.js";
|
|
3
8
|
export { SecretsSection, type SecretsSectionProps } from "./SecretsSection.js";
|
|
@@ -54,6 +54,24 @@ export function getActiveFileUploadProvider(): FileUploadProvider | null {
|
|
|
54
54
|
return null;
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
+
export async function getActiveFileUploadProviderForRequest(): Promise<FileUploadProvider | null> {
|
|
58
|
+
for (const provider of providers.values()) {
|
|
59
|
+
if (provider.isConfigured()) return provider;
|
|
60
|
+
if (provider.isConfiguredForRequest) {
|
|
61
|
+
try {
|
|
62
|
+
if (await provider.isConfiguredForRequest()) return provider;
|
|
63
|
+
} catch {
|
|
64
|
+
// Treat failed scoped credential lookups as unavailable. The upload
|
|
65
|
+
// call will surface real provider errors after a provider is selected.
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
if (builderFileUploadProvider.isConfigured()) {
|
|
70
|
+
return builderFileUploadProvider;
|
|
71
|
+
}
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
|
|
57
75
|
/**
|
|
58
76
|
* Upload a file via the active provider, or `null` if no provider is
|
|
59
77
|
* configured. Callers use `null` as the signal to fall back to SQL
|
|
@@ -63,12 +81,10 @@ export function getActiveFileUploadProvider(): FileUploadProvider | null {
|
|
|
63
81
|
export async function uploadFile(
|
|
64
82
|
input: FileUploadInput,
|
|
65
83
|
): Promise<FileUploadResult | null> {
|
|
66
|
-
const provider =
|
|
67
|
-
//
|
|
68
|
-
//
|
|
69
|
-
//
|
|
70
|
-
// where BUILDER_PRIVATE_KEY is set at the deploy level but the user has no
|
|
71
|
-
// personal credentials. Always resolve builder credentials asynchronously.
|
|
84
|
+
const provider = await getActiveFileUploadProviderForRequest();
|
|
85
|
+
// User-registered providers (S3, etc.) may be configured by sync runtime
|
|
86
|
+
// state or request-scoped DB secrets. Builder still gets an explicit async
|
|
87
|
+
// credential check below because its sync isConfigured() only checks env.
|
|
72
88
|
if (provider && provider !== builderFileUploadProvider) {
|
|
73
89
|
return provider.upload(input);
|
|
74
90
|
}
|
|
@@ -32,8 +32,13 @@ export interface FileUploadProvider {
|
|
|
32
32
|
id: string;
|
|
33
33
|
/** Human-readable name. */
|
|
34
34
|
name: string;
|
|
35
|
-
/** Returns true if this provider is
|
|
35
|
+
/** Returns true if this provider is configured from synchronous runtime state. */
|
|
36
36
|
isConfigured: () => boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Returns true if this provider is configured for the active request.
|
|
39
|
+
* Use for DB-backed user/org/workspace secrets that require request context.
|
|
40
|
+
*/
|
|
41
|
+
isConfiguredForRequest?: () => Promise<boolean>;
|
|
37
42
|
/** Upload a file and return a URL. Throw on failure. */
|
|
38
43
|
upload: (input: FileUploadInput) => Promise<FileUploadResult>;
|
|
39
44
|
}
|