@agent-native/core 0.127.3 → 0.128.0
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 +80 -0
- package/corpus/core/README.md +5 -26
- package/corpus/core/docs/content/actions.mdx +47 -4
- package/corpus/core/docs/content/native-chat-ui.mdx +7 -0
- package/corpus/core/docs/content/organizations-teams-permissions.mdx +109 -3
- package/corpus/core/docs/content/template-design-collaboration-and-full-apps.mdx +15 -0
- package/corpus/core/docs/content/toolkit-org-team.mdx +72 -12
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/a2a/artifact-response.ts +36 -29
- package/corpus/core/src/action.ts +83 -2
- package/corpus/core/src/chat-threads/store.ts +48 -43
- package/corpus/core/src/cli/skills-content/design-visual-edit-skill.ts +46 -3
- package/corpus/core/src/client/AgentPanel.tsx +26 -6
- package/corpus/core/src/client/AssistantChat.tsx +63 -7
- package/corpus/core/src/client/DefaultSpinner.tsx +29 -0
- package/corpus/core/src/client/org/TeamPage.tsx +161 -6
- package/corpus/core/src/client/org/hooks.ts +67 -0
- package/corpus/core/src/client/org/index.ts +9 -0
- package/corpus/core/src/client/transcription/use-live-transcription.ts +62 -10
- package/corpus/core/src/db/client.ts +42 -3
- package/corpus/core/src/db/ensure-additive-columns.ts +60 -33
- package/corpus/core/src/deploy/build.ts +31 -2
- package/corpus/core/src/mcp-client/routes.ts +10 -1
- package/corpus/core/src/org/app-roles-handlers.ts +152 -0
- package/corpus/core/src/org/app-roles.ts +355 -0
- package/corpus/core/src/org/index.ts +27 -1
- package/corpus/core/src/org/migrations.ts +22 -0
- package/corpus/core/src/org/plugin.ts +27 -0
- package/corpus/core/src/org/schema.ts +15 -0
- package/corpus/core/src/scripts/docs/search.ts +17 -0
- package/corpus/core/src/scripts/docs/source-search.ts +10 -0
- package/corpus/core/src/server/agent-chat/script-entries.ts +3 -0
- package/corpus/core/src/server/agent-chat-plugin.ts +53 -52
- package/corpus/core/src/server/core-routes-plugin.ts +6 -1
- package/corpus/core/src/server/framework-request-handler.ts +44 -6
- package/corpus/core/src/templates/default/.agents/skills/actions/SKILL.md +32 -0
- package/corpus/core/src/templates/default/.agents/skills/adding-a-feature/SKILL.md +7 -0
- package/corpus/core/src/templates/default/.agents/skills/security/SKILL.md +31 -0
- package/corpus/core/src/templates/headless/.agents/skills/actions/SKILL.md +32 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/actions/SKILL.md +32 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/adding-a-feature/SKILL.md +7 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/authentication/SKILL.md +40 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/security/SKILL.md +31 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/sharing/SKILL.md +4 -0
- package/corpus/templates/analytics/.agents/skills/actions/SKILL.md +32 -0
- package/corpus/templates/analytics/.agents/skills/security/SKILL.md +31 -0
- package/corpus/templates/analytics/.agents/skills/sharing/SKILL.md +4 -0
- package/corpus/templates/analytics/actions/data-source-status.ts +21 -12
- package/corpus/templates/analytics/app/global.css +7 -7
- package/corpus/templates/analytics/app/i18n-data.ts +30 -0
- package/corpus/templates/analytics/app/lib/data-source-status.ts +2 -1
- package/corpus/templates/analytics/app/pages/DataSources.tsx +54 -10
- package/corpus/templates/analytics/changelog/2026-07-28-analytics-pages-load-reliably-with-large-dashboard-workspaces.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-28-dashboard-loading-shimmer-now-flows-smoothly-in-one-directi.md +6 -0
- package/corpus/templates/analytics/server/lib/first-party-dashboard-repair.ts +5 -4
- package/corpus/templates/analytics/server/plugins/agent-chat.ts +54 -42
- package/corpus/templates/analytics/server/plugins/db.ts +1 -18
- package/corpus/templates/assets/.agents/skills/actions/SKILL.md +32 -0
- package/corpus/templates/assets/.agents/skills/security/SKILL.md +31 -0
- package/corpus/templates/assets/.agents/skills/sharing/SKILL.md +4 -0
- package/corpus/templates/brain/.agents/skills/actions/SKILL.md +32 -0
- package/corpus/templates/brain/.agents/skills/adding-a-feature/SKILL.md +7 -0
- package/corpus/templates/brain/.agents/skills/security/SKILL.md +31 -0
- package/corpus/templates/brain/.agents/skills/sharing/SKILL.md +4 -0
- package/corpus/templates/calendar/.agents/skills/actions/SKILL.md +32 -0
- package/corpus/templates/calendar/.agents/skills/security/SKILL.md +31 -0
- package/corpus/templates/calendar/.agents/skills/sharing/SKILL.md +4 -0
- package/corpus/templates/chat/.agents/skills/actions/SKILL.md +32 -0
- package/corpus/templates/chat/.agents/skills/adding-a-feature/SKILL.md +7 -0
- package/corpus/templates/chat/.agents/skills/security/SKILL.md +31 -0
- package/corpus/templates/chat/.agents/skills/sharing/SKILL.md +4 -0
- package/corpus/templates/clips/.agents/skills/actions/SKILL.md +32 -0
- package/corpus/templates/clips/.agents/skills/security/SKILL.md +31 -0
- package/corpus/templates/clips/actions/request-transcript.ts +77 -11
- package/corpus/templates/clips/actions/save-browser-transcript.ts +28 -7
- package/corpus/templates/clips/app/routes/record.tsx +11 -3
- package/corpus/templates/clips/changelog/2026-07-28-browser-recordings-no-longer-save-a-truncated-transcript-as-.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-28-browser-recordings-no-longer-stop-transcribing-partway-throu.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-28-desktop-full-screen-clips-now-get-an-instant-local-transcrip.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-28-long-transcriptions-no-longer-show-a-false-transcription-sto.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-28-restarting-for-an-update-now-installs-the-newest-release-ins.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-28-the-meeting-recording-pill-now-anchors-to-the-right-edge-of-.md +6 -0
- package/corpus/templates/clips/desktop/src/lib/audio-meter.ts +31 -2
- package/corpus/templates/clips/desktop/src/lib/recorder.ts +114 -13
- package/corpus/templates/clips/desktop/src/lib/updater.ts +12 -4
- package/corpus/templates/clips/desktop/src/overlays/live-audio-bars.tsx +40 -15
- package/corpus/templates/clips/desktop/src/styles.css +10 -7
- package/corpus/templates/clips/desktop/src-tauri/src/recording_indicator.rs +21 -14
- package/corpus/templates/clips/shared/transcript-status.ts +10 -0
- package/corpus/templates/content/.agents/skills/actions/SKILL.md +32 -0
- package/corpus/templates/content/.agents/skills/security/SKILL.md +31 -0
- package/corpus/templates/content/.agents/skills/sharing/SKILL.md +4 -0
- package/corpus/templates/crm/.agents/skills/sharing/SKILL.md +4 -0
- package/corpus/templates/design/.agents/skills/actions/SKILL.md +32 -0
- package/corpus/templates/design/.agents/skills/security/SKILL.md +31 -0
- package/corpus/templates/design/.agents/skills/sharing/SKILL.md +4 -0
- package/corpus/templates/design/.agents/skills/visual-edit/SKILL.md +46 -3
- package/corpus/templates/design/.generated/bridge/editor-chrome.generated.ts +7 -5
- package/corpus/templates/design/app/components/design/CanvasContextMenu.tsx +2 -2
- package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +7 -4
- package/corpus/templates/design/app/components/design/keyboard-shortcuts.ts +1 -1
- package/corpus/templates/design/app/hooks/useDesignHotkeys.ts +10 -4
- package/corpus/templates/design/app/lib/design-ui-events.ts +5 -0
- package/corpus/templates/design/app/root.tsx +18 -1
- package/corpus/templates/design/changelog/2026-07-28-show-or-hide-design-editing-chrome-with-cmd-on-apple-devices.md +6 -0
- package/corpus/templates/dispatch/.agents/skills/actions/SKILL.md +32 -0
- package/corpus/templates/dispatch/.agents/skills/security/SKILL.md +31 -0
- package/corpus/templates/dispatch/.agents/skills/sharing/SKILL.md +4 -0
- package/corpus/templates/forms/.agents/skills/actions/SKILL.md +32 -0
- package/corpus/templates/forms/.agents/skills/security/SKILL.md +31 -0
- package/corpus/templates/forms/.agents/skills/sharing/SKILL.md +4 -0
- package/corpus/templates/macros/.agents/skills/security/SKILL.md +31 -0
- package/corpus/templates/macros/.agents/skills/sharing/SKILL.md +4 -0
- package/corpus/templates/mail/.agents/skills/actions/SKILL.md +32 -0
- package/corpus/templates/mail/.agents/skills/security/SKILL.md +31 -0
- package/corpus/templates/mail/.agents/skills/sharing/SKILL.md +4 -0
- package/corpus/templates/plan/.agents/skills/actions/SKILL.md +32 -0
- package/corpus/templates/plan/.agents/skills/adding-a-feature/SKILL.md +7 -0
- package/corpus/templates/plan/.agents/skills/security/SKILL.md +31 -0
- package/corpus/templates/plan/.agents/skills/sharing/SKILL.md +4 -0
- package/corpus/templates/slides/.agents/skills/actions/SKILL.md +32 -0
- package/corpus/templates/slides/.agents/skills/security/SKILL.md +31 -0
- package/corpus/templates/slides/.agents/skills/sharing/SKILL.md +4 -0
- package/corpus/templates/tasks/.agents/skills/actions/SKILL.md +32 -0
- package/corpus/templates/tasks/.agents/skills/adding-a-feature/SKILL.md +7 -0
- package/corpus/templates/tasks/.agents/skills/security/SKILL.md +31 -0
- package/corpus/templates/tasks/.agents/skills/sharing/SKILL.md +4 -0
- package/dist/a2a/artifact-response.d.ts.map +1 -1
- package/dist/a2a/artifact-response.js +30 -29
- package/dist/a2a/artifact-response.js.map +1 -1
- package/dist/action.d.ts +36 -0
- package/dist/action.d.ts.map +1 -1
- package/dist/action.js +37 -2
- package/dist/action.js.map +1 -1
- package/dist/chat-threads/store.d.ts +12 -0
- package/dist/chat-threads/store.d.ts.map +1 -1
- package/dist/chat-threads/store.js +48 -42
- package/dist/chat-threads/store.js.map +1 -1
- package/dist/cli/skills-content/design-visual-edit-skill.d.ts +1 -1
- package/dist/cli/skills-content/design-visual-edit-skill.d.ts.map +1 -1
- package/dist/cli/skills-content/design-visual-edit-skill.js +46 -3
- package/dist/cli/skills-content/design-visual-edit-skill.js.map +1 -1
- package/dist/client/AgentPanel.d.ts +3 -1
- package/dist/client/AgentPanel.d.ts.map +1 -1
- package/dist/client/AgentPanel.js +11 -9
- package/dist/client/AgentPanel.js.map +1 -1
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +57 -6
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/DefaultSpinner.d.ts +7 -0
- package/dist/client/DefaultSpinner.d.ts.map +1 -1
- package/dist/client/DefaultSpinner.js +25 -1
- package/dist/client/DefaultSpinner.js.map +1 -1
- package/dist/client/org/TeamPage.d.ts +13 -1
- package/dist/client/org/TeamPage.d.ts.map +1 -1
- package/dist/client/org/TeamPage.js +41 -11
- package/dist/client/org/TeamPage.js.map +1 -1
- package/dist/client/org/hooks.d.ts +37 -0
- package/dist/client/org/hooks.d.ts.map +1 -1
- package/dist/client/org/hooks.js +37 -0
- package/dist/client/org/hooks.js.map +1 -1
- package/dist/client/org/index.d.ts +3 -2
- package/dist/client/org/index.d.ts.map +1 -1
- package/dist/client/org/index.js +1 -1
- package/dist/client/org/index.js.map +1 -1
- package/dist/client/transcription/use-live-transcription.d.ts +8 -0
- package/dist/client/transcription/use-live-transcription.d.ts.map +1 -1
- package/dist/client/transcription/use-live-transcription.js +38 -11
- package/dist/client/transcription/use-live-transcription.js.map +1 -1
- package/dist/collab/routes.d.ts +2 -2
- package/dist/db/client.d.ts +12 -0
- package/dist/db/client.d.ts.map +1 -1
- package/dist/db/client.js +40 -3
- package/dist/db/client.js.map +1 -1
- package/dist/db/ensure-additive-columns.d.ts.map +1 -1
- package/dist/db/ensure-additive-columns.js +54 -32
- package/dist/db/ensure-additive-columns.js.map +1 -1
- package/dist/deploy/build.d.ts +1 -0
- package/dist/deploy/build.d.ts.map +1 -1
- package/dist/deploy/build.js +23 -2
- package/dist/deploy/build.js.map +1 -1
- package/dist/file-upload/actions/upload-image.d.ts +1 -1
- package/dist/mcp-client/routes.d.ts +3 -1
- package/dist/mcp-client/routes.d.ts.map +1 -1
- package/dist/mcp-client/routes.js +8 -2
- package/dist/mcp-client/routes.js.map +1 -1
- package/dist/notifications/routes.d.ts +1 -1
- package/dist/org/app-roles-handlers.d.ts +27 -0
- package/dist/org/app-roles-handlers.d.ts.map +1 -0
- package/dist/org/app-roles-handlers.js +125 -0
- package/dist/org/app-roles-handlers.js.map +1 -0
- package/dist/org/app-roles.d.ts +136 -0
- package/dist/org/app-roles.d.ts.map +1 -0
- package/dist/org/app-roles.js +216 -0
- package/dist/org/app-roles.js.map +1 -0
- package/dist/org/index.d.ts +4 -1
- package/dist/org/index.d.ts.map +1 -1
- package/dist/org/index.js +3 -1
- package/dist/org/index.js.map +1 -1
- package/dist/org/migrations.d.ts.map +1 -1
- package/dist/org/migrations.js +22 -0
- package/dist/org/migrations.js.map +1 -1
- package/dist/org/plugin.d.ts +2 -0
- package/dist/org/plugin.d.ts.map +1 -1
- package/dist/org/plugin.js +20 -0
- package/dist/org/plugin.js.map +1 -1
- package/dist/org/schema.d.ts +143 -0
- package/dist/org/schema.d.ts.map +1 -1
- package/dist/org/schema.js +14 -0
- package/dist/org/schema.js.map +1 -1
- package/dist/progress/routes.d.ts +1 -1
- package/dist/provider-api/actions/custom-provider-registration.d.ts +4 -4
- package/dist/provider-api/actions/provider-api.d.ts +12 -12
- package/dist/scripts/docs/search.d.ts.map +1 -1
- package/dist/scripts/docs/search.js +15 -0
- package/dist/scripts/docs/search.js.map +1 -1
- package/dist/scripts/docs/source-search.d.ts +7 -0
- package/dist/scripts/docs/source-search.d.ts.map +1 -1
- package/dist/scripts/docs/source-search.js +9 -0
- package/dist/scripts/docs/source-search.js.map +1 -1
- package/dist/secrets/routes.d.ts +9 -9
- package/dist/server/agent-chat/script-entries.d.ts.map +1 -1
- package/dist/server/agent-chat/script-entries.js +3 -0
- package/dist/server/agent-chat/script-entries.js.map +1 -1
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +46 -48
- 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/core-routes-plugin.d.ts.map +1 -1
- package/dist/server/core-routes-plugin.js +6 -1
- package/dist/server/core-routes-plugin.js.map +1 -1
- package/dist/server/framework-request-handler.d.ts.map +1 -1
- package/dist/server/framework-request-handler.js +42 -6
- package/dist/server/framework-request-handler.js.map +1 -1
- package/dist/server/realtime-token.d.ts +1 -1
- package/dist/templates/chat/.agents/skills/actions/SKILL.md +32 -0
- package/dist/templates/chat/.agents/skills/adding-a-feature/SKILL.md +7 -0
- package/dist/templates/chat/.agents/skills/security/SKILL.md +31 -0
- package/dist/templates/chat/.agents/skills/sharing/SKILL.md +4 -0
- package/dist/templates/default/.agents/skills/actions/SKILL.md +32 -0
- package/dist/templates/default/.agents/skills/adding-a-feature/SKILL.md +7 -0
- package/dist/templates/default/.agents/skills/security/SKILL.md +31 -0
- package/dist/templates/headless/.agents/skills/actions/SKILL.md +32 -0
- package/dist/templates/workspace-core/.agents/skills/actions/SKILL.md +32 -0
- package/dist/templates/workspace-core/.agents/skills/adding-a-feature/SKILL.md +7 -0
- package/dist/templates/workspace-core/.agents/skills/authentication/SKILL.md +40 -0
- package/dist/templates/workspace-core/.agents/skills/security/SKILL.md +31 -0
- package/dist/templates/workspace-core/.agents/skills/sharing/SKILL.md +4 -0
- package/docs/content/actions.mdx +47 -4
- package/docs/content/native-chat-ui.mdx +7 -0
- package/docs/content/organizations-teams-permissions.mdx +109 -3
- package/docs/content/template-design-collaboration-and-full-apps.mdx +15 -0
- package/docs/content/toolkit-org-team.mdx +72 -12
- package/package.json +1 -1
- package/src/a2a/artifact-response.ts +36 -29
- package/src/action.ts +83 -2
- package/src/chat-threads/store.ts +48 -43
- package/src/cli/skills-content/design-visual-edit-skill.ts +46 -3
- package/src/client/AgentPanel.tsx +26 -6
- package/src/client/AssistantChat.tsx +63 -7
- package/src/client/DefaultSpinner.tsx +29 -0
- package/src/client/org/TeamPage.tsx +161 -6
- package/src/client/org/hooks.ts +67 -0
- package/src/client/org/index.ts +9 -0
- package/src/client/transcription/use-live-transcription.ts +62 -10
- package/src/db/client.ts +42 -3
- package/src/db/ensure-additive-columns.ts +60 -33
- package/src/deploy/build.ts +31 -2
- package/src/mcp-client/routes.ts +10 -1
- package/src/org/app-roles-handlers.ts +152 -0
- package/src/org/app-roles.ts +355 -0
- package/src/org/index.ts +27 -1
- package/src/org/migrations.ts +22 -0
- package/src/org/plugin.ts +27 -0
- package/src/org/schema.ts +15 -0
- package/src/scripts/docs/search.ts +17 -0
- package/src/scripts/docs/source-search.ts +10 -0
- package/src/server/agent-chat/script-entries.ts +3 -0
- package/src/server/agent-chat-plugin.ts +53 -52
- package/src/server/core-routes-plugin.ts +6 -1
- package/src/server/framework-request-handler.ts +44 -6
- package/src/templates/chat/.agents/skills/actions/SKILL.md +32 -0
- package/src/templates/chat/.agents/skills/adding-a-feature/SKILL.md +7 -0
- package/src/templates/chat/.agents/skills/security/SKILL.md +31 -0
- package/src/templates/chat/.agents/skills/sharing/SKILL.md +4 -0
- package/src/templates/default/.agents/skills/actions/SKILL.md +32 -0
- package/src/templates/default/.agents/skills/adding-a-feature/SKILL.md +7 -0
- package/src/templates/default/.agents/skills/security/SKILL.md +31 -0
- package/src/templates/headless/.agents/skills/actions/SKILL.md +32 -0
- package/src/templates/workspace-core/.agents/skills/actions/SKILL.md +32 -0
- package/src/templates/workspace-core/.agents/skills/adding-a-feature/SKILL.md +7 -0
- package/src/templates/workspace-core/.agents/skills/authentication/SKILL.md +40 -0
- package/src/templates/workspace-core/.agents/skills/security/SKILL.md +31 -0
- package/src/templates/workspace-core/.agents/skills/sharing/SKILL.md +4 -0
- package/corpus/core/src/templates/chat/.agents/skills/actions/SKILL.md +0 -530
- package/corpus/core/src/templates/chat/.agents/skills/adding-a-feature/SKILL.md +0 -191
- package/corpus/core/src/templates/chat/.agents/skills/agent-native-docs/SKILL.md +0 -115
- package/corpus/core/src/templates/chat/.agents/skills/agent-native-toolkit/SKILL.md +0 -177
- package/corpus/core/src/templates/chat/.agents/skills/capture-learnings/SKILL.md +0 -89
- package/corpus/core/src/templates/chat/.agents/skills/create-skill/SKILL.md +0 -221
- package/corpus/core/src/templates/chat/.agents/skills/customizing-agent-native/SKILL.md +0 -220
- package/corpus/core/src/templates/chat/.agents/skills/delegate-to-agent/SKILL.md +0 -263
- package/corpus/core/src/templates/chat/.agents/skills/feature-flags/SKILL.md +0 -169
- package/corpus/core/src/templates/chat/.agents/skills/frontend-design/SKILL.md +0 -174
- package/corpus/core/src/templates/chat/.agents/skills/real-time-sync/SKILL.md +0 -232
- package/corpus/core/src/templates/chat/.agents/skills/security/SKILL.md +0 -282
- package/corpus/core/src/templates/chat/.agents/skills/self-modifying-code/SKILL.md +0 -119
- package/corpus/core/src/templates/chat/.agents/skills/shadcn-ui/SKILL.md +0 -123
- package/corpus/core/src/templates/chat/.agents/skills/upgrade-agent-native/SKILL.md +0 -122
- package/corpus/core/src/templates/chat/.env.example +0 -5
- package/corpus/core/src/templates/chat/.ignore +0 -0
- package/corpus/core/src/templates/chat/.oxfmtrc.json +0 -8
- package/corpus/core/src/templates/chat/AGENTS.md +0 -77
- package/corpus/core/src/templates/chat/CHANGELOG.md +0 -10
- package/corpus/core/src/templates/chat/DEVELOPING.md +0 -185
- package/corpus/core/src/templates/chat/README.md +0 -32
- package/corpus/core/src/templates/chat/_gitignore +0 -46
- package/corpus/core/src/templates/chat/actions/hello.ts +0 -13
- package/corpus/core/src/templates/chat/actions/navigate.ts +0 -41
- package/corpus/core/src/templates/chat/actions/run.ts +0 -2
- package/corpus/core/src/templates/chat/actions/view-screen.ts +0 -31
- package/corpus/core/src/templates/chat/app/components/layout/Header.tsx +0 -60
- package/corpus/core/src/templates/chat/app/components/layout/Layout.tsx +0 -188
- package/corpus/core/src/templates/chat/app/components/layout/Sidebar.tsx +0 -505
- package/corpus/core/src/templates/chat/app/components/ui/button.tsx +0 -1
- package/corpus/core/src/templates/chat/app/components/ui/card.tsx +0 -1
- package/corpus/core/src/templates/chat/app/components/ui/dropdown-menu.tsx +0 -1
- package/corpus/core/src/templates/chat/app/components/ui/input.tsx +0 -1
- package/corpus/core/src/templates/chat/app/components/ui/label.tsx +0 -1
- package/corpus/core/src/templates/chat/app/components/ui/sheet.tsx +0 -1
- package/corpus/core/src/templates/chat/app/components/ui/toolkit-provider.tsx +0 -17
- package/corpus/core/src/templates/chat/app/components/ui/tooltip.tsx +0 -1
- package/corpus/core/src/templates/chat/app/design-system.ts +0 -3
- package/corpus/core/src/templates/chat/app/entry.client.tsx +0 -22
- package/corpus/core/src/templates/chat/app/entry.server.tsx +0 -10
- package/corpus/core/src/templates/chat/app/global.css +0 -93
- package/corpus/core/src/templates/chat/app/hooks/use-navigation-state.ts +0 -93
- package/corpus/core/src/templates/chat/app/i18n/ar-SA.ts +0 -68
- package/corpus/core/src/templates/chat/app/i18n/de-DE.ts +0 -71
- package/corpus/core/src/templates/chat/app/i18n/en-US.ts +0 -70
- package/corpus/core/src/templates/chat/app/i18n/es-ES.ts +0 -71
- package/corpus/core/src/templates/chat/app/i18n/fr-FR.ts +0 -71
- package/corpus/core/src/templates/chat/app/i18n/hi-IN.ts +0 -69
- package/corpus/core/src/templates/chat/app/i18n/index.ts +0 -34
- package/corpus/core/src/templates/chat/app/i18n/ja-JP.ts +0 -70
- package/corpus/core/src/templates/chat/app/i18n/ko-KR.ts +0 -70
- package/corpus/core/src/templates/chat/app/i18n/pt-BR.ts +0 -71
- package/corpus/core/src/templates/chat/app/i18n/zh-CN.ts +0 -66
- package/corpus/core/src/templates/chat/app/i18n/zh-TW.ts +0 -66
- package/corpus/core/src/templates/chat/app/i18n-data.ts +0 -556
- package/corpus/core/src/templates/chat/app/lib/agent-page.tsx +0 -49
- package/corpus/core/src/templates/chat/app/lib/app-config.ts +0 -11
- package/corpus/core/src/templates/chat/app/lib/tab-id.ts +0 -1
- package/corpus/core/src/templates/chat/app/lib/utils.ts +0 -1
- package/corpus/core/src/templates/chat/app/root.tsx +0 -173
- package/corpus/core/src/templates/chat/app/routes/_index.tsx +0 -94
- package/corpus/core/src/templates/chat/app/routes/agent.tsx +0 -24
- package/corpus/core/src/templates/chat/app/routes/chat.$threadId.tsx +0 -1
- package/corpus/core/src/templates/chat/app/routes/database.tsx +0 -17
- package/corpus/core/src/templates/chat/app/routes/extensions.$id.$slug.tsx +0 -2
- package/corpus/core/src/templates/chat/app/routes/extensions.$id.tsx +0 -11
- package/corpus/core/src/templates/chat/app/routes/extensions._index.tsx +0 -11
- package/corpus/core/src/templates/chat/app/routes/extensions.tsx +0 -5
- package/corpus/core/src/templates/chat/app/routes/observability.tsx +0 -19
- package/corpus/core/src/templates/chat/app/routes/settings.tsx +0 -89
- package/corpus/core/src/templates/chat/app/routes/team.tsx +0 -11
- package/corpus/core/src/templates/chat/app/routes.ts +0 -4
- package/corpus/core/src/templates/chat/app/vite-env.d.ts +0 -6
- package/corpus/core/src/templates/chat/changelog/2026-06-24-a-new-settings-page-gives-quick-access-to-language-workspace.md +0 -6
- package/corpus/core/src/templates/chat/changelog/2026-06-24-added-a-language-picker-and-localized-app-chrome-for-support.md +0 -6
- package/corpus/core/src/templates/chat/changelog/2026-06-27-traditional-chinese-copy-uses-taiwan-terminology.md +0 -6
- package/corpus/core/src/templates/chat/changelog/2026-06-28-left-sidebar-collapse-motion-and-footer-chrome-are-quieter.md +0 -6
- package/corpus/core/src/templates/chat/changelog/2026-06-29-chat-layouts-adapt-when-the-agent-sidebar-is-open.md +0 -6
- package/corpus/core/src/templates/chat/changelog/2026-07-08-settings-are-cleaner-and-searchable.md +0 -5
- package/corpus/core/src/templates/chat/changelog/2026-07-10-chat-now-makes-ai-connection-setup-clear-without-shifting-th.md +0 -6
- package/corpus/core/src/templates/chat/changelog/2026-07-13-a-full-agent-page-now-brings-context-files-connections-jobs-.md +0 -6
- package/corpus/core/src/templates/chat/changelog/2026-07-14-chat-opens-reliably-on-hosted-deployments-instead-of-failing.md +0 -6
- package/corpus/core/src/templates/chat/changelog/2026-07-14-fixed-chat-template-startup-with-older-core-versions.md +0 -6
- package/corpus/core/src/templates/chat/changelog/2026-07-15-chat-navigation-focuses-on-chat-and-agent.md +0 -6
- package/corpus/core/src/templates/chat/changelog/2026-07-17-the-agent-chat-sidebar-stays-closed-until-you-open-it-or-sta.md +0 -6
- package/corpus/core/src/templates/chat/changelog/2026-07-22-compact-sidebar-footer.md +0 -6
- package/corpus/core/src/templates/chat/changelog/2026-07-22-full-page-chat-keeps-the-active-conversation-when-moving-to-.md +0 -6
- package/corpus/core/src/templates/chat/changelog/2026-07-22-manage-agent-navigation-now-uses-the-connected-nodes-icon.md +0 -6
- package/corpus/core/src/templates/chat/changelog/2026-07-22-recent-chats-are-easier-to-scan-and-expand.md +0 -6
- package/corpus/core/src/templates/chat/changelog/2026-07-23-full-page-chat-is-better-centered-with-quieter-chat-history-.md +0 -6
- package/corpus/core/src/templates/chat/changelog/2026-07-24-borderless-secondary-surfaces.md +0 -6
- package/corpus/core/src/templates/chat/changelog/2026-07-24-sidebar-footer-controls-follow-a-consistent-order.md +0 -6
- package/corpus/core/src/templates/chat/changelog/2026-07-25-settings-navigation-now-keeps-manage-agent-as-a-dedicated-li.md +0 -6
- package/corpus/core/src/templates/chat/components.json +0 -20
- package/corpus/core/src/templates/chat/learnings.defaults.md +0 -5
- package/corpus/core/src/templates/chat/netlify.toml +0 -11
- package/corpus/core/src/templates/chat/package.json +0 -92
- package/corpus/core/src/templates/chat/public/agent-native-icon-dark.svg +0 -10
- package/corpus/core/src/templates/chat/public/agent-native-icon-light.svg +0 -10
- package/corpus/core/src/templates/chat/public/agent-native-logo-dark.svg +0 -21
- package/corpus/core/src/templates/chat/public/agent-native-logo-light.svg +0 -21
- package/corpus/core/src/templates/chat/public/favicon.svg +0 -1
- package/corpus/core/src/templates/chat/public/icon-180.svg +0 -1
- package/corpus/core/src/templates/chat/public/icon-192.svg +0 -1
- package/corpus/core/src/templates/chat/public/icon-512.svg +0 -1
- package/corpus/core/src/templates/chat/public/manifest.json +0 -21
- package/corpus/core/src/templates/chat/react-router.config.ts +0 -7
- package/corpus/core/src/templates/chat/server/middleware/auth.ts +0 -15
- package/corpus/core/src/templates/chat/server/plugins/agent-chat.ts +0 -21
- package/corpus/core/src/templates/chat/server/plugins/auth.ts +0 -17
- package/corpus/core/src/templates/chat/server/routes/[...page].get.ts +0 -5
- package/corpus/core/src/templates/chat/ssr-entry.ts +0 -15
- package/corpus/core/src/templates/chat/tsconfig.json +0 -21
- package/corpus/core/src/templates/chat/vite.config.ts +0 -19
|
@@ -132,38 +132,56 @@ async function loadGetTableConfig(): Promise<
|
|
|
132
132
|
}
|
|
133
133
|
|
|
134
134
|
/**
|
|
135
|
-
*
|
|
136
|
-
*
|
|
137
|
-
*
|
|
138
|
-
*
|
|
139
|
-
* Returns `null` when the table itself does not exist (caller no-ops —
|
|
140
|
-
* table creation owns that path) or when introspection fails outright.
|
|
135
|
+
* Load every requested Postgres table's live columns in one round trip.
|
|
136
|
+
* Calling information_schema separately for each table adds dozens of
|
|
137
|
+
* serialized network requests to every serverless cold start.
|
|
141
138
|
*/
|
|
142
|
-
async function
|
|
139
|
+
async function introspectPostgresColumns(
|
|
143
140
|
db: DbExec,
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
)
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
141
|
+
tables: DeclaredTableLike[],
|
|
142
|
+
): Promise<Map<string, Set<string>> | null> {
|
|
143
|
+
if (tables.length === 0) return new Map();
|
|
144
|
+
const pairs = [
|
|
145
|
+
...new Map(
|
|
146
|
+
tables.map((table) => {
|
|
147
|
+
const schema = table.schema || "public";
|
|
148
|
+
return [`${schema}.${table.name}`, { schema, table: table.name }];
|
|
149
|
+
}),
|
|
150
|
+
).values(),
|
|
151
|
+
];
|
|
152
|
+
const args: unknown[] = [];
|
|
153
|
+
const predicates = pairs.map(({ schema, table }) => {
|
|
154
|
+
args.push(schema, table);
|
|
155
|
+
return `(table_schema = ? AND table_name = ?)`;
|
|
156
|
+
});
|
|
157
|
+
try {
|
|
158
|
+
const { rows } = await db.execute({
|
|
159
|
+
sql: `SELECT table_schema, table_name, column_name
|
|
160
|
+
FROM information_schema.columns
|
|
161
|
+
WHERE ${predicates.join(" OR ")}`,
|
|
162
|
+
args,
|
|
163
|
+
});
|
|
164
|
+
const columns = new Map<string, Set<string>>();
|
|
165
|
+
for (const row of rows) {
|
|
166
|
+
const key = `${String(row.table_schema)}.${String(row.table_name)}`;
|
|
167
|
+
const tableColumns = columns.get(key) ?? new Set<string>();
|
|
168
|
+
tableColumns.add(String(row.column_name));
|
|
169
|
+
columns.set(key, tableColumns);
|
|
164
170
|
}
|
|
171
|
+
return columns;
|
|
172
|
+
} catch {
|
|
173
|
+
return null;
|
|
165
174
|
}
|
|
175
|
+
}
|
|
166
176
|
|
|
177
|
+
/**
|
|
178
|
+
* Live SQLite columns already present on `table`, keyed by column name.
|
|
179
|
+
* Returns `null` when the table does not exist or introspection fails.
|
|
180
|
+
*/
|
|
181
|
+
async function introspectSqliteLiveColumns(
|
|
182
|
+
db: DbExec,
|
|
183
|
+
table: string,
|
|
184
|
+
): Promise<Set<string> | null> {
|
|
167
185
|
// SQLite: PRAGMA table_info returns zero rows for a non-existent table
|
|
168
186
|
// (no error), so we can't distinguish "missing table" from "no columns"
|
|
169
187
|
// that way — probe sqlite_master first.
|
|
@@ -308,10 +326,13 @@ export async function ensureAdditiveColumns(
|
|
|
308
326
|
return result;
|
|
309
327
|
}
|
|
310
328
|
|
|
329
|
+
const declaredTables: DeclaredTableLike[] = [];
|
|
311
330
|
for (const tableObj of tables) {
|
|
312
|
-
let config: DeclaredTableLike;
|
|
313
331
|
try {
|
|
314
|
-
config = getTableConfig(tableObj);
|
|
332
|
+
const config = getTableConfig(tableObj);
|
|
333
|
+
if (config.name && PLAIN_IDENTIFIER.test(config.name)) {
|
|
334
|
+
declaredTables.push(config);
|
|
335
|
+
}
|
|
315
336
|
} catch (err) {
|
|
316
337
|
// Not a table this dialect's getTableConfig understands (e.g. a stray
|
|
317
338
|
// export that isn't a Drizzle table) — skip quietly rather than
|
|
@@ -319,15 +340,21 @@ export async function ensureAdditiveColumns(
|
|
|
319
340
|
logger.warn(
|
|
320
341
|
`[ensure-additive-columns] skipping non-table export: ${err instanceof Error ? err.message : String(err)}`,
|
|
321
342
|
);
|
|
322
|
-
continue;
|
|
323
343
|
}
|
|
344
|
+
}
|
|
324
345
|
|
|
325
|
-
|
|
326
|
-
|
|
346
|
+
const postgresColumns = isPostgres()
|
|
347
|
+
? await introspectPostgresColumns(db, declaredTables)
|
|
348
|
+
: null;
|
|
327
349
|
|
|
350
|
+
for (const config of declaredTables) {
|
|
351
|
+
const tableName = config.name;
|
|
328
352
|
let liveColumns: Set<string> | null;
|
|
329
353
|
try {
|
|
330
|
-
liveColumns =
|
|
354
|
+
liveColumns = isPostgres()
|
|
355
|
+
? (postgresColumns?.get(`${config.schema || "public"}.${tableName}`) ??
|
|
356
|
+
null)
|
|
357
|
+
: await introspectSqliteLiveColumns(db, tableName);
|
|
331
358
|
} catch (err) {
|
|
332
359
|
result.errors.push({
|
|
333
360
|
column: `${tableName}.*`,
|
|
@@ -1688,7 +1688,7 @@ export function generateCloudflarePagesStaticShellFromManifest(
|
|
|
1688
1688
|
? DEFAULT_ROOT_LOADER_REACT_ROUTER_TURBO_STREAM
|
|
1689
1689
|
: EMPTY_REACT_ROUTER_TURBO_STREAM;
|
|
1690
1690
|
|
|
1691
|
-
return `<!DOCTYPE html><html lang="en"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/><link rel="manifest" href="/manifest.json"/><link rel="icon" type="image/svg+xml" href="/favicon.svg"/>${modulePreloads}${stylesheets}</head><body><div style="display:flex;align-items:center;justify-content:center;height:100vh;width:100%"><svg role="status" aria-label="Loading" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="animation:an-spin 1s linear infinite;opacity:0.7"><path d="M21 12a9 9 0 1 1-6.219-8.56"></path></svg><style>@keyframes an-spin { to { transform: rotate(360deg) } } @media (prefers-color-scheme: dark) { html { background: #09090b; color: #fafafa } }</style></div><script>window.__reactRouterContext = ${JSON.stringify(context)};window.__reactRouterContext.stream = new ReadableStream({start(controller){window.__reactRouterContext.streamController = controller;}}).pipeThrough(new TextEncoderStream());</script><script type="module" async="">${routeModuleScript}</script><!--$--><script>window.__reactRouterContext.streamController.enqueue(${JSON.stringify(encodedInitialState)});</script><!--$--><script>window.__reactRouterContext.streamController.close();</script><!--/$--><!--/$--></body></html>`;
|
|
1691
|
+
return `<!DOCTYPE html><html lang="en"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/><link rel="manifest" href="/manifest.json"/><link rel="icon" type="image/svg+xml" href="/favicon.svg"/>${modulePreloads}${stylesheets}</head><body><div style="display:flex;flex-direction:column;align-items:center;justify-content:center;gap:16px;height:100vh;width:100%"><svg role="status" aria-label="Loading" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="animation:an-spin 1s linear infinite;opacity:0.7"><path d="M21 12a9 9 0 1 1-6.219-8.56"></path></svg><p class="an-stall-hint">Still loading. If this does not finish, reload the page — the browser console may show what failed.</p><style>@keyframes an-spin { to { transform: rotate(360deg) } } @keyframes an-stall-in { to { opacity: 0.6 } } .an-stall-hint { opacity: 0; margin: 0; max-width: 32rem; padding: 0 1.5rem; text-align: center; font-size: 0.875rem; line-height: 1.5; font-family: ui-sans-serif, system-ui, sans-serif; animation: an-stall-in 0.4s ease-out 10s forwards } @media (prefers-reduced-motion: reduce) { .an-stall-hint { animation-duration: 0s } } @media (prefers-color-scheme: dark) { html { background: #09090b; color: #fafafa } }</style></div><script>window.__reactRouterContext = ${JSON.stringify(context)};window.__reactRouterContext.stream = new ReadableStream({start(controller){window.__reactRouterContext.streamController = controller;}}).pipeThrough(new TextEncoderStream());</script><script type="module" async="">${routeModuleScript}</script><!--$--><script>window.__reactRouterContext.streamController.enqueue(${JSON.stringify(encodedInitialState)});</script><!--$--><script>window.__reactRouterContext.streamController.close();</script><!--/$--><!--/$--></body></html>`;
|
|
1692
1692
|
}
|
|
1693
1693
|
|
|
1694
1694
|
function writeCloudflarePagesStaticShell({
|
|
@@ -2343,6 +2343,28 @@ const LIBSQL_NATIVE_PACKAGE_NAMES = [
|
|
|
2343
2343
|
const FFMPEG_STATIC_PACKAGE_NAME = "ffmpeg-static";
|
|
2344
2344
|
const RESVG_SCOPE = "@resvg";
|
|
2345
2345
|
const RESVG_PACKAGE_PREFIX = "resvg-js";
|
|
2346
|
+
|
|
2347
|
+
// Serverless functions only ever run on 64-bit Linux. The darwin/win32/android
|
|
2348
|
+
// and 32-bit-arm prebuilds of these native packages are ~100MB that can never
|
|
2349
|
+
// execute there, and Netlify copies the whole server dir again for every extra
|
|
2350
|
+
// emitted function — so the dead weight is paid once per function. Cold start
|
|
2351
|
+
// scales with bundle size, and a page that opens several requests at once
|
|
2352
|
+
// scales out to that many cold containers, which is how this surfaces: 502/504
|
|
2353
|
+
// on the first burst rather than as an obviously slow deploy.
|
|
2354
|
+
const SERVERLESS_NATIVE_PACKAGE_SUFFIXES = [
|
|
2355
|
+
"linux-x64-gnu",
|
|
2356
|
+
"linux-x64-musl",
|
|
2357
|
+
"linux-arm64-gnu",
|
|
2358
|
+
"linux-arm64-musl",
|
|
2359
|
+
];
|
|
2360
|
+
|
|
2361
|
+
export function isServerlessNativePlatformPackage(
|
|
2362
|
+
packageName: string,
|
|
2363
|
+
): boolean {
|
|
2364
|
+
return SERVERLESS_NATIVE_PACKAGE_SUFFIXES.some((suffix) =>
|
|
2365
|
+
packageName.endsWith(suffix),
|
|
2366
|
+
);
|
|
2367
|
+
}
|
|
2346
2368
|
const FFMPEG_STATIC_BINARY_NAMES =
|
|
2347
2369
|
process.platform === "win32" ? ["ffmpeg.exe", "ffmpeg"] : ["ffmpeg"];
|
|
2348
2370
|
const SERVERLESS_FFMPEG_STATIC_PLATFORM = "linux";
|
|
@@ -3441,6 +3463,7 @@ function copyInstalledLibsqlNativePackages(serverDir: string | undefined) {
|
|
|
3441
3463
|
let copied = 0;
|
|
3442
3464
|
|
|
3443
3465
|
for (const packageName of LIBSQL_NATIVE_PACKAGE_NAMES) {
|
|
3466
|
+
if (!isServerlessNativePlatformPackage(packageName)) continue;
|
|
3444
3467
|
const src = findInstalledLibsqlNativePackage(nodeModulesRoots, packageName);
|
|
3445
3468
|
if (!src) continue;
|
|
3446
3469
|
|
|
@@ -3457,7 +3480,13 @@ function copyInstalledLibsqlNativePackages(serverDir: string | undefined) {
|
|
|
3457
3480
|
|
|
3458
3481
|
function copyInstalledResvgPackages(serverDir: string | undefined) {
|
|
3459
3482
|
if (!serverDir || !fs.existsSync(serverDir)) return;
|
|
3460
|
-
|
|
3483
|
+
// `resvg-js` itself is the JS wrapper that gets imported; everything else in
|
|
3484
|
+
// the scope is a per-platform prebuild.
|
|
3485
|
+
const packages = findInstalledResvgPackages(nodeModulesAncestors(cwd)).filter(
|
|
3486
|
+
({ packageName }) =>
|
|
3487
|
+
packageName === RESVG_PACKAGE_PREFIX ||
|
|
3488
|
+
isServerlessNativePlatformPackage(packageName),
|
|
3489
|
+
);
|
|
3461
3490
|
if (packages.length === 0) return;
|
|
3462
3491
|
|
|
3463
3492
|
const destScopeDir = path.join(serverDir, "node_modules", RESVG_SCOPE);
|
|
@@ -367,6 +367,9 @@ async function reconfigureManager(manager: McpClientManager): Promise<void> {
|
|
|
367
367
|
export function mountMcpServersRoutes(
|
|
368
368
|
nitroApp: any,
|
|
369
369
|
manager: McpClientManager,
|
|
370
|
+
options: {
|
|
371
|
+
waitUntilReady?: () => Promise<void>;
|
|
372
|
+
} = {},
|
|
370
373
|
): void {
|
|
371
374
|
const mountedApps: WeakSet<object> = ((
|
|
372
375
|
globalThis as any
|
|
@@ -375,13 +378,17 @@ export function mountMcpServersRoutes(
|
|
|
375
378
|
mountedApps.add(nitroApp);
|
|
376
379
|
|
|
377
380
|
mountMcpOAuthRoutes(nitroApp, {
|
|
378
|
-
reconfigure: () =>
|
|
381
|
+
reconfigure: async () => {
|
|
382
|
+
await options.waitUntilReady?.();
|
|
383
|
+
await reconfigureManager(manager);
|
|
384
|
+
},
|
|
379
385
|
});
|
|
380
386
|
|
|
381
387
|
try {
|
|
382
388
|
getH3App(nitroApp).use(
|
|
383
389
|
"/_agent-native/mcp/servers",
|
|
384
390
|
defineEventHandler(async (event: H3Event) => {
|
|
391
|
+
await options.waitUntilReady?.();
|
|
385
392
|
const method = getMethod(event);
|
|
386
393
|
const pathname = (event.url?.pathname || "")
|
|
387
394
|
.replace(/^\/+/, "")
|
|
@@ -421,6 +428,7 @@ export function mountMcpServersRoutes(
|
|
|
421
428
|
getH3App(nitroApp).use(
|
|
422
429
|
"/_agent-native/mcp/builtin",
|
|
423
430
|
defineEventHandler(async (event: H3Event) => {
|
|
431
|
+
await options.waitUntilReady?.();
|
|
424
432
|
const method = getMethod(event);
|
|
425
433
|
const pathname = (event.url?.pathname || "")
|
|
426
434
|
.replace(/^\/+/, "")
|
|
@@ -442,6 +450,7 @@ export function mountMcpServersRoutes(
|
|
|
442
450
|
getH3App(nitroApp).use(
|
|
443
451
|
"/_agent-native/mcp/apps",
|
|
444
452
|
defineEventHandler(async (event: H3Event) => {
|
|
453
|
+
await options.waitUntilReady?.();
|
|
445
454
|
const method = getMethod(event);
|
|
446
455
|
const pathname = (event.url?.pathname || "")
|
|
447
456
|
.replace(/^\/+/, "")
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import {
|
|
2
|
+
defineEventHandler,
|
|
3
|
+
getRequestURL,
|
|
4
|
+
createError,
|
|
5
|
+
type H3Event,
|
|
6
|
+
} from "h3";
|
|
7
|
+
|
|
8
|
+
import { getDbExec } from "../db/client.js";
|
|
9
|
+
import { readBody } from "../server/h3-helpers.js";
|
|
10
|
+
import {
|
|
11
|
+
getRegisteredAppRoles,
|
|
12
|
+
listAppMemberRoles,
|
|
13
|
+
setAppMemberRole,
|
|
14
|
+
type AppRolesDescriptor,
|
|
15
|
+
} from "./app-roles.js";
|
|
16
|
+
import { getOrgContext } from "./context.js";
|
|
17
|
+
import { canManageOrg } from "./permissions.js";
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Resolve the descriptor a request is talking about.
|
|
21
|
+
*
|
|
22
|
+
* The `appId` arrives from the client but can only ever select among
|
|
23
|
+
* descriptors the server already declared through `defineAppRoles`; an
|
|
24
|
+
* unregistered id is a 404, never an implicit new app. That keeps the trusted
|
|
25
|
+
* vocabulary in app source while still letting one workspace host several apps.
|
|
26
|
+
*/
|
|
27
|
+
function requireDescriptor(appId: string | null): AppRolesDescriptor<string> {
|
|
28
|
+
if (!appId?.trim()) {
|
|
29
|
+
throw createError({ statusCode: 400, message: "appId is required" });
|
|
30
|
+
}
|
|
31
|
+
const descriptor = getRegisteredAppRoles(appId.trim());
|
|
32
|
+
if (!descriptor) {
|
|
33
|
+
throw createError({
|
|
34
|
+
statusCode: 404,
|
|
35
|
+
message: `No app roles registered for "${appId}"`,
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
return descriptor;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** Extract the :email tail. The mount prefix is stripped before we see it. */
|
|
42
|
+
function extractMemberEmail(event: H3Event): string | undefined {
|
|
43
|
+
const path = getRequestURL(event).pathname;
|
|
44
|
+
const match =
|
|
45
|
+
path.match(/^\/([^/]+)\/?$/) ?? path.match(/\/app-roles\/([^/]+)\/?$/);
|
|
46
|
+
return match?.[1] ? decodeURIComponent(match[1]) : undefined;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
async function isOrgMember(orgId: string, email: string): Promise<boolean> {
|
|
50
|
+
const { rows } = await getDbExec().execute({
|
|
51
|
+
sql: `SELECT 1 FROM org_members WHERE org_id = ? AND LOWER(email) = ? LIMIT 1`,
|
|
52
|
+
args: [orgId, email.trim().toLowerCase()],
|
|
53
|
+
});
|
|
54
|
+
return rows.length > 0;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* GET /_agent-native/org/app-roles?appId=X — the app's vocabulary plus every
|
|
59
|
+
* assignment in the active org, and the caller's own resolved role.
|
|
60
|
+
*/
|
|
61
|
+
export const listAppRolesHandler = defineEventHandler(
|
|
62
|
+
async (event: H3Event) => {
|
|
63
|
+
const url = getRequestURL(event);
|
|
64
|
+
const descriptor = requireDescriptor(url.searchParams.get("appId"));
|
|
65
|
+
const ctx = await getOrgContext(event);
|
|
66
|
+
|
|
67
|
+
const base = {
|
|
68
|
+
appId: descriptor.appId,
|
|
69
|
+
roles: descriptor.roles,
|
|
70
|
+
defaultRole: descriptor.defaultRole ?? null,
|
|
71
|
+
roleLabels: descriptor.roleLabels ?? {},
|
|
72
|
+
canManage: canManageOrg(ctx.role),
|
|
73
|
+
};
|
|
74
|
+
if (!ctx.orgId) return { ...base, assignments: [], myRole: null };
|
|
75
|
+
|
|
76
|
+
const assignments = await listAppMemberRoles(descriptor.appId, ctx.orgId);
|
|
77
|
+
const mine = assignments.find(
|
|
78
|
+
(a) => a.email.toLowerCase() === ctx.email.toLowerCase(),
|
|
79
|
+
);
|
|
80
|
+
return {
|
|
81
|
+
...base,
|
|
82
|
+
assignments,
|
|
83
|
+
// The caller's own role, for progressive disclosure only. Every guarded
|
|
84
|
+
// operation re-resolves this server-side; a client that lies about it gains
|
|
85
|
+
// nothing but a differently-shaped UI.
|
|
86
|
+
myRole: mine && descriptor.roles.includes(mine.role) ? mine.role : null,
|
|
87
|
+
};
|
|
88
|
+
},
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* PUT /_agent-native/org/app-roles/:email — assign or clear an app role.
|
|
93
|
+
* Body: `{ appId, role }`, where `role: null` clears the assignment.
|
|
94
|
+
*
|
|
95
|
+
* Org owner/admin only. App roles never confer the right to manage app roles:
|
|
96
|
+
* that would let an app admin escalate inside a team they cannot otherwise
|
|
97
|
+
* administer, and it is the org roster this overlay hangs off.
|
|
98
|
+
*/
|
|
99
|
+
export const setAppRoleHandler = defineEventHandler(async (event: H3Event) => {
|
|
100
|
+
const ctx = await getOrgContext(event);
|
|
101
|
+
if (!ctx.email) {
|
|
102
|
+
throw createError({ statusCode: 401, message: "Authentication required" });
|
|
103
|
+
}
|
|
104
|
+
if (!ctx.orgId) {
|
|
105
|
+
throw createError({ statusCode: 400, message: "No active organization" });
|
|
106
|
+
}
|
|
107
|
+
if (!canManageOrg(ctx.role)) {
|
|
108
|
+
throw createError({
|
|
109
|
+
statusCode: 403,
|
|
110
|
+
message: "Organization admin role required",
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const body = await readBody(event);
|
|
115
|
+
const descriptor = requireDescriptor(body?.appId ?? null);
|
|
116
|
+
|
|
117
|
+
const email = extractMemberEmail(event);
|
|
118
|
+
if (!email) {
|
|
119
|
+
throw createError({ statusCode: 400, message: "Member email is required" });
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const role = body?.role ?? null;
|
|
123
|
+
if (role !== null && !descriptor.roles.includes(String(role))) {
|
|
124
|
+
throw createError({
|
|
125
|
+
statusCode: 400,
|
|
126
|
+
message: `Unknown ${descriptor.appId} role "${role}"`,
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// Assignments hang off membership. Writing one for a non-member would leave a
|
|
131
|
+
// row that resolves to nothing and reappears if that person is ever invited.
|
|
132
|
+
if (!(await isOrgMember(ctx.orgId, email))) {
|
|
133
|
+
throw createError({
|
|
134
|
+
statusCode: 404,
|
|
135
|
+
message: "Not a member of this organization",
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
await setAppMemberRole({
|
|
140
|
+
appId: descriptor.appId,
|
|
141
|
+
orgId: ctx.orgId,
|
|
142
|
+
email,
|
|
143
|
+
role: role === null ? null : String(role),
|
|
144
|
+
updatedBy: ctx.email,
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
return {
|
|
148
|
+
appId: descriptor.appId,
|
|
149
|
+
email,
|
|
150
|
+
role: role === null ? null : String(role),
|
|
151
|
+
};
|
|
152
|
+
});
|