@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
|
@@ -198,7 +198,9 @@ type PanelMode = "chat" | "cli" | "resources" | "settings";
|
|
|
198
198
|
export function normalizeAgentPanelModeForSurface(
|
|
199
199
|
mode: PanelMode,
|
|
200
200
|
allowSettingsMode: boolean,
|
|
201
|
+
chatOnly = false,
|
|
201
202
|
): PanelMode {
|
|
203
|
+
if (chatOnly) return "chat";
|
|
202
204
|
return mode === "settings" && !allowSettingsMode ? "chat" : mode;
|
|
203
205
|
}
|
|
204
206
|
const AGENT_PANEL_FONT_FAMILY =
|
|
@@ -597,6 +599,8 @@ export interface AgentPanelProps extends Omit<
|
|
|
597
599
|
showPageNewChatButton?: boolean;
|
|
598
600
|
/** Allow the sidebar settings view to render inside this panel. Default: true. */
|
|
599
601
|
allowSettingsMode?: boolean;
|
|
602
|
+
/** Keep this surface on chat even when mode controls are hidden. */
|
|
603
|
+
chatOnly?: boolean;
|
|
600
604
|
/** Optional link shown in Resources and Settings modes for the full Agent page. */
|
|
601
605
|
agentPageHref?: string;
|
|
602
606
|
/** Capability gate for source edits and CLI access. */
|
|
@@ -754,6 +758,7 @@ function AgentPanelInner({
|
|
|
754
758
|
showTabBar = true,
|
|
755
759
|
showPageNewChatButton = false,
|
|
756
760
|
allowSettingsMode = true,
|
|
761
|
+
chatOnly = false,
|
|
757
762
|
agentPageHref,
|
|
758
763
|
codeAccess,
|
|
759
764
|
...assistantChatProps
|
|
@@ -807,9 +812,17 @@ function AgentPanelInner({
|
|
|
807
812
|
saved === "resources" ||
|
|
808
813
|
saved === "settings"
|
|
809
814
|
)
|
|
810
|
-
return normalizeAgentPanelModeForSurface(
|
|
815
|
+
return normalizeAgentPanelModeForSurface(
|
|
816
|
+
saved,
|
|
817
|
+
allowSettingsMode,
|
|
818
|
+
chatOnly,
|
|
819
|
+
);
|
|
811
820
|
} catch {}
|
|
812
|
-
return normalizeAgentPanelModeForSurface(
|
|
821
|
+
return normalizeAgentPanelModeForSurface(
|
|
822
|
+
defaultMode,
|
|
823
|
+
allowSettingsMode,
|
|
824
|
+
chatOnly,
|
|
825
|
+
);
|
|
813
826
|
});
|
|
814
827
|
useEffect(() => {
|
|
815
828
|
try {
|
|
@@ -823,15 +836,21 @@ function AgentPanelInner({
|
|
|
823
836
|
const switchMode = useCallback(
|
|
824
837
|
(m: PanelMode) => {
|
|
825
838
|
startTransition(() =>
|
|
826
|
-
setMode(
|
|
839
|
+
setMode(
|
|
840
|
+
normalizeAgentPanelModeForSurface(m, allowSettingsMode, chatOnly),
|
|
841
|
+
),
|
|
827
842
|
);
|
|
828
843
|
},
|
|
829
|
-
[allowSettingsMode],
|
|
844
|
+
[allowSettingsMode, chatOnly],
|
|
830
845
|
);
|
|
831
846
|
useEffect(() => {
|
|
832
|
-
const nextMode = normalizeAgentPanelModeForSurface(
|
|
847
|
+
const nextMode = normalizeAgentPanelModeForSurface(
|
|
848
|
+
mode,
|
|
849
|
+
allowSettingsMode,
|
|
850
|
+
chatOnly,
|
|
851
|
+
);
|
|
833
852
|
if (nextMode !== mode) switchMode(nextMode);
|
|
834
|
-
}, [mode, allowSettingsMode, switchMode]);
|
|
853
|
+
}, [mode, allowSettingsMode, chatOnly, switchMode]);
|
|
835
854
|
const openRunThread = useCallback(
|
|
836
855
|
(threadId: string, run?: AgentRun) => {
|
|
837
856
|
switchMode("chat");
|
|
@@ -3349,6 +3368,7 @@ export function AgentSidebar({
|
|
|
3349
3368
|
threadUrlSync={threadUrlSync}
|
|
3350
3369
|
agentPageHref={agentPageHref}
|
|
3351
3370
|
allowSettingsMode={false}
|
|
3371
|
+
chatOnly
|
|
3352
3372
|
/>
|
|
3353
3373
|
</div>
|
|
3354
3374
|
</div>
|
|
@@ -333,8 +333,16 @@ function activeRunStuckThresholdMs(runInfo: ActiveRunLookup): number {
|
|
|
333
333
|
}
|
|
334
334
|
|
|
335
335
|
function activeRunLooksStale(runInfo: ActiveRunLookup): boolean {
|
|
336
|
+
// A run killed before it emitted anything has no `lastProgressAt`. Falling
|
|
337
|
+
// back to the heartbeat keeps that case from reading as perpetually fresh —
|
|
338
|
+
// "never reported progress" is the worst case, not an exemption from the
|
|
339
|
+
// staleness check.
|
|
336
340
|
const lastProgressAt =
|
|
337
|
-
typeof runInfo.lastProgressAt === "number"
|
|
341
|
+
typeof runInfo.lastProgressAt === "number"
|
|
342
|
+
? runInfo.lastProgressAt
|
|
343
|
+
: typeof runInfo.heartbeatAt === "number"
|
|
344
|
+
? runInfo.heartbeatAt
|
|
345
|
+
: null;
|
|
338
346
|
const nowMs =
|
|
339
347
|
typeof runInfo.serverNow === "number" ? runInfo.serverNow : Date.now();
|
|
340
348
|
const thresholdMs = activeRunStuckThresholdMs(runInfo);
|
|
@@ -345,6 +353,16 @@ function activeRunLooksStale(runInfo: ActiveRunLookup): boolean {
|
|
|
345
353
|
);
|
|
346
354
|
}
|
|
347
355
|
|
|
356
|
+
/**
|
|
357
|
+
* The stored active run is what keeps the "Thinking…" spinner up across a
|
|
358
|
+
* reload, and the `/runs/active` probe is the only path that clears it. A 5xx
|
|
359
|
+
* or a network drop there means "couldn't determine", NOT "still running" —
|
|
360
|
+
* collapsing the two is what strands the spinner forever when the server is
|
|
361
|
+
* briefly unreachable, because no caller reschedules the probe. Retry inside
|
|
362
|
+
* the call, then give up loudly.
|
|
363
|
+
*/
|
|
364
|
+
const ACTIVE_RUN_PROBE_RETRY_DELAYS_MS = [400, 1200];
|
|
365
|
+
|
|
348
366
|
/**
|
|
349
367
|
* Decide whether a reconnect should give up with "no progress". The signal is
|
|
350
368
|
* *time since the last streamed event*, NOT total reconnect duration: a healthy
|
|
@@ -3440,12 +3458,50 @@ const AssistantChatInner = forwardRef<
|
|
|
3440
3458
|
if (isRuntimeRunningRef.current || isAutoResumingRef.current) {
|
|
3441
3459
|
return false;
|
|
3442
3460
|
}
|
|
3461
|
+
const storedActiveRun = getActiveRun();
|
|
3462
|
+
let runRes: Response | null = null;
|
|
3463
|
+
for (let attempt = 0; ; attempt += 1) {
|
|
3464
|
+
try {
|
|
3465
|
+
const res = await fetch(
|
|
3466
|
+
`${apiUrl}/runs/active?threadId=${encodeURIComponent(threadId)}`,
|
|
3467
|
+
);
|
|
3468
|
+
if (res.ok) {
|
|
3469
|
+
runRes = res;
|
|
3470
|
+
break;
|
|
3471
|
+
}
|
|
3472
|
+
} catch {
|
|
3473
|
+
// Fall through to the retry/give-up path below.
|
|
3474
|
+
}
|
|
3475
|
+
const retryDelayMs = ACTIVE_RUN_PROBE_RETRY_DELAYS_MS[attempt];
|
|
3476
|
+
if (retryDelayMs === undefined) break;
|
|
3477
|
+
await new Promise((resolve) => setTimeout(resolve, retryDelayMs));
|
|
3478
|
+
}
|
|
3479
|
+
|
|
3480
|
+
if (!runRes) {
|
|
3481
|
+
// Still unreachable. Only a stored run for this thread is holding the
|
|
3482
|
+
// spinner up, so that is also the only case worth interrupting the user
|
|
3483
|
+
// for — drop it and say why, rather than leaving "Thinking…" forever.
|
|
3484
|
+
if (storedActiveRun?.threadId === threadId) {
|
|
3485
|
+
clearActiveRunIfMatches(threadId, storedActiveRun.runId);
|
|
3486
|
+
window.dispatchEvent(
|
|
3487
|
+
new CustomEvent("agent-chat:run-error", {
|
|
3488
|
+
detail: {
|
|
3489
|
+
message:
|
|
3490
|
+
"Couldn't reach the server to check whether the agent is still working. Send your message again to retry.",
|
|
3491
|
+
errorCode: "run_status_unavailable",
|
|
3492
|
+
recoverable: true,
|
|
3493
|
+
...(storedActiveRun.runId
|
|
3494
|
+
? { runId: storedActiveRun.runId }
|
|
3495
|
+
: {}),
|
|
3496
|
+
...(tabId ? { tabId } : {}),
|
|
3497
|
+
},
|
|
3498
|
+
}),
|
|
3499
|
+
);
|
|
3500
|
+
}
|
|
3501
|
+
return false;
|
|
3502
|
+
}
|
|
3503
|
+
|
|
3443
3504
|
try {
|
|
3444
|
-
const storedActiveRun = getActiveRun();
|
|
3445
|
-
const runRes = await fetch(
|
|
3446
|
-
`${apiUrl}/runs/active?threadId=${encodeURIComponent(threadId)}`,
|
|
3447
|
-
);
|
|
3448
|
-
if (!runRes.ok) return false;
|
|
3449
3505
|
const runInfo = (await runRes.json()) as ActiveRunLookup;
|
|
3450
3506
|
if (
|
|
3451
3507
|
!runInfo.active ||
|
|
@@ -3464,7 +3520,7 @@ const AssistantChatInner = forwardRef<
|
|
|
3464
3520
|
} catch {
|
|
3465
3521
|
return false;
|
|
3466
3522
|
}
|
|
3467
|
-
}, [apiUrl, refreshThreadFromServer, startReconnectToRun, threadId]);
|
|
3523
|
+
}, [apiUrl, refreshThreadFromServer, startReconnectToRun, tabId, threadId]);
|
|
3468
3524
|
|
|
3469
3525
|
useEffect(() => {
|
|
3470
3526
|
if (!threadId || !isNewThread) return;
|
|
@@ -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
|
)}
|
package/src/client/org/hooks.ts
CHANGED
|
@@ -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
|
package/src/client/org/index.ts
CHANGED
|
@@ -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,
|