@agent-native/core 0.79.17 → 0.79.18
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 +8 -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/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 +0 -17
- 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/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-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/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 +219 -155
- 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-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-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/hooks/use-navigation-state.ts +4 -2
- package/corpus/templates/plan/app/lib/route-prewarm.ts +0 -4
- package/corpus/templates/plan/app/routes/settings.tsx +75 -73
- package/corpus/templates/plan/app/routes/team.tsx +2 -8
- 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/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/collab/routes.d.ts +1 -1
- package/dist/file-upload/actions/upload-image.d.ts +2 -2
- 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 +1 -1
- package/dist/observability/routes.d.ts +2 -2
- 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/progress/routes.d.ts +1 -1
- package/dist/resources/handlers.d.ts +3 -3
- 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 +1 -1
- 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/server/transcribe-voice.d.ts +1 -1
- 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
|
@@ -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
|
}
|
|
@@ -5,6 +5,7 @@ import { getHeader, readRawBody as h3ReadRawBody } from "h3";
|
|
|
5
5
|
|
|
6
6
|
import { getDbExec } from "../../db/client.js";
|
|
7
7
|
import type { EnvKeyConfig } from "../../server/create-server.js";
|
|
8
|
+
import { resolveSecret } from "../../server/credential-provider.js";
|
|
8
9
|
import {
|
|
9
10
|
sendEmail,
|
|
10
11
|
isEmailConfigured,
|
|
@@ -113,8 +114,9 @@ export function emailAdapter(): PlatformAdapter {
|
|
|
113
114
|
},
|
|
114
115
|
|
|
115
116
|
async verifyWebhook(event: H3Event): Promise<boolean> {
|
|
116
|
-
const secret =
|
|
117
|
-
|
|
117
|
+
const secret =
|
|
118
|
+
(await resolveSecret("EMAIL_INBOUND_WEBHOOK_SECRET")) ?? undefined;
|
|
119
|
+
const provider = await getEmailProvider();
|
|
118
120
|
|
|
119
121
|
if (provider === "resend") {
|
|
120
122
|
return verifyResendWebhook(event, secret);
|
|
@@ -132,8 +134,10 @@ export function emailAdapter(): PlatformAdapter {
|
|
|
132
134
|
async parseIncomingMessage(
|
|
133
135
|
event: H3Event,
|
|
134
136
|
): Promise<IncomingMessage | null> {
|
|
135
|
-
const provider = getEmailProvider();
|
|
136
|
-
const agentAddress =
|
|
137
|
+
const provider = await getEmailProvider();
|
|
138
|
+
const agentAddress = (
|
|
139
|
+
await resolveSecret("EMAIL_AGENT_ADDRESS")
|
|
140
|
+
)?.toLowerCase();
|
|
137
141
|
if (!agentAddress) {
|
|
138
142
|
console.warn("[email] EMAIL_AGENT_ADDRESS not configured");
|
|
139
143
|
return null;
|
|
@@ -246,7 +250,7 @@ export function emailAdapter(): PlatformAdapter {
|
|
|
246
250
|
message: OutgoingMessage,
|
|
247
251
|
context: IncomingMessage,
|
|
248
252
|
): Promise<void> {
|
|
249
|
-
const agentAddress =
|
|
253
|
+
const agentAddress = await resolveSecret("EMAIL_AGENT_ADDRESS");
|
|
250
254
|
if (!agentAddress) {
|
|
251
255
|
console.error("[email] EMAIL_AGENT_ADDRESS not configured");
|
|
252
256
|
return;
|
|
@@ -259,9 +263,8 @@ export function emailAdapter(): PlatformAdapter {
|
|
|
259
263
|
// EMAIL_FROM overrides the from-address — required when the receiving
|
|
260
264
|
// address is on a sub-domain that can't be a verified sender (e.g.
|
|
261
265
|
// *.resend.app). Inbound and outbound addresses can differ.
|
|
262
|
-
const
|
|
263
|
-
|
|
264
|
-
: `${displayName} <${agentAddress}>`;
|
|
266
|
+
const emailFrom = await resolveSecret("EMAIL_FROM");
|
|
267
|
+
const fromAddress = emailFrom || `${displayName} <${agentAddress}>`;
|
|
265
268
|
|
|
266
269
|
const subject = context.platformContext.subject as string;
|
|
267
270
|
const reSubject = subject.startsWith("Re: ") ? subject : `Re: ${subject}`;
|
|
@@ -276,7 +279,7 @@ export function emailAdapter(): PlatformAdapter {
|
|
|
276
279
|
inReplyTo: context.platformContext.messageId as string,
|
|
277
280
|
references: buildReferencesHeader(context.platformContext),
|
|
278
281
|
cc: context.platformContext.isCC
|
|
279
|
-
? buildReplyAllCc(context)
|
|
282
|
+
? buildReplyAllCc(context, agentAddress)
|
|
280
283
|
: undefined,
|
|
281
284
|
});
|
|
282
285
|
} catch (err) {
|
|
@@ -288,7 +291,7 @@ export function emailAdapter(): PlatformAdapter {
|
|
|
288
291
|
message: OutgoingMessage,
|
|
289
292
|
target: OutboundTarget,
|
|
290
293
|
): Promise<void> {
|
|
291
|
-
const agentAddress =
|
|
294
|
+
const agentAddress = await resolveSecret("EMAIL_AGENT_ADDRESS");
|
|
292
295
|
if (!agentAddress) {
|
|
293
296
|
console.error("[email] EMAIL_AGENT_ADDRESS not configured");
|
|
294
297
|
return;
|
|
@@ -325,9 +328,11 @@ export function emailAdapter(): PlatformAdapter {
|
|
|
325
328
|
},
|
|
326
329
|
|
|
327
330
|
async getStatus(_baseUrl?: string): Promise<IntegrationStatus> {
|
|
328
|
-
const hasAgentAddress = !!
|
|
329
|
-
const hasEmailProvider = isEmailConfigured();
|
|
330
|
-
const hasWebhookSecret = !!
|
|
331
|
+
const hasAgentAddress = !!(await resolveSecret("EMAIL_AGENT_ADDRESS"));
|
|
332
|
+
const hasEmailProvider = await isEmailConfigured();
|
|
333
|
+
const hasWebhookSecret = !!(await resolveSecret(
|
|
334
|
+
"EMAIL_INBOUND_WEBHOOK_SECRET",
|
|
335
|
+
));
|
|
331
336
|
const configured = hasAgentAddress && hasEmailProvider;
|
|
332
337
|
|
|
333
338
|
return {
|
|
@@ -339,10 +344,10 @@ export function emailAdapter(): PlatformAdapter {
|
|
|
339
344
|
hasAgentAddress,
|
|
340
345
|
hasEmailProvider,
|
|
341
346
|
hasWebhookSecret,
|
|
342
|
-
provider: getEmailProvider(),
|
|
347
|
+
provider: await getEmailProvider(),
|
|
343
348
|
},
|
|
344
349
|
error: !configured
|
|
345
|
-
? "
|
|
350
|
+
? "Save EMAIL_AGENT_ADDRESS and either RESEND_API_KEY or SENDGRID_API_KEY in settings"
|
|
346
351
|
: undefined,
|
|
347
352
|
};
|
|
348
353
|
},
|
|
@@ -906,8 +911,11 @@ function buildReferencesHeader(ctx: Record<string, unknown>): string {
|
|
|
906
911
|
* Build CC list for reply-all when agent was CC'd.
|
|
907
912
|
* Include original To addresses and other CC addresses, excluding the agent and the original sender.
|
|
908
913
|
*/
|
|
909
|
-
function buildReplyAllCc(
|
|
910
|
-
|
|
914
|
+
function buildReplyAllCc(
|
|
915
|
+
context: IncomingMessage,
|
|
916
|
+
agentAddress: string,
|
|
917
|
+
): string[] | undefined {
|
|
918
|
+
const normalizedAgentAddress = agentAddress.toLowerCase();
|
|
911
919
|
const senderEmail = context.senderId?.toLowerCase();
|
|
912
920
|
const toAddresses = (context.platformContext.to as string[]) || [];
|
|
913
921
|
const ccAddresses = (context.platformContext.cc as string[]) || [];
|
|
@@ -916,7 +924,7 @@ function buildReplyAllCc(context: IncomingMessage): string[] | undefined {
|
|
|
916
924
|
for (const addr of [...toAddresses, ...ccAddresses]) {
|
|
917
925
|
const normalized = addr.toLowerCase().trim();
|
|
918
926
|
// Exclude agent address and original sender (sender goes in To)
|
|
919
|
-
if (normalized !==
|
|
927
|
+
if (normalized !== normalizedAgentAddress && normalized !== senderEmail) {
|
|
920
928
|
allRecipients.add(normalized);
|
|
921
929
|
}
|
|
922
930
|
}
|
|
@@ -2,6 +2,7 @@ import type { H3Event } from "h3";
|
|
|
2
2
|
import { createError, getHeader, readRawBody } from "h3";
|
|
3
3
|
|
|
4
4
|
import type { EnvKeyConfig } from "../../server/create-server.js";
|
|
5
|
+
import { resolveSecret } from "../../server/credential-provider.js";
|
|
5
6
|
import type {
|
|
6
7
|
PlatformAdapter,
|
|
7
8
|
IncomingMessage,
|
|
@@ -80,7 +81,7 @@ export function slackAdapter(): PlatformAdapter {
|
|
|
80
81
|
},
|
|
81
82
|
|
|
82
83
|
async verifyWebhook(event: H3Event): Promise<boolean> {
|
|
83
|
-
const signingSecret =
|
|
84
|
+
const signingSecret = await resolveSecret("SLACK_SIGNING_SECRET");
|
|
84
85
|
if (!signingSecret) return false;
|
|
85
86
|
|
|
86
87
|
const signature = getHeader(event, "x-slack-signature");
|
|
@@ -185,7 +186,7 @@ export function slackAdapter(): PlatformAdapter {
|
|
|
185
186
|
// redundant and added an extra chunk that we then had to overwrite.
|
|
186
187
|
// We just set the native status and return null so sendResponse posts
|
|
187
188
|
// the final reply as a fresh message.
|
|
188
|
-
const token =
|
|
189
|
+
const token = await resolveSecret("SLACK_BOT_TOKEN");
|
|
189
190
|
if (!token) return null;
|
|
190
191
|
|
|
191
192
|
const channelId = incoming.platformContext.channelId as string;
|
|
@@ -204,7 +205,7 @@ export function slackAdapter(): PlatformAdapter {
|
|
|
204
205
|
context: IncomingMessage,
|
|
205
206
|
opts?: { placeholderRef?: string },
|
|
206
207
|
): Promise<void> {
|
|
207
|
-
const token =
|
|
208
|
+
const token = await resolveSecret("SLACK_BOT_TOKEN");
|
|
208
209
|
if (!token) {
|
|
209
210
|
console.error("[slack] SLACK_BOT_TOKEN not configured");
|
|
210
211
|
return;
|
|
@@ -297,7 +298,7 @@ export function slackAdapter(): PlatformAdapter {
|
|
|
297
298
|
message: OutgoingMessage,
|
|
298
299
|
target: OutboundTarget,
|
|
299
300
|
): Promise<void> {
|
|
300
|
-
const token =
|
|
301
|
+
const token = await resolveSecret("SLACK_BOT_TOKEN");
|
|
301
302
|
if (!token) {
|
|
302
303
|
console.error("[slack] SLACK_BOT_TOKEN not configured");
|
|
303
304
|
return;
|
|
@@ -348,8 +349,8 @@ export function slackAdapter(): PlatformAdapter {
|
|
|
348
349
|
},
|
|
349
350
|
|
|
350
351
|
async getStatus(_baseUrl?: string): Promise<IntegrationStatus> {
|
|
351
|
-
const hasToken = !!
|
|
352
|
-
const hasSecret = !!
|
|
352
|
+
const hasToken = !!(await resolveSecret("SLACK_BOT_TOKEN"));
|
|
353
|
+
const hasSecret = !!(await resolveSecret("SLACK_SIGNING_SECRET"));
|
|
353
354
|
const configured = hasToken && hasSecret;
|
|
354
355
|
|
|
355
356
|
return {
|
|
@@ -362,7 +363,7 @@ export function slackAdapter(): PlatformAdapter {
|
|
|
362
363
|
hasSecret,
|
|
363
364
|
},
|
|
364
365
|
error: !configured
|
|
365
|
-
? "
|
|
366
|
+
? "Save SLACK_BOT_TOKEN and SLACK_SIGNING_SECRET in settings"
|
|
366
367
|
: undefined,
|
|
367
368
|
};
|
|
368
369
|
},
|
|
@@ -2,6 +2,7 @@ import type { H3Event } from "h3";
|
|
|
2
2
|
import { getHeader } from "h3";
|
|
3
3
|
|
|
4
4
|
import type { EnvKeyConfig } from "../../server/create-server.js";
|
|
5
|
+
import { resolveSecret } from "../../server/credential-provider.js";
|
|
5
6
|
import { readBody } from "../../server/h3-helpers.js";
|
|
6
7
|
import type {
|
|
7
8
|
PlatformAdapter,
|
|
@@ -86,7 +87,7 @@ export function telegramAdapter(): PlatformAdapter {
|
|
|
86
87
|
},
|
|
87
88
|
|
|
88
89
|
async verifyWebhook(event: H3Event): Promise<boolean> {
|
|
89
|
-
const secret =
|
|
90
|
+
const secret = await resolveSecret("TELEGRAM_WEBHOOK_SECRET");
|
|
90
91
|
if (!secret) {
|
|
91
92
|
if (shouldRefuseWhenSecretMissing()) {
|
|
92
93
|
if (!_telegramUnverifiedWarned) {
|
|
@@ -105,7 +106,7 @@ export function telegramAdapter(): PlatformAdapter {
|
|
|
105
106
|
);
|
|
106
107
|
}
|
|
107
108
|
// Dev mode: still require the bot token to be configured at all.
|
|
108
|
-
return !!
|
|
109
|
+
return !!(await resolveSecret("TELEGRAM_BOT_TOKEN"));
|
|
109
110
|
}
|
|
110
111
|
|
|
111
112
|
const headerSecret = getHeader(event, "x-telegram-bot-api-secret-token");
|
|
@@ -172,7 +173,7 @@ export function telegramAdapter(): PlatformAdapter {
|
|
|
172
173
|
message: OutgoingMessage,
|
|
173
174
|
context: IncomingMessage,
|
|
174
175
|
): Promise<void> {
|
|
175
|
-
const token =
|
|
176
|
+
const token = await resolveSecret("TELEGRAM_BOT_TOKEN");
|
|
176
177
|
if (!token) {
|
|
177
178
|
console.error("[telegram] TELEGRAM_BOT_TOKEN not configured");
|
|
178
179
|
return;
|
|
@@ -224,7 +225,7 @@ export function telegramAdapter(): PlatformAdapter {
|
|
|
224
225
|
message: OutgoingMessage,
|
|
225
226
|
target: OutboundTarget,
|
|
226
227
|
): Promise<void> {
|
|
227
|
-
const token =
|
|
228
|
+
const token = await resolveSecret("TELEGRAM_BOT_TOKEN");
|
|
228
229
|
if (!token) {
|
|
229
230
|
console.error("[telegram] TELEGRAM_BOT_TOKEN not configured");
|
|
230
231
|
return;
|
|
@@ -272,14 +273,13 @@ export function telegramAdapter(): PlatformAdapter {
|
|
|
272
273
|
},
|
|
273
274
|
|
|
274
275
|
async getStatus(_baseUrl?: string): Promise<IntegrationStatus> {
|
|
275
|
-
const
|
|
276
|
+
const token = await resolveSecret("TELEGRAM_BOT_TOKEN");
|
|
277
|
+
const hasToken = !!token;
|
|
276
278
|
|
|
277
279
|
let botName: string | undefined;
|
|
278
280
|
if (hasToken) {
|
|
279
281
|
try {
|
|
280
|
-
const res = await fetch(
|
|
281
|
-
`https://api.telegram.org/bot${process.env.TELEGRAM_BOT_TOKEN}/getMe`,
|
|
282
|
-
);
|
|
282
|
+
const res = await fetch(`https://api.telegram.org/bot${token}/getMe`);
|
|
283
283
|
const data = (await res.json()) as {
|
|
284
284
|
ok: boolean;
|
|
285
285
|
result?: { username?: string };
|
|
@@ -299,9 +299,7 @@ export function telegramAdapter(): PlatformAdapter {
|
|
|
299
299
|
hasToken,
|
|
300
300
|
botUsername: botName,
|
|
301
301
|
},
|
|
302
|
-
error: !hasToken
|
|
303
|
-
? "Set TELEGRAM_BOT_TOKEN in your environment"
|
|
304
|
-
: undefined,
|
|
302
|
+
error: !hasToken ? "Save TELEGRAM_BOT_TOKEN in settings" : undefined,
|
|
305
303
|
};
|
|
306
304
|
},
|
|
307
305
|
};
|
|
@@ -2,6 +2,7 @@ import type { H3Event } from "h3";
|
|
|
2
2
|
import { getQuery, getHeader, readRawBody as h3ReadRawBody } from "h3";
|
|
3
3
|
|
|
4
4
|
import type { EnvKeyConfig } from "../../server/create-server.js";
|
|
5
|
+
import { resolveSecret } from "../../server/credential-provider.js";
|
|
5
6
|
import type {
|
|
6
7
|
PlatformAdapter,
|
|
7
8
|
IncomingMessage,
|
|
@@ -103,7 +104,7 @@ export function whatsappAdapter(): PlatformAdapter {
|
|
|
103
104
|
const mode = query["hub.mode"];
|
|
104
105
|
const token = query["hub.verify_token"];
|
|
105
106
|
const challenge = query["hub.challenge"];
|
|
106
|
-
const expected =
|
|
107
|
+
const expected = await resolveSecret("WHATSAPP_VERIFY_TOKEN");
|
|
107
108
|
|
|
108
109
|
if (mode === "subscribe" && expected && typeof token === "string") {
|
|
109
110
|
// Timing-safe compare so an attacker can't measure character-wise
|
|
@@ -126,7 +127,7 @@ export function whatsappAdapter(): PlatformAdapter {
|
|
|
126
127
|
},
|
|
127
128
|
|
|
128
129
|
async verifyWebhook(event: H3Event): Promise<boolean> {
|
|
129
|
-
const appSecret =
|
|
130
|
+
const appSecret = await resolveSecret("WHATSAPP_APP_SECRET");
|
|
130
131
|
if (!appSecret) {
|
|
131
132
|
if (shouldRefuseWhenSecretMissing()) {
|
|
132
133
|
if (!_whatsappUnverifiedWarned) {
|
|
@@ -145,7 +146,7 @@ export function whatsappAdapter(): PlatformAdapter {
|
|
|
145
146
|
);
|
|
146
147
|
}
|
|
147
148
|
// Dev mode: still require the access token to be configured at all.
|
|
148
|
-
return !!
|
|
149
|
+
return !!(await resolveSecret("WHATSAPP_ACCESS_TOKEN"));
|
|
149
150
|
}
|
|
150
151
|
|
|
151
152
|
const signature = getHeader(event, "x-hub-signature-256");
|
|
@@ -223,8 +224,8 @@ export function whatsappAdapter(): PlatformAdapter {
|
|
|
223
224
|
message: OutgoingMessage,
|
|
224
225
|
context: IncomingMessage,
|
|
225
226
|
): Promise<void> {
|
|
226
|
-
const accessToken =
|
|
227
|
-
const phoneNumberId =
|
|
227
|
+
const accessToken = await resolveSecret("WHATSAPP_ACCESS_TOKEN");
|
|
228
|
+
const phoneNumberId = await resolveSecret("WHATSAPP_PHONE_NUMBER_ID");
|
|
228
229
|
if (!accessToken || !phoneNumberId) {
|
|
229
230
|
console.error(
|
|
230
231
|
"[whatsapp] WHATSAPP_ACCESS_TOKEN or WHATSAPP_PHONE_NUMBER_ID not configured",
|
|
@@ -269,9 +270,11 @@ export function whatsappAdapter(): PlatformAdapter {
|
|
|
269
270
|
},
|
|
270
271
|
|
|
271
272
|
async getStatus(_baseUrl?: string): Promise<IntegrationStatus> {
|
|
272
|
-
const hasAccessToken = !!
|
|
273
|
-
const hasVerifyToken = !!
|
|
274
|
-
const hasPhoneNumberId = !!
|
|
273
|
+
const hasAccessToken = !!(await resolveSecret("WHATSAPP_ACCESS_TOKEN"));
|
|
274
|
+
const hasVerifyToken = !!(await resolveSecret("WHATSAPP_VERIFY_TOKEN"));
|
|
275
|
+
const hasPhoneNumberId = !!(await resolveSecret(
|
|
276
|
+
"WHATSAPP_PHONE_NUMBER_ID",
|
|
277
|
+
));
|
|
275
278
|
const configured = hasAccessToken && hasVerifyToken && hasPhoneNumberId;
|
|
276
279
|
|
|
277
280
|
return {
|
|
@@ -285,7 +288,7 @@ export function whatsappAdapter(): PlatformAdapter {
|
|
|
285
288
|
hasPhoneNumberId,
|
|
286
289
|
},
|
|
287
290
|
error: !configured
|
|
288
|
-
? "
|
|
291
|
+
? "Save WHATSAPP_ACCESS_TOKEN, WHATSAPP_VERIFY_TOKEN, and WHATSAPP_PHONE_NUMBER_ID in settings"
|
|
289
292
|
: undefined,
|
|
290
293
|
};
|
|
291
294
|
},
|