@agent-native/core 0.79.16 → 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 +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/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 +55 -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/library/library-layout.tsx +3 -3
- 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/changelog/2026-06-26-the-clips-library-now-matches-the-shared-recessed-shell-styl.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/awareness.d.ts +2 -2
- package/dist/collab/awareness.d.ts.map +1 -1
- package/dist/collab/routes.d.ts +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 +1 -1
- 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/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/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 +55 -3
- package/dist/templates/workspace-root/AGENTS.md +3 -2
- package/dist/templates/workspace-root/README.md +1 -1
- package/dist/templates/workspace-root/scripts/repair-workspace-org.ts +29 -90
- package/dist/terminal/pty-server.d.ts.map +1 -1
- package/dist/terminal/pty-server.js +3 -36
- package/dist/terminal/pty-server.js.map +1 -1
- package/dist/triggers/dispatcher.js +1 -1
- package/dist/triggers/dispatcher.js.map +1 -1
- package/docs/content/file-uploads.md +11 -4
- package/docs/content/locales/ar-SA/multi-app-workspace.md +3 -3
- package/docs/content/locales/de-DE/multi-app-workspace.md +3 -3
- package/docs/content/locales/es-ES/multi-app-workspace.md +3 -3
- package/docs/content/locales/fr-FR/multi-app-workspace.md +3 -3
- package/docs/content/locales/hi-IN/multi-app-workspace.md +3 -3
- package/docs/content/locales/ja-JP/multi-app-workspace.md +3 -3
- package/docs/content/locales/ko-KR/multi-app-workspace.md +3 -3
- package/docs/content/locales/pt-BR/multi-app-workspace.md +3 -3
- package/docs/content/locales/zh-CN/multi-app-workspace.md +3 -3
- package/docs/content/locales/zh-TW/multi-app-workspace.md +3 -3
- package/docs/content/multi-app-workspace.md +3 -3
- package/docs/content/template-clips.md +14 -5
- package/package.json +1 -1
- package/src/templates/workspace-root/AGENTS.md +3 -2
- package/src/templates/workspace-root/README.md +1 -1
- package/src/templates/workspace-root/scripts/repair-workspace-org.ts +29 -90
- package/corpus/core/src/server/env-var-writes.ts +0 -16
- package/corpus/templates/analytics/app/pages/Team.tsx +0 -9
- package/corpus/templates/calendar/app/pages/Team.tsx +0 -12
- package/corpus/templates/mail/app/pages/Team.tsx +0 -17
- package/dist/server/env-var-writes.d.ts +0 -10
- package/dist/server/env-var-writes.d.ts.map +0 -1
- package/dist/server/env-var-writes.js +0 -18
- package/dist/server/env-var-writes.js.map +0 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Email transport for system emails (password resets, invitations, notifications).
|
|
3
3
|
*
|
|
4
|
-
* Providers are selected by
|
|
4
|
+
* Providers are selected by scoped secrets:
|
|
5
5
|
* RESEND_API_KEY — https://resend.com
|
|
6
6
|
* SENDGRID_API_KEY — https://sendgrid.com
|
|
7
7
|
* EMAIL_FROM — "Name <addr@domain>" (optional; defaults to Resend's sandbox)
|
|
@@ -10,6 +10,8 @@
|
|
|
10
10
|
* so the reset-password flow still works end-to-end for local development.
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
+
import { resolveSecret } from "./credential-provider.js";
|
|
14
|
+
|
|
13
15
|
export type EmailProvider = "resend" | "sendgrid" | "dev";
|
|
14
16
|
|
|
15
17
|
export interface EmailAttachment {
|
|
@@ -33,32 +35,65 @@ export interface SendEmailArgs {
|
|
|
33
35
|
attachments?: EmailAttachment[];
|
|
34
36
|
}
|
|
35
37
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
+
interface EmailTransportConfig {
|
|
39
|
+
provider: EmailProvider;
|
|
40
|
+
resendApiKey?: string;
|
|
41
|
+
sendgridApiKey?: string;
|
|
42
|
+
from?: string;
|
|
38
43
|
}
|
|
39
44
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
45
|
+
async function resolveEmailTransport(): Promise<EmailTransportConfig> {
|
|
46
|
+
const [resendApiKey, sendgridApiKey, from] = await Promise.all([
|
|
47
|
+
resolveSecret("RESEND_API_KEY"),
|
|
48
|
+
resolveSecret("SENDGRID_API_KEY"),
|
|
49
|
+
resolveSecret("EMAIL_FROM"),
|
|
50
|
+
]);
|
|
51
|
+
const resolvedFrom = from ?? undefined;
|
|
52
|
+
if (resendApiKey) {
|
|
53
|
+
return {
|
|
54
|
+
provider: "resend",
|
|
55
|
+
resendApiKey,
|
|
56
|
+
from: resolvedFrom,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
if (sendgridApiKey) {
|
|
60
|
+
return {
|
|
61
|
+
provider: "sendgrid",
|
|
62
|
+
sendgridApiKey,
|
|
63
|
+
from: resolvedFrom,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
return { provider: "dev", from: resolvedFrom };
|
|
44
67
|
}
|
|
45
68
|
|
|
46
|
-
function
|
|
47
|
-
|
|
69
|
+
export async function isEmailConfigured(): Promise<boolean> {
|
|
70
|
+
return (await resolveEmailTransport()).provider !== "dev";
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export async function getEmailProvider(): Promise<EmailProvider> {
|
|
74
|
+
return (await resolveEmailTransport()).provider;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function getFromAddress(
|
|
78
|
+
config: EmailTransportConfig,
|
|
79
|
+
override?: string,
|
|
80
|
+
): string {
|
|
81
|
+
const explicit = override || config.from;
|
|
48
82
|
if (explicit) return explicit;
|
|
49
83
|
// Resend lets unverified accounts send from its sandbox domain; SendGrid
|
|
50
84
|
// does not, so falling back there would cause silent 403s at runtime.
|
|
51
|
-
if (provider === "sendgrid") {
|
|
85
|
+
if (config.provider === "sendgrid") {
|
|
52
86
|
throw new Error(
|
|
53
|
-
"EMAIL_FROM is required when using SendGrid —
|
|
87
|
+
"EMAIL_FROM is required when using SendGrid — save it as a verified sender address.",
|
|
54
88
|
);
|
|
55
89
|
}
|
|
56
90
|
return "Agent Native <onboarding@resend.dev>";
|
|
57
91
|
}
|
|
58
92
|
|
|
59
93
|
export async function sendEmail(args: SendEmailArgs): Promise<void> {
|
|
60
|
-
const
|
|
61
|
-
const
|
|
94
|
+
const config = await resolveEmailTransport();
|
|
95
|
+
const provider = config.provider;
|
|
96
|
+
const from = getFromAddress(config, args.from);
|
|
62
97
|
|
|
63
98
|
if (provider === "resend") {
|
|
64
99
|
const payload: Record<string, unknown> = {
|
|
@@ -89,7 +124,7 @@ export async function sendEmail(args: SendEmailArgs): Promise<void> {
|
|
|
89
124
|
const res = await fetch("https://api.resend.com/emails", {
|
|
90
125
|
method: "POST",
|
|
91
126
|
headers: {
|
|
92
|
-
Authorization: `Bearer ${
|
|
127
|
+
Authorization: `Bearer ${config.resendApiKey}`,
|
|
93
128
|
"Content-Type": "application/json",
|
|
94
129
|
},
|
|
95
130
|
body: JSON.stringify(payload),
|
|
@@ -140,7 +175,7 @@ export async function sendEmail(args: SendEmailArgs): Promise<void> {
|
|
|
140
175
|
const res = await fetch("https://api.sendgrid.com/v3/mail/send", {
|
|
141
176
|
method: "POST",
|
|
142
177
|
headers: {
|
|
143
|
-
Authorization: `Bearer ${
|
|
178
|
+
Authorization: `Bearer ${config.sendgridApiKey}`,
|
|
144
179
|
"Content-Type": "application/json",
|
|
145
180
|
},
|
|
146
181
|
body: JSON.stringify(sgPayload),
|
|
@@ -157,12 +192,12 @@ export async function sendEmail(args: SendEmailArgs): Promise<void> {
|
|
|
157
192
|
// to send rather than silently leaking secrets to logs.
|
|
158
193
|
if (process.env.NODE_ENV === "production") {
|
|
159
194
|
throw new Error(
|
|
160
|
-
"No email provider configured.
|
|
195
|
+
"No email provider configured. Save RESEND_API_KEY or SENDGRID_API_KEY in settings.",
|
|
161
196
|
);
|
|
162
197
|
}
|
|
163
198
|
console.log(
|
|
164
199
|
`\n[agent-native:email] No email provider configured. ` +
|
|
165
|
-
`
|
|
200
|
+
`Save RESEND_API_KEY or SENDGRID_API_KEY in settings to send real emails.\n` +
|
|
166
201
|
`---\nTo: ${args.to}\nFrom: ${from}\nSubject: ${args.subject}\n\n` +
|
|
167
202
|
`${args.text || stripHtml(args.html)}\n---\n`,
|
|
168
203
|
);
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
export {
|
|
2
2
|
createServer,
|
|
3
|
-
upsertEnvFile,
|
|
4
3
|
type CreateServerOptions,
|
|
5
4
|
type EnvKeyConfig,
|
|
6
5
|
} from "./create-server.js";
|
|
@@ -325,6 +324,7 @@ export {
|
|
|
325
324
|
unregisterFileUploadProvider,
|
|
326
325
|
listFileUploadProviders,
|
|
327
326
|
getActiveFileUploadProvider,
|
|
327
|
+
getActiveFileUploadProviderForRequest,
|
|
328
328
|
uploadFile,
|
|
329
329
|
builderFileUploadProvider,
|
|
330
330
|
type FileUploadInput,
|
|
@@ -381,6 +381,7 @@ export {
|
|
|
381
381
|
resolveHasCompleteBuilderConnection,
|
|
382
382
|
resolveBuilderCredentials,
|
|
383
383
|
resolveBuilderCredential,
|
|
384
|
+
readDeployCredentialEnv,
|
|
384
385
|
writeBuilderCredentials,
|
|
385
386
|
deleteBuilderCredentials,
|
|
386
387
|
resolveSecret,
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
import type { H3Event } from "h3";
|
|
2
|
+
|
|
3
|
+
import { getOrgContext } from "../org/context.js";
|
|
4
|
+
import {
|
|
5
|
+
getRequiredSecret,
|
|
6
|
+
type RegisteredSecret,
|
|
7
|
+
type SecretScope,
|
|
8
|
+
} from "../secrets/register.js";
|
|
9
|
+
import { writeAppSecret } from "../secrets/storage.js";
|
|
10
|
+
import { getSession } from "./auth.js";
|
|
11
|
+
|
|
12
|
+
const KEY_NAME_RE = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
13
|
+
|
|
14
|
+
export type ScopedKeySaveRequestScope =
|
|
15
|
+
| "app"
|
|
16
|
+
| "auto"
|
|
17
|
+
| "org"
|
|
18
|
+
| "user"
|
|
19
|
+
| "workspace"
|
|
20
|
+
| undefined;
|
|
21
|
+
|
|
22
|
+
export interface ScopedKeyValue {
|
|
23
|
+
key: string;
|
|
24
|
+
value: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface ScopedKeySaveRow {
|
|
28
|
+
key: string;
|
|
29
|
+
scope: SecretScope;
|
|
30
|
+
scopeId: string;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export class ScopedKeyStorageError extends Error {
|
|
34
|
+
constructor(
|
|
35
|
+
readonly statusCode: number,
|
|
36
|
+
message: string,
|
|
37
|
+
) {
|
|
38
|
+
super(message);
|
|
39
|
+
this.name = "ScopedKeyStorageError";
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function findUnsupportedScopedKeyNames(
|
|
44
|
+
vars: unknown,
|
|
45
|
+
allowedKeys: Iterable<string>,
|
|
46
|
+
): string[] {
|
|
47
|
+
if (!Array.isArray(vars)) return [];
|
|
48
|
+
|
|
49
|
+
const allowed = new Set(allowedKeys);
|
|
50
|
+
const unsupported = new Set<string>();
|
|
51
|
+
for (const entry of vars) {
|
|
52
|
+
if (!entry || typeof entry !== "object") continue;
|
|
53
|
+
const key = (entry as { key?: unknown }).key;
|
|
54
|
+
const normalizedKey = typeof key === "string" ? key.trim() : "";
|
|
55
|
+
if (normalizedKey && !allowed.has(normalizedKey)) {
|
|
56
|
+
unsupported.add(normalizedKey);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return [...unsupported];
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function redactSecretFromMessage(message: string, secretValue: string): string {
|
|
63
|
+
if (!message || !secretValue) return message;
|
|
64
|
+
return message.split(secretValue).join("[redacted]");
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function normalizeKeyValueVars(vars: unknown): ScopedKeyValue[] {
|
|
68
|
+
if (!Array.isArray(vars) || vars.length === 0) {
|
|
69
|
+
throw new ScopedKeyStorageError(400, "vars array required");
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const out: ScopedKeyValue[] = [];
|
|
73
|
+
for (const entry of vars) {
|
|
74
|
+
if (!entry || typeof entry !== "object") {
|
|
75
|
+
throw new ScopedKeyStorageError(400, "Each var must be an object");
|
|
76
|
+
}
|
|
77
|
+
const { key, value } = entry as { key?: unknown; value?: unknown };
|
|
78
|
+
const normalizedKey = typeof key === "string" ? key.trim() : "";
|
|
79
|
+
if (!normalizedKey || !KEY_NAME_RE.test(normalizedKey)) {
|
|
80
|
+
throw new ScopedKeyStorageError(
|
|
81
|
+
400,
|
|
82
|
+
normalizedKey
|
|
83
|
+
? `Invalid key name "${normalizedKey}"`
|
|
84
|
+
: "Each var requires a key",
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
const normalizedValue = typeof value === "string" ? value.trim() : "";
|
|
88
|
+
if (!normalizedValue) {
|
|
89
|
+
throw new ScopedKeyStorageError(
|
|
90
|
+
400,
|
|
91
|
+
`Value for ${normalizedKey} must be non-empty`,
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
out.push({ key: normalizedKey, value: normalizedValue });
|
|
95
|
+
}
|
|
96
|
+
return out;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function resolveTargetScope(
|
|
100
|
+
secret: RegisteredSecret | undefined,
|
|
101
|
+
requestedScope: ScopedKeySaveRequestScope,
|
|
102
|
+
): SecretScope {
|
|
103
|
+
if (secret?.kind === "api-key") return secret.scope;
|
|
104
|
+
if (requestedScope === "org") return "org";
|
|
105
|
+
if (requestedScope === "workspace" || requestedScope === "app") {
|
|
106
|
+
return "workspace";
|
|
107
|
+
}
|
|
108
|
+
return "user";
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
async function resolveScopeId(
|
|
112
|
+
event: H3Event,
|
|
113
|
+
scope: SecretScope,
|
|
114
|
+
): Promise<{
|
|
115
|
+
scopeId: string;
|
|
116
|
+
orgRole: string | null;
|
|
117
|
+
orgId: string | null;
|
|
118
|
+
}> {
|
|
119
|
+
const session = await getSession(event).catch(() => null);
|
|
120
|
+
const email = session?.email ?? null;
|
|
121
|
+
|
|
122
|
+
if (scope === "user") {
|
|
123
|
+
if (!email) {
|
|
124
|
+
throw new ScopedKeyStorageError(401, "Sign in to save keys");
|
|
125
|
+
}
|
|
126
|
+
return { scopeId: email, orgRole: null, orgId: null };
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const orgCtx = await getOrgContext(event).catch(() => null);
|
|
130
|
+
const orgId = orgCtx?.orgId ?? null;
|
|
131
|
+
const orgRole = orgCtx?.role ?? null;
|
|
132
|
+
|
|
133
|
+
if (scope === "org") {
|
|
134
|
+
if (!orgId) {
|
|
135
|
+
throw new ScopedKeyStorageError(401, "No active organization");
|
|
136
|
+
}
|
|
137
|
+
return { scopeId: orgId, orgRole, orgId };
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if (orgId) {
|
|
141
|
+
return { scopeId: orgId, orgRole, orgId };
|
|
142
|
+
}
|
|
143
|
+
if (!email) {
|
|
144
|
+
throw new ScopedKeyStorageError(401, "Sign in to save workspace keys");
|
|
145
|
+
}
|
|
146
|
+
return { scopeId: `solo:${email}`, orgRole: null, orgId: null };
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function assertCanMutateScope(
|
|
150
|
+
scope: SecretScope,
|
|
151
|
+
scopeId: string,
|
|
152
|
+
orgRole: string | null,
|
|
153
|
+
): void {
|
|
154
|
+
if (scope === "user") return;
|
|
155
|
+
if (scope === "workspace" && scopeId.startsWith("solo:")) return;
|
|
156
|
+
if (orgRole === "owner" || orgRole === "admin") return;
|
|
157
|
+
throw new ScopedKeyStorageError(
|
|
158
|
+
403,
|
|
159
|
+
scope === "org"
|
|
160
|
+
? "Only organization owners and admins can set org-scoped keys"
|
|
161
|
+
: "Only organization owners and admins can set workspace-scoped keys",
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
async function validateRegisteredSecret(
|
|
166
|
+
secret: RegisteredSecret | undefined,
|
|
167
|
+
value: string,
|
|
168
|
+
): Promise<void> {
|
|
169
|
+
if (!secret) return;
|
|
170
|
+
if (secret.kind === "oauth") {
|
|
171
|
+
throw new ScopedKeyStorageError(
|
|
172
|
+
400,
|
|
173
|
+
`"${secret.key}" is an OAuth-kind secret and must be connected via OAuth`,
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
if (!secret.validator) return;
|
|
177
|
+
try {
|
|
178
|
+
const result = await secret.validator(value);
|
|
179
|
+
const ok = typeof result === "boolean" ? result : result?.ok === true;
|
|
180
|
+
if (ok) return;
|
|
181
|
+
const error =
|
|
182
|
+
typeof result === "object" && result && result.error
|
|
183
|
+
? String(result.error)
|
|
184
|
+
: "Validator rejected the value";
|
|
185
|
+
throw new ScopedKeyStorageError(400, redactSecretFromMessage(error, value));
|
|
186
|
+
} catch (err) {
|
|
187
|
+
if (err instanceof ScopedKeyStorageError) throw err;
|
|
188
|
+
const message =
|
|
189
|
+
err instanceof Error
|
|
190
|
+
? `Validator threw: ${err.message}`
|
|
191
|
+
: "Validator threw";
|
|
192
|
+
throw new ScopedKeyStorageError(
|
|
193
|
+
400,
|
|
194
|
+
redactSecretFromMessage(message, value),
|
|
195
|
+
);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
export async function saveKeyValuesToScopedSecrets(
|
|
200
|
+
event: H3Event,
|
|
201
|
+
vars: unknown,
|
|
202
|
+
requestedScope?: ScopedKeySaveRequestScope,
|
|
203
|
+
): Promise<{ saved: string[]; rows: ScopedKeySaveRow[] }> {
|
|
204
|
+
const normalized = normalizeKeyValueVars(vars);
|
|
205
|
+
const rows: ScopedKeySaveRow[] = [];
|
|
206
|
+
|
|
207
|
+
for (const entry of normalized) {
|
|
208
|
+
const secret = getRequiredSecret(entry.key);
|
|
209
|
+
const scope = resolveTargetScope(secret, requestedScope);
|
|
210
|
+
const { scopeId, orgRole } = await resolveScopeId(event, scope);
|
|
211
|
+
assertCanMutateScope(scope, scopeId, orgRole);
|
|
212
|
+
await validateRegisteredSecret(secret, entry.value);
|
|
213
|
+
await writeAppSecret({
|
|
214
|
+
key: entry.key,
|
|
215
|
+
value: entry.value,
|
|
216
|
+
scope,
|
|
217
|
+
scopeId,
|
|
218
|
+
});
|
|
219
|
+
rows.push({ key: entry.key, scope, scopeId });
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
return { saved: rows.map((row) => row.key), rows };
|
|
223
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Isomorphic Agent
|
|
2
|
+
* Isomorphic Agent Key Utility
|
|
3
3
|
*
|
|
4
4
|
* Works in both browser and Node.js contexts:
|
|
5
5
|
* - Browser: sends via postMessage to the parent window
|
|
@@ -18,7 +18,7 @@ const isBrowser =
|
|
|
18
18
|
typeof window !== "undefined" && typeof window.postMessage === "function";
|
|
19
19
|
|
|
20
20
|
/**
|
|
21
|
-
* Send
|
|
21
|
+
* Send key/value settings to the host for scoped secret persistence.
|
|
22
22
|
* Automatically detects environment (browser vs Node.js) and uses the right transport.
|
|
23
23
|
*/
|
|
24
24
|
function setVars(vars: EnvVar[]): void {
|
|
@@ -41,6 +41,6 @@ function setVars(vars: EnvVar[]): void {
|
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
export const agentEnv = {
|
|
44
|
-
/** Send
|
|
44
|
+
/** Send key/value settings to the host for scoped secret persistence. */
|
|
45
45
|
setVars,
|
|
46
46
|
};
|
|
@@ -55,6 +55,8 @@
|
|
|
55
55
|
--agent-native-lower-surface: hsl(
|
|
56
56
|
var(--sidebar-background, var(--background))
|
|
57
57
|
);
|
|
58
|
+
--agent-native-raised-surface: hsl(var(--background));
|
|
59
|
+
--agent-native-card-surface: hsl(var(--card));
|
|
58
60
|
--agent-native-raised-border: hsl(var(--border));
|
|
59
61
|
--agent-native-raised-radius: 8px;
|
|
60
62
|
--agent-native-raised-shadow-left: -1px 0 3px rgb(0 0 0 / 0.018);
|
|
@@ -86,6 +88,16 @@
|
|
|
86
88
|
hsl(var(--sidebar-background, var(--background))) 94%,
|
|
87
89
|
black
|
|
88
90
|
);
|
|
91
|
+
--agent-native-raised-surface: color-mix(
|
|
92
|
+
in srgb,
|
|
93
|
+
hsl(var(--background)) 78%,
|
|
94
|
+
hsl(var(--muted)) 22%
|
|
95
|
+
);
|
|
96
|
+
--agent-native-card-surface: color-mix(
|
|
97
|
+
in srgb,
|
|
98
|
+
var(--agent-native-raised-surface) 88%,
|
|
99
|
+
hsl(var(--muted)) 12%
|
|
100
|
+
);
|
|
89
101
|
}
|
|
90
102
|
}
|
|
91
103
|
|
|
@@ -107,6 +119,13 @@
|
|
|
107
119
|
border-inline-end-color: transparent !important;
|
|
108
120
|
}
|
|
109
121
|
|
|
122
|
+
.agent-layout-shell
|
|
123
|
+
.agent-layout-left-drawer
|
|
124
|
+
> :where(.border-e, .border-r):first-child {
|
|
125
|
+
border-inline-end-color: transparent !important;
|
|
126
|
+
border-right-color: transparent !important;
|
|
127
|
+
}
|
|
128
|
+
|
|
110
129
|
.agent-sidebar-panel > .agent-sidebar-panel-inner {
|
|
111
130
|
background: inherit;
|
|
112
131
|
}
|
|
@@ -119,26 +138,59 @@
|
|
|
119
138
|
.agent-sidebar-main-surface {
|
|
120
139
|
position: relative;
|
|
121
140
|
z-index: 1;
|
|
122
|
-
background:
|
|
141
|
+
background: var(--agent-native-raised-surface);
|
|
123
142
|
transition:
|
|
124
143
|
border-radius 260ms cubic-bezier(0.32, 0.72, 0, 1),
|
|
144
|
+
border-color 260ms cubic-bezier(0.32, 0.72, 0, 1),
|
|
125
145
|
box-shadow 260ms cubic-bezier(0.32, 0.72, 0, 1);
|
|
126
146
|
}
|
|
127
147
|
|
|
128
148
|
.agent-layout-shell
|
|
129
149
|
:where(.agent-layout-main-surface, .agent-sidebar-main-surface)
|
|
130
150
|
> :first-child
|
|
131
|
-
> :where(header, div).border-b
|
|
151
|
+
> :where(header, div).border-b,
|
|
132
152
|
.agent-layout-shell
|
|
133
153
|
:where(.agent-layout-main-surface, .agent-sidebar-main-surface)
|
|
134
|
-
> :where(header, div).border-b
|
|
154
|
+
> :where(header, div).border-b,
|
|
135
155
|
.agent-layout-shell
|
|
136
156
|
.agent-layout-left-drawer
|
|
137
157
|
> :where(header, div).border-b:first-child,
|
|
158
|
+
.agent-layout-shell
|
|
159
|
+
.agent-layout-left-drawer
|
|
160
|
+
> :first-child
|
|
161
|
+
> :where(header, div).border-b,
|
|
138
162
|
.agent-layout-shell .agent-native-shell-topbar {
|
|
139
163
|
border-bottom-color: transparent !important;
|
|
140
164
|
}
|
|
141
165
|
|
|
166
|
+
.agent-layout-shell
|
|
167
|
+
:where(.agent-layout-main-surface, .agent-sidebar-main-surface)
|
|
168
|
+
> :first-child
|
|
169
|
+
> :where(header, div).border-b,
|
|
170
|
+
.agent-layout-shell
|
|
171
|
+
:where(.agent-layout-main-surface, .agent-sidebar-main-surface)
|
|
172
|
+
> :where(header, div).border-b {
|
|
173
|
+
background-color: var(--agent-native-raised-surface) !important;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
.agent-layout-shell
|
|
177
|
+
:where(.agent-layout-main-surface, .agent-sidebar-main-surface)
|
|
178
|
+
> :first-child
|
|
179
|
+
> :where(header, div).border-b.h-12,
|
|
180
|
+
.agent-layout-shell
|
|
181
|
+
:where(.agent-layout-main-surface, .agent-sidebar-main-surface)
|
|
182
|
+
> :where(header, div).border-b.h-12 {
|
|
183
|
+
min-height: 4rem;
|
|
184
|
+
height: 4rem;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
.dark
|
|
188
|
+
.agent-layout-shell
|
|
189
|
+
:where(.agent-layout-main-surface, .agent-sidebar-main-surface)
|
|
190
|
+
:where(.bg-card) {
|
|
191
|
+
background-color: var(--agent-native-card-surface) !important;
|
|
192
|
+
}
|
|
193
|
+
|
|
142
194
|
@media (min-width: 768px) {
|
|
143
195
|
.agent-layout-main-surface,
|
|
144
196
|
.agent-layout-shell > .agent-sidebar-shell > .agent-sidebar-main-surface {
|
|
@@ -170,7 +170,8 @@ Use the workspace root `.env` for shared identity and cross-app trust settings:
|
|
|
170
170
|
- `WORKSPACE_OWNER_EMAIL` — initial owner/admin email for repairs and
|
|
171
171
|
integration defaults.
|
|
172
172
|
- `A2A_SECRET` — shared secret for cross-app A2A signing. Generate with
|
|
173
|
-
`openssl rand -hex 32`
|
|
173
|
+
`openssl rand -hex 32` and configure through your deployment/scoped secret
|
|
174
|
+
manager.
|
|
174
175
|
|
|
175
176
|
`DISPATCH_DEFAULT_OWNER_EMAIL` is optional. Set it only for trusted,
|
|
176
177
|
single-workspace deployments where unlinked integration requests should run as
|
|
@@ -183,7 +184,7 @@ When asked to repair workspace org or A2A configuration:
|
|
|
183
184
|
1. Read `.env` first. Do not infer the organization, domain, owner email, or
|
|
184
185
|
secret from old examples.
|
|
185
186
|
2. Run `pnpm repair:workspace-org -- --name "<org>" --domain example.com --owner-email owner@example.com`
|
|
186
|
-
to
|
|
187
|
+
to validate generic workspace identity values without writing `.env`.
|
|
187
188
|
3. Prefer the app's organization settings UI or authenticated org routes for
|
|
188
189
|
changing `allowed_domain` and `a2a_secret`.
|
|
189
190
|
4. If direct SQL is unavoidable, inspect the live schema first and use only
|
|
@@ -97,7 +97,7 @@ cross-app trust:
|
|
|
97
97
|
- `A2A_SECRET` — shared signing secret for cross-app A2A calls.
|
|
98
98
|
|
|
99
99
|
Run `pnpm repair:workspace-org -- --name "<org>" --domain example.com --owner-email owner@example.com`
|
|
100
|
-
to
|
|
100
|
+
to validate those values without writing env files. Existing
|
|
101
101
|
organization rows should still be repaired through the app's org settings UI or
|
|
102
102
|
authenticated org routes whenever possible.
|
|
103
103
|
|