@agent-native/core 0.127.3 → 0.128.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/corpus/README.md +2 -2
- package/corpus/core/CHANGELOG.md +101 -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 +2 -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/builder-design-systems.ts +299 -82
- 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/server/index.ts +8 -0
- 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/_gitignore +2 -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/assets/_gitignore +2 -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/calendar/_gitignore +2 -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/_gitignore +2 -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/content/_gitignore +2 -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/_gitignore +2 -0
- 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/i18n-data.ts +10 -0
- package/corpus/templates/design/app/lib/builder-design-system-upload.ts +280 -0
- package/corpus/templates/design/app/lib/design-ui-events.ts +5 -0
- package/corpus/templates/design/app/pages/DesignSystemSetup.tsx +90 -54
- package/corpus/templates/design/app/root.tsx +18 -1
- package/corpus/templates/design/changelog/2026-07-28-figma-fig-uploads-now-show-indexing-progress-and-an-open-in-.md +6 -0
- 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/design/server/handlers/design-system-decode-job-status.ts +49 -0
- package/corpus/templates/design/server/handlers/design-system-upload-start.ts +87 -0
- package/corpus/templates/design/server/handlers/index-design-system-sources.ts +82 -0
- package/corpus/templates/design/server/routes/api/design-system-decode-job-status.get.ts +1 -0
- package/corpus/templates/design/server/routes/api/design-system-upload-start.post.ts +1 -0
- package/corpus/templates/design/server/routes/api/index-design-system-sources.post.ts +1 -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/dispatch/_gitignore +2 -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/forms/_gitignore +2 -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/macros/_gitignore +2 -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/mail/_gitignore +2 -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/plan/_gitignore +2 -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/slides/_gitignore +2 -0
- package/corpus/templates/slides/app/components/design-system/DesignSystemSetup.tsx +126 -53
- package/corpus/templates/slides/app/components/design-system/builder-design-system-upload.ts +271 -0
- package/corpus/templates/slides/app/components/design-system/builder-index-response.ts +1 -1
- package/corpus/templates/slides/app/i18n/en-US.ts +1 -0
- package/corpus/templates/slides/server/handlers/design-system-decode-job-status.ts +49 -0
- package/corpus/templates/slides/server/handlers/design-system-upload-start.ts +87 -0
- package/corpus/templates/slides/server/handlers/index-design-system-sources.ts +79 -0
- package/corpus/templates/slides/server/routes/api/design-system-decode-job-status.get.ts +1 -0
- package/corpus/templates/slides/server/routes/api/design-system-upload-start.post.ts +1 -0
- package/corpus/templates/slides/server/routes/api/index-design-system-sources.post.ts +1 -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/corpus/templates/tasks/_gitignore +2 -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 +1 -1
- 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/provider-api/actions/custom-provider-registration.d.ts +8 -8
- package/dist/provider-api/actions/provider-api.d.ts +4 -4
- 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/builder-design-systems.d.ts +49 -0
- package/dist/server/builder-design-systems.d.ts.map +1 -1
- package/dist/server/builder-design-systems.js +221 -69
- package/dist/server/builder-design-systems.js.map +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/index.d.ts +1 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +1 -1
- package/dist/server/index.js.map +1 -1
- package/dist/server/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 +2 -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/builder-design-systems.ts +299 -82
- package/src/server/core-routes-plugin.ts +6 -1
- package/src/server/framework-request-handler.ts +44 -6
- package/src/server/index.ts +8 -0
- 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
- package/corpus/templates/design/server/handlers/index-design-system-with-builder.ts +0 -151
- package/corpus/templates/design/server/routes/api/index-design-system-with-builder.post.ts +0 -1
- package/corpus/templates/slides/server/handlers/index-design-system-with-builder.ts +0 -119
- package/corpus/templates/slides/server/routes/api/index-design-system-with-builder.post.ts +0 -1
|
@@ -2,14 +2,23 @@
|
|
|
2
2
|
* Full-screen loading spinner rendered during SSR and initial hydration.
|
|
3
3
|
* Uses inline SVG + styles because Tailwind may not be loaded yet on the server.
|
|
4
4
|
* Respects the user's OS color scheme so dark-mode users don't get a white flash.
|
|
5
|
+
*
|
|
6
|
+
* The stall hint is revealed by a pure-CSS `animation-delay`, never a timer:
|
|
7
|
+
* the states that strand a user here (hydration never runs, the route module
|
|
8
|
+
* 404s, a cold dev-server compile) are exactly the states where no JS of ours
|
|
9
|
+
* executes, so a `setTimeout` fallback would never fire. A featureless spinner
|
|
10
|
+
* is indistinguishable from a blank screen, and reads as "the app is broken"
|
|
11
|
+
* rather than "look at the terminal" — that mis-read is what this text buys.
|
|
5
12
|
*/
|
|
6
13
|
export function DefaultSpinner() {
|
|
7
14
|
return (
|
|
8
15
|
<div
|
|
9
16
|
style={{
|
|
10
17
|
display: "flex",
|
|
18
|
+
flexDirection: "column",
|
|
11
19
|
alignItems: "center",
|
|
12
20
|
justifyContent: "center",
|
|
21
|
+
gap: 16,
|
|
13
22
|
height: "100vh",
|
|
14
23
|
width: "100%",
|
|
15
24
|
}}
|
|
@@ -29,8 +38,28 @@ export function DefaultSpinner() {
|
|
|
29
38
|
>
|
|
30
39
|
<path d="M21 12a9 9 0 1 1-6.219-8.56" />
|
|
31
40
|
</svg>
|
|
41
|
+
<p className="an-stall-hint">
|
|
42
|
+
Still loading. A first run compiles dependencies and can take a minute —
|
|
43
|
+
if it does not finish, check the terminal running the dev server for
|
|
44
|
+
errors.
|
|
45
|
+
</p>
|
|
32
46
|
<style>{`
|
|
33
47
|
@keyframes an-spin { to { transform: rotate(360deg) } }
|
|
48
|
+
@keyframes an-stall-in { to { opacity: 0.6 } }
|
|
49
|
+
.an-stall-hint {
|
|
50
|
+
opacity: 0;
|
|
51
|
+
margin: 0;
|
|
52
|
+
max-width: 32rem;
|
|
53
|
+
padding: 0 1.5rem;
|
|
54
|
+
text-align: center;
|
|
55
|
+
font-size: 0.875rem;
|
|
56
|
+
line-height: 1.5;
|
|
57
|
+
font-family: ui-sans-serif, system-ui, sans-serif;
|
|
58
|
+
animation: an-stall-in 0.4s ease-out 10s forwards;
|
|
59
|
+
}
|
|
60
|
+
@media (prefers-reduced-motion: reduce) {
|
|
61
|
+
.an-stall-hint { animation-duration: 0s }
|
|
62
|
+
}
|
|
34
63
|
html {
|
|
35
64
|
background: hsl(var(--background, 0 0% 100%));
|
|
36
65
|
color: hsl(var(--foreground, 240 10% 3.9%));
|
|
@@ -56,6 +56,9 @@ import {
|
|
|
56
56
|
type ReactNode,
|
|
57
57
|
} from "react";
|
|
58
58
|
|
|
59
|
+
// Type-only: erased at build time, so declaring app roles pulls no server or
|
|
60
|
+
// database code into the browser bundle.
|
|
61
|
+
import type { AppRolesDescriptor } from "../../org/app-roles.js";
|
|
59
62
|
import type { DomainMatchOrg } from "../../org/types.js";
|
|
60
63
|
import {
|
|
61
64
|
Tooltip,
|
|
@@ -82,6 +85,8 @@ import {
|
|
|
82
85
|
useSetA2ASecret,
|
|
83
86
|
useSyncA2ASecret,
|
|
84
87
|
useJoinByDomain,
|
|
88
|
+
useAppRoles,
|
|
89
|
+
useSetAppMemberRole,
|
|
85
90
|
type InviteRole,
|
|
86
91
|
type SyncA2ASecretResult,
|
|
87
92
|
} from "./hooks.js";
|
|
@@ -127,6 +132,17 @@ export interface TeamPageProps {
|
|
|
127
132
|
* tweak page width.
|
|
128
133
|
*/
|
|
129
134
|
className?: string;
|
|
135
|
+
/**
|
|
136
|
+
* Opt in to an app-role column on the members table, using the same
|
|
137
|
+
* descriptor the app passes to `defineAppRoles`. Pass it explicitly rather
|
|
138
|
+
* than letting the page discover registered apps: a workspace can host
|
|
139
|
+
* several, and a members table that silently grows a column when some
|
|
140
|
+
* unrelated module registers itself is a surprise, not a feature.
|
|
141
|
+
*
|
|
142
|
+
* Only org owners/admins can change assignments; everyone else sees the
|
|
143
|
+
* column read-only.
|
|
144
|
+
*/
|
|
145
|
+
appRoles?: AppRolesDescriptor;
|
|
130
146
|
}
|
|
131
147
|
|
|
132
148
|
function RoleIcon({ role }: { role: string }) {
|
|
@@ -383,7 +399,7 @@ interface PendingInviteListItem {
|
|
|
383
399
|
role: string;
|
|
384
400
|
}
|
|
385
401
|
|
|
386
|
-
function MembersCard() {
|
|
402
|
+
function MembersCard({ appRoles }: { appRoles?: AppRolesDescriptor }) {
|
|
387
403
|
const t = useT();
|
|
388
404
|
const { data: org } = useOrg();
|
|
389
405
|
const { data: membersData, isLoading: isLoadingMembers } = useOrgMembers();
|
|
@@ -457,6 +473,7 @@ function MembersCard() {
|
|
|
457
473
|
isLoadingMembers={isLoadingMembers}
|
|
458
474
|
currentUserEmail={org.email}
|
|
459
475
|
currentUserRole={org.role ?? null}
|
|
476
|
+
appRoles={appRoles}
|
|
460
477
|
/>
|
|
461
478
|
|
|
462
479
|
{isOwner && <DangerZoneCard orgName={org.orgName ?? ""} />}
|
|
@@ -470,16 +487,26 @@ function MembersTableCard({
|
|
|
470
487
|
isLoadingMembers,
|
|
471
488
|
currentUserEmail,
|
|
472
489
|
currentUserRole,
|
|
490
|
+
appRoles,
|
|
473
491
|
}: {
|
|
474
492
|
members: MemberListItem[];
|
|
475
493
|
pendingInvites: PendingInviteListItem[];
|
|
476
494
|
isLoadingMembers: boolean;
|
|
477
495
|
currentUserEmail: string;
|
|
478
496
|
currentUserRole: string | null;
|
|
497
|
+
appRoles?: AppRolesDescriptor;
|
|
479
498
|
}) {
|
|
480
499
|
const t = useT();
|
|
481
500
|
const [showInviteForm, setShowInviteForm] = useState(false);
|
|
482
501
|
const canInvite = currentUserRole === "owner" || currentUserRole === "admin";
|
|
502
|
+
const { data: appRoleData } = useAppRoles(appRoles?.appId);
|
|
503
|
+
const appRoleByEmail = new Map(
|
|
504
|
+
(appRoleData?.assignments ?? []).map((a) => [
|
|
505
|
+
a.email.toLowerCase(),
|
|
506
|
+
a.role,
|
|
507
|
+
]),
|
|
508
|
+
);
|
|
509
|
+
const columnCount = appRoles ? 5 : 4;
|
|
483
510
|
|
|
484
511
|
return (
|
|
485
512
|
<section className="rounded-lg border border-border bg-card">
|
|
@@ -516,6 +543,9 @@ function MembersTableCard({
|
|
|
516
543
|
<TableRow>
|
|
517
544
|
<TableHead>{t("org.member")}</TableHead>
|
|
518
545
|
<TableHead>{t("org.role")}</TableHead>
|
|
546
|
+
{appRoles && (
|
|
547
|
+
<TableHead>{appRoles.label ?? appRoles.appId}</TableHead>
|
|
548
|
+
)}
|
|
519
549
|
<TableHead>{t("org.status")}</TableHead>
|
|
520
550
|
<TableHead className="text-end">{t("org.actions")}</TableHead>
|
|
521
551
|
</TableRow>
|
|
@@ -524,7 +554,7 @@ function MembersTableCard({
|
|
|
524
554
|
{isLoadingMembers && members.length === 0 ? (
|
|
525
555
|
[0, 1, 2].map((i) => (
|
|
526
556
|
<TableRow key={i}>
|
|
527
|
-
<TableCell colSpan={
|
|
557
|
+
<TableCell colSpan={columnCount}>
|
|
528
558
|
<div
|
|
529
559
|
className="h-3.5 rounded bg-muted animate-pulse"
|
|
530
560
|
style={{ width: `${180 + i * 48}px` }}
|
|
@@ -535,7 +565,7 @@ function MembersTableCard({
|
|
|
535
565
|
) : members.length === 0 && pendingInvites.length === 0 ? (
|
|
536
566
|
<TableRow>
|
|
537
567
|
<TableCell
|
|
538
|
-
colSpan={
|
|
568
|
+
colSpan={columnCount}
|
|
539
569
|
className="py-8 text-center text-sm text-muted-foreground"
|
|
540
570
|
>
|
|
541
571
|
{t("org.noMembers")}
|
|
@@ -550,10 +580,17 @@ function MembersTableCard({
|
|
|
550
580
|
role={m.role}
|
|
551
581
|
isCurrentUser={m.email === currentUserEmail}
|
|
552
582
|
currentUserRole={currentUserRole}
|
|
583
|
+
appRoles={appRoles}
|
|
584
|
+
appRole={appRoleByEmail.get(m.email.toLowerCase()) ?? null}
|
|
585
|
+
canManageAppRoles={Boolean(appRoleData?.canManage)}
|
|
553
586
|
/>
|
|
554
587
|
))}
|
|
555
588
|
{pendingInvites.map((inv) => (
|
|
556
|
-
<PendingInviteRow
|
|
589
|
+
<PendingInviteRow
|
|
590
|
+
key={inv.id}
|
|
591
|
+
invite={inv}
|
|
592
|
+
hasAppRoleColumn={Boolean(appRoles)}
|
|
593
|
+
/>
|
|
557
594
|
))}
|
|
558
595
|
</>
|
|
559
596
|
)}
|
|
@@ -665,7 +702,13 @@ function RoleBadge({ role }: { role: string }) {
|
|
|
665
702
|
);
|
|
666
703
|
}
|
|
667
704
|
|
|
668
|
-
function PendingInviteRow({
|
|
705
|
+
function PendingInviteRow({
|
|
706
|
+
invite,
|
|
707
|
+
hasAppRoleColumn,
|
|
708
|
+
}: {
|
|
709
|
+
invite: PendingInviteListItem;
|
|
710
|
+
hasAppRoleColumn?: boolean;
|
|
711
|
+
}) {
|
|
669
712
|
const t = useT();
|
|
670
713
|
return (
|
|
671
714
|
<TableRow className="opacity-70">
|
|
@@ -675,6 +718,13 @@ function PendingInviteRow({ invite }: { invite: PendingInviteListItem }) {
|
|
|
675
718
|
<TableCell>
|
|
676
719
|
<RoleBadge role={invite.role} />
|
|
677
720
|
</TableCell>
|
|
721
|
+
{/* App roles hang off membership, so there is nothing to assign until the
|
|
722
|
+
invitation is accepted. */}
|
|
723
|
+
{hasAppRoleColumn && (
|
|
724
|
+
<TableCell>
|
|
725
|
+
<span className="text-muted-foreground">-</span>
|
|
726
|
+
</TableCell>
|
|
727
|
+
)}
|
|
678
728
|
<TableCell>
|
|
679
729
|
<span className="rounded border border-border px-1.5 py-0.5 text-[10px] text-muted-foreground">
|
|
680
730
|
{t("org.invited")}
|
|
@@ -685,16 +735,112 @@ function PendingInviteRow({ invite }: { invite: PendingInviteListItem }) {
|
|
|
685
735
|
);
|
|
686
736
|
}
|
|
687
737
|
|
|
738
|
+
/** Sentinel for "clear the assignment" — Select cannot carry an empty value. */
|
|
739
|
+
const UNASSIGNED = "__unassigned__";
|
|
740
|
+
|
|
741
|
+
function AppRoleCell({
|
|
742
|
+
email,
|
|
743
|
+
appRoles,
|
|
744
|
+
appRole,
|
|
745
|
+
canManage,
|
|
746
|
+
}: {
|
|
747
|
+
email: string;
|
|
748
|
+
appRoles: AppRolesDescriptor;
|
|
749
|
+
appRole: string | null;
|
|
750
|
+
canManage: boolean;
|
|
751
|
+
}) {
|
|
752
|
+
const [editing, setEditing] = useState(false);
|
|
753
|
+
const setAppRole = useSetAppMemberRole(appRoles.appId);
|
|
754
|
+
const labelFor = (r: string) => appRoles.roleLabels?.[r] ?? r;
|
|
755
|
+
|
|
756
|
+
if (editing) {
|
|
757
|
+
return (
|
|
758
|
+
<TableCell>
|
|
759
|
+
<Select
|
|
760
|
+
defaultOpen
|
|
761
|
+
value={appRole ?? UNASSIGNED}
|
|
762
|
+
onOpenChange={(open) => {
|
|
763
|
+
if (!open) setEditing(false);
|
|
764
|
+
}}
|
|
765
|
+
onValueChange={(value) => {
|
|
766
|
+
const next = value === UNASSIGNED ? null : value;
|
|
767
|
+
if (next === appRole) {
|
|
768
|
+
setEditing(false);
|
|
769
|
+
return;
|
|
770
|
+
}
|
|
771
|
+
setAppRole.mutate(
|
|
772
|
+
{ email, role: next },
|
|
773
|
+
{ onSuccess: () => setEditing(false) },
|
|
774
|
+
);
|
|
775
|
+
}}
|
|
776
|
+
disabled={setAppRole.isPending}
|
|
777
|
+
>
|
|
778
|
+
<SelectTrigger
|
|
779
|
+
autoFocus
|
|
780
|
+
className="h-auto w-auto rounded-md border border-border bg-background px-1.5 py-0.5 text-[11px]"
|
|
781
|
+
>
|
|
782
|
+
<SelectValue />
|
|
783
|
+
</SelectTrigger>
|
|
784
|
+
<SelectContent>
|
|
785
|
+
<SelectItem value={UNASSIGNED}>
|
|
786
|
+
{appRoles.defaultRole ? labelFor(appRoles.defaultRole) : "—"}
|
|
787
|
+
</SelectItem>
|
|
788
|
+
{appRoles.roles.map((r) => (
|
|
789
|
+
<SelectItem key={r} value={r}>
|
|
790
|
+
{labelFor(r)}
|
|
791
|
+
</SelectItem>
|
|
792
|
+
))}
|
|
793
|
+
</SelectContent>
|
|
794
|
+
</Select>
|
|
795
|
+
</TableCell>
|
|
796
|
+
);
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
// An unassigned member shows the app's default only as a hint. The default
|
|
800
|
+
// never satisfies a server guard, so it must not read as a granted role.
|
|
801
|
+
const display = appRole ? (
|
|
802
|
+
<span className="inline-flex items-center rounded border border-border px-2 py-1 text-xs text-muted-foreground">
|
|
803
|
+
{labelFor(appRole)}
|
|
804
|
+
</span>
|
|
805
|
+
) : (
|
|
806
|
+
<span className="text-xs text-muted-foreground/70">
|
|
807
|
+
{appRoles.defaultRole ? labelFor(appRoles.defaultRole) : "—"}
|
|
808
|
+
</span>
|
|
809
|
+
);
|
|
810
|
+
|
|
811
|
+
return (
|
|
812
|
+
<TableCell>
|
|
813
|
+
{canManage ? (
|
|
814
|
+
<Button
|
|
815
|
+
type="button"
|
|
816
|
+
onClick={() => setEditing(true)}
|
|
817
|
+
className="cursor-pointer rounded hover:opacity-80"
|
|
818
|
+
>
|
|
819
|
+
{display}
|
|
820
|
+
</Button>
|
|
821
|
+
) : (
|
|
822
|
+
display
|
|
823
|
+
)}
|
|
824
|
+
</TableCell>
|
|
825
|
+
);
|
|
826
|
+
}
|
|
827
|
+
|
|
688
828
|
function MemberRow({
|
|
689
829
|
email,
|
|
690
830
|
role,
|
|
691
831
|
isCurrentUser,
|
|
692
832
|
currentUserRole,
|
|
833
|
+
appRoles,
|
|
834
|
+
appRole,
|
|
835
|
+
canManageAppRoles,
|
|
693
836
|
}: {
|
|
694
837
|
email: string;
|
|
695
838
|
role: string;
|
|
696
839
|
isCurrentUser: boolean;
|
|
697
840
|
currentUserRole: string | null;
|
|
841
|
+
appRoles?: AppRolesDescriptor;
|
|
842
|
+
appRole?: string | null;
|
|
843
|
+
canManageAppRoles?: boolean;
|
|
698
844
|
}) {
|
|
699
845
|
const t = useT();
|
|
700
846
|
const removeMember = useRemoveMember();
|
|
@@ -719,6 +865,14 @@ function MemberRow({
|
|
|
719
865
|
<TableCell>
|
|
720
866
|
<RoleBadge role={role} />
|
|
721
867
|
</TableCell>
|
|
868
|
+
{appRoles && (
|
|
869
|
+
<AppRoleCell
|
|
870
|
+
email={email}
|
|
871
|
+
appRoles={appRoles}
|
|
872
|
+
appRole={appRole ?? null}
|
|
873
|
+
canManage={Boolean(canManageAppRoles)}
|
|
874
|
+
/>
|
|
875
|
+
)}
|
|
722
876
|
<TableCell>
|
|
723
877
|
{isCurrentUser ? (
|
|
724
878
|
<span className="rounded border border-border px-1.5 py-0.5 text-[10px] text-muted-foreground">
|
|
@@ -1620,6 +1774,7 @@ export function TeamPage({
|
|
|
1620
1774
|
showTitle = true,
|
|
1621
1775
|
createOrgDescription,
|
|
1622
1776
|
className,
|
|
1777
|
+
appRoles,
|
|
1623
1778
|
}: TeamPageProps) {
|
|
1624
1779
|
const t = useT();
|
|
1625
1780
|
const { data: org, isLoading } = useOrg();
|
|
@@ -1652,7 +1807,7 @@ export function TeamPage({
|
|
|
1652
1807
|
{!org?.orgId ? (
|
|
1653
1808
|
<CreateOrgCard description={createOrgDescription} />
|
|
1654
1809
|
) : (
|
|
1655
|
-
<MembersCard />
|
|
1810
|
+
<MembersCard appRoles={appRoles} />
|
|
1656
1811
|
)}
|
|
1657
1812
|
</>
|
|
1658
1813
|
)}
|
|
@@ -318,6 +318,73 @@ export function useSetOrgDomain() {
|
|
|
318
318
|
});
|
|
319
319
|
}
|
|
320
320
|
|
|
321
|
+
export interface AppRoleAssignment {
|
|
322
|
+
email: string;
|
|
323
|
+
role: string;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
export interface AppRolesInfo {
|
|
327
|
+
appId: string;
|
|
328
|
+
roles: string[];
|
|
329
|
+
/** Shown for members with no assignment. Never satisfies a server guard. */
|
|
330
|
+
defaultRole: string | null;
|
|
331
|
+
roleLabels: Record<string, string>;
|
|
332
|
+
/** Whether the current user may change assignments (org owner/admin). */
|
|
333
|
+
canManage: boolean;
|
|
334
|
+
assignments: AppRoleAssignment[];
|
|
335
|
+
myRole: string | null;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
/**
|
|
339
|
+
* App-role vocabulary and assignments for the active org.
|
|
340
|
+
*
|
|
341
|
+
* `myRole` and `canManage` are progressive disclosure only — every guarded
|
|
342
|
+
* operation re-resolves both server-side, so a client that shows the wrong
|
|
343
|
+
* affordance still cannot perform the operation.
|
|
344
|
+
*/
|
|
345
|
+
export function useAppRoles(appId: string | undefined) {
|
|
346
|
+
const { data: org } = useOrg();
|
|
347
|
+
return useQuery<AppRolesInfo>({
|
|
348
|
+
queryKey: ["org-app-roles", appId ?? null, org?.orgId ?? null],
|
|
349
|
+
queryFn: () =>
|
|
350
|
+
apiFetch(`${ORG_BASE}/app-roles?appId=${encodeURIComponent(appId!)}`),
|
|
351
|
+
enabled: Boolean(appId),
|
|
352
|
+
staleTime: 30_000,
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
/** The current user's role in one app, or `null` when unassigned. */
|
|
357
|
+
export function useAppRole(appId: string | undefined): {
|
|
358
|
+
role: string | null;
|
|
359
|
+
isLoading: boolean;
|
|
360
|
+
error: Error | null;
|
|
361
|
+
} {
|
|
362
|
+
const query = useAppRoles(appId);
|
|
363
|
+
return {
|
|
364
|
+
role: query.data?.myRole ?? null,
|
|
365
|
+
isLoading: query.isLoading,
|
|
366
|
+
error: query.error,
|
|
367
|
+
};
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
export function useSetAppMemberRole(appId: string) {
|
|
371
|
+
const qc = useQueryClient();
|
|
372
|
+
return useMutation<
|
|
373
|
+
{ appId: string; email: string; role: string | null },
|
|
374
|
+
Error,
|
|
375
|
+
{ email: string; role: string | null }
|
|
376
|
+
>({
|
|
377
|
+
mutationFn: ({ email, role }) =>
|
|
378
|
+
apiFetch(`${ORG_BASE}/app-roles/${encodeURIComponent(email)}`, {
|
|
379
|
+
method: "PUT",
|
|
380
|
+
body: JSON.stringify({ appId, role }),
|
|
381
|
+
}),
|
|
382
|
+
onSuccess: async () => {
|
|
383
|
+
await qc.invalidateQueries({ queryKey: ["org-app-roles"] });
|
|
384
|
+
},
|
|
385
|
+
});
|
|
386
|
+
}
|
|
387
|
+
|
|
321
388
|
/**
|
|
322
389
|
* Fetch the org's A2A secret on demand (owner/admin). Deliberately a separate
|
|
323
390
|
* request from `useOrg()` so the secret only reaches the browser when the
|
|
@@ -19,6 +19,9 @@ export {
|
|
|
19
19
|
useSetA2ASecret,
|
|
20
20
|
useSyncA2ASecret,
|
|
21
21
|
useOrgRole,
|
|
22
|
+
useAppRoles,
|
|
23
|
+
useAppRole,
|
|
24
|
+
useSetAppMemberRole,
|
|
22
25
|
} from "./hooks.js";
|
|
23
26
|
|
|
24
27
|
export type {
|
|
@@ -27,8 +30,14 @@ export type {
|
|
|
27
30
|
BulkInviteResult,
|
|
28
31
|
SyncA2ASecretResult,
|
|
29
32
|
UseOrgRoleResult,
|
|
33
|
+
AppRoleAssignment,
|
|
34
|
+
AppRolesInfo,
|
|
30
35
|
} from "./hooks.js";
|
|
31
36
|
|
|
37
|
+
// Type-only re-export so templates can annotate the `appRoles` prop without
|
|
38
|
+
// importing the server module.
|
|
39
|
+
export type { AppRolesDescriptor } from "../../org/app-roles.js";
|
|
40
|
+
|
|
32
41
|
export { OrgSwitcher, type OrgSwitcherProps } from "./OrgSwitcher.js";
|
|
33
42
|
export {
|
|
34
43
|
InvitationBanner,
|
|
@@ -15,6 +15,8 @@ import { useCallback, useEffect, useRef, useState } from "react";
|
|
|
15
15
|
|
|
16
16
|
const NETWORK_RESTART_BASE_MS = 1_000;
|
|
17
17
|
const NETWORK_RESTART_MAX_MS = 30_000;
|
|
18
|
+
const RESTART_RETRY_BASE_MS = 400;
|
|
19
|
+
const MAX_RESTART_ATTEMPTS = 8;
|
|
18
20
|
|
|
19
21
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
20
22
|
function getSpeechRecognitionCtor(): any {
|
|
@@ -42,6 +44,14 @@ export interface LiveTranscriptionApi {
|
|
|
42
44
|
stopAndWait: (timeoutMs?: number) => Promise<string>;
|
|
43
45
|
pause: () => void;
|
|
44
46
|
resume: () => void;
|
|
47
|
+
/**
|
|
48
|
+
* Non-null when recognition died before the caller asked it to stop, so the
|
|
49
|
+
* returned transcript covers only part of the session. Callers must pass it
|
|
50
|
+
* along rather than storing a partial transcript as a finished one. Read
|
|
51
|
+
* through a getter (not state) so a stop handler can never observe a stale
|
|
52
|
+
* "everything was fine" value from an earlier render.
|
|
53
|
+
*/
|
|
54
|
+
getIncompleteReason: () => string | null;
|
|
45
55
|
}
|
|
46
56
|
|
|
47
57
|
export function useLiveTranscription(
|
|
@@ -64,6 +74,20 @@ export function useLiveTranscription(
|
|
|
64
74
|
const restartTimerRef = useRef<number | null>(null);
|
|
65
75
|
const networkErrorCountRef = useRef(0);
|
|
66
76
|
const restartDelayRef = useRef(0);
|
|
77
|
+
const restartFailureCountRef = useRef(0);
|
|
78
|
+
const incompleteReasonRef = useRef<string | null>(null);
|
|
79
|
+
|
|
80
|
+
// First reason wins: it names what actually broke the capture, and later
|
|
81
|
+
// teardown noise must not overwrite it.
|
|
82
|
+
const markIncomplete = useCallback((reason: string) => {
|
|
83
|
+
if (incompleteReasonRef.current) return;
|
|
84
|
+
incompleteReasonRef.current = reason;
|
|
85
|
+
}, []);
|
|
86
|
+
|
|
87
|
+
const getIncompleteReason = useCallback(
|
|
88
|
+
() => incompleteReasonRef.current,
|
|
89
|
+
[],
|
|
90
|
+
);
|
|
67
91
|
|
|
68
92
|
const currentTranscript = useCallback(
|
|
69
93
|
() =>
|
|
@@ -102,6 +126,8 @@ export function useLiveTranscription(
|
|
|
102
126
|
stoppedManuallyRef.current = false;
|
|
103
127
|
networkErrorCountRef.current = 0;
|
|
104
128
|
restartDelayRef.current = 0;
|
|
129
|
+
restartFailureCountRef.current = 0;
|
|
130
|
+
incompleteReasonRef.current = null;
|
|
105
131
|
setTranscript("");
|
|
106
132
|
setInterimText("");
|
|
107
133
|
|
|
@@ -122,6 +148,7 @@ export function useLiveTranscription(
|
|
|
122
148
|
if (event.results.length > 0) {
|
|
123
149
|
networkErrorCountRef.current = 0;
|
|
124
150
|
restartDelayRef.current = 0;
|
|
151
|
+
restartFailureCountRef.current = 0;
|
|
125
152
|
}
|
|
126
153
|
};
|
|
127
154
|
|
|
@@ -133,6 +160,9 @@ export function useLiveTranscription(
|
|
|
133
160
|
event.error === "audio-capture"
|
|
134
161
|
) {
|
|
135
162
|
stoppedManuallyRef.current = true;
|
|
163
|
+
markIncomplete(
|
|
164
|
+
`Browser speech recognition stopped mid-recording (${event.error}).`,
|
|
165
|
+
);
|
|
136
166
|
setIsActive(false);
|
|
137
167
|
return;
|
|
138
168
|
}
|
|
@@ -163,17 +193,34 @@ export function useLiveTranscription(
|
|
|
163
193
|
}
|
|
164
194
|
try {
|
|
165
195
|
recognition.start();
|
|
196
|
+
restartFailureCountRef.current = 0;
|
|
166
197
|
} catch {
|
|
167
|
-
|
|
198
|
+
// Chrome throws InvalidStateError while the previous session is
|
|
199
|
+
// still releasing. `onend` has already fired and will not fire
|
|
200
|
+
// again, so this timer is the only thing left that can revive
|
|
201
|
+
// recognition — giving up here freezes the transcript mid-recording
|
|
202
|
+
// and the partial text then looks like the whole recording.
|
|
203
|
+
const attempt = ++restartFailureCountRef.current;
|
|
204
|
+
if (attempt >= MAX_RESTART_ATTEMPTS) {
|
|
205
|
+
markIncomplete(
|
|
206
|
+
"Browser speech recognition stopped mid-recording and could not be restarted.",
|
|
207
|
+
);
|
|
208
|
+
setIsActive(false);
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
restartTimerRef.current = window.setTimeout(
|
|
212
|
+
restart,
|
|
213
|
+
RESTART_RETRY_BASE_MS * attempt,
|
|
214
|
+
);
|
|
168
215
|
}
|
|
169
216
|
};
|
|
170
|
-
|
|
217
|
+
// Never call start() synchronously from inside onend — Chrome still
|
|
218
|
+
// has the session marked as running during dispatch and throws.
|
|
219
|
+
restartTimerRef.current = window.setTimeout(
|
|
220
|
+
restart,
|
|
221
|
+
restartDelayRef.current,
|
|
222
|
+
);
|
|
171
223
|
restartDelayRef.current = 0;
|
|
172
|
-
if (delayMs > 0) {
|
|
173
|
-
restartTimerRef.current = window.setTimeout(restart, delayMs);
|
|
174
|
-
} else {
|
|
175
|
-
restart();
|
|
176
|
-
}
|
|
177
224
|
return;
|
|
178
225
|
}
|
|
179
226
|
setIsActive(false);
|
|
@@ -185,10 +232,14 @@ export function useLiveTranscription(
|
|
|
185
232
|
try {
|
|
186
233
|
recognition.start();
|
|
187
234
|
setIsActive(true);
|
|
188
|
-
} catch {
|
|
189
|
-
|
|
235
|
+
} catch (err) {
|
|
236
|
+
// Browser may block without user gesture. Nothing was captured, and the
|
|
237
|
+
// caller must not treat the resulting empty text as "no speech".
|
|
238
|
+
markIncomplete(
|
|
239
|
+
`Browser speech recognition could not start (${(err as Error)?.message || "unknown error"}).`,
|
|
240
|
+
);
|
|
190
241
|
}
|
|
191
|
-
}, [currentTranscript, lang]);
|
|
242
|
+
}, [currentTranscript, lang, markIncomplete]);
|
|
192
243
|
|
|
193
244
|
const stop = useCallback((): string => {
|
|
194
245
|
const text = currentTranscript();
|
|
@@ -307,5 +358,6 @@ export function useLiveTranscription(
|
|
|
307
358
|
stopAndWait,
|
|
308
359
|
pause,
|
|
309
360
|
resume,
|
|
361
|
+
getIncompleteReason,
|
|
310
362
|
};
|
|
311
363
|
}
|
|
@@ -1595,6 +1595,35 @@ async function initClient(): Promise<void> {
|
|
|
1595
1595
|
* Get the singleton database client. Returns a `DbExec` whose first
|
|
1596
1596
|
* `execute()` call lazily initializes the underlying driver.
|
|
1597
1597
|
*/
|
|
1598
|
+
/**
|
|
1599
|
+
* Point a missing-table failure at the cause instead of the symptom.
|
|
1600
|
+
*
|
|
1601
|
+
* The driver reports `no such table: x` / `relation "x" does not exist` from
|
|
1602
|
+
* whichever query happened to touch it first, so the stack lands in an action
|
|
1603
|
+
* and reads as a bug in that action. The actual cause is almost always that no
|
|
1604
|
+
* migration ever created the table — a template with no `server/plugins/db.ts`
|
|
1605
|
+
* creates none, and core's own tables self-heal, so app tables are the only
|
|
1606
|
+
* ones that fail this way. Appends rather than replaces: `isDuplicateColumnError`
|
|
1607
|
+
* and friends match substrings of the driver's original text.
|
|
1608
|
+
*/
|
|
1609
|
+
export function annotateMissingTable(err: unknown, sql: unknown): unknown {
|
|
1610
|
+
if (!(err instanceof Error)) return err;
|
|
1611
|
+
const match =
|
|
1612
|
+
/no such table:?\s*["'`]?([\w.]+)/i.exec(err.message) ??
|
|
1613
|
+
/relation\s+["'`]?([\w.]+)["'`]?\s+does not exist/i.exec(err.message);
|
|
1614
|
+
if (!match) return err;
|
|
1615
|
+
if (err.message.includes("server/plugins/db.ts")) return err;
|
|
1616
|
+
const statement =
|
|
1617
|
+
typeof sql === "string" ? sql : (sql as { sql?: string })?.sql;
|
|
1618
|
+
err.message =
|
|
1619
|
+
`${err.message}\n` +
|
|
1620
|
+
` [agent-native] Table "${match[1]}" does not exist. App tables are created by migrations in ` +
|
|
1621
|
+
`server/plugins/db.ts — check that the plugin exists and declares a migration for this table, ` +
|
|
1622
|
+
`then restart the dev server so it runs.` +
|
|
1623
|
+
(statement ? `\n Statement: ${statement.slice(0, 200)}` : "");
|
|
1624
|
+
return err;
|
|
1625
|
+
}
|
|
1626
|
+
|
|
1598
1627
|
export function getDbExec(): DbExec {
|
|
1599
1628
|
if (_exec) return _exec;
|
|
1600
1629
|
|
|
@@ -1608,6 +1637,16 @@ export function getDbExec(): DbExec {
|
|
|
1608
1637
|
return sql;
|
|
1609
1638
|
}
|
|
1610
1639
|
|
|
1640
|
+
async function execAnnotated(
|
|
1641
|
+
s: string | { sql: string; args?: unknown[] },
|
|
1642
|
+
): ReturnType<DbExec["execute"]> {
|
|
1643
|
+
try {
|
|
1644
|
+
return await _exec!.execute(sanitize(s));
|
|
1645
|
+
} catch (err) {
|
|
1646
|
+
throw annotateMissingTable(err, s);
|
|
1647
|
+
}
|
|
1648
|
+
}
|
|
1649
|
+
|
|
1611
1650
|
// Return a proxy that lazy-inits on first call
|
|
1612
1651
|
const proxy: DbExec = {
|
|
1613
1652
|
async execute(sql) {
|
|
@@ -1624,7 +1663,7 @@ export function getDbExec(): DbExec {
|
|
|
1624
1663
|
}
|
|
1625
1664
|
// After init, swap to a sanitizing wrapper around the real client
|
|
1626
1665
|
const wrapper: DbExec = {
|
|
1627
|
-
execute: (s) =>
|
|
1666
|
+
execute: (s) => execAnnotated(s),
|
|
1628
1667
|
atomicBatch: _exec!.atomicBatch
|
|
1629
1668
|
? (statements) =>
|
|
1630
1669
|
_exec!.atomicBatch!(statements.map((s) => sanitize(s)))
|
|
@@ -1640,7 +1679,7 @@ export function getDbExec(): DbExec {
|
|
|
1640
1679
|
: undefined,
|
|
1641
1680
|
};
|
|
1642
1681
|
Object.assign(proxy, wrapper);
|
|
1643
|
-
return
|
|
1682
|
+
return execAnnotated(sql);
|
|
1644
1683
|
},
|
|
1645
1684
|
async transaction(fn) {
|
|
1646
1685
|
if (!_initPromise) _initPromise = initClient();
|
|
@@ -1652,7 +1691,7 @@ export function getDbExec(): DbExec {
|
|
|
1652
1691
|
throw err;
|
|
1653
1692
|
}
|
|
1654
1693
|
const wrapper: DbExec = {
|
|
1655
|
-
execute: (s) =>
|
|
1694
|
+
execute: (s) => execAnnotated(s),
|
|
1656
1695
|
atomicBatch: _exec!.atomicBatch
|
|
1657
1696
|
? (statements) =>
|
|
1658
1697
|
_exec!.atomicBatch!(statements.map((s) => sanitize(s)))
|