@agent-native/core 0.121.2 → 0.122.1
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/README.md +4 -12
- package/corpus/README.md +2 -2
- package/corpus/core/CHANGELOG.md +148 -0
- package/corpus/core/docs/content/actions.mdx +2 -2
- package/corpus/core/docs/content/agent-surfaces.mdx +1 -1
- package/corpus/core/docs/content/authentication.mdx +2 -0
- package/corpus/core/docs/content/deployment.mdx +36 -0
- package/corpus/core/docs/content/http-api.mdx +266 -0
- package/corpus/core/docs/content/syncing-template-changes.mdx +159 -0
- package/corpus/core/package.json +2 -1
- package/corpus/core/src/a2a/activity.ts +38 -27
- package/corpus/core/src/a2a/client.ts +57 -4
- package/corpus/core/src/agent/engine/builder-engine.ts +35 -4
- package/corpus/core/src/agent/run-manager.ts +20 -1
- package/corpus/core/src/agent/run-store.ts +4 -1
- package/corpus/core/src/agent/types.ts +28 -8
- package/corpus/core/src/chat-threads/store.ts +45 -0
- package/corpus/core/src/checkpoints/index.ts +2 -0
- package/corpus/core/src/checkpoints/route-match.ts +13 -0
- package/corpus/core/src/cli/create.ts +105 -17
- package/corpus/core/src/cli/index.ts +20 -0
- package/corpus/core/src/cli/template-baseline.ts +410 -0
- package/corpus/core/src/cli/template-sync.ts +1004 -0
- package/corpus/core/src/cli/templates-meta.ts +1 -0
- package/corpus/core/src/client/AssistantChat.tsx +38 -12
- package/corpus/core/src/client/NewWorkspaceAppFlow.tsx +75 -10
- package/corpus/core/src/client/chat/message-components.tsx +127 -66
- package/corpus/core/src/client/chat/tool-call-display.tsx +29 -5
- package/corpus/core/src/client/error-format.ts +18 -0
- package/corpus/core/src/client/org/OrgSwitcher.tsx +30 -8
- package/corpus/core/src/client/org/TeamPage.tsx +7 -6
- package/corpus/core/src/client/settings/SettingsPanel.tsx +9 -9
- package/corpus/core/src/client/settings/SettingsTabsPage.tsx +12 -2
- package/corpus/core/src/client/sse-event-processor.ts +3 -0
- package/corpus/core/src/data-widgets/index.ts +41 -0
- package/corpus/core/src/deploy/build.ts +11 -9
- package/corpus/core/src/extensions/url-safety.ts +67 -4
- package/corpus/core/src/integrations/webhook-handler.ts +63 -9
- package/corpus/core/src/org/auto-join-domain.ts +4 -3
- package/corpus/core/src/org/context.ts +108 -39
- package/corpus/core/src/org/index.ts +5 -0
- package/corpus/core/src/org/service-identity.ts +60 -0
- package/corpus/core/src/provider-api/index.ts +22 -1
- package/corpus/core/src/scripts/docs/search.ts +12 -1
- package/corpus/core/src/server/agent-chat/context-tools.ts +9 -4
- package/corpus/core/src/server/agent-chat/framework-prompts.ts +38 -66
- package/corpus/core/src/server/agent-chat-plugin.ts +17 -10
- package/corpus/core/src/server/agents-bundle.ts +84 -5
- package/corpus/core/src/server/auth.ts +4 -3
- package/corpus/core/src/server/builder-browser.ts +47 -19
- package/corpus/core/src/server/core-routes-plugin.ts +2 -2
- package/corpus/core/src/server/credential-provider.ts +209 -68
- package/corpus/core/src/server/index.ts +3 -0
- package/corpus/core/src/server/prompts/framework-core-compact.ts +6 -13
- package/corpus/core/src/server/prompts/framework-core.ts +9 -21
- package/corpus/core/src/server/prompts/index.ts +0 -1
- package/corpus/core/src/server/prompts/shared-rules.ts +19 -11
- package/corpus/core/src/server/ssr-handler.ts +13 -2
- package/corpus/core/src/settings/user-settings.ts +13 -1
- package/corpus/core/src/shared/cache-control.ts +141 -0
- package/corpus/core/src/templates/chat/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
- package/corpus/core/src/templates/chat/_gitignore +1 -0
- package/corpus/core/src/templates/chat/app/components/layout/Sidebar.tsx +0 -7
- package/corpus/core/src/templates/default/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
- package/corpus/core/src/templates/default/app/root.tsx +1 -1
- package/corpus/core/src/templates/default/public/manifest.json +2 -2
- package/corpus/core/src/templates/headless/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
- package/corpus/core/src/templates/workspace-core/.agents/skills/performance/SKILL.md +19 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
- package/corpus/core/src/templates/workspace-core/.agents/skills/visual-answer/SKILL.md +1 -0
- package/corpus/core/src/vite/agents-bundle-plugin.ts +7 -6
- package/corpus/core/src/vite/client.ts +69 -3
- package/corpus/templates/analytics/.agents/skills/adhoc-analysis/SKILL.md +4 -5
- package/corpus/templates/analytics/.agents/skills/admin-surfaces/SKILL.md +55 -0
- package/corpus/templates/analytics/.agents/skills/dashboard-management/SKILL.md +10 -0
- package/corpus/templates/analytics/.agents/skills/dashboard-management/references/template-catalog-and-demo.md +62 -0
- package/corpus/templates/analytics/.agents/skills/dashboard-ops/SKILL.md +85 -0
- package/corpus/templates/analytics/.agents/skills/data-querying/SKILL.md +27 -2
- package/corpus/templates/analytics/.agents/skills/data-querying/references/inline-chart-embeds.md +139 -0
- package/corpus/templates/analytics/.agents/skills/monitoring/SKILL.md +77 -0
- package/corpus/templates/analytics/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
- package/corpus/templates/analytics/AGENTS.md +91 -563
- package/corpus/templates/analytics/_gitignore +1 -0
- package/corpus/templates/analytics/actions/bigquery.ts +12 -4
- package/corpus/templates/analytics/actions/generate-chart.ts +5 -5
- package/corpus/templates/analytics/app/components/dashboard/SqlChart.tsx +30 -1
- package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +1 -23
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/DashboardFilterBar.tsx +3 -0
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/SqlChartCard.tsx +1 -1
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +1 -0
- package/corpus/templates/analytics/app/routes/_index.tsx +1 -1
- package/corpus/templates/analytics/changelog/2026-07-24-analytics-finds-saved-dashboards-and-queries-far-more-reliab.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-24-notion-access-errors-now-explain-that-a-page-needs-sharing-w.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-25-app-branding-now-uses-the-product-name-without-the-agent-nat.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-25-settings-navigation-now-keeps-manage-agent-as-a-dedicated-li.md +6 -0
- package/corpus/templates/analytics/package.json +1 -1
- package/corpus/templates/analytics/public/manifest.json +1 -1
- package/corpus/templates/analytics/server/lib/agent-chat-plan-mode.ts +7 -0
- package/corpus/templates/analytics/server/lib/analytics-query-catalog.ts +191 -30
- package/corpus/templates/analytics/server/lib/bigquery.ts +11 -1
- package/corpus/templates/analytics/server/lib/notion.ts +15 -4
- package/corpus/templates/analytics/server/plugins/agent-chat.ts +10 -0
- package/corpus/templates/analytics/server/plugins/auth.ts +1 -1
- package/corpus/templates/assets/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
- package/corpus/templates/assets/app/components/layout/Sidebar.tsx +0 -2
- package/corpus/templates/assets/app/routes/_index.tsx +1 -1
- package/corpus/templates/assets/changelog/2026-07-25-app-branding-now-uses-the-product-name-without-the-agent-nat.md +6 -0
- package/corpus/templates/assets/changelog/2026-07-25-settings-navigation-now-keeps-manage-agent-as-a-dedicated-li.md +6 -0
- package/corpus/templates/assets/server/plugins/auth.ts +1 -1
- package/corpus/templates/brain/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
- package/corpus/templates/brain/_gitignore +1 -0
- package/corpus/templates/brain/app/lib/brain.ts +0 -7
- package/corpus/templates/brain/app/routes/_index.tsx +1 -2
- package/corpus/templates/brain/changelog/2026-07-25-app-branding-now-uses-the-product-name-without-the-agent-nat.md +6 -0
- package/corpus/templates/brain/changelog/2026-07-25-settings-navigation-now-keeps-manage-agent-as-a-dedicated-li.md +6 -0
- package/corpus/templates/brain/package.json +1 -1
- package/corpus/templates/brain/public/manifest.json +1 -1
- package/corpus/templates/brain/server/plugins/auth.ts +1 -1
- package/corpus/templates/calendar/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
- package/corpus/templates/calendar/_gitignore +1 -0
- package/corpus/templates/calendar/app/components/layout/Sidebar.tsx +0 -6
- package/corpus/templates/calendar/app/routes/_app._index.tsx +1 -1
- package/corpus/templates/calendar/changelog/2026-07-25-app-branding-now-uses-the-product-name-without-the-agent-nat.md +6 -0
- package/corpus/templates/calendar/changelog/2026-07-25-settings-navigation-now-keeps-manage-agent-as-a-dedicated-li.md +6 -0
- package/corpus/templates/calendar/package.json +1 -1
- package/corpus/templates/calendar/public/manifest.json +1 -1
- package/corpus/templates/calendar/server/plugins/auth.ts +1 -1
- package/corpus/templates/chat/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
- package/corpus/templates/chat/_gitignore +1 -0
- package/corpus/templates/chat/app/components/layout/Sidebar.tsx +0 -7
- package/corpus/templates/chat/changelog/2026-07-25-settings-navigation-now-keeps-manage-agent-as-a-dedicated-li.md +6 -0
- package/corpus/templates/clips/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
- package/corpus/templates/clips/.agents/skills/video-sharing/SKILL.md +34 -0
- package/corpus/templates/clips/AGENTS.md +5 -4
- package/corpus/templates/clips/_gitignore +1 -0
- package/corpus/templates/clips/actions/cleanup-transcript.ts +5 -0
- package/corpus/templates/clips/actions/get-recording-insights.ts +44 -8
- package/corpus/templates/clips/actions/get-recording-player-data.ts +39 -70
- package/corpus/templates/clips/actions/import-loom-recording.ts +53 -98
- package/corpus/templates/clips/actions/lib/loom-import-job.ts +260 -0
- package/corpus/templates/clips/actions/list-clip-views.ts +2 -4
- package/corpus/templates/clips/actions/list-recordings.ts +69 -19
- package/corpus/templates/clips/actions/list-viewers.ts +5 -2
- package/corpus/templates/clips/actions/regenerate-summary.ts +5 -1
- package/corpus/templates/clips/actions/request-transcript.ts +28 -1
- package/corpus/templates/clips/app/components/editor/stitch-manager.tsx +21 -1
- package/corpus/templates/clips/app/components/library/library-layout.tsx +0 -7
- package/corpus/templates/clips/app/components/meetings/quick-ask-sidebar.tsx +14 -1
- package/corpus/templates/clips/app/components/player/insights-panel.tsx +8 -20
- package/corpus/templates/clips/app/components/player/recording-views-badge.tsx +335 -0
- package/corpus/templates/clips/app/components/player/video-player.tsx +13 -8
- package/corpus/templates/clips/app/components/sharing/share-ui.tsx +2 -1
- package/corpus/templates/clips/app/i18n/en-US.ts +13 -2
- package/corpus/templates/clips/app/lib/capture-permissions.ts +110 -0
- package/corpus/templates/clips/app/lib/recording-link.ts +32 -0
- package/corpus/templates/clips/app/routes/_app.library._index.tsx +1 -1
- package/corpus/templates/clips/app/routes/_app.meetings.$meetingId.tsx +27 -0
- package/corpus/templates/clips/app/routes/_index.tsx +1 -1
- package/corpus/templates/clips/app/routes/r.$recordingId.tsx +52 -15
- package/corpus/templates/clips/app/routes/record.tsx +82 -31
- package/corpus/templates/clips/app/routes/share.$shareId.tsx +42 -31
- package/corpus/templates/clips/changelog/2026-07-24-clip-pages-now-show-a-view-count-with-viewer-avatars-next-to.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-24-clip-summaries-read-like-a-description-you-d-write-yourself-.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-24-clip-view-counts-now-separate-human-views-from-agent-views-s.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-24-clips-actions-can-now-be-called-by-org-service-tokens-so-ext.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-24-clips-no-longer-briefly-shows-a-dock-icon-while-launching.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-24-fixed-owner-and-editor-share-links-redirecting-to-the-record.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-24-meeting-and-note-recordings-now-start-as-a-compact-pill-on-t.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-24-new-clips-now-copy-a-shareable-link-instead-of-the-owner-onl.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-24-opening-a-share-link-as-the-clip-s-owner-now-goes-straight-t.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-24-permissions-and-rewind-controls-now-use-compact-consistent-h.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-24-quitting-the-desktop-app-no-longer-shows-a-false-macos-crash.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-24-screen-recording-permission-errors-now-name-the-exact-app-to.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-24-the-desktop-app-now-copies-a-new-clip-s-share-link-to-your-c.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-24-the-recording-toolbar-now-stays-above-other-apps-including-o.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-24-transcript-captions-now-use-real-speech-timings-instead-of-a.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-24-video-playback-no-longer-stutters-and-replays-the-last-momen.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-25-app-branding-now-uses-the-product-name-without-the-agent-nat.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-25-settings-navigation-now-keeps-manage-agent-as-a-dedicated-li.md +6 -0
- package/corpus/templates/clips/chrome-extension/src/background.ts +17 -1
- package/corpus/templates/clips/desktop/package.json +2 -0
- package/corpus/templates/clips/desktop/src/app.tsx +89 -0
- package/corpus/templates/clips/desktop/src/hooks/useMeetingTranscription.ts +9 -3
- package/corpus/templates/clips/desktop/src/lib/audio-meter.ts +51 -0
- package/corpus/templates/clips/desktop/src/lib/native-notification.ts +44 -0
- package/corpus/templates/clips/desktop/src/lib/recording-link.ts +67 -0
- package/corpus/templates/clips/desktop/src/overlays/live-audio-bars.tsx +35 -35
- package/corpus/templates/clips/desktop/src/overlays/live-transcript.tsx +3 -2
- package/corpus/templates/clips/desktop/src/overlays/recording-pill.tsx +47 -46
- package/corpus/templates/clips/desktop/src/styles.css +127 -78
- package/corpus/templates/clips/desktop/src-tauri/Cargo.toml +7 -0
- package/corpus/templates/clips/desktop/src-tauri/Info.plist +6 -0
- package/corpus/templates/clips/desktop/src-tauri/capabilities/default.json +1 -0
- package/corpus/templates/clips/desktop/src-tauri/src/clips/mod.rs +7 -3
- package/corpus/templates/clips/desktop/src-tauri/src/lib.rs +4 -1
- package/corpus/templates/clips/desktop/src-tauri/src/main.rs +8 -0
- package/corpus/templates/clips/desktop/src-tauri/src/recording_indicator.rs +21 -10
- package/corpus/templates/clips/desktop/src-tauri/src/util.rs +40 -0
- package/corpus/templates/clips/server/db/schema.ts +27 -0
- package/corpus/templates/clips/server/lib/agent-views.ts +145 -0
- package/corpus/templates/clips/server/lib/post-finalize-dispatch.ts +2 -1
- package/corpus/templates/clips/server/lib/public-agent-context.ts +7 -0
- package/corpus/templates/clips/server/lib/recording-share-grant.ts +79 -0
- package/corpus/templates/clips/server/lib/recordings.ts +51 -3
- package/corpus/templates/clips/server/plugins/auth.ts +1 -1
- package/corpus/templates/clips/server/plugins/db.ts +31 -0
- package/corpus/templates/clips/server/routes/api/_agent-native-background/post-finalize-worker.post.ts +56 -3
- package/corpus/templates/clips/server/routes/api/public-recording.get.ts +49 -17
- package/corpus/templates/clips/shared/recording-link.ts +43 -0
- package/corpus/templates/clips/shared/share-attribution.ts +4 -0
- package/corpus/templates/clips/shared/share-dashboard-redirect.ts +42 -0
- package/corpus/templates/clips/shared/view-analytics.ts +26 -0
- package/corpus/templates/content/.agents/skills/content/SKILL.md +5 -0
- package/corpus/templates/content/.agents/skills/content/references/local-file-mode.md +135 -0
- package/corpus/templates/content/.agents/skills/document-editing/SKILL.md +12 -0
- package/corpus/templates/content/.agents/skills/document-editing/references/databases.md +238 -0
- package/corpus/templates/content/.agents/skills/document-editing/references/document-behavior.md +91 -0
- package/corpus/templates/content/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
- package/corpus/templates/content/AGENTS.md +62 -583
- package/corpus/templates/content/_gitignore +1 -0
- package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +1 -39
- package/corpus/templates/content/app/routes/_app._index.tsx +1 -2
- package/corpus/templates/content/changelog/2026-07-25-app-branding-now-uses-the-product-name-without-the-agent-nat.md +6 -0
- package/corpus/templates/content/changelog/2026-07-25-settings-navigation-now-keeps-manage-agent-as-a-dedicated-li.md +6 -0
- package/corpus/templates/content/package.json +1 -1
- package/corpus/templates/content/public/manifest.json +1 -1
- package/corpus/templates/content/server/plugins/auth.ts +1 -1
- package/corpus/templates/design/.agents/skills/creative-context/SKILL.md +11 -0
- package/corpus/templates/design/.agents/skills/design-generation/SKILL.md +50 -8
- package/corpus/templates/design/.agents/skills/design-generation/references/code-layers.md +81 -0
- package/corpus/templates/design/.agents/skills/design-generation/references/code-workspace.md +42 -0
- package/corpus/templates/design/.agents/skills/design-generation/references/editor-extensions.md +34 -0
- package/corpus/templates/design/.agents/skills/responsive-breakpoints/SKILL.md +4 -1
- package/corpus/templates/design/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
- package/corpus/templates/design/.agents/skills/visual-edit/SKILL.md +17 -0
- package/corpus/templates/design/.generated/bridge/editor-chrome.generated.ts +8196 -0
- package/corpus/templates/design/.generated/bridge/embedded-wheel.generated.ts +265 -0
- package/corpus/templates/design/.generated/bridge/hit-test.generated.ts +642 -0
- package/corpus/templates/design/.generated/bridge/motion-preview.generated.ts +571 -0
- package/corpus/templates/design/.generated/bridge/nav.generated.ts +91 -0
- package/corpus/templates/design/.generated/bridge/sample.generated.ts +23 -0
- package/corpus/templates/design/.generated/bridge/shader-fill-preview.generated.ts +263 -0
- package/corpus/templates/design/.generated/bridge/shader-runtime.generated.ts +518 -0
- package/corpus/templates/design/.generated/bridge/tweak.generated.ts +20 -0
- package/corpus/templates/design/.generated/bridge/zoom.generated.ts +32 -0
- package/corpus/templates/design/AGENTS.md +88 -503
- package/corpus/templates/design/_gitignore +1 -0
- package/corpus/templates/design/app/components/layout/Sidebar.tsx +0 -2
- package/corpus/templates/design/app/routes/_index.tsx +1 -1
- package/corpus/templates/design/changelog/2026-07-25-app-branding-now-uses-the-product-name-without-the-agent-nat.md +6 -0
- package/corpus/templates/design/changelog/2026-07-25-settings-navigation-now-keeps-manage-agent-as-a-dedicated-li.md +6 -0
- package/corpus/templates/design/server/plugins/auth.ts +1 -1
- package/corpus/templates/dispatch/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
- package/corpus/templates/dispatch/_gitignore +1 -0
- package/corpus/templates/dispatch/app/dispatch-extensions.tsx +1 -10
- package/corpus/templates/dispatch/app/routes/overview.tsx +1 -1
- package/corpus/templates/dispatch/changelog/2026-07-24-signing-in-now-puts-you-in-your-companys-workspace.md +6 -0
- package/corpus/templates/dispatch/changelog/2026-07-25-app-branding-now-uses-the-product-name-without-the-agent-nat.md +6 -0
- package/corpus/templates/dispatch/changelog/2026-07-25-settings-navigation-now-keeps-manage-agent-as-a-dedicated-li.md +6 -0
- package/corpus/templates/dispatch/package.json +1 -1
- package/corpus/templates/dispatch/public/manifest.json +1 -1
- package/corpus/templates/forms/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
- package/corpus/templates/forms/_gitignore +1 -0
- package/corpus/templates/forms/app/components/layout/Sidebar.tsx +0 -35
- package/corpus/templates/forms/changelog/2026-07-25-app-branding-now-uses-the-product-name-without-the-agent-nat.md +6 -0
- package/corpus/templates/forms/changelog/2026-07-25-settings-navigation-now-keeps-manage-agent-as-a-dedicated-li.md +6 -0
- package/corpus/templates/forms/package.json +1 -1
- package/corpus/templates/forms/public/manifest.json +1 -1
- package/corpus/templates/forms/server/lib/public-form-ssr.ts +2 -2
- package/corpus/templates/forms/server/plugins/auth.ts +1 -1
- package/corpus/templates/macros/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
- package/corpus/templates/macros/_gitignore +1 -0
- package/corpus/templates/macros/app/components/layout/AppLayout.tsx +0 -2
- package/corpus/templates/macros/changelog/2026-07-25-app-branding-now-uses-the-product-name-without-the-agent-nat.md +6 -0
- package/corpus/templates/macros/changelog/2026-07-25-settings-navigation-now-keeps-manage-agent-as-a-dedicated-li.md +6 -0
- package/corpus/templates/macros/package.json +1 -1
- package/corpus/templates/macros/server/plugins/auth.ts +2 -2
- package/corpus/templates/mail/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
- package/corpus/templates/mail/_gitignore +1 -0
- package/corpus/templates/mail/app/components/layout/AppLayout.tsx +0 -39
- package/corpus/templates/mail/app/routes/$view.$threadId.tsx +1 -1
- package/corpus/templates/mail/app/routes/$view.tsx +1 -1
- package/corpus/templates/mail/app/routes/_index.tsx +1 -1
- package/corpus/templates/mail/changelog/2026-07-25-app-branding-now-uses-the-product-name-without-the-agent-nat.md +6 -0
- package/corpus/templates/mail/changelog/2026-07-25-settings-navigation-now-keeps-manage-agent-as-a-dedicated-li.md +6 -0
- package/corpus/templates/mail/package.json +1 -1
- package/corpus/templates/mail/public/manifest.json +1 -1
- package/corpus/templates/mail/server/plugins/auth.ts +1 -1
- package/corpus/templates/plan/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
- package/corpus/templates/plan/_gitignore +1 -0
- package/corpus/templates/plan/agent-native.app-skill.json +1 -1
- package/corpus/templates/plan/app/components/layout/Sidebar.tsx +4 -9
- package/corpus/templates/plan/app/lib/app-config.ts +1 -1
- package/corpus/templates/plan/changelog/2026-07-25-app-branding-now-uses-the-product-name-without-the-agent-nat.md +6 -0
- package/corpus/templates/plan/changelog/2026-07-25-settings-navigation-now-keeps-manage-agent-as-a-dedicated-li.md +6 -0
- package/corpus/templates/plan/package.json +1 -1
- package/corpus/templates/plan/public/manifest.json +1 -1
- package/corpus/templates/plan/server/plugins/auth.ts +1 -1
- package/corpus/templates/slides/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
- package/corpus/templates/slides/_gitignore +1 -0
- package/corpus/templates/slides/app/components/layout/Sidebar.tsx +0 -2
- package/corpus/templates/slides/app/routes/_index.tsx +1 -1
- package/corpus/templates/slides/changelog/2026-07-25-app-branding-now-uses-the-product-name-without-the-agent-nat.md +6 -0
- package/corpus/templates/slides/changelog/2026-07-25-settings-navigation-now-keeps-manage-agent-as-a-dedicated-li.md +6 -0
- package/corpus/templates/slides/package.json +1 -1
- package/corpus/templates/slides/public/manifest.json +1 -1
- package/corpus/templates/slides/server/plugins/auth.ts +1 -1
- package/corpus/templates/slides/server/plugins/db.ts +4 -0
- package/corpus/templates/tasks/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
- package/corpus/templates/tasks/AGENTS.md +1 -1
- package/corpus/templates/tasks/_gitignore +1 -0
- package/dist/a2a/activity.d.ts +4 -1
- package/dist/a2a/activity.d.ts.map +1 -1
- package/dist/a2a/activity.js +27 -16
- package/dist/a2a/activity.js.map +1 -1
- package/dist/a2a/client.d.ts.map +1 -1
- package/dist/a2a/client.js +58 -4
- package/dist/a2a/client.js.map +1 -1
- package/dist/agent/engine/builder-engine.d.ts +1 -0
- package/dist/agent/engine/builder-engine.d.ts.map +1 -1
- package/dist/agent/engine/builder-engine.js +31 -4
- package/dist/agent/engine/builder-engine.js.map +1 -1
- package/dist/agent/run-manager.d.ts.map +1 -1
- package/dist/agent/run-manager.js +18 -1
- package/dist/agent/run-manager.js.map +1 -1
- package/dist/agent/run-store.d.ts +1 -0
- package/dist/agent/run-store.d.ts.map +1 -1
- package/dist/agent/run-store.js +2 -1
- package/dist/agent/run-store.js.map +1 -1
- package/dist/agent/types.d.ts +12 -1
- package/dist/agent/types.d.ts.map +1 -1
- package/dist/agent/types.js +21 -1
- package/dist/agent/types.js.map +1 -1
- package/dist/chat-threads/store.d.ts +10 -0
- package/dist/chat-threads/store.d.ts.map +1 -1
- package/dist/chat-threads/store.js +41 -0
- package/dist/chat-threads/store.js.map +1 -1
- package/dist/checkpoints/index.d.ts +1 -0
- package/dist/checkpoints/index.d.ts.map +1 -1
- package/dist/checkpoints/index.js +1 -0
- package/dist/checkpoints/index.js.map +1 -1
- package/dist/checkpoints/route-match.d.ts +8 -0
- package/dist/checkpoints/route-match.d.ts.map +1 -0
- package/dist/checkpoints/route-match.js +13 -0
- package/dist/checkpoints/route-match.js.map +1 -0
- package/dist/cli/create.d.ts +35 -4
- package/dist/cli/create.d.ts.map +1 -1
- package/dist/cli/create.js +69 -19
- package/dist/cli/create.js.map +1 -1
- package/dist/cli/index.js +19 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/template-baseline.d.ts +54 -0
- package/dist/cli/template-baseline.d.ts.map +1 -0
- package/dist/cli/template-baseline.js +334 -0
- package/dist/cli/template-baseline.js.map +1 -0
- package/dist/cli/template-sync.d.ts +57 -0
- package/dist/cli/template-sync.d.ts.map +1 -0
- package/dist/cli/template-sync.js +787 -0
- package/dist/cli/template-sync.js.map +1 -0
- package/dist/cli/templates-meta.d.ts.map +1 -1
- package/dist/cli/templates-meta.js +1 -0
- package/dist/cli/templates-meta.js.map +1 -1
- package/dist/client/AssistantChat.d.ts +2 -1
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +38 -10
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/NewWorkspaceAppFlow.d.ts.map +1 -1
- package/dist/client/NewWorkspaceAppFlow.js +32 -2
- package/dist/client/NewWorkspaceAppFlow.js.map +1 -1
- package/dist/client/chat/message-components.d.ts +20 -0
- package/dist/client/chat/message-components.d.ts.map +1 -1
- package/dist/client/chat/message-components.js +81 -46
- package/dist/client/chat/message-components.js.map +1 -1
- package/dist/client/chat/tool-call-display.d.ts.map +1 -1
- package/dist/client/chat/tool-call-display.js +14 -6
- package/dist/client/chat/tool-call-display.js.map +1 -1
- package/dist/client/error-format.d.ts.map +1 -1
- package/dist/client/error-format.js +13 -0
- package/dist/client/error-format.js.map +1 -1
- package/dist/client/org/OrgSwitcher.d.ts +8 -1
- package/dist/client/org/OrgSwitcher.d.ts.map +1 -1
- package/dist/client/org/OrgSwitcher.js +3 -2
- package/dist/client/org/OrgSwitcher.js.map +1 -1
- package/dist/client/org/TeamPage.d.ts.map +1 -1
- package/dist/client/org/TeamPage.js +1 -1
- package/dist/client/org/TeamPage.js.map +1 -1
- package/dist/client/settings/SettingsPanel.js +9 -9
- package/dist/client/settings/SettingsPanel.js.map +1 -1
- package/dist/client/settings/SettingsTabsPage.d.ts.map +1 -1
- package/dist/client/settings/SettingsTabsPage.js +7 -4
- package/dist/client/settings/SettingsTabsPage.js.map +1 -1
- package/dist/client/sse-event-processor.d.ts.map +1 -1
- package/dist/client/sse-event-processor.js +3 -0
- package/dist/client/sse-event-processor.js.map +1 -1
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/awareness.d.ts.map +1 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/data-widgets/index.d.ts +3 -0
- package/dist/data-widgets/index.d.ts.map +1 -1
- package/dist/data-widgets/index.js +33 -0
- package/dist/data-widgets/index.js.map +1 -1
- package/dist/deploy/build.d.ts.map +1 -1
- package/dist/deploy/build.js +11 -7
- package/dist/deploy/build.js.map +1 -1
- package/dist/eject/provider-api-definitions.d.ts +1 -0
- package/dist/eject/provider-api-definitions.d.ts.map +1 -1
- package/dist/extensions/url-safety.d.ts +9 -16
- package/dist/extensions/url-safety.d.ts.map +1 -1
- package/dist/extensions/url-safety.js +48 -4
- package/dist/extensions/url-safety.js.map +1 -1
- package/dist/file-upload/actions/upload-image.d.ts +1 -1
- package/dist/integrations/webhook-handler.d.ts.map +1 -1
- package/dist/integrations/webhook-handler.js +46 -9
- package/dist/integrations/webhook-handler.js.map +1 -1
- package/dist/notifications/routes.d.ts +2 -2
- package/dist/observability/routes.d.ts +3 -3
- package/dist/org/auto-join-domain.d.ts +3 -2
- package/dist/org/auto-join-domain.d.ts.map +1 -1
- package/dist/org/auto-join-domain.js +1 -1
- package/dist/org/auto-join-domain.js.map +1 -1
- package/dist/org/context.d.ts.map +1 -1
- package/dist/org/context.js +84 -28
- package/dist/org/context.js.map +1 -1
- package/dist/org/index.d.ts +1 -0
- package/dist/org/index.d.ts.map +1 -1
- package/dist/org/index.js +1 -0
- package/dist/org/index.js.map +1 -1
- package/dist/org/service-identity.d.ts +43 -0
- package/dist/org/service-identity.d.ts.map +1 -0
- package/dist/org/service-identity.js +34 -0
- package/dist/org/service-identity.js.map +1 -0
- package/dist/provider-api/actions/custom-provider-registration.d.ts +14 -14
- package/dist/provider-api/actions/provider-api.d.ts +13 -11
- package/dist/provider-api/actions/provider-api.d.ts.map +1 -1
- package/dist/provider-api/index.d.ts +4 -0
- package/dist/provider-api/index.d.ts.map +1 -1
- package/dist/provider-api/index.js +17 -1
- package/dist/provider-api/index.js.map +1 -1
- package/dist/scripts/docs/search.d.ts.map +1 -1
- package/dist/scripts/docs/search.js +12 -1
- package/dist/scripts/docs/search.js.map +1 -1
- package/dist/server/agent-chat/context-tools.d.ts.map +1 -1
- package/dist/server/agent-chat/context-tools.js +3 -3
- package/dist/server/agent-chat/context-tools.js.map +1 -1
- package/dist/server/agent-chat/framework-prompts.d.ts +8 -3
- package/dist/server/agent-chat/framework-prompts.d.ts.map +1 -1
- package/dist/server/agent-chat/framework-prompts.js +33 -62
- package/dist/server/agent-chat/framework-prompts.js.map +1 -1
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +16 -10
- 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/agents-bundle.d.ts +18 -0
- package/dist/server/agents-bundle.d.ts.map +1 -1
- package/dist/server/agents-bundle.js +70 -4
- package/dist/server/agents-bundle.js.map +1 -1
- package/dist/server/auth.d.ts.map +1 -1
- package/dist/server/auth.js +4 -3
- package/dist/server/auth.js.map +1 -1
- package/dist/server/builder-browser.d.ts.map +1 -1
- package/dist/server/builder-browser.js +43 -19
- package/dist/server/builder-browser.js.map +1 -1
- package/dist/server/core-routes-plugin.js +2 -2
- package/dist/server/core-routes-plugin.js.map +1 -1
- package/dist/server/credential-provider.d.ts +38 -2
- package/dist/server/credential-provider.d.ts.map +1 -1
- package/dist/server/credential-provider.js +142 -64
- package/dist/server/credential-provider.js.map +1 -1
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +1 -1
- package/dist/server/index.js.map +1 -1
- package/dist/server/prompts/framework-core-compact.d.ts +1 -1
- package/dist/server/prompts/framework-core-compact.d.ts.map +1 -1
- package/dist/server/prompts/framework-core-compact.js +7 -13
- package/dist/server/prompts/framework-core-compact.js.map +1 -1
- package/dist/server/prompts/framework-core.d.ts +1 -1
- package/dist/server/prompts/framework-core.d.ts.map +1 -1
- package/dist/server/prompts/framework-core.js +10 -21
- package/dist/server/prompts/framework-core.js.map +1 -1
- package/dist/server/prompts/index.d.ts +1 -1
- package/dist/server/prompts/index.d.ts.map +1 -1
- package/dist/server/prompts/index.js +1 -1
- package/dist/server/prompts/index.js.map +1 -1
- package/dist/server/prompts/shared-rules.d.ts +16 -10
- package/dist/server/prompts/shared-rules.d.ts.map +1 -1
- package/dist/server/prompts/shared-rules.js +19 -10
- package/dist/server/prompts/shared-rules.js.map +1 -1
- package/dist/server/ssr-handler.d.ts +1 -1
- package/dist/server/ssr-handler.d.ts.map +1 -1
- package/dist/server/ssr-handler.js +10 -3
- package/dist/server/ssr-handler.js.map +1 -1
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/dist/settings/user-settings.d.ts.map +1 -1
- package/dist/settings/user-settings.js +13 -1
- package/dist/settings/user-settings.js.map +1 -1
- package/dist/shared/cache-control.d.ts +52 -0
- package/dist/shared/cache-control.d.ts.map +1 -1
- package/dist/shared/cache-control.js +107 -0
- package/dist/shared/cache-control.js.map +1 -1
- package/dist/templates/chat/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
- package/dist/templates/chat/_gitignore +1 -0
- package/dist/templates/chat/app/components/layout/Sidebar.tsx +0 -7
- package/dist/templates/chat/changelog/2026-07-25-settings-navigation-now-keeps-manage-agent-as-a-dedicated-li.md +6 -0
- package/dist/templates/default/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
- package/dist/templates/default/app/root.tsx +1 -1
- package/dist/templates/default/public/manifest.json +2 -2
- package/dist/templates/headless/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
- package/dist/templates/workspace-core/.agents/skills/performance/SKILL.md +19 -0
- package/dist/templates/workspace-core/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
- package/dist/templates/workspace-core/.agents/skills/visual-answer/SKILL.md +1 -0
- package/dist/vite/agents-bundle-plugin.d.ts.map +1 -1
- package/dist/vite/agents-bundle-plugin.js +8 -7
- package/dist/vite/agents-bundle-plugin.js.map +1 -1
- package/dist/vite/client.d.ts.map +1 -1
- package/dist/vite/client.js +66 -1
- package/dist/vite/client.js.map +1 -1
- package/docs/content/actions.mdx +2 -2
- package/docs/content/agent-surfaces.mdx +1 -1
- package/docs/content/authentication.mdx +2 -0
- package/docs/content/deployment.mdx +36 -0
- package/docs/content/http-api.mdx +266 -0
- package/docs/content/syncing-template-changes.mdx +159 -0
- package/package.json +4 -3
- package/src/a2a/activity.ts +38 -27
- package/src/a2a/client.ts +57 -4
- package/src/agent/engine/builder-engine.ts +35 -4
- package/src/agent/run-manager.ts +20 -1
- package/src/agent/run-store.ts +4 -1
- package/src/agent/types.ts +28 -8
- package/src/chat-threads/store.ts +45 -0
- package/src/checkpoints/index.ts +2 -0
- package/src/checkpoints/route-match.ts +13 -0
- package/src/cli/create.ts +105 -17
- package/src/cli/index.ts +20 -0
- package/src/cli/template-baseline.ts +410 -0
- package/src/cli/template-sync.ts +1004 -0
- package/src/cli/templates-meta.ts +1 -0
- package/src/client/AssistantChat.tsx +38 -12
- package/src/client/NewWorkspaceAppFlow.tsx +75 -10
- package/src/client/chat/message-components.tsx +127 -66
- package/src/client/chat/tool-call-display.tsx +29 -5
- package/src/client/error-format.ts +18 -0
- package/src/client/org/OrgSwitcher.tsx +30 -8
- package/src/client/org/TeamPage.tsx +7 -6
- package/src/client/settings/SettingsPanel.tsx +9 -9
- package/src/client/settings/SettingsTabsPage.tsx +12 -2
- package/src/client/sse-event-processor.ts +3 -0
- package/src/data-widgets/index.ts +41 -0
- package/src/deploy/build.ts +11 -9
- package/src/extensions/url-safety.ts +67 -4
- package/src/integrations/webhook-handler.ts +63 -9
- package/src/org/auto-join-domain.ts +4 -3
- package/src/org/context.ts +108 -39
- package/src/org/index.ts +5 -0
- package/src/org/service-identity.ts +60 -0
- package/src/provider-api/index.ts +22 -1
- package/src/scripts/docs/search.ts +12 -1
- package/src/server/__snapshots__/agent-chat-plugin.surface.spec.ts.snap +25 -36
- package/src/server/agent-chat/context-tools.ts +9 -4
- package/src/server/agent-chat/framework-prompts.ts +38 -66
- package/src/server/agent-chat-plugin.ts +17 -10
- package/src/server/agents-bundle.ts +84 -5
- package/src/server/auth.ts +4 -3
- package/src/server/builder-browser.ts +47 -19
- package/src/server/core-routes-plugin.ts +2 -2
- package/src/server/credential-provider.ts +209 -68
- package/src/server/index.ts +3 -0
- package/src/server/prompts/framework-core-compact.ts +6 -13
- package/src/server/prompts/framework-core.ts +9 -21
- package/src/server/prompts/index.ts +0 -1
- package/src/server/prompts/shared-rules.ts +19 -11
- package/src/server/ssr-handler.ts +13 -2
- package/src/settings/user-settings.ts +13 -1
- package/src/shared/cache-control.ts +141 -0
- package/src/templates/chat/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
- package/src/templates/chat/_gitignore +1 -0
- package/src/templates/chat/app/components/layout/Sidebar.tsx +0 -7
- package/src/templates/chat/changelog/2026-07-25-settings-navigation-now-keeps-manage-agent-as-a-dedicated-li.md +6 -0
- package/src/templates/default/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
- package/src/templates/default/app/root.tsx +1 -1
- package/src/templates/default/public/manifest.json +2 -2
- package/src/templates/headless/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
- package/src/templates/workspace-core/.agents/skills/performance/SKILL.md +19 -0
- package/src/templates/workspace-core/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
- package/src/templates/workspace-core/.agents/skills/visual-answer/SKILL.md +1 -0
- package/src/vite/agents-bundle-plugin.ts +7 -6
- package/src/vite/client.ts +69 -3
|
@@ -3001,18 +3001,10 @@ export function useAgentSettingsTabs(): SettingsTabItem[] {
|
|
|
3001
3001
|
const organization = searchTab("organization");
|
|
3002
3002
|
const workspace = searchTab("workspace");
|
|
3003
3003
|
return [
|
|
3004
|
-
{
|
|
3005
|
-
...agent,
|
|
3006
|
-
icon: IconHierarchy2,
|
|
3007
|
-
group: "agent",
|
|
3008
|
-
href: "/agent#settings",
|
|
3009
|
-
searchEntries: undefined,
|
|
3010
|
-
content: <Navigate to="/agent#settings" replace />,
|
|
3011
|
-
},
|
|
3012
3004
|
{
|
|
3013
3005
|
...connections,
|
|
3014
3006
|
icon: IconPlugConnected,
|
|
3015
|
-
group: "
|
|
3007
|
+
group: "workspace",
|
|
3016
3008
|
content: <ConnectionsSettingsContent settingsPanelProps={baseProps} />,
|
|
3017
3009
|
},
|
|
3018
3010
|
{
|
|
@@ -3047,6 +3039,14 @@ export function useAgentSettingsTabs(): SettingsTabItem[] {
|
|
|
3047
3039
|
keywords: "extensions widgets mini apps tools sandboxed apps",
|
|
3048
3040
|
content: <ExtensionsSettingsContent />,
|
|
3049
3041
|
},
|
|
3042
|
+
{
|
|
3043
|
+
...agent,
|
|
3044
|
+
icon: IconHierarchy2,
|
|
3045
|
+
group: "manage-agent",
|
|
3046
|
+
href: "/agent#settings",
|
|
3047
|
+
searchEntries: undefined,
|
|
3048
|
+
content: <Navigate to="/agent#settings" replace />,
|
|
3049
|
+
},
|
|
3050
3050
|
];
|
|
3051
3051
|
}, [baseProps]);
|
|
3052
3052
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Tabs, useDesignSystem } from "@agent-native/toolkit/design-system";
|
|
2
2
|
import {
|
|
3
|
+
IconArrowUpRight,
|
|
3
4
|
IconHistory,
|
|
4
5
|
IconSearch,
|
|
5
6
|
IconSettings,
|
|
@@ -216,6 +217,8 @@ export function SettingsTabsPage({
|
|
|
216
217
|
const hasOrganizationTab = extraTabs.some(
|
|
217
218
|
(tab) => tab.id === "organization",
|
|
218
219
|
);
|
|
220
|
+
const inlineTabs = extraTabs.filter((tab) => !tab.href);
|
|
221
|
+
const linkedTabs = extraTabs.filter((tab) => tab.href);
|
|
219
222
|
const next: SettingsTabItem[] = [
|
|
220
223
|
{
|
|
221
224
|
id: "general",
|
|
@@ -234,7 +237,7 @@ export function SettingsTabsPage({
|
|
|
234
237
|
keywords: "profile photo avatar identity signed in email name",
|
|
235
238
|
});
|
|
236
239
|
}
|
|
237
|
-
next.push(...
|
|
240
|
+
next.push(...inlineTabs);
|
|
238
241
|
if (team && !hasOrganizationTab) {
|
|
239
242
|
next.push({
|
|
240
243
|
id: "team",
|
|
@@ -249,10 +252,11 @@ export function SettingsTabsPage({
|
|
|
249
252
|
id: "whats-new",
|
|
250
253
|
label: whatsNewLabel,
|
|
251
254
|
icon: IconHistory,
|
|
252
|
-
group: "
|
|
255
|
+
group: next.at(-1)?.group ?? "app",
|
|
253
256
|
content: whatsNew,
|
|
254
257
|
});
|
|
255
258
|
}
|
|
259
|
+
next.push(...linkedTabs);
|
|
256
260
|
return next;
|
|
257
261
|
}, [
|
|
258
262
|
account,
|
|
@@ -615,6 +619,12 @@ export function SettingsTabsPage({
|
|
|
615
619
|
/>
|
|
616
620
|
) : null}
|
|
617
621
|
<span className="truncate">{tab.label}</span>
|
|
622
|
+
{tab.href ? (
|
|
623
|
+
<IconArrowUpRight
|
|
624
|
+
aria-hidden="true"
|
|
625
|
+
className="size-3.5 shrink-0 text-muted-foreground/80"
|
|
626
|
+
/>
|
|
627
|
+
) : null}
|
|
618
628
|
</>
|
|
619
629
|
);
|
|
620
630
|
if (tab.href) {
|
|
@@ -625,6 +625,9 @@ function isAutoRecoverableError(ev: SSEEvent, errMsg: string): boolean {
|
|
|
625
625
|
code === "unauthorized" ||
|
|
626
626
|
code === "authentication_error" ||
|
|
627
627
|
code === "permission_error" ||
|
|
628
|
+
code === "builder_auth_error" ||
|
|
629
|
+
// The account cannot use this model; another POST picks the same one.
|
|
630
|
+
code === "builder_model_unauthorized" ||
|
|
628
631
|
code === "http_401" ||
|
|
629
632
|
code === "http_403" ||
|
|
630
633
|
code === "rate_limit_exceeded" ||
|
|
@@ -282,6 +282,47 @@ export function isDataWidgetResult(value: unknown): value is DataWidgetResult {
|
|
|
282
282
|
return normalizeDataWidgetResult(value) !== null;
|
|
283
283
|
}
|
|
284
284
|
|
|
285
|
+
export const DATA_WIDGET_MAX_ROWS = 50;
|
|
286
|
+
export const DATA_WIDGET_MAX_CHART_POINTS = 200;
|
|
287
|
+
|
|
288
|
+
// Widget rows arrive as tool-call arguments the model decodes token by token, so an
|
|
289
|
+
// uncapped table costs minutes of wall clock before anything renders. Clamp server-side
|
|
290
|
+
// rather than rejecting: the model has already paid for the tokens by the time we see them.
|
|
291
|
+
export function clampDataWidgetRows(
|
|
292
|
+
result: DataWidgetResult,
|
|
293
|
+
): DataWidgetResult {
|
|
294
|
+
const source = result as Partial<DataInsightsWidgetResult>;
|
|
295
|
+
const table = source.table;
|
|
296
|
+
const chartSeries = source.chartSeries;
|
|
297
|
+
|
|
298
|
+
const clampedTable =
|
|
299
|
+
table && table.rows.length > DATA_WIDGET_MAX_ROWS
|
|
300
|
+
? {
|
|
301
|
+
...table,
|
|
302
|
+
rows: table.rows.slice(0, DATA_WIDGET_MAX_ROWS),
|
|
303
|
+
totalRows: table.totalRows ?? table.rows.length,
|
|
304
|
+
sampledRows: DATA_WIDGET_MAX_ROWS,
|
|
305
|
+
truncated: true,
|
|
306
|
+
}
|
|
307
|
+
: table;
|
|
308
|
+
|
|
309
|
+
const clampedChart =
|
|
310
|
+
chartSeries && chartSeries.data.length > DATA_WIDGET_MAX_CHART_POINTS
|
|
311
|
+
? {
|
|
312
|
+
...chartSeries,
|
|
313
|
+
data: chartSeries.data.slice(0, DATA_WIDGET_MAX_CHART_POINTS),
|
|
314
|
+
sampled: true,
|
|
315
|
+
}
|
|
316
|
+
: chartSeries;
|
|
317
|
+
|
|
318
|
+
if (clampedTable === table && clampedChart === chartSeries) return result;
|
|
319
|
+
return {
|
|
320
|
+
...result,
|
|
321
|
+
...(clampedTable ? { table: clampedTable } : {}),
|
|
322
|
+
...(clampedChart ? { chartSeries: clampedChart } : {}),
|
|
323
|
+
} as DataWidgetResult;
|
|
324
|
+
}
|
|
325
|
+
|
|
285
326
|
const dataTableColumnSchema = z
|
|
286
327
|
.object({
|
|
287
328
|
key: z.string().min(1),
|
package/src/deploy/build.ts
CHANGED
|
@@ -36,10 +36,8 @@ import {
|
|
|
36
36
|
} from "../integrations/integration-durable-dispatch-config.js";
|
|
37
37
|
import { normalizeAppBasePath } from "../server/app-base-path.js";
|
|
38
38
|
import {
|
|
39
|
-
DEFAULT_SSR_CDN_CACHE_CONTROL,
|
|
40
|
-
DEFAULT_SSR_NETLIFY_CDN_CACHE_CONTROL,
|
|
41
39
|
DEFAULT_SPECULATION_RULES_PATH,
|
|
42
|
-
|
|
40
|
+
resolveSsrCacheHeaders,
|
|
43
41
|
} from "../shared/cache-control.js";
|
|
44
42
|
import { mcpEmbedStaticAssetRouteRules } from "../shared/mcp-embed-headers.js";
|
|
45
43
|
import {
|
|
@@ -698,6 +696,9 @@ export function generateWorkerEntry(
|
|
|
698
696
|
options: GenerateWorkerEntryOptions = {},
|
|
699
697
|
): string {
|
|
700
698
|
const includeReactRouterSsr = options.includeReactRouterSsr ?? true;
|
|
699
|
+
// The worker ships as a static bundle with no access to runtime env, so the
|
|
700
|
+
// deployment-wide SSR cache policy is baked in from this build's env.
|
|
701
|
+
const ssrCacheHeaders = resolveSsrCacheHeaders();
|
|
701
702
|
const routeImports: string[] = [];
|
|
702
703
|
const routeRegistrations: string[] = [];
|
|
703
704
|
|
|
@@ -984,9 +985,10 @@ function injectHeadScript(html, script) {
|
|
|
984
985
|
return html.slice(0, headCloseIdx) + script + html.slice(headCloseIdx);
|
|
985
986
|
}
|
|
986
987
|
|
|
987
|
-
|
|
988
|
-
const
|
|
989
|
-
const
|
|
988
|
+
// Resolved from AGENT_NATIVE_SSR_CACHE at build time.
|
|
989
|
+
const SSR_CACHE_CONTROL = ${JSON.stringify(ssrCacheHeaders["cache-control"])};
|
|
990
|
+
const SSR_CDN_CACHE_CONTROL = ${JSON.stringify(ssrCacheHeaders["cdn-cache-control"])};
|
|
991
|
+
const SSR_NETLIFY_CDN_CACHE_CONTROL = ${JSON.stringify(ssrCacheHeaders["netlify-cdn-cache-control"])};
|
|
990
992
|
const DEFAULT_SPECULATION_RULES_PATH = ${JSON.stringify(DEFAULT_SPECULATION_RULES_PATH)};
|
|
991
993
|
const IMMUTABLE_ASSET_CACHE_CONTROL = ${JSON.stringify(IMMUTABLE_ASSET_CACHE_CONTROL)};
|
|
992
994
|
const IMMUTABLE_ASSET_PATHS = new Set(${JSON.stringify(
|
|
@@ -1084,13 +1086,13 @@ function applyDefaultSsrCacheHeader(headers, status, pathname) {
|
|
|
1084
1086
|
else headers.delete("vary");
|
|
1085
1087
|
}
|
|
1086
1088
|
|
|
1087
|
-
headers.set("cache-control",
|
|
1088
|
-
headers.set("cdn-cache-control",
|
|
1089
|
+
headers.set("cache-control", SSR_CACHE_CONTROL);
|
|
1090
|
+
headers.set("cdn-cache-control", SSR_CDN_CACHE_CONTROL);
|
|
1089
1091
|
// Netlify function responses are dynamic by default and can otherwise show
|
|
1090
1092
|
// Cache-Status fwd=bypass even with Cache-Control: public. Keep this
|
|
1091
1093
|
// Netlify-specific header so SSR HTML/.data are served from the shared
|
|
1092
1094
|
// durable CDN cache instead of stampeding origin — for every visitor.
|
|
1093
|
-
headers.set("netlify-cdn-cache-control",
|
|
1095
|
+
headers.set("netlify-cdn-cache-control", SSR_NETLIFY_CDN_CACHE_CONTROL);
|
|
1094
1096
|
}
|
|
1095
1097
|
|
|
1096
1098
|
function applyDefaultSpeculationRulesHeader(headers, status, basePath) {
|
|
@@ -163,7 +163,32 @@ export async function isBlockedExtensionUrlWithDns(
|
|
|
163
163
|
* runtimes); the caller should fall back to the regular `fetch` path —
|
|
164
164
|
* `isBlockedExtensionUrlWithDns` will still have caught most rebinding cases.
|
|
165
165
|
*/
|
|
166
|
-
|
|
166
|
+
function normalizeLookupHostname(hostname: string): string {
|
|
167
|
+
return hostname.toLowerCase().replace(/^\[|\]$/g, "");
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function normalizeAllowedPrivateOriginKeys(
|
|
171
|
+
origins: readonly string[],
|
|
172
|
+
): Set<string> {
|
|
173
|
+
const keys = new Set<string>();
|
|
174
|
+
for (const origin of origins) {
|
|
175
|
+
try {
|
|
176
|
+
const parsed = new URL(origin);
|
|
177
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
178
|
+
continue;
|
|
179
|
+
}
|
|
180
|
+
const port = parsed.port || (parsed.protocol === "https:" ? "443" : "80");
|
|
181
|
+
keys.add(`${normalizeLookupHostname(parsed.hostname)}:${port}`);
|
|
182
|
+
} catch {
|
|
183
|
+
// Ignore malformed deployment configuration and retain the private-IP guard.
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
return keys;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
export async function createSsrfSafeDispatcher(
|
|
190
|
+
allowedPrivateOrigins: readonly string[] = [],
|
|
191
|
+
): Promise<unknown | null> {
|
|
167
192
|
// Keep the optional undici import opaque to Vite/Rolldown. A static
|
|
168
193
|
// `import("undici")` makes browser builds try to resolve and bundle undici
|
|
169
194
|
// even though this dispatcher is only useful in Node server runtimes.
|
|
@@ -182,6 +207,9 @@ export async function createSsrfSafeDispatcher(): Promise<unknown | null> {
|
|
|
182
207
|
|
|
183
208
|
const { Agent } = undici;
|
|
184
209
|
const { lookup } = dnsModule;
|
|
210
|
+
const allowedPrivateOriginKeys = normalizeAllowedPrivateOriginKeys(
|
|
211
|
+
allowedPrivateOrigins,
|
|
212
|
+
);
|
|
185
213
|
if (!Agent || !lookup) return null;
|
|
186
214
|
|
|
187
215
|
return new Agent({
|
|
@@ -209,7 +237,10 @@ export async function createSsrfSafeDispatcher(): Promise<unknown | null> {
|
|
|
209
237
|
? addresses
|
|
210
238
|
: [{ address: addresses, family: 4 }];
|
|
211
239
|
for (const record of list) {
|
|
212
|
-
|
|
240
|
+
const allowedOrigin = allowedPrivateOriginKeys.has(
|
|
241
|
+
`${normalizeLookupHostname(hostname)}:${String(options?.port ?? "")}`,
|
|
242
|
+
);
|
|
243
|
+
if (isPrivateHost(record.address) && !allowedOrigin) {
|
|
213
244
|
const e = new Error(
|
|
214
245
|
`Connect blocked: ${hostname} resolved to private address ${record.address}`,
|
|
215
246
|
) as NodeJS.ErrnoException;
|
|
@@ -264,10 +295,39 @@ export async function ssrfSafeFetch(
|
|
|
264
295
|
maxRedirects?: number;
|
|
265
296
|
httpsOnly?: boolean;
|
|
266
297
|
assertUrlAllowed?: (url: string) => void | Promise<void>;
|
|
298
|
+
/**
|
|
299
|
+
* Exact origins that may resolve to a private address. A workspace runs
|
|
300
|
+
* every app on loopback behind one gateway, so sibling A2A calls are
|
|
301
|
+
* private by construction; without this they are indistinguishable from an
|
|
302
|
+
* SSRF attempt and get blocked. Only ever pass origins the deployment
|
|
303
|
+
* itself configured (never a request-supplied value).
|
|
304
|
+
*/
|
|
305
|
+
allowedPrivateOrigins?: readonly string[];
|
|
267
306
|
} = {},
|
|
268
307
|
): Promise<Response> {
|
|
269
308
|
const maxRedirects = options.maxRedirects ?? 3;
|
|
270
|
-
const dispatcher =
|
|
309
|
+
const dispatcher =
|
|
310
|
+
(await createSsrfSafeDispatcher(options.allowedPrivateOrigins)) ??
|
|
311
|
+
undefined;
|
|
312
|
+
const allowedPrivateOrigins = new Set(
|
|
313
|
+
(options.allowedPrivateOrigins ?? [])
|
|
314
|
+
.map((origin) => {
|
|
315
|
+
try {
|
|
316
|
+
return new URL(origin).origin;
|
|
317
|
+
} catch {
|
|
318
|
+
return "";
|
|
319
|
+
}
|
|
320
|
+
})
|
|
321
|
+
.filter(Boolean),
|
|
322
|
+
);
|
|
323
|
+
const isAllowedPrivateOrigin = (candidate: string): boolean => {
|
|
324
|
+
if (allowedPrivateOrigins.size === 0) return false;
|
|
325
|
+
try {
|
|
326
|
+
return allowedPrivateOrigins.has(new URL(candidate).origin);
|
|
327
|
+
} catch {
|
|
328
|
+
return false;
|
|
329
|
+
}
|
|
330
|
+
};
|
|
271
331
|
|
|
272
332
|
let currentUrl = url;
|
|
273
333
|
for (let hop = 0; hop <= maxRedirects; hop++) {
|
|
@@ -277,7 +337,10 @@ export async function ssrfSafeFetch(
|
|
|
277
337
|
`SSRF blocked: refusing to fetch non-HTTPS address (${currentUrl})`,
|
|
278
338
|
);
|
|
279
339
|
}
|
|
280
|
-
if (
|
|
340
|
+
if (
|
|
341
|
+
!isAllowedPrivateOrigin(currentUrl) &&
|
|
342
|
+
(await isBlockedExtensionUrlWithDns(currentUrl))
|
|
343
|
+
) {
|
|
281
344
|
throw new Error(
|
|
282
345
|
`SSRF blocked: refusing to fetch private/internal address (${currentUrl})`,
|
|
283
346
|
);
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
type A2AToolResultSummary,
|
|
9
9
|
} from "../a2a/artifact-response.js";
|
|
10
10
|
import { collectFinalResponseTextFromAgentEvents } from "../a2a/response-text.js";
|
|
11
|
+
import { isInBackgroundFunctionRuntime } from "../agent/durable-background.js";
|
|
11
12
|
import {
|
|
12
13
|
formatLlmCredentialErrorMessage,
|
|
13
14
|
isLlmCredentialError,
|
|
@@ -41,7 +42,11 @@ import {
|
|
|
41
42
|
threadDataToEngineMessages,
|
|
42
43
|
} from "../agent/thread-data-builder.js";
|
|
43
44
|
import { attachToolSearch } from "../agent/tool-search.js";
|
|
44
|
-
import {
|
|
45
|
+
import {
|
|
46
|
+
createThread,
|
|
47
|
+
getThread,
|
|
48
|
+
grantThreadUserShare,
|
|
49
|
+
} from "../chat-threads/store.js";
|
|
45
50
|
import { updateThreadData } from "../chat-threads/store.js";
|
|
46
51
|
import { isLocalDatabase } from "../db/client.js";
|
|
47
52
|
import { getOrgA2ASecret, resolveOrgIdForEmail } from "../org/context.js";
|
|
@@ -88,6 +93,20 @@ const DEFERRED_RESPONSE_DISPATCH_SETTLE_WAIT_MS = 1_500;
|
|
|
88
93
|
const DEFERRED_RESPONSE_MAX_HANDLER_MS = 2_500;
|
|
89
94
|
const EMPTY_INTEGRATION_RESPONSE_MESSAGE =
|
|
90
95
|
"The model finished without a visible answer. Try again, or open the thread in Dispatch to inspect the run.";
|
|
96
|
+
const CUTOFF_INTEGRATION_RESPONSE_MESSAGE =
|
|
97
|
+
"I ran out of time on this one before I could write up an answer — it needed more research than a single run allows. " +
|
|
98
|
+
"Open the thread in Dispatch to see what I gathered, or ask me again in smaller pieces (one source at a time works best).";
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* True when the run stopped at a continuation boundary rather than finishing:
|
|
102
|
+
* the run-manager's soft timeout emits `auto_continue` and aborts the loop, and
|
|
103
|
+
* the loop itself emits one when it hits an internal step budget. The run's
|
|
104
|
+
* status is still "completed", so without this check a cut-off research request
|
|
105
|
+
* is reported to the user as a model that answered with nothing.
|
|
106
|
+
*/
|
|
107
|
+
function endedAtContinuationBoundary(run: ActiveRun): boolean {
|
|
108
|
+
return run.events.some((runEvent) => runEvent.event.type === "auto_continue");
|
|
109
|
+
}
|
|
91
110
|
|
|
92
111
|
type ToolDoneEvent = {
|
|
93
112
|
type: "tool_done";
|
|
@@ -789,6 +808,29 @@ async function processIncomingMessage(
|
|
|
789
808
|
await releaseApplicableIntegrationBudgets(budgetReservations.reservations);
|
|
790
809
|
throw error;
|
|
791
810
|
}
|
|
811
|
+
|
|
812
|
+
// Channel conversations run as the integration service principal, so the
|
|
813
|
+
// thread is owned by `integration@<platform>` and not by the human who asked.
|
|
814
|
+
// The "Open thread" deep link we hand back would then 404 for them and the
|
|
815
|
+
// chat surface would silently render an empty new chat, so grant each
|
|
816
|
+
// verified participant an explicit share on the thread they are driving.
|
|
817
|
+
if (
|
|
818
|
+
incoming.senderVerified === true &&
|
|
819
|
+
incoming.senderEmail &&
|
|
820
|
+
incoming.senderEmail.trim().toLowerCase() !== ownerEmail.toLowerCase()
|
|
821
|
+
) {
|
|
822
|
+
await grantThreadUserShare(
|
|
823
|
+
threadId,
|
|
824
|
+
incoming.senderEmail,
|
|
825
|
+
"editor",
|
|
826
|
+
ownerEmail,
|
|
827
|
+
).catch((error) => {
|
|
828
|
+
console.warn(
|
|
829
|
+
`[integrations] Could not grant ${incoming.platform} sender access to thread ${threadId}:`,
|
|
830
|
+
error instanceof Error ? error.message : error,
|
|
831
|
+
);
|
|
832
|
+
});
|
|
833
|
+
}
|
|
792
834
|
const existingMessages: EngineMessage[] = [];
|
|
793
835
|
if (thread?.threadData) {
|
|
794
836
|
existingMessages.push(...threadDataToEngineMessages(thread.threadData));
|
|
@@ -1051,7 +1093,10 @@ async function processIncomingMessage(
|
|
|
1051
1093
|
"directly is the most reliable way to get an answer right now.";
|
|
1052
1094
|
} else {
|
|
1053
1095
|
responseText =
|
|
1054
|
-
verifiedMutationReceipt ??
|
|
1096
|
+
verifiedMutationReceipt ??
|
|
1097
|
+
(endedAtContinuationBoundary(completedRun)
|
|
1098
|
+
? CUTOFF_INTEGRATION_RESPONSE_MESSAGE
|
|
1099
|
+
: EMPTY_INTEGRATION_RESPONSE_MESSAGE);
|
|
1055
1100
|
}
|
|
1056
1101
|
}
|
|
1057
1102
|
if (approval?.type === "approval_required") {
|
|
@@ -1346,13 +1391,22 @@ async function processIncomingMessage(
|
|
|
1346
1391
|
resolve(outcome);
|
|
1347
1392
|
}
|
|
1348
1393
|
},
|
|
1349
|
-
//
|
|
1350
|
-
//
|
|
1351
|
-
//
|
|
1352
|
-
//
|
|
1353
|
-
//
|
|
1354
|
-
//
|
|
1355
|
-
|
|
1394
|
+
// Without the hosted soft timeout, a wedged model connection can outlive
|
|
1395
|
+
// the worker and leave Slack's native stream in "working" forever when
|
|
1396
|
+
// the host kills the process. Checkpoint at the safe boundary so
|
|
1397
|
+
// onComplete can always close the provider progress surface first.
|
|
1398
|
+
//
|
|
1399
|
+
// Which boundary that is depends on where this task is actually running:
|
|
1400
|
+
// when durable dispatch routes it to the emitted `-background` function
|
|
1401
|
+
// it has ~15min, and clamping it to the 40s foreground budget anyway cut
|
|
1402
|
+
// off every research-shaped request (multi-source sweeps, long tool
|
|
1403
|
+
// chains) with no visible answer. `isInBackgroundFunctionRuntime()` is
|
|
1404
|
+
// the runtime proof — never a config guess — so the wider ceiling is
|
|
1405
|
+
// taken only where the ~60s synchronous wall genuinely does not apply.
|
|
1406
|
+
{
|
|
1407
|
+
useHostedSoftTimeoutDefault: true,
|
|
1408
|
+
backgroundFunction: isInBackgroundFunctionRuntime(),
|
|
1409
|
+
},
|
|
1356
1410
|
);
|
|
1357
1411
|
});
|
|
1358
1412
|
}
|
|
@@ -14,9 +14,10 @@ export interface AutoJoinDomainOptions {
|
|
|
14
14
|
/**
|
|
15
15
|
* The signup hook should not clobber an org selected by an invite flow, but
|
|
16
16
|
* request-time org resolution may need to move an existing account from a
|
|
17
|
-
* personal workspace into its newly matched company org.
|
|
17
|
+
* personal workspace into its newly matched company org. `"never"` joins
|
|
18
|
+
* without touching `active-org-id` — the caller decides activation itself.
|
|
18
19
|
*/
|
|
19
|
-
activateJoinedOrg?: "if-missing" | "always";
|
|
20
|
+
activateJoinedOrg?: "if-missing" | "always" | "never";
|
|
20
21
|
}
|
|
21
22
|
|
|
22
23
|
/**
|
|
@@ -96,7 +97,7 @@ export async function autoJoinDomainMatchingOrgs(
|
|
|
96
97
|
// one, unless the caller is request-time org resolution intentionally moving
|
|
97
98
|
// an existing account into its newly matched company org.
|
|
98
99
|
let activeOrgId: string | null = null;
|
|
99
|
-
if (joined[0]) {
|
|
100
|
+
if (joined[0] && options.activateJoinedOrg !== "never") {
|
|
100
101
|
try {
|
|
101
102
|
const existing = await getUserSetting(email, "active-org-id");
|
|
102
103
|
const hasActive = Boolean(existing?.orgId);
|
package/src/org/context.ts
CHANGED
|
@@ -20,12 +20,33 @@ function normalizeOrgRole(value: unknown): OrgRole | null {
|
|
|
20
20
|
: null;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
function
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
23
|
+
function emailDomainOf(email: string): string | null {
|
|
24
|
+
return email.split("@")[1]?.toLowerCase() || null;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* A workspace the user owns that nobody else has joined is a default/personal
|
|
29
|
+
* workspace whatever it happens to be named, so moving the user into their
|
|
30
|
+
* company org is safe. An org with other members is a team they deliberately
|
|
31
|
+
* belong to — join the domain org in the background but leave them there.
|
|
32
|
+
*/
|
|
33
|
+
async function isSoloOwnedWorkspace(
|
|
34
|
+
exec: ReturnType<typeof getDbExec>,
|
|
35
|
+
orgId: string,
|
|
36
|
+
memberships: MembershipRow[],
|
|
37
|
+
): Promise<boolean> {
|
|
38
|
+
const membership = memberships.find((m) => m.orgId === orgId);
|
|
39
|
+
if (!membership || membership.role !== "owner") return false;
|
|
40
|
+
try {
|
|
41
|
+
const { rows } = await exec.execute({
|
|
42
|
+
sql: `SELECT COUNT(*) AS "memberCount" FROM org_members WHERE org_id = ?`,
|
|
43
|
+
args: [orgId],
|
|
44
|
+
});
|
|
45
|
+
const row = rows[0] as any;
|
|
46
|
+
return Number(row?.memberCount ?? row?.membercount ?? 0) <= 1;
|
|
47
|
+
} catch {
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
29
50
|
}
|
|
30
51
|
|
|
31
52
|
function autoCreateDefaultOrgEnabled(): boolean {
|
|
@@ -61,7 +82,12 @@ export async function getOrgContext(event: H3Event): Promise<OrgContext> {
|
|
|
61
82
|
return (ctx.__anOrgContextCache ??= resolveOrgContextUncached(event));
|
|
62
83
|
}
|
|
63
84
|
|
|
64
|
-
type MembershipRow = {
|
|
85
|
+
type MembershipRow = {
|
|
86
|
+
orgId: string;
|
|
87
|
+
role: OrgRole;
|
|
88
|
+
orgName: string;
|
|
89
|
+
allowedDomain: string | null;
|
|
90
|
+
};
|
|
65
91
|
|
|
66
92
|
const MEMBERSHIPS_CACHE_KEY = "__anOrgMembershipsCache";
|
|
67
93
|
const ACTIVE_ORG_SETTING_CACHE_KEY = "__anActiveOrgSettingCache";
|
|
@@ -157,17 +183,26 @@ async function resolveOrgContextUncached(event: H3Event): Promise<OrgContext> {
|
|
|
157
183
|
return { email, orgId: null, orgName: null, role: null };
|
|
158
184
|
}
|
|
159
185
|
|
|
160
|
-
const shouldTryDomainAutoJoin =
|
|
161
|
-
memberships.length === 0 ||
|
|
162
|
-
(memberships.length === 1 &&
|
|
163
|
-
isLikelyPersonalWorkspace(memberships[0], email, session));
|
|
164
186
|
const activeOrgSetting = await loadActiveOrgSettingForEvent(event, email);
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
187
|
+
const explicitPersonal = activeOrgSetting?.orgId === null;
|
|
188
|
+
|
|
189
|
+
const emailDomain = emailDomainOf(email);
|
|
190
|
+
// Membership in a domain-matched org is the only durable "already joined"
|
|
191
|
+
// signal. Recognizing the personal workspace by its *name* instead breaks the
|
|
192
|
+
// moment the provider display name or the workspace name changes, which
|
|
193
|
+
// strands an existing user in Personal with no way into their company org.
|
|
194
|
+
const shouldTryDomainAutoJoin =
|
|
195
|
+
!explicitPersonal &&
|
|
196
|
+
emailDomain !== null &&
|
|
197
|
+
!memberships.some((m) => m.allowedDomain?.toLowerCase() === emailDomain);
|
|
198
|
+
|
|
199
|
+
if (
|
|
200
|
+
!explicitPersonal &&
|
|
201
|
+
activeOrgSetting?.orgId &&
|
|
202
|
+
!shouldTryDomainAutoJoin
|
|
203
|
+
) {
|
|
169
204
|
const active = memberships.find((m) => m.orgId === activeOrgSetting.orgId);
|
|
170
|
-
if (active
|
|
205
|
+
if (active) {
|
|
171
206
|
return {
|
|
172
207
|
email,
|
|
173
208
|
orgId: active.orgId,
|
|
@@ -182,30 +217,63 @@ async function resolveOrgContextUncached(event: H3Event): Promise<OrgContext> {
|
|
|
182
217
|
: null;
|
|
183
218
|
|
|
184
219
|
if (shouldTryDomainAutoJoin) {
|
|
220
|
+
const membershipsBeforeJoin = memberships;
|
|
185
221
|
const joined = await autoJoinDomainMatchingOrgs(email, {
|
|
186
|
-
activateJoinedOrg: "
|
|
222
|
+
activateJoinedOrg: "never",
|
|
187
223
|
});
|
|
188
|
-
|
|
224
|
+
const joinedOrgId = joined.joined[0]?.orgId ?? null;
|
|
225
|
+
if (joinedOrgId) {
|
|
189
226
|
const refreshed = await loadMemberships(exec, email);
|
|
190
227
|
if (refreshed !== null) {
|
|
191
228
|
memberships = refreshed;
|
|
192
229
|
updateMembershipsForEvent(event, email, refreshed);
|
|
193
230
|
}
|
|
194
|
-
}
|
|
195
231
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
232
|
+
const currentOrgId =
|
|
233
|
+
activeOrgSetting?.orgId ??
|
|
234
|
+
sessionOrgId ??
|
|
235
|
+
membershipsBeforeJoin[0]?.orgId ??
|
|
236
|
+
null;
|
|
237
|
+
const shouldActivate =
|
|
238
|
+
!explicitPersonal &&
|
|
239
|
+
(currentOrgId === null ||
|
|
240
|
+
(await isSoloOwnedWorkspace(
|
|
241
|
+
exec,
|
|
242
|
+
currentOrgId,
|
|
243
|
+
membershipsBeforeJoin,
|
|
244
|
+
)));
|
|
245
|
+
|
|
246
|
+
if (shouldActivate) {
|
|
247
|
+
await putUserSetting(email, "active-org-id", { orgId: joinedOrgId });
|
|
248
|
+
const active = memberships.find((m) => m.orgId === joinedOrgId);
|
|
249
|
+
if (active) {
|
|
250
|
+
return {
|
|
251
|
+
email,
|
|
252
|
+
orgId: active.orgId,
|
|
253
|
+
orgName: active.orgName,
|
|
254
|
+
role: active.role,
|
|
255
|
+
};
|
|
256
|
+
}
|
|
205
257
|
}
|
|
206
258
|
}
|
|
207
259
|
}
|
|
208
260
|
|
|
261
|
+
if (explicitPersonal) {
|
|
262
|
+
return { email, orgId: null, orgName: null, role: null };
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
if (activeOrgSetting?.orgId) {
|
|
266
|
+
const active = memberships.find((m) => m.orgId === activeOrgSetting.orgId);
|
|
267
|
+
if (active) {
|
|
268
|
+
return {
|
|
269
|
+
email,
|
|
270
|
+
orgId: active.orgId,
|
|
271
|
+
orgName: active.orgName,
|
|
272
|
+
role: active.role,
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
209
277
|
if (sessionOrgId) {
|
|
210
278
|
const active =
|
|
211
279
|
sessionMembership ?? memberships.find((m) => m.orgId === sessionOrgId);
|
|
@@ -247,24 +315,25 @@ async function resolveOrgContextUncached(event: H3Event): Promise<OrgContext> {
|
|
|
247
315
|
async function loadMemberships(
|
|
248
316
|
exec: ReturnType<typeof getDbExec>,
|
|
249
317
|
email: string,
|
|
250
|
-
): Promise<
|
|
251
|
-
orgId: string;
|
|
252
|
-
role: OrgRole;
|
|
253
|
-
orgName: string;
|
|
254
|
-
}> | null> {
|
|
318
|
+
): Promise<MembershipRow[] | null> {
|
|
255
319
|
try {
|
|
256
320
|
const { rows } = await exec.execute({
|
|
257
|
-
sql: `SELECT m.org_id AS "orgId", m.role AS role, o.name AS "orgName"
|
|
321
|
+
sql: `SELECT m.org_id AS "orgId", m.role AS role, o.name AS "orgName",
|
|
322
|
+
o.allowed_domain AS "allowedDomain"
|
|
258
323
|
FROM org_members m
|
|
259
324
|
INNER JOIN organizations o ON m.org_id = o.id
|
|
260
325
|
WHERE LOWER(m.email) = ?`,
|
|
261
326
|
args: [email.toLowerCase()],
|
|
262
327
|
});
|
|
263
|
-
return rows.map((r: any) =>
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
328
|
+
return rows.map((r: any) => {
|
|
329
|
+
const domain = r.allowedDomain ?? r.allowed_domain;
|
|
330
|
+
return {
|
|
331
|
+
orgId: String(r.orgId ?? r.org_id),
|
|
332
|
+
role: String(r.role) as OrgRole,
|
|
333
|
+
orgName: String(r.orgName ?? r.org_name),
|
|
334
|
+
allowedDomain: domain ? String(domain) : null,
|
|
335
|
+
};
|
|
336
|
+
});
|
|
268
337
|
} catch {
|
|
269
338
|
// Tables may not exist yet on first boot before migrations finish.
|
|
270
339
|
return null;
|
package/src/org/index.ts
CHANGED
|
@@ -28,6 +28,11 @@ export {
|
|
|
28
28
|
createOrganization,
|
|
29
29
|
} from "./context.js";
|
|
30
30
|
|
|
31
|
+
export {
|
|
32
|
+
implicitServiceOrgRole,
|
|
33
|
+
parseServiceIdentityEmail,
|
|
34
|
+
} from "./service-identity.js";
|
|
35
|
+
|
|
31
36
|
export { acceptPendingInvitationsForEmail } from "./accept-pending.js";
|
|
32
37
|
export type { AcceptPendingResult } from "./accept-pending.js";
|
|
33
38
|
|