@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
|
@@ -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
|
},
|
|
@@ -2,16 +2,18 @@ import { defineEventHandler, setResponseStatus, getMethod, getQuery } from "h3";
|
|
|
2
2
|
import { getRequestHeader } from "h3";
|
|
3
3
|
import { createRemoteJWKSet, jwtVerify } from "jose";
|
|
4
4
|
|
|
5
|
-
import { getOrgContext } from "../org/context.js";
|
|
5
|
+
import { getOrgContext, resolveOrgIdForEmail } from "../org/context.js";
|
|
6
6
|
import { loadResourcesForPrompt } from "../server/agent-chat-plugin.js";
|
|
7
7
|
import { withConfiguredAppBasePath } from "../server/app-base-path.js";
|
|
8
8
|
import { getSession } from "../server/auth.js";
|
|
9
9
|
import { FRAMEWORK_ROUTE_PREFIX } from "../server/core-routes-plugin.js";
|
|
10
|
+
import { resolveSecret } from "../server/credential-provider.js";
|
|
10
11
|
import {
|
|
11
12
|
getH3App,
|
|
12
13
|
markDefaultPluginProvided,
|
|
13
14
|
} from "../server/framework-request-handler.js";
|
|
14
15
|
import { readBody } from "../server/h3-helpers.js";
|
|
16
|
+
import { runWithRequestContext } from "../server/request-context.js";
|
|
15
17
|
import {
|
|
16
18
|
processA2AContinuationById,
|
|
17
19
|
processDueA2AContinuations,
|
|
@@ -175,6 +177,12 @@ type RemoteCodeCommandEnvelope = {
|
|
|
175
177
|
source?: unknown;
|
|
176
178
|
};
|
|
177
179
|
|
|
180
|
+
type IntegrationCredentialContext = {
|
|
181
|
+
userEmail: string;
|
|
182
|
+
orgId?: string;
|
|
183
|
+
isIntegrationCaller?: boolean;
|
|
184
|
+
};
|
|
185
|
+
|
|
178
186
|
const REMOTE_DEVICE_ONLINE_MS = 90_000;
|
|
179
187
|
|
|
180
188
|
export async function enqueueRemoteCommand(
|
|
@@ -517,8 +525,7 @@ export function createIntegrationsPlugin(
|
|
|
517
525
|
// init can leave us with an empty string forever. The getter
|
|
518
526
|
// re-resolves on every webhook so freshly-set secrets work without
|
|
519
527
|
// a redeploy.
|
|
520
|
-
const getApiKey = () =>
|
|
521
|
-
options?.apiKey ?? process.env.ANTHROPIC_API_KEY ?? "";
|
|
528
|
+
const getApiKey = () => options?.apiKey ?? "";
|
|
522
529
|
|
|
523
530
|
// Build the system prompt
|
|
524
531
|
const baseSystemPrompt = options?.systemPrompt ?? INTEGRATION_SYSTEM_PROMPT;
|
|
@@ -569,6 +576,39 @@ export function createIntegrationsPlugin(
|
|
|
569
576
|
};
|
|
570
577
|
}
|
|
571
578
|
|
|
579
|
+
function toCredentialContext(
|
|
580
|
+
ctx: { ownerEmail: string; orgId: string | null },
|
|
581
|
+
opts?: { isIntegrationCaller?: boolean },
|
|
582
|
+
): IntegrationCredentialContext {
|
|
583
|
+
return {
|
|
584
|
+
userEmail: ctx.ownerEmail,
|
|
585
|
+
...(ctx.orgId ? { orgId: ctx.orgId } : {}),
|
|
586
|
+
...(opts?.isIntegrationCaller ? { isIntegrationCaller: true } : {}),
|
|
587
|
+
};
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
async function credentialContextForIntegrationConfig(
|
|
591
|
+
config: Awaited<ReturnType<typeof getIntegrationConfig>>,
|
|
592
|
+
): Promise<IntegrationCredentialContext | null> {
|
|
593
|
+
const ownerEmail =
|
|
594
|
+
typeof config?.owner === "string" ? config.owner.trim() : "";
|
|
595
|
+
if (!ownerEmail) return null;
|
|
596
|
+
const orgId = await resolveOrgIdForEmail(ownerEmail).catch(() => null);
|
|
597
|
+
return {
|
|
598
|
+
userEmail: ownerEmail,
|
|
599
|
+
...(orgId ? { orgId } : {}),
|
|
600
|
+
isIntegrationCaller: true,
|
|
601
|
+
};
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
async function withCredentialContext<T>(
|
|
605
|
+
context: IntegrationCredentialContext | null,
|
|
606
|
+
fn: () => Promise<T>,
|
|
607
|
+
): Promise<T> {
|
|
608
|
+
if (!context) return fn();
|
|
609
|
+
return runWithRequestContext(context, fn);
|
|
610
|
+
}
|
|
611
|
+
|
|
572
612
|
async function requireRemoteDevice(event: any) {
|
|
573
613
|
const token = extractBearerToken(
|
|
574
614
|
getRequestHeader(event, "authorization"),
|
|
@@ -627,11 +667,15 @@ export function createIntegrationsPlugin(
|
|
|
627
667
|
setResponseStatus(event, 405);
|
|
628
668
|
return { error: "Method not allowed" };
|
|
629
669
|
}
|
|
630
|
-
if (!(await requireSession(event))) return { error: "unauthorized" };
|
|
631
670
|
const baseUrl = getBaseUrl(event);
|
|
671
|
+
const ctx = await requireSessionContext(event);
|
|
672
|
+
if (!ctx) return { error: "unauthorized" };
|
|
673
|
+
const credentialContext = toCredentialContext(ctx);
|
|
632
674
|
const statuses: IntegrationStatus[] = [];
|
|
633
675
|
for (const adapter of adapters) {
|
|
634
|
-
const status = await
|
|
676
|
+
const status = await withCredentialContext(credentialContext, () =>
|
|
677
|
+
adapter.getStatus(baseUrl),
|
|
678
|
+
);
|
|
635
679
|
const config = await getIntegrationConfig(adapter.platform);
|
|
636
680
|
status.enabled = !!config?.configData?.enabled;
|
|
637
681
|
status.webhookUrl = `${baseUrl}${P}/${adapter.platform}/webhook`;
|
|
@@ -1422,9 +1466,13 @@ export function createIntegrationsPlugin(
|
|
|
1422
1466
|
|
|
1423
1467
|
// ─── GET /:platform/status ─────────────────────────────
|
|
1424
1468
|
if (action === "status" && method === "GET") {
|
|
1425
|
-
|
|
1469
|
+
const ctx = await requireSessionContext(event);
|
|
1470
|
+
if (!ctx) return { error: "unauthorized" };
|
|
1426
1471
|
const baseUrl = getBaseUrl(event);
|
|
1427
|
-
const status = await
|
|
1472
|
+
const status = await withCredentialContext(
|
|
1473
|
+
toCredentialContext(ctx),
|
|
1474
|
+
() => adapter.getStatus(baseUrl),
|
|
1475
|
+
);
|
|
1428
1476
|
const config = await getIntegrationConfig(platform);
|
|
1429
1477
|
status.enabled = !!config?.configData?.enabled;
|
|
1430
1478
|
status.webhookUrl = `${baseUrl}${P}/${platform}/webhook`;
|
|
@@ -1482,14 +1530,20 @@ export function createIntegrationsPlugin(
|
|
|
1482
1530
|
return "ok";
|
|
1483
1531
|
}
|
|
1484
1532
|
|
|
1533
|
+
const config = await getIntegrationConfig(platform);
|
|
1534
|
+
const credentialContext =
|
|
1535
|
+
await credentialContextForIntegrationConfig(config);
|
|
1536
|
+
|
|
1485
1537
|
// Handle platform verification challenges (e.g. Slack url_verification)
|
|
1486
1538
|
// before checking enable state or parsing the message.
|
|
1487
|
-
const verification = await
|
|
1539
|
+
const verification = await withCredentialContext(
|
|
1540
|
+
credentialContext,
|
|
1541
|
+
() => adapter.handleVerification(event),
|
|
1542
|
+
);
|
|
1488
1543
|
if (verification.handled) {
|
|
1489
1544
|
return verification.response ?? "ok";
|
|
1490
1545
|
}
|
|
1491
1546
|
|
|
1492
|
-
const config = await getIntegrationConfig(platform);
|
|
1493
1547
|
if (!config?.configData?.enabled) {
|
|
1494
1548
|
setResponseStatus(event, 404);
|
|
1495
1549
|
return { error: `Integration ${platform} is not enabled` };
|
|
@@ -1500,13 +1554,17 @@ export function createIntegrationsPlugin(
|
|
|
1500
1554
|
// hangs on streaming providers), and that means handleWebhook's
|
|
1501
1555
|
// own verifyWebhook step is bypassed. Without this call anyone
|
|
1502
1556
|
// could POST a forged Slack/Telegram/email payload.
|
|
1503
|
-
const isValid = await
|
|
1557
|
+
const isValid = await withCredentialContext(credentialContext, () =>
|
|
1558
|
+
adapter.verifyWebhook(event),
|
|
1559
|
+
);
|
|
1504
1560
|
if (!isValid) {
|
|
1505
1561
|
setResponseStatus(event, 401);
|
|
1506
1562
|
return { error: "Invalid webhook signature" };
|
|
1507
1563
|
}
|
|
1508
1564
|
|
|
1509
|
-
const incoming = await
|
|
1565
|
+
const incoming = await withCredentialContext(credentialContext, () =>
|
|
1566
|
+
adapter.parseIncomingMessage(event),
|
|
1567
|
+
);
|
|
1510
1568
|
if (!incoming) {
|
|
1511
1569
|
setResponseStatus(event, 200);
|
|
1512
1570
|
return "ok";
|
|
@@ -1582,10 +1640,18 @@ export function createIntegrationsPlugin(
|
|
|
1582
1640
|
if (platform === "telegram") {
|
|
1583
1641
|
const baseUrl = getBaseUrl(event);
|
|
1584
1642
|
const webhookUrl = `${baseUrl}${P}/telegram/webhook`;
|
|
1585
|
-
const
|
|
1643
|
+
const ctx = await requireSessionContext(event);
|
|
1644
|
+
if (!ctx) return { error: "unauthorized" };
|
|
1645
|
+
const token = await withCredentialContext(
|
|
1646
|
+
toCredentialContext(ctx),
|
|
1647
|
+
() => resolveSecret("TELEGRAM_BOT_TOKEN"),
|
|
1648
|
+
);
|
|
1586
1649
|
if (!token) {
|
|
1587
1650
|
setResponseStatus(event, 400);
|
|
1588
|
-
return {
|
|
1651
|
+
return {
|
|
1652
|
+
error:
|
|
1653
|
+
"TELEGRAM_BOT_TOKEN not configured. Save it in settings.",
|
|
1654
|
+
};
|
|
1589
1655
|
}
|
|
1590
1656
|
try {
|
|
1591
1657
|
const res = await fetch(
|
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
import {
|
|
18
18
|
canUseDeployCredentialFallbackForRequest,
|
|
19
19
|
readDeployCredentialEnv,
|
|
20
|
+
resolveSecret,
|
|
20
21
|
} from "../server/credential-provider.js";
|
|
21
22
|
import { getSetting } from "../settings/store.js";
|
|
22
23
|
import { registerOnboardingStep } from "./registry.js";
|
|
@@ -287,12 +288,14 @@ const emailStep: OnboardingStep = {
|
|
|
287
288
|
},
|
|
288
289
|
},
|
|
289
290
|
],
|
|
290
|
-
isComplete: () => {
|
|
291
|
-
if (
|
|
291
|
+
isComplete: async () => {
|
|
292
|
+
if (await resolveSecret("RESEND_API_KEY")) return true;
|
|
292
293
|
// SendGrid rejects Resend's sandbox sender, so EMAIL_FROM must also be
|
|
293
294
|
// set — otherwise sendEmail() throws at runtime even though the API key
|
|
294
295
|
// is configured.
|
|
295
|
-
if (
|
|
296
|
+
if (await resolveSecret("SENDGRID_API_KEY")) {
|
|
297
|
+
return !!(await resolveSecret("EMAIL_FROM"));
|
|
298
|
+
}
|
|
296
299
|
return false;
|
|
297
300
|
},
|
|
298
301
|
};
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
export type OnboardingMethodBadge = "recommended" | "beta" | "free" | "soon";
|
|
11
11
|
|
|
12
|
-
/** Fields for a form-style onboarding method (key/value
|
|
12
|
+
/** Fields for a form-style onboarding method (key/value secret entry). */
|
|
13
13
|
export interface OnboardingFormField {
|
|
14
14
|
key: string;
|
|
15
15
|
label: string;
|
|
@@ -5435,10 +5435,7 @@ export function createAgentChatPlugin(
|
|
|
5435
5435
|
// Sub-agents must inherit the parent run's resolved key so
|
|
5436
5436
|
// delegations spawned by agent-teams don't silently fall back
|
|
5437
5437
|
// to the platform key while the parent uses BYO credentials.
|
|
5438
|
-
apiKey:
|
|
5439
|
-
runCtx?.userApiKey ??
|
|
5440
|
-
options?.apiKey ??
|
|
5441
|
-
process.env.ANTHROPIC_API_KEY,
|
|
5438
|
+
apiKey: runCtx?.userApiKey ?? options?.apiKey,
|
|
5442
5439
|
})
|
|
5443
5440
|
);
|
|
5444
5441
|
},
|
|
@@ -6949,7 +6946,7 @@ Non-code requests are still fine on this surface: read data, navigate the UI, su
|
|
|
6949
6946
|
const { getOwnerActiveApiKey } =
|
|
6950
6947
|
await import("../agent/production-agent.js");
|
|
6951
6948
|
const userApiKey = await getOwnerActiveApiKey(ownerEmail);
|
|
6952
|
-
const apiKey = userApiKey
|
|
6949
|
+
const apiKey = userApiKey;
|
|
6953
6950
|
if (!apiKey) {
|
|
6954
6951
|
// Fallback: truncate the message
|
|
6955
6952
|
return { title: cleanMessage.trim().slice(0, 60) };
|
|
@@ -7985,7 +7982,7 @@ Non-code requests are still fine on this surface: read data, navigate the UI, su
|
|
|
7985
7982
|
: await buildSchemaBlock(owner, databaseToolsMode);
|
|
7986
7983
|
return basePrompt + resources + schemaBlock;
|
|
7987
7984
|
},
|
|
7988
|
-
apiKey: options?.apiKey
|
|
7985
|
+
apiKey: options?.apiKey,
|
|
7989
7986
|
model: options?.model,
|
|
7990
7987
|
appId: options?.appId,
|
|
7991
7988
|
};
|
|
@@ -8084,7 +8081,7 @@ Non-code requests are still fine on this surface: read data, navigate the UI, su
|
|
|
8084
8081
|
: await buildSchemaBlock(owner, databaseToolsMode);
|
|
8085
8082
|
return basePrompt + resources + schemaBlock;
|
|
8086
8083
|
},
|
|
8087
|
-
apiKey: options?.apiKey
|
|
8084
|
+
apiKey: options?.apiKey,
|
|
8088
8085
|
model: options?.model,
|
|
8089
8086
|
appId: options?.appId,
|
|
8090
8087
|
});
|