@agent-native/core 0.117.1 → 0.117.2
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 +10 -0
- package/corpus/core/package.json +2 -1
- package/corpus/core/src/cli/context-xray-local.ts +1 -1
- package/corpus/core/src/client/extensions/ExtensionViewer.tsx +4 -4
- package/corpus/core/src/client/extensions/ExtensionsSidebarSection.tsx +11 -11
- package/corpus/core/src/client/extensions/agent-native-extension-runtime.ts +1 -1
- package/corpus/core/src/client/extensions/delete-extension.ts +2 -2
- package/corpus/core/src/client/org/OrgSwitcher.tsx +25 -1
- package/corpus/core/src/client/settings/SettingsPanel.tsx +102 -10
- package/corpus/core/src/client/sharing/ShareButton.tsx +7 -6
- package/corpus/core/src/db/client.ts +13 -10
- package/corpus/core/src/extensions/actions.ts +13 -5
- package/corpus/core/src/extensions/local.ts +1 -0
- package/corpus/core/src/extensions/routes.ts +10 -5
- package/corpus/core/src/extensions/schema.ts +5 -0
- package/corpus/core/src/extensions/slots/store.ts +14 -4
- package/corpus/core/src/extensions/store.ts +55 -19
- package/corpus/core/src/extensions/theme.ts +1 -1
- package/corpus/core/src/file-upload/registry.ts +9 -0
- package/corpus/core/src/index.browser.ts +5 -0
- package/corpus/core/src/index.ts +1 -0
- package/corpus/core/src/localization/default-messages.ts +23 -6
- package/corpus/core/src/server/action-discovery.ts +8 -0
- package/corpus/core/src/server/better-auth-instance.ts +7 -2
- package/corpus/core/src/server/email-template.ts +18 -0
- package/corpus/core/src/server/email-templates.ts +3 -0
- package/corpus/core/src/server/email.ts +40 -4
- package/corpus/core/src/sharing/actions/share-resource.ts +1 -0
- package/corpus/core/src/templates/default/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
- package/corpus/core/src/templates/default/app/global.css +1 -1
- package/corpus/core/src/templates/default/app/i18n/ar-SA.ts +6 -6
- package/corpus/core/src/templates/default/app/i18n/de-DE.ts +6 -6
- package/corpus/core/src/templates/default/app/i18n/en-US.ts +6 -6
- package/corpus/core/src/templates/default/app/i18n/es-ES.ts +6 -6
- package/corpus/core/src/templates/default/app/i18n/fr-FR.ts +6 -6
- package/corpus/core/src/templates/default/app/i18n/hi-IN.ts +6 -6
- package/corpus/core/src/templates/default/app/i18n/ja-JP.ts +6 -6
- package/corpus/core/src/templates/default/app/i18n/ko-KR.ts +6 -6
- package/corpus/core/src/templates/default/app/i18n/pt-BR.ts +6 -6
- package/corpus/core/src/templates/default/app/i18n/zh-CN.ts +7 -7
- package/corpus/core/src/templates/default/app/i18n/zh-TW.ts +7 -7
- package/corpus/core/src/templates/headless/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
- package/corpus/core/src/user-profile/actions/get-user-profile.ts +16 -0
- package/corpus/core/src/user-profile/actions/update-user-profile.ts +24 -0
- package/corpus/core/src/user-profile/index.ts +5 -0
- package/corpus/core/src/user-profile/shared.ts +14 -0
- package/corpus/core/src/user-profile/store.ts +50 -0
- package/corpus/templates/analytics/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
- package/corpus/templates/assets/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
- package/corpus/templates/assets/app/components/layout/Sidebar.tsx +2 -2
- package/corpus/templates/assets/app/global.css +1 -1
- package/corpus/templates/assets/changelog/2026-07-22-manage-agent-navigation-now-uses-the-connected-nodes-icon.md +6 -0
- package/corpus/templates/brain/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
- package/corpus/templates/brain/app/global.css +2 -2
- package/corpus/templates/brain/app/lib/brain.ts +2 -2
- package/corpus/templates/brain/app/root.tsx +2 -2
- package/corpus/templates/brain/changelog/2026-07-22-manage-agent-navigation-now-uses-the-connected-nodes-icon.md +6 -0
- package/corpus/templates/calendar/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
- package/corpus/templates/calendar/app/components/layout/Sidebar.tsx +6 -2
- package/corpus/templates/calendar/app/global.css +1 -1
- package/corpus/templates/calendar/app/root.tsx +2 -2
- package/corpus/templates/calendar/changelog/2026-07-22-manage-agent-navigation-now-uses-the-connected-nodes-icon.md +6 -0
- package/corpus/templates/chat/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
- package/corpus/templates/chat/app/components/layout/Sidebar.tsx +2 -2
- package/corpus/templates/chat/app/global.css +1 -1
- package/corpus/templates/chat/app/root.tsx +2 -2
- package/corpus/templates/chat/changelog/2026-07-22-manage-agent-navigation-now-uses-the-connected-nodes-icon.md +6 -0
- package/corpus/templates/clips/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
- package/corpus/templates/clips/actions/export-to-brain.ts +1 -1
- package/corpus/templates/clips/actions/invite-member.ts +1 -0
- package/corpus/templates/clips/app/components/library/library-layout.tsx +2 -2
- package/corpus/templates/clips/app/components/recorder/recorder-engine.ts +20 -11
- package/corpus/templates/clips/app/global.css +1 -1
- package/corpus/templates/clips/app/root.tsx +7 -2
- package/corpus/templates/clips/app/routes/record.tsx +2 -88
- package/corpus/templates/clips/changelog/2026-07-22-builder-connected-recordings-start-resumable-upload-sessions.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-22-clip-thumbnails-now-come-from-the-recording-instead-of-the-p.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-22-clips-emails-now-render-the-agent-native-logo-in-gmail-and-o.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-22-dismissed-zoom-and-teams-meeting-note-prompts-now-stay-dismi.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-22-manage-agent-navigation-now-uses-the-connected-nodes-icon.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-22-quieter-permissions-and-rewind-controls.md +6 -0
- package/corpus/templates/clips/desktop/src/app.tsx +86 -52
- package/corpus/templates/clips/desktop/src/lib/meeting-notification-dismissal.ts +31 -0
- package/corpus/templates/clips/desktop/src/lib/recorder.ts +4 -167
- package/corpus/templates/clips/desktop/src/overlays/meeting-notification.tsx +10 -1
- package/corpus/templates/clips/desktop/src/styles.css +98 -36
- package/corpus/templates/clips/desktop/src-tauri/src/adhoc_meetings_watcher.rs +67 -4
- package/corpus/templates/clips/desktop/src-tauri/src/lib.rs +1 -1
- package/corpus/templates/clips/desktop/src-tauri/src/meetings_watcher.rs +51 -0
- package/corpus/templates/clips/desktop/src-tauri/src/native_screen/custom_capture.rs +5 -1
- package/corpus/templates/clips/desktop/src-tauri/src/native_screen.rs +0 -189
- package/corpus/templates/clips/desktop/src-tauri/src/notifications.rs +62 -0
- package/corpus/templates/clips/server/plugins/db.ts +6 -2
- package/corpus/templates/content/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
- package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +3 -3
- package/corpus/templates/content/app/global.css +1 -1
- package/corpus/templates/content/app/root.tsx +2 -2
- package/corpus/templates/content/changelog/2026-07-22-manage-agent-navigation-now-uses-the-connected-nodes-icon.md +6 -0
- package/corpus/templates/crm/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
- package/corpus/templates/crm/app/global.css +1 -1
- package/corpus/templates/design/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
- package/corpus/templates/design/app/components/design/CanvasContextMenu.tsx +19 -1
- package/corpus/templates/design/app/components/design/DesignCanvas.tsx +12 -1
- package/corpus/templates/design/app/components/design/EditPanel.tsx +177 -52
- package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +179 -59
- package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +74 -27
- package/corpus/templates/design/app/components/design/multi-screen/types.ts +2 -0
- package/corpus/templates/design/app/components/layout/Sidebar.tsx +2 -2
- package/corpus/templates/design/app/global.css +1 -1
- package/corpus/templates/design/app/hooks/use-navigation-state.ts +6 -5
- package/corpus/templates/design/app/root.tsx +2 -2
- package/corpus/templates/design/changelog/2026-07-22-design-owners-can-keep-editing-their-designs-after-switching.md +6 -0
- package/corpus/templates/design/changelog/2026-07-22-inspector-tabs-keep-their-text-labels-at-narrow-widths.md +6 -0
- package/corpus/templates/design/changelog/2026-07-22-manage-agent-navigation-now-uses-the-connected-nodes-icon.md +6 -0
- package/corpus/templates/design/changelog/2026-07-22-narrow-breakpoint-previews-keep-their-device-labels-readable.md +6 -0
- package/corpus/templates/design/changelog/2026-07-22-removed-the-draft-status-chip-from-the-design-editor.md +6 -0
- package/corpus/templates/design/changelog/2026-07-22-responsive-breakpoint-controls-stay-within-narrow-sidebars.md +6 -0
- package/corpus/templates/design/changelog/2026-07-22-responsive-peers-now-use-a-softer-selection-highlight-withou.md +6 -0
- package/corpus/templates/design/changelog/2026-07-22-rotate-from-context-menu.md +6 -0
- package/corpus/templates/design/changelog/2026-07-22-the-selection-outline-now-stays-attached-while-moving-screen.md +6 -0
- package/corpus/templates/design/changelog/2026-07-22-view-only-designs-now-support-figma-style-layer-inspection-w.md +6 -0
- package/corpus/templates/design/server/db/index.ts +4 -0
- package/corpus/templates/dispatch/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
- package/corpus/templates/dispatch/app/dispatch-extensions.tsx +2 -2
- package/corpus/templates/dispatch/app/global.css +1 -1
- package/corpus/templates/dispatch/app/root.tsx +2 -2
- package/corpus/templates/dispatch/changelog/2026-07-22-manage-agent-navigation-now-uses-the-connected-nodes-icon.md +6 -0
- package/corpus/templates/forms/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
- package/corpus/templates/forms/app/components/layout/Layout.tsx +1 -1
- package/corpus/templates/forms/app/components/layout/Sidebar.tsx +3 -3
- package/corpus/templates/forms/app/global.css +1 -1
- package/corpus/templates/forms/app/hooks/use-forms.ts +55 -2
- package/corpus/templates/forms/app/i18n/en-US.ts +2 -0
- package/corpus/templates/forms/app/pages/FormBuilderPage.tsx +3 -3
- package/corpus/templates/forms/app/pages/FormsListPage.tsx +23 -6
- package/corpus/templates/forms/app/root.tsx +2 -2
- package/corpus/templates/forms/changelog/2026-07-22-forms-now-archive-with-optimistic-feedback.md +6 -0
- package/corpus/templates/forms/changelog/2026-07-22-manage-agent-navigation-now-uses-the-connected-nodes-icon.md +6 -0
- package/corpus/templates/forms/server/plugins/agent-chat.ts +1 -1
- package/corpus/templates/macros/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
- package/corpus/templates/macros/app/components/layout/AppLayout.tsx +2 -2
- package/corpus/templates/macros/app/root.tsx +2 -2
- package/corpus/templates/macros/changelog/2026-07-22-manage-agent-navigation-now-uses-the-connected-nodes-icon.md +6 -0
- package/corpus/templates/mail/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
- package/corpus/templates/mail/app/components/layout/AppLayout.tsx +3 -3
- package/corpus/templates/mail/app/components/layout/CommandPalette.tsx +2 -2
- package/corpus/templates/mail/app/global.css +1 -1
- package/corpus/templates/mail/changelog/2026-07-22-manage-agent-navigation-now-uses-the-connected-nodes-icon.md +6 -0
- package/corpus/templates/plan/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
- package/corpus/templates/plan/app/components/layout/Sidebar.tsx +2 -2
- package/corpus/templates/plan/app/global.css +1 -1
- package/corpus/templates/plan/app/root.tsx +2 -2
- package/corpus/templates/plan/changelog/2026-07-22-manage-agent-navigation-now-uses-the-connected-nodes-icon.md +6 -0
- package/corpus/templates/slides/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
- package/corpus/templates/slides/app/components/layout/Sidebar.tsx +2 -2
- package/corpus/templates/slides/app/root.tsx +2 -2
- package/corpus/templates/slides/changelog/2026-07-22-manage-agent-navigation-now-uses-the-connected-nodes-icon.md +6 -0
- package/corpus/templates/slides/changelog/2026-07-22-slides-no-longer-fail-intermittently-on-fresh-server-instances.md +6 -0
- package/corpus/templates/slides/changelog/2026-07-22-uploaded-screenshots-can-now-be-analyzed-and-recreated-as-ed.md +6 -0
- package/corpus/templates/slides/server/lib/chat-attachments.ts +7 -3
- package/corpus/templates/slides/server/plugins/db.ts +44 -17
- package/corpus/templates/tasks/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
- package/corpus/templates/tasks/app/global.css +1 -1
- package/dist/cli/context-xray-local.js +1 -1
- package/dist/cli/context-xray-local.js.map +1 -1
- package/dist/client/extensions/ExtensionViewer.js +2 -2
- package/dist/client/extensions/ExtensionViewer.js.map +1 -1
- package/dist/client/extensions/ExtensionsSidebarSection.js +11 -11
- package/dist/client/extensions/ExtensionsSidebarSection.js.map +1 -1
- package/dist/client/extensions/agent-native-extension-runtime.js +1 -1
- package/dist/client/extensions/agent-native-extension-runtime.js.map +1 -1
- package/dist/client/extensions/delete-extension.d.ts +1 -1
- package/dist/client/extensions/delete-extension.d.ts.map +1 -1
- package/dist/client/extensions/delete-extension.js +1 -1
- package/dist/client/extensions/delete-extension.js.map +1 -1
- package/dist/client/org/OrgSwitcher.d.ts +3 -1
- package/dist/client/org/OrgSwitcher.d.ts.map +1 -1
- package/dist/client/org/OrgSwitcher.js +12 -4
- package/dist/client/org/OrgSwitcher.js.map +1 -1
- package/dist/client/settings/SettingsPanel.d.ts.map +1 -1
- package/dist/client/settings/SettingsPanel.js +37 -4
- package/dist/client/settings/SettingsPanel.js.map +1 -1
- package/dist/client/sharing/ShareButton.d.ts +3 -4
- package/dist/client/sharing/ShareButton.d.ts.map +1 -1
- package/dist/client/sharing/ShareButton.js +3 -2
- package/dist/client/sharing/ShareButton.js.map +1 -1
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/awareness.d.ts.map +1 -1
- package/dist/db/client.d.ts +7 -7
- package/dist/db/client.d.ts.map +1 -1
- package/dist/db/client.js +13 -10
- package/dist/db/client.js.map +1 -1
- package/dist/extensions/actions.d.ts.map +1 -1
- package/dist/extensions/actions.js +8 -5
- package/dist/extensions/actions.js.map +1 -1
- package/dist/extensions/local.d.ts.map +1 -1
- package/dist/extensions/local.js +1 -0
- package/dist/extensions/local.js.map +1 -1
- package/dist/extensions/routes.d.ts.map +1 -1
- package/dist/extensions/routes.js +9 -4
- package/dist/extensions/routes.js.map +1 -1
- package/dist/extensions/schema.d.ts +23 -2
- package/dist/extensions/schema.d.ts.map +1 -1
- package/dist/extensions/schema.js +5 -0
- package/dist/extensions/schema.js.map +1 -1
- package/dist/extensions/slots/store.d.ts +1 -1
- package/dist/extensions/slots/store.d.ts.map +1 -1
- package/dist/extensions/slots/store.js +4 -4
- package/dist/extensions/slots/store.js.map +1 -1
- package/dist/extensions/store.d.ts +1 -0
- package/dist/extensions/store.d.ts.map +1 -1
- package/dist/extensions/store.js +38 -21
- package/dist/extensions/store.js.map +1 -1
- package/dist/extensions/theme.js +1 -1
- package/dist/extensions/theme.js.map +1 -1
- package/dist/file-upload/registry.d.ts.map +1 -1
- package/dist/file-upload/registry.js +9 -0
- package/dist/file-upload/registry.js.map +1 -1
- package/dist/index.browser.d.ts +1 -0
- package/dist/index.browser.d.ts.map +1 -1
- package/dist/index.browser.js +1 -0
- package/dist/index.browser.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/localization/default-messages.d.ts +16 -0
- package/dist/localization/default-messages.d.ts.map +1 -1
- package/dist/localization/default-messages.js +22 -6
- package/dist/localization/default-messages.js.map +1 -1
- package/dist/provider-api/actions/custom-provider-registration.d.ts +7 -7
- package/dist/provider-api/actions/provider-api.d.ts +11 -11
- package/dist/provider-api/corpus-jobs.d.ts +2 -2
- package/dist/secrets/routes.d.ts +6 -6
- package/dist/server/action-discovery.d.ts.map +1 -1
- package/dist/server/action-discovery.js +8 -0
- package/dist/server/action-discovery.js.map +1 -1
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/better-auth-instance.d.ts +7 -2
- package/dist/server/better-auth-instance.d.ts.map +1 -1
- package/dist/server/better-auth-instance.js.map +1 -1
- package/dist/server/email-template.d.ts +3 -0
- package/dist/server/email-template.d.ts.map +1 -1
- package/dist/server/email-template.js +13 -0
- package/dist/server/email-template.js.map +1 -1
- package/dist/server/email-templates.d.ts.map +1 -1
- package/dist/server/email-templates.js +3 -0
- package/dist/server/email-templates.js.map +1 -1
- package/dist/server/email.d.ts.map +1 -1
- package/dist/server/email.js +27 -4
- package/dist/server/email.js.map +1 -1
- package/dist/sharing/actions/share-resource.js +1 -0
- package/dist/sharing/actions/share-resource.js.map +1 -1
- package/dist/templates/chat/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
- package/dist/templates/chat/app/components/layout/Sidebar.tsx +2 -2
- package/dist/templates/chat/app/global.css +1 -1
- package/dist/templates/chat/app/root.tsx +2 -2
- package/dist/templates/chat/changelog/2026-07-22-manage-agent-navigation-now-uses-the-connected-nodes-icon.md +6 -0
- package/dist/templates/default/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
- package/dist/templates/default/app/global.css +1 -1
- package/dist/templates/default/app/i18n/ar-SA.ts +6 -6
- package/dist/templates/default/app/i18n/de-DE.ts +6 -6
- package/dist/templates/default/app/i18n/en-US.ts +6 -6
- package/dist/templates/default/app/i18n/es-ES.ts +6 -6
- package/dist/templates/default/app/i18n/fr-FR.ts +6 -6
- package/dist/templates/default/app/i18n/hi-IN.ts +6 -6
- package/dist/templates/default/app/i18n/ja-JP.ts +6 -6
- package/dist/templates/default/app/i18n/ko-KR.ts +6 -6
- package/dist/templates/default/app/i18n/pt-BR.ts +6 -6
- package/dist/templates/default/app/i18n/zh-CN.ts +7 -7
- package/dist/templates/default/app/i18n/zh-TW.ts +7 -7
- package/dist/templates/headless/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
- package/dist/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
- package/dist/user-profile/actions/get-user-profile.d.ts +4 -0
- package/dist/user-profile/actions/get-user-profile.d.ts.map +1 -0
- package/dist/user-profile/actions/get-user-profile.js +14 -0
- package/dist/user-profile/actions/get-user-profile.js.map +1 -0
- package/dist/user-profile/actions/update-user-profile.d.ts +6 -0
- package/dist/user-profile/actions/update-user-profile.d.ts.map +1 -0
- package/dist/user-profile/actions/update-user-profile.js +20 -0
- package/dist/user-profile/actions/update-user-profile.js.map +1 -0
- package/dist/user-profile/index.d.ts +2 -0
- package/dist/user-profile/index.d.ts.map +1 -0
- package/dist/user-profile/index.js +2 -0
- package/dist/user-profile/index.js.map +1 -0
- package/dist/user-profile/shared.d.ts +7 -0
- package/dist/user-profile/shared.d.ts.map +1 -0
- package/dist/user-profile/shared.js +6 -0
- package/dist/user-profile/shared.js.map +1 -0
- package/dist/user-profile/store.d.ts +4 -0
- package/dist/user-profile/store.d.ts.map +1 -0
- package/dist/user-profile/store.js +38 -0
- package/dist/user-profile/store.js.map +1 -0
- package/package.json +2 -1
- package/src/cli/context-xray-local.ts +1 -1
- package/src/client/extensions/ExtensionViewer.tsx +4 -4
- package/src/client/extensions/ExtensionsSidebarSection.tsx +11 -11
- package/src/client/extensions/agent-native-extension-runtime.ts +1 -1
- package/src/client/extensions/delete-extension.ts +2 -2
- package/src/client/org/OrgSwitcher.tsx +25 -1
- package/src/client/settings/SettingsPanel.tsx +102 -10
- package/src/client/sharing/ShareButton.tsx +7 -6
- package/src/db/client.ts +13 -10
- package/src/extensions/actions.ts +13 -5
- package/src/extensions/local.ts +1 -0
- package/src/extensions/routes.ts +10 -5
- package/src/extensions/schema.ts +5 -0
- package/src/extensions/slots/store.ts +14 -4
- package/src/extensions/store.ts +55 -19
- package/src/extensions/theme.ts +1 -1
- package/src/file-upload/registry.ts +9 -0
- package/src/index.browser.ts +5 -0
- package/src/index.ts +1 -0
- package/src/localization/default-messages.ts +23 -6
- package/src/server/action-discovery.ts +8 -0
- package/src/server/better-auth-instance.ts +7 -2
- package/src/server/email-template.ts +18 -0
- package/src/server/email-templates.ts +3 -0
- package/src/server/email.ts +40 -4
- package/src/sharing/actions/share-resource.ts +1 -0
- package/src/templates/chat/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
- package/src/templates/chat/app/components/layout/Sidebar.tsx +2 -2
- package/src/templates/chat/app/global.css +1 -1
- package/src/templates/chat/app/root.tsx +2 -2
- package/src/templates/chat/changelog/2026-07-22-manage-agent-navigation-now-uses-the-connected-nodes-icon.md +6 -0
- package/src/templates/default/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
- package/src/templates/default/app/global.css +1 -1
- package/src/templates/default/app/i18n/ar-SA.ts +6 -6
- package/src/templates/default/app/i18n/de-DE.ts +6 -6
- package/src/templates/default/app/i18n/en-US.ts +6 -6
- package/src/templates/default/app/i18n/es-ES.ts +6 -6
- package/src/templates/default/app/i18n/fr-FR.ts +6 -6
- package/src/templates/default/app/i18n/hi-IN.ts +6 -6
- package/src/templates/default/app/i18n/ja-JP.ts +6 -6
- package/src/templates/default/app/i18n/ko-KR.ts +6 -6
- package/src/templates/default/app/i18n/pt-BR.ts +6 -6
- package/src/templates/default/app/i18n/zh-CN.ts +7 -7
- package/src/templates/default/app/i18n/zh-TW.ts +7 -7
- package/src/templates/headless/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
- package/src/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
- package/src/user-profile/actions/get-user-profile.ts +16 -0
- package/src/user-profile/actions/update-user-profile.ts +24 -0
- package/src/user-profile/index.ts +5 -0
- package/src/user-profile/shared.ts +14 -0
- package/src/user-profile/store.ts +50 -0
|
@@ -839,7 +839,11 @@ export function createExtensionActionEntries(): Record<string, ActionEntry> {
|
|
|
839
839
|
|
|
840
840
|
await ensureExtensionsTables();
|
|
841
841
|
const access = await resolveAccess("extension", extensionId);
|
|
842
|
-
if (
|
|
842
|
+
if (
|
|
843
|
+
!access ||
|
|
844
|
+
(access.resource as ExtensionRow | undefined)?.archivedAt ||
|
|
845
|
+
access.role === "viewer"
|
|
846
|
+
)
|
|
843
847
|
return `Error: editor access required for extension ${extensionId}.`;
|
|
844
848
|
|
|
845
849
|
const userEmail = getRequestUserEmail()?.toLowerCase() ?? "";
|
|
@@ -942,7 +946,11 @@ export function createExtensionActionEntries(): Record<string, ActionEntry> {
|
|
|
942
946
|
|
|
943
947
|
await ensureExtensionsTables();
|
|
944
948
|
const access = await resolveAccess("extension", extensionId);
|
|
945
|
-
if (
|
|
949
|
+
if (
|
|
950
|
+
!access ||
|
|
951
|
+
(access.resource as ExtensionRow | undefined)?.archivedAt
|
|
952
|
+
)
|
|
953
|
+
return `Error: no access to extension ${extensionId}.`;
|
|
946
954
|
|
|
947
955
|
const userEmail = getRequestUserEmail()?.toLowerCase() ?? "";
|
|
948
956
|
const scope = args?.scope ?? "user";
|
|
@@ -1012,14 +1020,14 @@ export function createExtensionActionEntries(): Record<string, ActionEntry> {
|
|
|
1012
1020
|
"delete-extension": {
|
|
1013
1021
|
tool: {
|
|
1014
1022
|
description:
|
|
1015
|
-
"
|
|
1023
|
+
"Archive an extension everywhere it is shared. Archiving is a soft delete: the extension and its history, data, sharing, and slot configuration are retained, but it disappears from normal lists. Requires owner/admin access. If the user only wants a shared extension removed from their own sidebar/list, use hide-extension instead.",
|
|
1016
1024
|
parameters: {
|
|
1017
1025
|
type: "object",
|
|
1018
1026
|
properties: {
|
|
1019
1027
|
id: {
|
|
1020
1028
|
type: "string",
|
|
1021
1029
|
description:
|
|
1022
|
-
"Extension id to
|
|
1030
|
+
"Extension id to archive. Use list-extensions first if you only know the display name.",
|
|
1023
1031
|
},
|
|
1024
1032
|
},
|
|
1025
1033
|
required: ["id"],
|
|
@@ -1036,7 +1044,7 @@ export function createExtensionActionEntries(): Record<string, ActionEntry> {
|
|
|
1036
1044
|
try {
|
|
1037
1045
|
const ok = await deleteExtension(id);
|
|
1038
1046
|
if (!ok) return `Error: extension not found: ${id}`;
|
|
1039
|
-
return { ok: true,
|
|
1047
|
+
return { ok: true, archived: summarizeDeletedExtension(extension) };
|
|
1040
1048
|
} catch (err: any) {
|
|
1041
1049
|
return {
|
|
1042
1050
|
ok: false,
|
|
@@ -227,8 +227,8 @@ async function dispatch(
|
|
|
227
227
|
}
|
|
228
228
|
|
|
229
229
|
const access = await resolveAccess("extension", parts[0]);
|
|
230
|
-
const extension = access?.resource;
|
|
231
|
-
if (!extension) {
|
|
230
|
+
const extension = access?.resource as ExtensionRow | undefined;
|
|
231
|
+
if (!access || !extension || extension.archivedAt) {
|
|
232
232
|
setResponseStatus(event, 404);
|
|
233
233
|
return { error: "Extension not found" };
|
|
234
234
|
}
|
|
@@ -317,11 +317,12 @@ async function dispatch(
|
|
|
317
317
|
}
|
|
318
318
|
|
|
319
319
|
const access = await resolveAccess("extension", parts[0]);
|
|
320
|
-
|
|
320
|
+
const extension = access?.resource as ExtensionRow | undefined;
|
|
321
|
+
if (!access || !extension || extension.archivedAt) {
|
|
321
322
|
setResponseStatus(event, 404);
|
|
322
323
|
return { error: "Extension not found" };
|
|
323
324
|
}
|
|
324
|
-
return extensionResponse(
|
|
325
|
+
return extensionResponse(extension, access.role);
|
|
325
326
|
}
|
|
326
327
|
|
|
327
328
|
// POST /:id/hide — remove from the current user's Extensions list/sidebar
|
|
@@ -433,7 +434,7 @@ async function dispatch(
|
|
|
433
434
|
setResponseStatus(event, 404);
|
|
434
435
|
return { error: "Extension not found" };
|
|
435
436
|
}
|
|
436
|
-
return { ok: true };
|
|
437
|
+
return { ok: true, archived: true };
|
|
437
438
|
}
|
|
438
439
|
|
|
439
440
|
setResponseStatus(event, 404);
|
|
@@ -662,6 +663,10 @@ async function requireExtensionDataAccess(
|
|
|
662
663
|
minRole: ShareRole,
|
|
663
664
|
): Promise<{ ok: true } | { ok: false; response: unknown }> {
|
|
664
665
|
const access = await resolveAccess("extension", extensionId);
|
|
666
|
+
if (access?.resource && (access.resource as ExtensionRow).archivedAt) {
|
|
667
|
+
setResponseStatus(event, 404);
|
|
668
|
+
return { ok: false, response: { error: "Extension not found" } };
|
|
669
|
+
}
|
|
665
670
|
if (access) {
|
|
666
671
|
if (ROLE_RANK[access.role] < ROLE_RANK[minRole]) {
|
|
667
672
|
setResponseStatus(event, 403);
|
|
@@ -27,6 +27,7 @@ export const extensions = table("tools", {
|
|
|
27
27
|
icon: text("icon"),
|
|
28
28
|
createdAt: text("created_at").notNull().default(now()),
|
|
29
29
|
updatedAt: text("updated_at").notNull().default(now()),
|
|
30
|
+
archivedAt: text("archived_at"),
|
|
30
31
|
hiddenAt: text("hidden_at"),
|
|
31
32
|
hiddenBy: text("hidden_by"),
|
|
32
33
|
...ownableColumns(),
|
|
@@ -66,6 +67,7 @@ export const EXTENSIONS_CREATE_SQL = `CREATE TABLE IF NOT EXISTS tools (
|
|
|
66
67
|
icon TEXT,
|
|
67
68
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
68
69
|
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
70
|
+
archived_at TEXT,
|
|
69
71
|
hidden_at TEXT,
|
|
70
72
|
hidden_by TEXT,
|
|
71
73
|
owner_email TEXT NOT NULL DEFAULT 'local@localhost',
|
|
@@ -81,6 +83,7 @@ export const EXTENSIONS_CREATE_SQL_PG = `CREATE TABLE IF NOT EXISTS tools (
|
|
|
81
83
|
icon TEXT,
|
|
82
84
|
created_at TEXT NOT NULL DEFAULT now(),
|
|
83
85
|
updated_at TEXT NOT NULL DEFAULT now(),
|
|
86
|
+
archived_at TEXT,
|
|
84
87
|
hidden_at TEXT,
|
|
85
88
|
hidden_by TEXT,
|
|
86
89
|
owner_email TEXT NOT NULL DEFAULT 'local@localhost',
|
|
@@ -162,6 +165,8 @@ export const EXTENSION_DATA_DROP_OLD_INDEX_SQL_PG = `DROP INDEX IF EXISTS tool_d
|
|
|
162
165
|
export const EXTENSIONS_OWNER_INDEX_SQL = `CREATE INDEX IF NOT EXISTS tools_owner_idx ON tools (owner_email)`;
|
|
163
166
|
export const EXTENSIONS_ORG_INDEX_SQL = `CREATE INDEX IF NOT EXISTS tools_org_idx ON tools (org_id)`;
|
|
164
167
|
export const EXTENSIONS_UPDATED_INDEX_SQL = `CREATE INDEX IF NOT EXISTS tools_updated_at_idx ON tools (updated_at)`;
|
|
168
|
+
export const EXTENSIONS_ARCHIVED_AT_COLUMN_SQL = `ALTER TABLE tools ADD COLUMN IF NOT EXISTS archived_at TEXT`;
|
|
169
|
+
export const EXTENSIONS_ARCHIVED_AT_INDEX_SQL = `CREATE INDEX IF NOT EXISTS tools_archived_at_idx ON tools (archived_at)`;
|
|
165
170
|
|
|
166
171
|
// Global (admin) hide: when set, the extension row is hidden from EVERYONE's
|
|
167
172
|
// list, distinct from the per-user `tool_hidden_extensions` table. Additive
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
2
|
|
|
3
|
-
import { and, eq, inArray, sql } from "drizzle-orm";
|
|
3
|
+
import { and, eq, inArray, isNull, sql } from "drizzle-orm";
|
|
4
4
|
|
|
5
5
|
import { getDbExec, isPostgres } from "../../db/client.js";
|
|
6
6
|
import { createGetDb } from "../../db/create-get-db.js";
|
|
@@ -203,7 +203,12 @@ export async function listExtensionsForSlot(slotId: string): Promise<
|
|
|
203
203
|
icon: extensions.icon,
|
|
204
204
|
})
|
|
205
205
|
.from(extensions)
|
|
206
|
-
.where(
|
|
206
|
+
.where(
|
|
207
|
+
and(
|
|
208
|
+
accessFilter(extensions, extensionShares),
|
|
209
|
+
isNull(extensions.archivedAt),
|
|
210
|
+
),
|
|
211
|
+
);
|
|
207
212
|
const localRows = (await listLocalExtensions())
|
|
208
213
|
.filter((extension) => extension.source.slots.includes(slotId))
|
|
209
214
|
.map((extension) => ({
|
|
@@ -397,7 +402,12 @@ export async function listSlotInstallsForUser(slotId: string): Promise<
|
|
|
397
402
|
updatedAt: extensions.updatedAt,
|
|
398
403
|
})
|
|
399
404
|
.from(extensions)
|
|
400
|
-
.where(
|
|
405
|
+
.where(
|
|
406
|
+
and(
|
|
407
|
+
accessFilter(extensions, extensionShares),
|
|
408
|
+
isNull(extensions.archivedAt),
|
|
409
|
+
),
|
|
410
|
+
);
|
|
401
411
|
const byId = new Map(accessible.map((t: any) => [t.id, t]));
|
|
402
412
|
|
|
403
413
|
const sqlInstalls = (installs as ExtensionSlotInstallRow[])
|
|
@@ -419,7 +429,7 @@ export async function listSlotInstallsForUser(slotId: string): Promise<
|
|
|
419
429
|
return [...localInstalls, ...sqlInstalls];
|
|
420
430
|
}
|
|
421
431
|
|
|
422
|
-
/** Delete every slot/install row referencing
|
|
432
|
+
/** Delete every slot/install row referencing an extension for maintenance. */
|
|
423
433
|
export async function cascadeDeleteExtensionSlots(
|
|
424
434
|
extensionId: string,
|
|
425
435
|
): Promise<void> {
|
|
@@ -52,6 +52,8 @@ import {
|
|
|
52
52
|
EXTENSIONS_OWNER_INDEX_SQL,
|
|
53
53
|
EXTENSIONS_ORG_INDEX_SQL,
|
|
54
54
|
EXTENSIONS_UPDATED_INDEX_SQL,
|
|
55
|
+
EXTENSIONS_ARCHIVED_AT_COLUMN_SQL,
|
|
56
|
+
EXTENSIONS_ARCHIVED_AT_INDEX_SQL,
|
|
55
57
|
EXTENSIONS_HIDDEN_AT_COLUMN_SQL,
|
|
56
58
|
EXTENSIONS_HIDDEN_BY_COLUMN_SQL,
|
|
57
59
|
EXTENSIONS_HIDDEN_AT_INDEX_SQL,
|
|
@@ -103,6 +105,11 @@ export async function ensureExtensionsTables(): Promise<void> {
|
|
|
103
105
|
"tools_updated_at_idx",
|
|
104
106
|
EXTENSIONS_UPDATED_INDEX_SQL,
|
|
105
107
|
);
|
|
108
|
+
await ensureExtensionsArchivedColumn(client, pg);
|
|
109
|
+
await ensureIndexExists(
|
|
110
|
+
"tools_archived_at_idx",
|
|
111
|
+
EXTENSIONS_ARCHIVED_AT_INDEX_SQL,
|
|
112
|
+
);
|
|
106
113
|
await ensureExtensionsGlobalHideColumns(client, pg); // ADD COLUMN — guarded inside
|
|
107
114
|
await ensureIndexExists(
|
|
108
115
|
"tools_hidden_at_idx",
|
|
@@ -176,6 +183,10 @@ export async function ensureExtensionsTables(): Promise<void> {
|
|
|
176
183
|
await retryOnDdlRace(() => client.execute(EXTENSIONS_OWNER_INDEX_SQL));
|
|
177
184
|
await retryOnDdlRace(() => client.execute(EXTENSIONS_ORG_INDEX_SQL));
|
|
178
185
|
await retryOnDdlRace(() => client.execute(EXTENSIONS_UPDATED_INDEX_SQL));
|
|
186
|
+
await ensureExtensionsArchivedColumn(client, pg);
|
|
187
|
+
await retryOnDdlRace(() =>
|
|
188
|
+
client.execute(EXTENSIONS_ARCHIVED_AT_INDEX_SQL),
|
|
189
|
+
);
|
|
179
190
|
await ensureExtensionsGlobalHideColumns(client, pg);
|
|
180
191
|
await retryOnDdlRace(() =>
|
|
181
192
|
client.execute(EXTENSIONS_HIDDEN_AT_INDEX_SQL),
|
|
@@ -346,6 +357,31 @@ async function ensureExtensionsGlobalHideColumns(
|
|
|
346
357
|
await addCol(EXTENSIONS_HIDDEN_BY_COLUMN_SQL, "hidden_by", "TEXT");
|
|
347
358
|
}
|
|
348
359
|
|
|
360
|
+
async function ensureExtensionsArchivedColumn(
|
|
361
|
+
client: ReturnType<typeof getDbExec>,
|
|
362
|
+
pg: boolean,
|
|
363
|
+
): Promise<void> {
|
|
364
|
+
if (pg) {
|
|
365
|
+
await ensureColumnExists(
|
|
366
|
+
"tools",
|
|
367
|
+
"archived_at",
|
|
368
|
+
EXTENSIONS_ARCHIVED_AT_COLUMN_SQL,
|
|
369
|
+
);
|
|
370
|
+
return;
|
|
371
|
+
}
|
|
372
|
+
await client
|
|
373
|
+
.execute("ALTER TABLE tools ADD COLUMN archived_at TEXT")
|
|
374
|
+
.catch((err: any) => {
|
|
375
|
+
if (
|
|
376
|
+
!String(err?.message ?? err)
|
|
377
|
+
.toLowerCase()
|
|
378
|
+
.includes("duplicate")
|
|
379
|
+
) {
|
|
380
|
+
throw err;
|
|
381
|
+
}
|
|
382
|
+
});
|
|
383
|
+
}
|
|
384
|
+
|
|
349
385
|
export function registerExtensionsShareable() {
|
|
350
386
|
registerShareableResource({
|
|
351
387
|
type: "extension",
|
|
@@ -373,6 +409,7 @@ export interface ExtensionRow {
|
|
|
373
409
|
icon: string | null;
|
|
374
410
|
createdAt: string;
|
|
375
411
|
updatedAt: string;
|
|
412
|
+
archivedAt: string | null;
|
|
376
413
|
hiddenAt: string | null;
|
|
377
414
|
hiddenBy: string | null;
|
|
378
415
|
ownerEmail: string;
|
|
@@ -881,9 +918,10 @@ export async function listExtensions(
|
|
|
881
918
|
// on repeated `.where()` calls, so combine the access filter and the
|
|
882
919
|
// global-hidden filter into one condition.
|
|
883
920
|
const base = accessFilter(extensions, extensionShares);
|
|
921
|
+
const visible = and(base, isNull(extensions.archivedAt));
|
|
884
922
|
const where = options.includeGloballyHidden
|
|
885
|
-
?
|
|
886
|
-
: and(
|
|
923
|
+
? visible
|
|
924
|
+
: and(visible, isNull(extensions.hiddenAt));
|
|
887
925
|
const rows = (await db
|
|
888
926
|
.select()
|
|
889
927
|
.from(extensions)
|
|
@@ -899,7 +937,8 @@ export async function listExtensions(
|
|
|
899
937
|
export async function getExtension(id: string): Promise<ExtensionRow | null> {
|
|
900
938
|
await ensureExtensionsTables();
|
|
901
939
|
const access = await resolveAccess("extension", id);
|
|
902
|
-
|
|
940
|
+
const resource = access?.resource as ExtensionRow | undefined;
|
|
941
|
+
return resource?.archivedAt ? null : (resource ?? null);
|
|
903
942
|
}
|
|
904
943
|
|
|
905
944
|
export interface ListExtensionHistoryOptions {
|
|
@@ -983,7 +1022,7 @@ export async function restoreExtensionHistoryVersion(
|
|
|
983
1022
|
.from(extensions)
|
|
984
1023
|
.where(eq(extensions.id, id));
|
|
985
1024
|
const existing = existingRows[0] as ExtensionRow | undefined;
|
|
986
|
-
if (!existing) return null;
|
|
1025
|
+
if (!existing || existing.archivedAt) return null;
|
|
987
1026
|
|
|
988
1027
|
await ensureExtensionHistoryBaseline(existing);
|
|
989
1028
|
const target = await getPersistedHistoryEntry(id, version, true);
|
|
@@ -1045,6 +1084,7 @@ export async function createExtension(
|
|
|
1045
1084
|
icon: data.icon ?? null,
|
|
1046
1085
|
createdAt: now,
|
|
1047
1086
|
updatedAt: now,
|
|
1087
|
+
archivedAt: null,
|
|
1048
1088
|
hiddenAt: null,
|
|
1049
1089
|
hiddenBy: null,
|
|
1050
1090
|
ownerEmail: userEmail,
|
|
@@ -1098,6 +1138,7 @@ export async function findRecentDuplicateExtension(data: {
|
|
|
1098
1138
|
eq(extensions.description, description),
|
|
1099
1139
|
icon === null ? isNull(extensions.icon) : eq(extensions.icon, icon),
|
|
1100
1140
|
gte(extensions.createdAt, fiveMinutesAgo),
|
|
1141
|
+
isNull(extensions.archivedAt),
|
|
1101
1142
|
isNull(extensions.hiddenAt),
|
|
1102
1143
|
),
|
|
1103
1144
|
)
|
|
@@ -1146,7 +1187,7 @@ export async function updateExtension(
|
|
|
1146
1187
|
.from(extensions)
|
|
1147
1188
|
.where(eq(extensions.id, id));
|
|
1148
1189
|
const existing = existingRows[0] as ExtensionRow | undefined;
|
|
1149
|
-
if (!existing) return null;
|
|
1190
|
+
if (!existing || existing.archivedAt) return null;
|
|
1150
1191
|
await ensureExtensionHistoryBaseline(existing);
|
|
1151
1192
|
await db.update(extensions).set(updates).where(eq(extensions.id, id));
|
|
1152
1193
|
const rows = await db.select().from(extensions).where(eq(extensions.id, id));
|
|
@@ -1200,7 +1241,9 @@ export async function updateExtensionContent(
|
|
|
1200
1241
|
.select()
|
|
1201
1242
|
.from(extensions)
|
|
1202
1243
|
.where(eq(extensions.id, id));
|
|
1203
|
-
if (!existingRows[0])
|
|
1244
|
+
if (!existingRows[0] || (existingRows[0] as ExtensionRow).archivedAt) {
|
|
1245
|
+
return null;
|
|
1246
|
+
}
|
|
1204
1247
|
const existing = existingRows[0] as ExtensionRow;
|
|
1205
1248
|
const existingContent = existing.content;
|
|
1206
1249
|
await ensureExtensionHistoryBaseline(existing);
|
|
@@ -1234,20 +1277,13 @@ export async function deleteExtension(id: string): Promise<boolean> {
|
|
|
1234
1277
|
const rows = await db.select().from(extensions).where(eq(extensions.id, id));
|
|
1235
1278
|
const row = rows[0] as ExtensionRow | undefined;
|
|
1236
1279
|
if (!row) return false;
|
|
1280
|
+
if (row.archivedAt) return true;
|
|
1237
1281
|
const targets = await extensionChangeTargetsForRow(row);
|
|
1238
|
-
|
|
1239
|
-
await db
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
});
|
|
1244
|
-
await getDbExec().execute({
|
|
1245
|
-
sql: `DELETE FROM tool_history WHERE tool_id = ?`,
|
|
1246
|
-
args: [id],
|
|
1247
|
-
});
|
|
1248
|
-
const { cascadeDeleteExtensionSlots } = await import("./slots/store.js");
|
|
1249
|
-
await cascadeDeleteExtensionSlots(id);
|
|
1250
|
-
await db.delete(extensions).where(eq(extensions.id, id));
|
|
1282
|
+
const archivedAt = new Date().toISOString();
|
|
1283
|
+
await db
|
|
1284
|
+
.update(extensions)
|
|
1285
|
+
.set({ archivedAt, updatedAt: archivedAt })
|
|
1286
|
+
.where(eq(extensions.id, id));
|
|
1251
1287
|
await notifyExtensionChanged(targets);
|
|
1252
1288
|
return true;
|
|
1253
1289
|
}
|
|
@@ -92,7 +92,7 @@ export function getThemeVars(_isDark?: boolean): string {
|
|
|
92
92
|
--muted-foreground: 240 5% 64.9%;
|
|
93
93
|
--accent: 240 3.7% 15.9%;
|
|
94
94
|
--accent-foreground: 0 0% 98%;
|
|
95
|
-
--destructive: 0
|
|
95
|
+
--destructive: 0 84% 60%;
|
|
96
96
|
--destructive-foreground: 0 0% 98%;
|
|
97
97
|
--border: 240 3.7% 15.9%;
|
|
98
98
|
--input: 240 3.7% 15.9%;
|
|
@@ -69,6 +69,15 @@ export async function getActiveFileUploadProviderForRequest(): Promise<FileUploa
|
|
|
69
69
|
if (builderFileUploadProvider.isConfigured()) {
|
|
70
70
|
return builderFileUploadProvider;
|
|
71
71
|
}
|
|
72
|
+
try {
|
|
73
|
+
const { resolveHasBuilderPrivateKey } =
|
|
74
|
+
await import("../server/credential-provider.js");
|
|
75
|
+
if (await resolveHasBuilderPrivateKey()) {
|
|
76
|
+
return builderFileUploadProvider;
|
|
77
|
+
}
|
|
78
|
+
} catch {
|
|
79
|
+
// Treat failed scoped credential lookups as unavailable.
|
|
80
|
+
}
|
|
72
81
|
return null;
|
|
73
82
|
}
|
|
74
83
|
|
|
@@ -100,6 +100,11 @@ export {
|
|
|
100
100
|
type ActionMcpAppResourceConfig,
|
|
101
101
|
type ActionMcpAppResourceMeta,
|
|
102
102
|
} from "./action.js";
|
|
103
|
+
export {
|
|
104
|
+
normalizeUserProfileName,
|
|
105
|
+
USER_PROFILE_SETTING_KEY,
|
|
106
|
+
type UserProfile,
|
|
107
|
+
} from "./user-profile/index.js";
|
|
103
108
|
export {
|
|
104
109
|
ACTION_CHAT_UI_DATA_CHART_RENDERER,
|
|
105
110
|
ACTION_CHAT_UI_DATA_INSIGHTS_RENDERER,
|
package/corpus/core/src/index.ts
CHANGED
|
@@ -32,6 +32,23 @@ const messages = {
|
|
|
32
32
|
openTeamSettings: "Open team settings",
|
|
33
33
|
openResourceSettings: "Open resource settings",
|
|
34
34
|
backHome: "Back to home",
|
|
35
|
+
profileTitle: "Account",
|
|
36
|
+
profileDescription: "Your name, profile photo, and signed-in identity.",
|
|
37
|
+
profileLoading: "Loading...",
|
|
38
|
+
profileSignedOut: "Signed out",
|
|
39
|
+
profilePhotoUpdated: "Photo updated",
|
|
40
|
+
profilePhotoError: "Could not update photo",
|
|
41
|
+
profileUploading: "Uploading...",
|
|
42
|
+
profileChangePhoto: "Change photo",
|
|
43
|
+
profileNameLabel: "Name",
|
|
44
|
+
profileNamePlaceholder: "Your name",
|
|
45
|
+
profileNameDescription:
|
|
46
|
+
"This name is used when referring to you across Agent-Native apps.",
|
|
47
|
+
profileSave: "Save changes",
|
|
48
|
+
profileSaving: "Saving...",
|
|
49
|
+
profileSaved: "Profile updated",
|
|
50
|
+
profileSaveError: "Could not update profile",
|
|
51
|
+
profileMenuItem: "Profile",
|
|
35
52
|
},
|
|
36
53
|
agentResources: {
|
|
37
54
|
openDocs: "Open {{section}} documentation",
|
|
@@ -634,23 +651,23 @@ const messages = {
|
|
|
634
651
|
hideEveryone: "Hide from everyone",
|
|
635
652
|
localFileDescription:
|
|
636
653
|
"This extension is backed by {{entryPath}}. Edit or remove it from the workspace.",
|
|
637
|
-
deleteQuestion: "
|
|
654
|
+
deleteQuestion: "Archive {{name}}?",
|
|
638
655
|
removeQuestion: "Remove {{name}}?",
|
|
639
656
|
hideForYouDescription:
|
|
640
657
|
"This hides it from your Extensions list without deleting it for anyone else.",
|
|
641
|
-
removeEverywhereDescription: "This
|
|
658
|
+
removeEverywhereDescription: "This archives it everywhere it is shared.",
|
|
642
659
|
cancel: "Cancel",
|
|
643
660
|
remove: "Remove",
|
|
644
661
|
removing: "Removing...",
|
|
645
|
-
delete: "
|
|
646
|
-
deleting: "
|
|
662
|
+
delete: "Archive",
|
|
663
|
+
deleting: "Archiving...",
|
|
647
664
|
openFullView: "Open full view",
|
|
648
665
|
removeFromWidgetArea: "Remove from this widget area",
|
|
649
|
-
deleteExtensionEllipsis: "
|
|
666
|
+
deleteExtensionEllipsis: "Archive extension...",
|
|
650
667
|
removeFromMyListEllipsis: "Remove from my list...",
|
|
651
668
|
removeFromWidgetAreaForMe: "Remove from this widget area (for me)",
|
|
652
669
|
deleteEverywhereConfirmation:
|
|
653
|
-
"This
|
|
670
|
+
"This archives the extension everywhere, for everyone it's shared with.",
|
|
654
671
|
addWidget: "Add widget",
|
|
655
672
|
loading: "Loading...",
|
|
656
673
|
noWidgetsAvailable: "No widgets available for this slot yet.",
|
|
@@ -658,6 +658,14 @@ export async function mergeCoreSharingActions(
|
|
|
658
658
|
"set-localization-preference",
|
|
659
659
|
() => import("../localization/actions/set-localization-preference.js"),
|
|
660
660
|
],
|
|
661
|
+
[
|
|
662
|
+
"get-user-profile",
|
|
663
|
+
() => import("../user-profile/actions/get-user-profile.js"),
|
|
664
|
+
],
|
|
665
|
+
[
|
|
666
|
+
"update-user-profile",
|
|
667
|
+
() => import("../user-profile/actions/update-user-profile.js"),
|
|
668
|
+
],
|
|
661
669
|
[
|
|
662
670
|
"change-appearance",
|
|
663
671
|
() => import("../appearance/actions/change-appearance.js"),
|
|
@@ -740,8 +740,8 @@ export function getBetterAuthSync(): BetterAuthInstance | undefined {
|
|
|
740
740
|
* The subset of Better Auth's internal adapter we use for federated-SSO
|
|
741
741
|
* JIT account linking. Better Auth owns these writes (id + timestamp +
|
|
742
742
|
* schema handling), so callers never hand-roll SQL against `user`/`account`.
|
|
743
|
-
* Read-only lookups
|
|
744
|
-
*
|
|
743
|
+
* Read-only lookups plus account-linking and profile-update operations used by
|
|
744
|
+
* shared Core surfaces. Better Auth owns the actual identity writes.
|
|
745
745
|
*/
|
|
746
746
|
export interface BetterAuthInternalAdapter {
|
|
747
747
|
findUserByEmail: (
|
|
@@ -761,6 +761,11 @@ export interface BetterAuthInternalAdapter {
|
|
|
761
761
|
name: string;
|
|
762
762
|
emailVerified?: boolean;
|
|
763
763
|
}) => Promise<{ id: string }>;
|
|
764
|
+
/** Optional because older/custom adapter shapes may not expose mutations. */
|
|
765
|
+
updateUser?: (
|
|
766
|
+
userId: string,
|
|
767
|
+
data: { name?: string; image?: string | null },
|
|
768
|
+
) => Promise<unknown>;
|
|
764
769
|
}
|
|
765
770
|
|
|
766
771
|
/**
|
|
@@ -18,6 +18,10 @@
|
|
|
18
18
|
* });
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
|
+
import { getAppName } from "./app-name.js";
|
|
22
|
+
|
|
23
|
+
export const AGENT_NATIVE_EMAIL_LOGO_CONTENT_ID = "agent-native-logo";
|
|
24
|
+
|
|
21
25
|
export interface EmailCta {
|
|
22
26
|
label: string;
|
|
23
27
|
url: string;
|
|
@@ -34,6 +38,8 @@ export interface RenderEmailArgs {
|
|
|
34
38
|
cta?: EmailCta;
|
|
35
39
|
/** Small muted text under the CTA (e.g. expiry note). */
|
|
36
40
|
footer?: string;
|
|
41
|
+
/** Optional app name shown beside the framework logo. */
|
|
42
|
+
brandName?: string;
|
|
37
43
|
/**
|
|
38
44
|
* Optional brand hex color for the CTA button and inline links. Defaults to
|
|
39
45
|
* a monochrome near-white button with dark text.
|
|
@@ -71,6 +77,7 @@ function sanitizeHexColor(input: string | undefined): string | undefined {
|
|
|
71
77
|
export function renderEmail(args: RenderEmailArgs): RenderedEmail {
|
|
72
78
|
const preheader = args.preheader || "";
|
|
73
79
|
const brand = sanitizeHexColor(args.brandColor);
|
|
80
|
+
const brandName = args.brandName?.trim() || getAppName() || "Agent Native";
|
|
74
81
|
|
|
75
82
|
// Monochrome default: near-white button with dark text. Brand override:
|
|
76
83
|
// colored button with white text.
|
|
@@ -104,6 +111,16 @@ export function renderEmail(args: RenderEmailArgs): RenderedEmail {
|
|
|
104
111
|
? `<p style="margin:28px 0 0 0; font-size:13px; line-height:1.5; color:#71717a;">${escapeHtml(args.footer)}</p>`
|
|
105
112
|
: "";
|
|
106
113
|
|
|
114
|
+
const brandHeaderHtml = `
|
|
115
|
+
<table role="presentation" cellpadding="0" cellspacing="0" border="0" width="100%" style="margin:0 0 28px 0; padding:0 0 24px 0; border-bottom:1px solid #27272a;">
|
|
116
|
+
<tr>
|
|
117
|
+
<td align="center">
|
|
118
|
+
<img src="cid:${AGENT_NATIVE_EMAIL_LOGO_CONTENT_ID}" alt="${escapeAttr(brandName)}" width="28" height="28" style="display:inline-block; vertical-align:middle; width:28px; height:28px; margin:0 8px 0 0; border:0;" />
|
|
119
|
+
<span style="font-size:18px; line-height:28px; font-weight:600; color:#fafafa; vertical-align:middle;">${escapeHtml(brandName)}</span>
|
|
120
|
+
</td>
|
|
121
|
+
</tr>
|
|
122
|
+
</table>`;
|
|
123
|
+
|
|
107
124
|
const html = `<!DOCTYPE html>
|
|
108
125
|
<html lang="en">
|
|
109
126
|
<head>
|
|
@@ -129,6 +146,7 @@ export function renderEmail(args: RenderEmailArgs): RenderedEmail {
|
|
|
129
146
|
<table role="presentation" cellpadding="0" cellspacing="0" border="0" width="100%" style="max-width:560px;">
|
|
130
147
|
<tr>
|
|
131
148
|
<td style="background-color:#141417; border:1px solid #27272a; border-radius:16px; padding:36px 36px 32px 36px;">
|
|
149
|
+
${brandHeaderHtml}
|
|
132
150
|
<h1 style="margin:0 0 20px 0; font-size:24px; line-height:1.3; font-weight:600; color:#fafafa; letter-spacing:-0.02em;">
|
|
133
151
|
${escapeHtml(args.heading)}
|
|
134
152
|
</h1>
|
|
@@ -58,6 +58,7 @@ export function renderInviteEmail(
|
|
|
58
58
|
const onApp = appName ? ` on ${appName}` : "";
|
|
59
59
|
|
|
60
60
|
const { html, text } = renderEmail({
|
|
61
|
+
brandName: appName,
|
|
61
62
|
preheader: `${inviter} invited you to join ${orgName}${onApp}.`,
|
|
62
63
|
heading: `You're invited to join ${orgName}`,
|
|
63
64
|
paragraphs: [
|
|
@@ -95,6 +96,7 @@ export function renderVerifySignupEmail(
|
|
|
95
96
|
const appName = resolveAppName();
|
|
96
97
|
|
|
97
98
|
const { html, text } = renderEmail({
|
|
99
|
+
brandName: appName,
|
|
98
100
|
preheader: `Confirm ${email} to finish setting up your ${appName} account.`,
|
|
99
101
|
heading: `Verify your email for ${appName}`,
|
|
100
102
|
paragraphs: [
|
|
@@ -130,6 +132,7 @@ export function renderResetPasswordEmail(
|
|
|
130
132
|
const appName = resolveAppName();
|
|
131
133
|
|
|
132
134
|
const { html, text } = renderEmail({
|
|
135
|
+
brandName: appName,
|
|
133
136
|
preheader: `Reset the password for ${email}. This link expires in 1 hour.`,
|
|
134
137
|
heading: `Reset your ${appName} password`,
|
|
135
138
|
paragraphs: [
|
|
@@ -10,7 +10,10 @@
|
|
|
10
10
|
* so the reset-password flow still works end-to-end for local development.
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
+
import { readFileSync } from "node:fs";
|
|
14
|
+
|
|
13
15
|
import { resolveSecret } from "./credential-provider.js";
|
|
16
|
+
import { AGENT_NATIVE_EMAIL_LOGO_CONTENT_ID } from "./email-template.js";
|
|
14
17
|
|
|
15
18
|
export type EmailProvider = "resend" | "sendgrid" | "dev";
|
|
16
19
|
|
|
@@ -35,6 +38,38 @@ export interface SendEmailArgs {
|
|
|
35
38
|
attachments?: EmailAttachment[];
|
|
36
39
|
}
|
|
37
40
|
|
|
41
|
+
let cachedAgentNativeLogo: Buffer | undefined;
|
|
42
|
+
|
|
43
|
+
function getAgentNativeLogoAttachment(): EmailAttachment {
|
|
44
|
+
cachedAgentNativeLogo ??= readFileSync(
|
|
45
|
+
new URL("../../src/assets/branding/favicon.png", import.meta.url),
|
|
46
|
+
);
|
|
47
|
+
return {
|
|
48
|
+
filename: "agent-native-logo.png",
|
|
49
|
+
content: cachedAgentNativeLogo,
|
|
50
|
+
contentType: "image/png",
|
|
51
|
+
contentId: AGENT_NATIVE_EMAIL_LOGO_CONTENT_ID,
|
|
52
|
+
disposition: "inline",
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function resolveAttachments(
|
|
57
|
+
args: SendEmailArgs,
|
|
58
|
+
): EmailAttachment[] | undefined {
|
|
59
|
+
if (!args.html.includes(`cid:${AGENT_NATIVE_EMAIL_LOGO_CONTENT_ID}`)) {
|
|
60
|
+
return args.attachments;
|
|
61
|
+
}
|
|
62
|
+
if (
|
|
63
|
+
args.attachments?.some(
|
|
64
|
+
(attachment) =>
|
|
65
|
+
attachment.contentId === AGENT_NATIVE_EMAIL_LOGO_CONTENT_ID,
|
|
66
|
+
)
|
|
67
|
+
) {
|
|
68
|
+
return args.attachments;
|
|
69
|
+
}
|
|
70
|
+
return [...(args.attachments ?? []), getAgentNativeLogoAttachment()];
|
|
71
|
+
}
|
|
72
|
+
|
|
38
73
|
interface EmailTransportConfig {
|
|
39
74
|
provider: EmailProvider;
|
|
40
75
|
resendApiKey?: string;
|
|
@@ -94,6 +129,7 @@ export async function sendEmail(args: SendEmailArgs): Promise<void> {
|
|
|
94
129
|
const config = await resolveEmailTransport();
|
|
95
130
|
const provider = config.provider;
|
|
96
131
|
const from = getFromAddress(config, args.from);
|
|
132
|
+
const attachments = resolveAttachments(args);
|
|
97
133
|
|
|
98
134
|
if (provider === "resend") {
|
|
99
135
|
const payload: Record<string, unknown> = {
|
|
@@ -105,8 +141,8 @@ export async function sendEmail(args: SendEmailArgs): Promise<void> {
|
|
|
105
141
|
};
|
|
106
142
|
if (args.cc) payload.cc = Array.isArray(args.cc) ? args.cc : [args.cc];
|
|
107
143
|
if (args.replyTo) payload.reply_to = args.replyTo;
|
|
108
|
-
if (
|
|
109
|
-
payload.attachments =
|
|
144
|
+
if (attachments?.length) {
|
|
145
|
+
payload.attachments = attachments.map((a) => ({
|
|
110
146
|
filename: a.filename,
|
|
111
147
|
content:
|
|
112
148
|
typeof a.content === "string"
|
|
@@ -159,8 +195,8 @@ export async function sendEmail(args: SendEmailArgs): Promise<void> {
|
|
|
159
195
|
if (args.inReplyTo) sgHeaders["In-Reply-To"] = args.inReplyTo;
|
|
160
196
|
if (args.references) sgHeaders["References"] = args.references;
|
|
161
197
|
if (Object.keys(sgHeaders).length) sgPayload.headers = sgHeaders;
|
|
162
|
-
if (
|
|
163
|
-
sgPayload.attachments =
|
|
198
|
+
if (attachments?.length) {
|
|
199
|
+
sgPayload.attachments = attachments.map((a) => ({
|
|
164
200
|
filename: a.filename,
|
|
165
201
|
content:
|
|
166
202
|
typeof a.content === "string"
|
|
@@ -299,6 +299,7 @@ export default defineAction({
|
|
|
299
299
|
process.env.APP_NAME || process.env.VITE_APP_NAME || "Agent Native";
|
|
300
300
|
const subject = `${actor} shared "${resourceTitle}" with you on ${appName}`;
|
|
301
301
|
const { html, text } = renderEmail({
|
|
302
|
+
brandName: appName,
|
|
302
303
|
preheader: subject,
|
|
303
304
|
heading: "You've been given access",
|
|
304
305
|
paragraphs: [
|
|
@@ -59,6 +59,12 @@ quick controls and deep links such as:
|
|
|
59
59
|
- `/settings/usage`
|
|
60
60
|
- `/settings/apps/:appId`
|
|
61
61
|
|
|
62
|
+
The shared Account section is the canonical profile surface at
|
|
63
|
+
`/settings#account`. It owns the editable display name and existing avatar
|
|
64
|
+
control through the authenticated `get-user-profile` and `update-user-profile`
|
|
65
|
+
actions. Shared workspace chrome such as `OrgSwitcher` should link to this
|
|
66
|
+
surface rather than creating an app-local profile page.
|
|
67
|
+
|
|
62
68
|
When adding a new API key, OAuth grant, provider connection, model selector, app
|
|
63
69
|
preference, notification preference, or usage/billing surface, register it as a
|
|
64
70
|
settings tab or app settings panel first. Only add sidebar UI when it is needed
|