@agent-native/core 0.127.3 → 0.128.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/corpus/README.md +2 -2
- package/corpus/core/CHANGELOG.md +80 -0
- package/corpus/core/README.md +5 -26
- package/corpus/core/docs/content/actions.mdx +47 -4
- package/corpus/core/docs/content/native-chat-ui.mdx +7 -0
- package/corpus/core/docs/content/organizations-teams-permissions.mdx +109 -3
- package/corpus/core/docs/content/template-design-collaboration-and-full-apps.mdx +15 -0
- package/corpus/core/docs/content/toolkit-org-team.mdx +72 -12
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/a2a/artifact-response.ts +36 -29
- package/corpus/core/src/action.ts +83 -2
- package/corpus/core/src/chat-threads/store.ts +48 -43
- package/corpus/core/src/cli/skills-content/design-visual-edit-skill.ts +46 -3
- package/corpus/core/src/client/AgentPanel.tsx +26 -6
- package/corpus/core/src/client/AssistantChat.tsx +63 -7
- package/corpus/core/src/client/DefaultSpinner.tsx +29 -0
- package/corpus/core/src/client/org/TeamPage.tsx +161 -6
- package/corpus/core/src/client/org/hooks.ts +67 -0
- package/corpus/core/src/client/org/index.ts +9 -0
- package/corpus/core/src/client/transcription/use-live-transcription.ts +62 -10
- package/corpus/core/src/db/client.ts +42 -3
- package/corpus/core/src/db/ensure-additive-columns.ts +60 -33
- package/corpus/core/src/deploy/build.ts +31 -2
- package/corpus/core/src/mcp-client/routes.ts +10 -1
- package/corpus/core/src/org/app-roles-handlers.ts +152 -0
- package/corpus/core/src/org/app-roles.ts +355 -0
- package/corpus/core/src/org/index.ts +27 -1
- package/corpus/core/src/org/migrations.ts +22 -0
- package/corpus/core/src/org/plugin.ts +27 -0
- package/corpus/core/src/org/schema.ts +15 -0
- package/corpus/core/src/scripts/docs/search.ts +17 -0
- package/corpus/core/src/scripts/docs/source-search.ts +10 -0
- package/corpus/core/src/server/agent-chat/script-entries.ts +3 -0
- package/corpus/core/src/server/agent-chat-plugin.ts +53 -52
- package/corpus/core/src/server/core-routes-plugin.ts +6 -1
- package/corpus/core/src/server/framework-request-handler.ts +44 -6
- package/corpus/core/src/templates/default/.agents/skills/actions/SKILL.md +32 -0
- package/corpus/core/src/templates/default/.agents/skills/adding-a-feature/SKILL.md +7 -0
- package/corpus/core/src/templates/default/.agents/skills/security/SKILL.md +31 -0
- package/corpus/core/src/templates/headless/.agents/skills/actions/SKILL.md +32 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/actions/SKILL.md +32 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/adding-a-feature/SKILL.md +7 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/authentication/SKILL.md +40 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/security/SKILL.md +31 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/sharing/SKILL.md +4 -0
- package/corpus/templates/analytics/.agents/skills/actions/SKILL.md +32 -0
- package/corpus/templates/analytics/.agents/skills/security/SKILL.md +31 -0
- package/corpus/templates/analytics/.agents/skills/sharing/SKILL.md +4 -0
- package/corpus/templates/analytics/actions/data-source-status.ts +21 -12
- package/corpus/templates/analytics/app/global.css +7 -7
- package/corpus/templates/analytics/app/i18n-data.ts +30 -0
- package/corpus/templates/analytics/app/lib/data-source-status.ts +2 -1
- package/corpus/templates/analytics/app/pages/DataSources.tsx +54 -10
- package/corpus/templates/analytics/changelog/2026-07-28-analytics-pages-load-reliably-with-large-dashboard-workspaces.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-28-dashboard-loading-shimmer-now-flows-smoothly-in-one-directi.md +6 -0
- package/corpus/templates/analytics/server/lib/first-party-dashboard-repair.ts +5 -4
- package/corpus/templates/analytics/server/plugins/agent-chat.ts +54 -42
- package/corpus/templates/analytics/server/plugins/db.ts +1 -18
- package/corpus/templates/assets/.agents/skills/actions/SKILL.md +32 -0
- package/corpus/templates/assets/.agents/skills/security/SKILL.md +31 -0
- package/corpus/templates/assets/.agents/skills/sharing/SKILL.md +4 -0
- package/corpus/templates/brain/.agents/skills/actions/SKILL.md +32 -0
- package/corpus/templates/brain/.agents/skills/adding-a-feature/SKILL.md +7 -0
- package/corpus/templates/brain/.agents/skills/security/SKILL.md +31 -0
- package/corpus/templates/brain/.agents/skills/sharing/SKILL.md +4 -0
- package/corpus/templates/calendar/.agents/skills/actions/SKILL.md +32 -0
- package/corpus/templates/calendar/.agents/skills/security/SKILL.md +31 -0
- package/corpus/templates/calendar/.agents/skills/sharing/SKILL.md +4 -0
- package/corpus/templates/chat/.agents/skills/actions/SKILL.md +32 -0
- package/corpus/templates/chat/.agents/skills/adding-a-feature/SKILL.md +7 -0
- package/corpus/templates/chat/.agents/skills/security/SKILL.md +31 -0
- package/corpus/templates/chat/.agents/skills/sharing/SKILL.md +4 -0
- package/corpus/templates/clips/.agents/skills/actions/SKILL.md +32 -0
- package/corpus/templates/clips/.agents/skills/security/SKILL.md +31 -0
- package/corpus/templates/clips/actions/request-transcript.ts +77 -11
- package/corpus/templates/clips/actions/save-browser-transcript.ts +28 -7
- package/corpus/templates/clips/app/routes/record.tsx +11 -3
- package/corpus/templates/clips/changelog/2026-07-28-browser-recordings-no-longer-save-a-truncated-transcript-as-.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-28-browser-recordings-no-longer-stop-transcribing-partway-throu.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-28-desktop-full-screen-clips-now-get-an-instant-local-transcrip.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-28-long-transcriptions-no-longer-show-a-false-transcription-sto.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-28-restarting-for-an-update-now-installs-the-newest-release-ins.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-28-the-meeting-recording-pill-now-anchors-to-the-right-edge-of-.md +6 -0
- package/corpus/templates/clips/desktop/src/lib/audio-meter.ts +31 -2
- package/corpus/templates/clips/desktop/src/lib/recorder.ts +114 -13
- package/corpus/templates/clips/desktop/src/lib/updater.ts +12 -4
- package/corpus/templates/clips/desktop/src/overlays/live-audio-bars.tsx +40 -15
- package/corpus/templates/clips/desktop/src/styles.css +10 -7
- package/corpus/templates/clips/desktop/src-tauri/src/recording_indicator.rs +21 -14
- package/corpus/templates/clips/shared/transcript-status.ts +10 -0
- package/corpus/templates/content/.agents/skills/actions/SKILL.md +32 -0
- package/corpus/templates/content/.agents/skills/security/SKILL.md +31 -0
- package/corpus/templates/content/.agents/skills/sharing/SKILL.md +4 -0
- package/corpus/templates/crm/.agents/skills/sharing/SKILL.md +4 -0
- package/corpus/templates/design/.agents/skills/actions/SKILL.md +32 -0
- package/corpus/templates/design/.agents/skills/security/SKILL.md +31 -0
- package/corpus/templates/design/.agents/skills/sharing/SKILL.md +4 -0
- package/corpus/templates/design/.agents/skills/visual-edit/SKILL.md +46 -3
- package/corpus/templates/design/.generated/bridge/editor-chrome.generated.ts +7 -5
- package/corpus/templates/design/app/components/design/CanvasContextMenu.tsx +2 -2
- package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +7 -4
- package/corpus/templates/design/app/components/design/keyboard-shortcuts.ts +1 -1
- package/corpus/templates/design/app/hooks/useDesignHotkeys.ts +10 -4
- package/corpus/templates/design/app/lib/design-ui-events.ts +5 -0
- package/corpus/templates/design/app/root.tsx +18 -1
- package/corpus/templates/design/changelog/2026-07-28-show-or-hide-design-editing-chrome-with-cmd-on-apple-devices.md +6 -0
- package/corpus/templates/dispatch/.agents/skills/actions/SKILL.md +32 -0
- package/corpus/templates/dispatch/.agents/skills/security/SKILL.md +31 -0
- package/corpus/templates/dispatch/.agents/skills/sharing/SKILL.md +4 -0
- package/corpus/templates/forms/.agents/skills/actions/SKILL.md +32 -0
- package/corpus/templates/forms/.agents/skills/security/SKILL.md +31 -0
- package/corpus/templates/forms/.agents/skills/sharing/SKILL.md +4 -0
- package/corpus/templates/macros/.agents/skills/security/SKILL.md +31 -0
- package/corpus/templates/macros/.agents/skills/sharing/SKILL.md +4 -0
- package/corpus/templates/mail/.agents/skills/actions/SKILL.md +32 -0
- package/corpus/templates/mail/.agents/skills/security/SKILL.md +31 -0
- package/corpus/templates/mail/.agents/skills/sharing/SKILL.md +4 -0
- package/corpus/templates/plan/.agents/skills/actions/SKILL.md +32 -0
- package/corpus/templates/plan/.agents/skills/adding-a-feature/SKILL.md +7 -0
- package/corpus/templates/plan/.agents/skills/security/SKILL.md +31 -0
- package/corpus/templates/plan/.agents/skills/sharing/SKILL.md +4 -0
- package/corpus/templates/slides/.agents/skills/actions/SKILL.md +32 -0
- package/corpus/templates/slides/.agents/skills/security/SKILL.md +31 -0
- package/corpus/templates/slides/.agents/skills/sharing/SKILL.md +4 -0
- package/corpus/templates/tasks/.agents/skills/actions/SKILL.md +32 -0
- package/corpus/templates/tasks/.agents/skills/adding-a-feature/SKILL.md +7 -0
- package/corpus/templates/tasks/.agents/skills/security/SKILL.md +31 -0
- package/corpus/templates/tasks/.agents/skills/sharing/SKILL.md +4 -0
- package/dist/a2a/artifact-response.d.ts.map +1 -1
- package/dist/a2a/artifact-response.js +30 -29
- package/dist/a2a/artifact-response.js.map +1 -1
- package/dist/action.d.ts +36 -0
- package/dist/action.d.ts.map +1 -1
- package/dist/action.js +37 -2
- package/dist/action.js.map +1 -1
- package/dist/chat-threads/store.d.ts +12 -0
- package/dist/chat-threads/store.d.ts.map +1 -1
- package/dist/chat-threads/store.js +48 -42
- package/dist/chat-threads/store.js.map +1 -1
- package/dist/cli/skills-content/design-visual-edit-skill.d.ts +1 -1
- package/dist/cli/skills-content/design-visual-edit-skill.d.ts.map +1 -1
- package/dist/cli/skills-content/design-visual-edit-skill.js +46 -3
- package/dist/cli/skills-content/design-visual-edit-skill.js.map +1 -1
- package/dist/client/AgentPanel.d.ts +3 -1
- package/dist/client/AgentPanel.d.ts.map +1 -1
- package/dist/client/AgentPanel.js +11 -9
- package/dist/client/AgentPanel.js.map +1 -1
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +57 -6
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/DefaultSpinner.d.ts +7 -0
- package/dist/client/DefaultSpinner.d.ts.map +1 -1
- package/dist/client/DefaultSpinner.js +25 -1
- package/dist/client/DefaultSpinner.js.map +1 -1
- package/dist/client/org/TeamPage.d.ts +13 -1
- package/dist/client/org/TeamPage.d.ts.map +1 -1
- package/dist/client/org/TeamPage.js +41 -11
- package/dist/client/org/TeamPage.js.map +1 -1
- package/dist/client/org/hooks.d.ts +37 -0
- package/dist/client/org/hooks.d.ts.map +1 -1
- package/dist/client/org/hooks.js +37 -0
- package/dist/client/org/hooks.js.map +1 -1
- package/dist/client/org/index.d.ts +3 -2
- package/dist/client/org/index.d.ts.map +1 -1
- package/dist/client/org/index.js +1 -1
- package/dist/client/org/index.js.map +1 -1
- package/dist/client/transcription/use-live-transcription.d.ts +8 -0
- package/dist/client/transcription/use-live-transcription.d.ts.map +1 -1
- package/dist/client/transcription/use-live-transcription.js +38 -11
- package/dist/client/transcription/use-live-transcription.js.map +1 -1
- package/dist/collab/routes.d.ts +2 -2
- package/dist/db/client.d.ts +12 -0
- package/dist/db/client.d.ts.map +1 -1
- package/dist/db/client.js +40 -3
- package/dist/db/client.js.map +1 -1
- package/dist/db/ensure-additive-columns.d.ts.map +1 -1
- package/dist/db/ensure-additive-columns.js +54 -32
- package/dist/db/ensure-additive-columns.js.map +1 -1
- package/dist/deploy/build.d.ts +1 -0
- package/dist/deploy/build.d.ts.map +1 -1
- package/dist/deploy/build.js +23 -2
- package/dist/deploy/build.js.map +1 -1
- package/dist/file-upload/actions/upload-image.d.ts +1 -1
- package/dist/mcp-client/routes.d.ts +3 -1
- package/dist/mcp-client/routes.d.ts.map +1 -1
- package/dist/mcp-client/routes.js +8 -2
- package/dist/mcp-client/routes.js.map +1 -1
- package/dist/notifications/routes.d.ts +1 -1
- package/dist/org/app-roles-handlers.d.ts +27 -0
- package/dist/org/app-roles-handlers.d.ts.map +1 -0
- package/dist/org/app-roles-handlers.js +125 -0
- package/dist/org/app-roles-handlers.js.map +1 -0
- package/dist/org/app-roles.d.ts +136 -0
- package/dist/org/app-roles.d.ts.map +1 -0
- package/dist/org/app-roles.js +216 -0
- package/dist/org/app-roles.js.map +1 -0
- package/dist/org/index.d.ts +4 -1
- package/dist/org/index.d.ts.map +1 -1
- package/dist/org/index.js +3 -1
- package/dist/org/index.js.map +1 -1
- package/dist/org/migrations.d.ts.map +1 -1
- package/dist/org/migrations.js +22 -0
- package/dist/org/migrations.js.map +1 -1
- package/dist/org/plugin.d.ts +2 -0
- package/dist/org/plugin.d.ts.map +1 -1
- package/dist/org/plugin.js +20 -0
- package/dist/org/plugin.js.map +1 -1
- package/dist/org/schema.d.ts +143 -0
- package/dist/org/schema.d.ts.map +1 -1
- package/dist/org/schema.js +14 -0
- package/dist/org/schema.js.map +1 -1
- package/dist/progress/routes.d.ts +1 -1
- package/dist/provider-api/actions/custom-provider-registration.d.ts +4 -4
- package/dist/provider-api/actions/provider-api.d.ts +12 -12
- package/dist/scripts/docs/search.d.ts.map +1 -1
- package/dist/scripts/docs/search.js +15 -0
- package/dist/scripts/docs/search.js.map +1 -1
- package/dist/scripts/docs/source-search.d.ts +7 -0
- package/dist/scripts/docs/source-search.d.ts.map +1 -1
- package/dist/scripts/docs/source-search.js +9 -0
- package/dist/scripts/docs/source-search.js.map +1 -1
- package/dist/secrets/routes.d.ts +9 -9
- package/dist/server/agent-chat/script-entries.d.ts.map +1 -1
- package/dist/server/agent-chat/script-entries.js +3 -0
- package/dist/server/agent-chat/script-entries.js.map +1 -1
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +46 -48
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/core-routes-plugin.d.ts.map +1 -1
- package/dist/server/core-routes-plugin.js +6 -1
- package/dist/server/core-routes-plugin.js.map +1 -1
- package/dist/server/framework-request-handler.d.ts.map +1 -1
- package/dist/server/framework-request-handler.js +42 -6
- package/dist/server/framework-request-handler.js.map +1 -1
- package/dist/server/realtime-token.d.ts +1 -1
- package/dist/templates/chat/.agents/skills/actions/SKILL.md +32 -0
- package/dist/templates/chat/.agents/skills/adding-a-feature/SKILL.md +7 -0
- package/dist/templates/chat/.agents/skills/security/SKILL.md +31 -0
- package/dist/templates/chat/.agents/skills/sharing/SKILL.md +4 -0
- package/dist/templates/default/.agents/skills/actions/SKILL.md +32 -0
- package/dist/templates/default/.agents/skills/adding-a-feature/SKILL.md +7 -0
- package/dist/templates/default/.agents/skills/security/SKILL.md +31 -0
- package/dist/templates/headless/.agents/skills/actions/SKILL.md +32 -0
- package/dist/templates/workspace-core/.agents/skills/actions/SKILL.md +32 -0
- package/dist/templates/workspace-core/.agents/skills/adding-a-feature/SKILL.md +7 -0
- package/dist/templates/workspace-core/.agents/skills/authentication/SKILL.md +40 -0
- package/dist/templates/workspace-core/.agents/skills/security/SKILL.md +31 -0
- package/dist/templates/workspace-core/.agents/skills/sharing/SKILL.md +4 -0
- package/docs/content/actions.mdx +47 -4
- package/docs/content/native-chat-ui.mdx +7 -0
- package/docs/content/organizations-teams-permissions.mdx +109 -3
- package/docs/content/template-design-collaboration-and-full-apps.mdx +15 -0
- package/docs/content/toolkit-org-team.mdx +72 -12
- package/package.json +1 -1
- package/src/a2a/artifact-response.ts +36 -29
- package/src/action.ts +83 -2
- package/src/chat-threads/store.ts +48 -43
- package/src/cli/skills-content/design-visual-edit-skill.ts +46 -3
- package/src/client/AgentPanel.tsx +26 -6
- package/src/client/AssistantChat.tsx +63 -7
- package/src/client/DefaultSpinner.tsx +29 -0
- package/src/client/org/TeamPage.tsx +161 -6
- package/src/client/org/hooks.ts +67 -0
- package/src/client/org/index.ts +9 -0
- package/src/client/transcription/use-live-transcription.ts +62 -10
- package/src/db/client.ts +42 -3
- package/src/db/ensure-additive-columns.ts +60 -33
- package/src/deploy/build.ts +31 -2
- package/src/mcp-client/routes.ts +10 -1
- package/src/org/app-roles-handlers.ts +152 -0
- package/src/org/app-roles.ts +355 -0
- package/src/org/index.ts +27 -1
- package/src/org/migrations.ts +22 -0
- package/src/org/plugin.ts +27 -0
- package/src/org/schema.ts +15 -0
- package/src/scripts/docs/search.ts +17 -0
- package/src/scripts/docs/source-search.ts +10 -0
- package/src/server/agent-chat/script-entries.ts +3 -0
- package/src/server/agent-chat-plugin.ts +53 -52
- package/src/server/core-routes-plugin.ts +6 -1
- package/src/server/framework-request-handler.ts +44 -6
- package/src/templates/chat/.agents/skills/actions/SKILL.md +32 -0
- package/src/templates/chat/.agents/skills/adding-a-feature/SKILL.md +7 -0
- package/src/templates/chat/.agents/skills/security/SKILL.md +31 -0
- package/src/templates/chat/.agents/skills/sharing/SKILL.md +4 -0
- package/src/templates/default/.agents/skills/actions/SKILL.md +32 -0
- package/src/templates/default/.agents/skills/adding-a-feature/SKILL.md +7 -0
- package/src/templates/default/.agents/skills/security/SKILL.md +31 -0
- package/src/templates/headless/.agents/skills/actions/SKILL.md +32 -0
- package/src/templates/workspace-core/.agents/skills/actions/SKILL.md +32 -0
- package/src/templates/workspace-core/.agents/skills/adding-a-feature/SKILL.md +7 -0
- package/src/templates/workspace-core/.agents/skills/authentication/SKILL.md +40 -0
- package/src/templates/workspace-core/.agents/skills/security/SKILL.md +31 -0
- package/src/templates/workspace-core/.agents/skills/sharing/SKILL.md +4 -0
- package/corpus/core/src/templates/chat/.agents/skills/actions/SKILL.md +0 -530
- package/corpus/core/src/templates/chat/.agents/skills/adding-a-feature/SKILL.md +0 -191
- package/corpus/core/src/templates/chat/.agents/skills/agent-native-docs/SKILL.md +0 -115
- package/corpus/core/src/templates/chat/.agents/skills/agent-native-toolkit/SKILL.md +0 -177
- package/corpus/core/src/templates/chat/.agents/skills/capture-learnings/SKILL.md +0 -89
- package/corpus/core/src/templates/chat/.agents/skills/create-skill/SKILL.md +0 -221
- package/corpus/core/src/templates/chat/.agents/skills/customizing-agent-native/SKILL.md +0 -220
- package/corpus/core/src/templates/chat/.agents/skills/delegate-to-agent/SKILL.md +0 -263
- package/corpus/core/src/templates/chat/.agents/skills/feature-flags/SKILL.md +0 -169
- package/corpus/core/src/templates/chat/.agents/skills/frontend-design/SKILL.md +0 -174
- package/corpus/core/src/templates/chat/.agents/skills/real-time-sync/SKILL.md +0 -232
- package/corpus/core/src/templates/chat/.agents/skills/security/SKILL.md +0 -282
- package/corpus/core/src/templates/chat/.agents/skills/self-modifying-code/SKILL.md +0 -119
- package/corpus/core/src/templates/chat/.agents/skills/shadcn-ui/SKILL.md +0 -123
- package/corpus/core/src/templates/chat/.agents/skills/upgrade-agent-native/SKILL.md +0 -122
- package/corpus/core/src/templates/chat/.env.example +0 -5
- package/corpus/core/src/templates/chat/.ignore +0 -0
- package/corpus/core/src/templates/chat/.oxfmtrc.json +0 -8
- package/corpus/core/src/templates/chat/AGENTS.md +0 -77
- package/corpus/core/src/templates/chat/CHANGELOG.md +0 -10
- package/corpus/core/src/templates/chat/DEVELOPING.md +0 -185
- package/corpus/core/src/templates/chat/README.md +0 -32
- package/corpus/core/src/templates/chat/_gitignore +0 -46
- package/corpus/core/src/templates/chat/actions/hello.ts +0 -13
- package/corpus/core/src/templates/chat/actions/navigate.ts +0 -41
- package/corpus/core/src/templates/chat/actions/run.ts +0 -2
- package/corpus/core/src/templates/chat/actions/view-screen.ts +0 -31
- package/corpus/core/src/templates/chat/app/components/layout/Header.tsx +0 -60
- package/corpus/core/src/templates/chat/app/components/layout/Layout.tsx +0 -188
- package/corpus/core/src/templates/chat/app/components/layout/Sidebar.tsx +0 -505
- package/corpus/core/src/templates/chat/app/components/ui/button.tsx +0 -1
- package/corpus/core/src/templates/chat/app/components/ui/card.tsx +0 -1
- package/corpus/core/src/templates/chat/app/components/ui/dropdown-menu.tsx +0 -1
- package/corpus/core/src/templates/chat/app/components/ui/input.tsx +0 -1
- package/corpus/core/src/templates/chat/app/components/ui/label.tsx +0 -1
- package/corpus/core/src/templates/chat/app/components/ui/sheet.tsx +0 -1
- package/corpus/core/src/templates/chat/app/components/ui/toolkit-provider.tsx +0 -17
- package/corpus/core/src/templates/chat/app/components/ui/tooltip.tsx +0 -1
- package/corpus/core/src/templates/chat/app/design-system.ts +0 -3
- package/corpus/core/src/templates/chat/app/entry.client.tsx +0 -22
- package/corpus/core/src/templates/chat/app/entry.server.tsx +0 -10
- package/corpus/core/src/templates/chat/app/global.css +0 -93
- package/corpus/core/src/templates/chat/app/hooks/use-navigation-state.ts +0 -93
- package/corpus/core/src/templates/chat/app/i18n/ar-SA.ts +0 -68
- package/corpus/core/src/templates/chat/app/i18n/de-DE.ts +0 -71
- package/corpus/core/src/templates/chat/app/i18n/en-US.ts +0 -70
- package/corpus/core/src/templates/chat/app/i18n/es-ES.ts +0 -71
- package/corpus/core/src/templates/chat/app/i18n/fr-FR.ts +0 -71
- package/corpus/core/src/templates/chat/app/i18n/hi-IN.ts +0 -69
- package/corpus/core/src/templates/chat/app/i18n/index.ts +0 -34
- package/corpus/core/src/templates/chat/app/i18n/ja-JP.ts +0 -70
- package/corpus/core/src/templates/chat/app/i18n/ko-KR.ts +0 -70
- package/corpus/core/src/templates/chat/app/i18n/pt-BR.ts +0 -71
- package/corpus/core/src/templates/chat/app/i18n/zh-CN.ts +0 -66
- package/corpus/core/src/templates/chat/app/i18n/zh-TW.ts +0 -66
- package/corpus/core/src/templates/chat/app/i18n-data.ts +0 -556
- package/corpus/core/src/templates/chat/app/lib/agent-page.tsx +0 -49
- package/corpus/core/src/templates/chat/app/lib/app-config.ts +0 -11
- package/corpus/core/src/templates/chat/app/lib/tab-id.ts +0 -1
- package/corpus/core/src/templates/chat/app/lib/utils.ts +0 -1
- package/corpus/core/src/templates/chat/app/root.tsx +0 -173
- package/corpus/core/src/templates/chat/app/routes/_index.tsx +0 -94
- package/corpus/core/src/templates/chat/app/routes/agent.tsx +0 -24
- package/corpus/core/src/templates/chat/app/routes/chat.$threadId.tsx +0 -1
- package/corpus/core/src/templates/chat/app/routes/database.tsx +0 -17
- package/corpus/core/src/templates/chat/app/routes/extensions.$id.$slug.tsx +0 -2
- package/corpus/core/src/templates/chat/app/routes/extensions.$id.tsx +0 -11
- package/corpus/core/src/templates/chat/app/routes/extensions._index.tsx +0 -11
- package/corpus/core/src/templates/chat/app/routes/extensions.tsx +0 -5
- package/corpus/core/src/templates/chat/app/routes/observability.tsx +0 -19
- package/corpus/core/src/templates/chat/app/routes/settings.tsx +0 -89
- package/corpus/core/src/templates/chat/app/routes/team.tsx +0 -11
- package/corpus/core/src/templates/chat/app/routes.ts +0 -4
- package/corpus/core/src/templates/chat/app/vite-env.d.ts +0 -6
- package/corpus/core/src/templates/chat/changelog/2026-06-24-a-new-settings-page-gives-quick-access-to-language-workspace.md +0 -6
- package/corpus/core/src/templates/chat/changelog/2026-06-24-added-a-language-picker-and-localized-app-chrome-for-support.md +0 -6
- package/corpus/core/src/templates/chat/changelog/2026-06-27-traditional-chinese-copy-uses-taiwan-terminology.md +0 -6
- package/corpus/core/src/templates/chat/changelog/2026-06-28-left-sidebar-collapse-motion-and-footer-chrome-are-quieter.md +0 -6
- package/corpus/core/src/templates/chat/changelog/2026-06-29-chat-layouts-adapt-when-the-agent-sidebar-is-open.md +0 -6
- package/corpus/core/src/templates/chat/changelog/2026-07-08-settings-are-cleaner-and-searchable.md +0 -5
- package/corpus/core/src/templates/chat/changelog/2026-07-10-chat-now-makes-ai-connection-setup-clear-without-shifting-th.md +0 -6
- package/corpus/core/src/templates/chat/changelog/2026-07-13-a-full-agent-page-now-brings-context-files-connections-jobs-.md +0 -6
- package/corpus/core/src/templates/chat/changelog/2026-07-14-chat-opens-reliably-on-hosted-deployments-instead-of-failing.md +0 -6
- package/corpus/core/src/templates/chat/changelog/2026-07-14-fixed-chat-template-startup-with-older-core-versions.md +0 -6
- package/corpus/core/src/templates/chat/changelog/2026-07-15-chat-navigation-focuses-on-chat-and-agent.md +0 -6
- package/corpus/core/src/templates/chat/changelog/2026-07-17-the-agent-chat-sidebar-stays-closed-until-you-open-it-or-sta.md +0 -6
- package/corpus/core/src/templates/chat/changelog/2026-07-22-compact-sidebar-footer.md +0 -6
- package/corpus/core/src/templates/chat/changelog/2026-07-22-full-page-chat-keeps-the-active-conversation-when-moving-to-.md +0 -6
- package/corpus/core/src/templates/chat/changelog/2026-07-22-manage-agent-navigation-now-uses-the-connected-nodes-icon.md +0 -6
- package/corpus/core/src/templates/chat/changelog/2026-07-22-recent-chats-are-easier-to-scan-and-expand.md +0 -6
- package/corpus/core/src/templates/chat/changelog/2026-07-23-full-page-chat-is-better-centered-with-quieter-chat-history-.md +0 -6
- package/corpus/core/src/templates/chat/changelog/2026-07-24-borderless-secondary-surfaces.md +0 -6
- package/corpus/core/src/templates/chat/changelog/2026-07-24-sidebar-footer-controls-follow-a-consistent-order.md +0 -6
- package/corpus/core/src/templates/chat/changelog/2026-07-25-settings-navigation-now-keeps-manage-agent-as-a-dedicated-li.md +0 -6
- package/corpus/core/src/templates/chat/components.json +0 -20
- package/corpus/core/src/templates/chat/learnings.defaults.md +0 -5
- package/corpus/core/src/templates/chat/netlify.toml +0 -11
- package/corpus/core/src/templates/chat/package.json +0 -92
- package/corpus/core/src/templates/chat/public/agent-native-icon-dark.svg +0 -10
- package/corpus/core/src/templates/chat/public/agent-native-icon-light.svg +0 -10
- package/corpus/core/src/templates/chat/public/agent-native-logo-dark.svg +0 -21
- package/corpus/core/src/templates/chat/public/agent-native-logo-light.svg +0 -21
- package/corpus/core/src/templates/chat/public/favicon.svg +0 -1
- package/corpus/core/src/templates/chat/public/icon-180.svg +0 -1
- package/corpus/core/src/templates/chat/public/icon-192.svg +0 -1
- package/corpus/core/src/templates/chat/public/icon-512.svg +0 -1
- package/corpus/core/src/templates/chat/public/manifest.json +0 -21
- package/corpus/core/src/templates/chat/react-router.config.ts +0 -7
- package/corpus/core/src/templates/chat/server/middleware/auth.ts +0 -15
- package/corpus/core/src/templates/chat/server/plugins/agent-chat.ts +0 -21
- package/corpus/core/src/templates/chat/server/plugins/auth.ts +0 -17
- package/corpus/core/src/templates/chat/server/routes/[...page].get.ts +0 -5
- package/corpus/core/src/templates/chat/ssr-entry.ts +0 -15
- package/corpus/core/src/templates/chat/tsconfig.json +0 -21
- package/corpus/core/src/templates/chat/vite.config.ts +0 -19
|
@@ -50,6 +50,11 @@ const ARTIFACT_IDENTITY_WRITE_TOOLS = new Set([
|
|
|
50
50
|
"create-deck",
|
|
51
51
|
"duplicate-deck",
|
|
52
52
|
"add-slide",
|
|
53
|
+
"update-slide",
|
|
54
|
+
"patch-deck",
|
|
55
|
+
"save-deck",
|
|
56
|
+
"import-pptx",
|
|
57
|
+
"restore-deck-version",
|
|
53
58
|
"update-dashboard",
|
|
54
59
|
"rename-dashboard",
|
|
55
60
|
"save-analysis",
|
|
@@ -513,27 +518,43 @@ function addImageArtifact(
|
|
|
513
518
|
});
|
|
514
519
|
}
|
|
515
520
|
|
|
516
|
-
function isReadyDeckArtifact(parsed: Record<string, unknown>): boolean {
|
|
517
|
-
const slideCount = numberValue(parsed.slideCount);
|
|
518
|
-
if (slideCount !== undefined) return slideCount > 0;
|
|
519
|
-
if (Array.isArray(parsed.slides)) return parsed.slides.length > 0;
|
|
520
|
-
return true;
|
|
521
|
-
}
|
|
522
|
-
|
|
523
521
|
function addDeckArtifact(
|
|
524
522
|
decks: Map<string, CreatedDeckArtifact>,
|
|
525
523
|
parsed: Record<string, unknown>,
|
|
526
|
-
options: { requireReady: boolean },
|
|
527
524
|
): void {
|
|
528
525
|
const id = deckIdValue(parsed);
|
|
529
526
|
if (!id) return;
|
|
530
|
-
if (options.requireReady && !isReadyDeckArtifact(parsed)) return;
|
|
531
527
|
decks.set(id, {
|
|
532
528
|
id,
|
|
533
529
|
url: stringValue(parsed.url) ?? stringValue(parsed.urlPath),
|
|
534
530
|
});
|
|
535
531
|
}
|
|
536
532
|
|
|
533
|
+
// Deck writes are spread across a dozen actions (create-deck, add-slide,
|
|
534
|
+
// patch-deck, save-deck, update-slide, import-*, restore-deck-version), so a
|
|
535
|
+
// per-tool allow-list refuses a real deck URL every time an action is added.
|
|
536
|
+
// Trust any successful result that names a deck the way the deck routes do: an
|
|
537
|
+
// explicit deckId, or a canonical /deck/<id> URL the action itself returned.
|
|
538
|
+
function addDeckArtifactFromAnyResult(
|
|
539
|
+
decks: Map<string, CreatedDeckArtifact>,
|
|
540
|
+
parsed: Record<string, unknown>,
|
|
541
|
+
): void {
|
|
542
|
+
const url = stringValue(parsed.url) ?? stringValue(parsed.urlPath);
|
|
543
|
+
const deckId = stringValue(parsed.deckId);
|
|
544
|
+
if (deckId) {
|
|
545
|
+
decks.set(deckId, {
|
|
546
|
+
id: deckId,
|
|
547
|
+
url:
|
|
548
|
+
url && artifactUrlReferencesId(url, "deck", deckId) ? url : undefined,
|
|
549
|
+
});
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
const reference = url ? parseArtifactReferenceUrl(url) : null;
|
|
553
|
+
if (reference?.kind === "deck") {
|
|
554
|
+
decks.set(reference.id, { id: reference.id, url });
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
|
|
537
558
|
function addListedDeckArtifacts(
|
|
538
559
|
decks: Map<string, CreatedDeckArtifact>,
|
|
539
560
|
parsed: Record<string, unknown>,
|
|
@@ -543,7 +564,7 @@ function addListedDeckArtifacts(
|
|
|
543
564
|
for (const item of items) {
|
|
544
565
|
const deck = asRecord(item);
|
|
545
566
|
if (!deck) continue;
|
|
546
|
-
addDeckArtifact(decks, deck
|
|
567
|
+
addDeckArtifact(decks, deck);
|
|
547
568
|
}
|
|
548
569
|
}
|
|
549
570
|
|
|
@@ -617,6 +638,8 @@ function collectArtifacts(results: A2AToolResultSummary[]): {
|
|
|
617
638
|
const parsed = parseToolResultJson(toolResult.result);
|
|
618
639
|
if (!parsed) continue;
|
|
619
640
|
|
|
641
|
+
addDeckArtifactFromAnyResult(decks, parsed);
|
|
642
|
+
|
|
620
643
|
if (toolResult.tool === "save-monitor") {
|
|
621
644
|
const id = stringValue(parsed.id);
|
|
622
645
|
const url = stringValue(parsed.monitorAppUrl);
|
|
@@ -711,14 +734,10 @@ function collectArtifacts(results: A2AToolResultSummary[]): {
|
|
|
711
734
|
|
|
712
735
|
if (
|
|
713
736
|
toolResult.tool === "create-deck" ||
|
|
714
|
-
toolResult.tool === "duplicate-deck"
|
|
737
|
+
toolResult.tool === "duplicate-deck" ||
|
|
738
|
+
toolResult.tool === "get-deck"
|
|
715
739
|
) {
|
|
716
|
-
addDeckArtifact(decks, parsed
|
|
717
|
-
continue;
|
|
718
|
-
}
|
|
719
|
-
|
|
720
|
-
if (toolResult.tool === "get-deck") {
|
|
721
|
-
addDeckArtifact(decks, parsed, { requireReady: false });
|
|
740
|
+
addDeckArtifact(decks, parsed);
|
|
722
741
|
continue;
|
|
723
742
|
}
|
|
724
743
|
|
|
@@ -727,18 +746,6 @@ function collectArtifacts(results: A2AToolResultSummary[]): {
|
|
|
727
746
|
continue;
|
|
728
747
|
}
|
|
729
748
|
|
|
730
|
-
if (toolResult.tool === "add-slide") {
|
|
731
|
-
const id = stringValue(parsed.deckId);
|
|
732
|
-
const slideCount = numberValue(parsed.slideCount);
|
|
733
|
-
if (id && slideCount !== undefined && slideCount > 0) {
|
|
734
|
-
decks.set(id, {
|
|
735
|
-
id,
|
|
736
|
-
url: stringValue(parsed.url) ?? stringValue(parsed.urlPath),
|
|
737
|
-
});
|
|
738
|
-
}
|
|
739
|
-
continue;
|
|
740
|
-
}
|
|
741
|
-
|
|
742
749
|
if (
|
|
743
750
|
toolResult.tool === "update-dashboard" ||
|
|
744
751
|
toolResult.tool === "rename-dashboard" ||
|
package/src/action.ts
CHANGED
|
@@ -123,6 +123,19 @@ export interface ActionRunContext {
|
|
|
123
123
|
turnId?: string;
|
|
124
124
|
}
|
|
125
125
|
|
|
126
|
+
/**
|
|
127
|
+
* Pre-run authorization gate. Throw to deny with a specific message (the
|
|
128
|
+
* framework's `ForbiddenError` carries a 403), or return `false` for a generic
|
|
129
|
+
* denial. Returning `undefined` allows the call — a guard that forgets to
|
|
130
|
+
* return is therefore permissive, which is why `false` is honoured at all:
|
|
131
|
+
* `(args) => someCheck(args)` written against a boolean helper would otherwise
|
|
132
|
+
* pass silently on every denial.
|
|
133
|
+
*/
|
|
134
|
+
export type ActionAuthorize<TArgs> = (
|
|
135
|
+
args: TArgs,
|
|
136
|
+
ctx?: ActionRunContext,
|
|
137
|
+
) => void | boolean | Promise<void | boolean>;
|
|
138
|
+
|
|
126
139
|
export interface AgentActionStopOptions {
|
|
127
140
|
/** Optional stable code surfaced in run metadata and tests. */
|
|
128
141
|
errorCode?: string;
|
|
@@ -466,6 +479,30 @@ interface DefineActionWithSchema<
|
|
|
466
479
|
args: StandardSchemaV1.InferOutput<TSchema>,
|
|
467
480
|
ctx?: ActionRunContext,
|
|
468
481
|
) => boolean | Promise<boolean>);
|
|
482
|
+
/**
|
|
483
|
+
* Authorization gate that runs before `run()` on **every** caller — agent
|
|
484
|
+
* tool, HTTP, frontend, MCP, A2A, and CLI. It wraps `run` itself rather than
|
|
485
|
+
* hanging off the action entry, because a flag consulted by the dispatcher
|
|
486
|
+
* only guards the dispatchers that remember to consult it.
|
|
487
|
+
*
|
|
488
|
+
* This is *authorization*, not approval: `needsApproval` asks a human to
|
|
489
|
+
* bless one call the caller is already allowed to make, while `authorize`
|
|
490
|
+
* decides whether they are allowed at all. It also does not replace
|
|
491
|
+
* `accessFilter` / `assertAccess` — those scope which rows a permitted caller
|
|
492
|
+
* may see; this decides whether the operation is open to them.
|
|
493
|
+
*
|
|
494
|
+
* ```ts
|
|
495
|
+
* import { coachAccess } from "../lib/access.js";
|
|
496
|
+
*
|
|
497
|
+
* export default defineAction({
|
|
498
|
+
* description: "Archive a training plan.",
|
|
499
|
+
* schema,
|
|
500
|
+
* authorize: coachAccess.requireAny("coach-admin"),
|
|
501
|
+
* run: async (args) => { ... },
|
|
502
|
+
* });
|
|
503
|
+
* ```
|
|
504
|
+
*/
|
|
505
|
+
authorize?: ActionAuthorize<StandardSchemaV1.InferOutput<TSchema>>;
|
|
469
506
|
/**
|
|
470
507
|
* Audit-log configuration. **Default-on for mutating actions** — you only
|
|
471
508
|
* need this to tune capture: declare the mutated `target` (so the change
|
|
@@ -556,6 +593,9 @@ interface DefineActionWithParams<
|
|
|
556
593
|
args: InferParams<TParams>,
|
|
557
594
|
ctx?: ActionRunContext,
|
|
558
595
|
) => boolean | Promise<boolean>);
|
|
596
|
+
/** Pre-run authorization gate applied to every caller. See the schema
|
|
597
|
+
* overload above for full semantics. */
|
|
598
|
+
authorize?: ActionAuthorize<InferParams<TParams>>;
|
|
559
599
|
/** Audit-log configuration (default-on for mutations). See the schema
|
|
560
600
|
* overload above and the `audit-log` skill. */
|
|
561
601
|
audit?: ActionAuditConfig;
|
|
@@ -714,12 +754,21 @@ export function defineAction(options: any) {
|
|
|
714
754
|
);
|
|
715
755
|
}
|
|
716
756
|
|
|
757
|
+
// Authorization sits INSIDE input validation, so a gate that inspects `args`
|
|
758
|
+
// is handed the parsed, coerced value its type promises rather than whatever
|
|
759
|
+
// shape the caller sent. Putting it outside would have every guard reading
|
|
760
|
+
// attacker-shaped input while typed as though it were validated.
|
|
761
|
+
const guardedRun =
|
|
762
|
+
typeof options.authorize === "function"
|
|
763
|
+
? wrapRunWithAuthorize(options.run, options.authorize)
|
|
764
|
+
: options.run;
|
|
765
|
+
|
|
717
766
|
// Wrap run() with INPUT validation when schema is provided.
|
|
718
767
|
// Pass toolParameters so the validation error can echo the expected signature
|
|
719
768
|
// (required vs optional fields) and help the caller self-correct.
|
|
720
769
|
const inputValidatedRun = hasSchema
|
|
721
|
-
? wrapWithValidation(options.schema,
|
|
722
|
-
:
|
|
770
|
+
? wrapWithValidation(options.schema, guardedRun, toolParameters)
|
|
771
|
+
: guardedRun;
|
|
723
772
|
|
|
724
773
|
// Then wrap with OUTPUT validation when an outputSchema is provided. This
|
|
725
774
|
// composes AROUND the input-validated run so the order is: validate input →
|
|
@@ -877,6 +926,38 @@ export function defineAction(options: any) {
|
|
|
877
926
|
};
|
|
878
927
|
}
|
|
879
928
|
|
|
929
|
+
/**
|
|
930
|
+
* Wrap an action's run with its `authorize` gate.
|
|
931
|
+
*
|
|
932
|
+
* The gate is applied here, around `run`, rather than exposed as a flag on the
|
|
933
|
+
* action entry: `run` is the one thing all six dispatch sites (agent loop, HTTP
|
|
934
|
+
* route, frontend, MCP, A2A, CLI) go through, so there is no caller that can
|
|
935
|
+
* reach the body without passing the check. `needsApproval` took the flag route
|
|
936
|
+
* and is consequently honoured only inside the agent loop.
|
|
937
|
+
*
|
|
938
|
+
* Composed so the full order is: validate input → authorize → run → validate
|
|
939
|
+
* output → audit. The audit wrapper is outermost, so a denial is still recorded
|
|
940
|
+
* as an attempt — which is precisely what an audit trail is for.
|
|
941
|
+
*
|
|
942
|
+
* A guard that throws denies with its own message. A guard that returns `false`
|
|
943
|
+
* denies generically. Anything else — including `undefined` — allows.
|
|
944
|
+
*/
|
|
945
|
+
function wrapRunWithAuthorize(
|
|
946
|
+
run: (args: any, ctx?: ActionRunContext) => any,
|
|
947
|
+
authorize: ActionAuthorize<any>,
|
|
948
|
+
): (args: any, ctx?: ActionRunContext) => Promise<any> {
|
|
949
|
+
return async function authorizedRun(args: any, ctx?: ActionRunContext) {
|
|
950
|
+
const verdict = await authorize(args, ctx);
|
|
951
|
+
if (verdict === false) {
|
|
952
|
+
const err = new Error("Not authorized") as Error & { statusCode: number };
|
|
953
|
+
err.name = "ForbiddenError";
|
|
954
|
+
err.statusCode = 403;
|
|
955
|
+
throw err;
|
|
956
|
+
}
|
|
957
|
+
return run(args, ctx);
|
|
958
|
+
};
|
|
959
|
+
}
|
|
960
|
+
|
|
880
961
|
/**
|
|
881
962
|
* Wrap an action's (already input/output-validated) run so each call records an
|
|
882
963
|
* audit event after it resolves — on success and on error. Best-effort: the
|
|
@@ -159,9 +159,6 @@ async function ensureTable(): Promise<void> {
|
|
|
159
159
|
"chat_thread_shares_resource_idx",
|
|
160
160
|
CHAT_THREAD_SHARES_RESOURCE_INDEX_SQL,
|
|
161
161
|
);
|
|
162
|
-
// One-time backfill of message_count for legacy rows written before
|
|
163
|
-
// the column was maintained.
|
|
164
|
-
await backfillLegacyMessageCounts(client);
|
|
165
162
|
return;
|
|
166
163
|
}
|
|
167
164
|
|
|
@@ -221,15 +218,6 @@ async function ensureTable(): Promise<void> {
|
|
|
221
218
|
// Index already exists or the dialect rejected a duplicate.
|
|
222
219
|
}
|
|
223
220
|
}
|
|
224
|
-
// One-time backfill of message_count for legacy rows written before
|
|
225
|
-
// the column was maintained. The list/summary path now reads
|
|
226
|
-
// message_count directly (instead of re-parsing the thread_data blob)
|
|
227
|
-
// and filters on `message_count > 0`, so any legacy row that has
|
|
228
|
-
// messages but a stale `message_count = 0` would otherwise vanish from
|
|
229
|
-
// the sidebar. Recompute the count from thread_data and persist it so
|
|
230
|
-
// the hot path can stay blob-free. Idempotent: only touches rows where
|
|
231
|
-
// the count is still 0 but the blob clearly contains a messages array.
|
|
232
|
-
await backfillLegacyMessageCounts(client);
|
|
233
221
|
})().catch((err) => {
|
|
234
222
|
// Retry init on the next call after a failed startup.
|
|
235
223
|
_initPromise = undefined;
|
|
@@ -240,28 +228,47 @@ async function ensureTable(): Promise<void> {
|
|
|
240
228
|
}
|
|
241
229
|
|
|
242
230
|
/**
|
|
243
|
-
*
|
|
244
|
-
*
|
|
245
|
-
*
|
|
246
|
-
*
|
|
247
|
-
* those rows disappear from the sidebar. Runs once at table bootstrap and is
|
|
248
|
-
* idempotent — after the first pass no row matches the WHERE clause again.
|
|
231
|
+
* Explicitly repair `message_count` for legacy rows written before the count
|
|
232
|
+
* was maintained. This must never run from table/bootstrap initialization:
|
|
233
|
+
* serverless isolates would each scan the full `thread_data` blob column on
|
|
234
|
+
* cold start. Operators may invoke it once when upgrading an old database.
|
|
249
235
|
*/
|
|
250
|
-
async function
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
236
|
+
export async function repairLegacyChatThreadMessageCounts(
|
|
237
|
+
options: {
|
|
238
|
+
batchSize?: number;
|
|
239
|
+
} = {},
|
|
240
|
+
): Promise<{ scanned: number; updated: number }> {
|
|
241
|
+
await ensureTable();
|
|
242
|
+
const client = getDbExec();
|
|
243
|
+
const batchSize = Math.max(1, Math.min(options.batchSize ?? 100, 1_000));
|
|
244
|
+
let afterId = "";
|
|
245
|
+
let scanned = 0;
|
|
246
|
+
let updated = 0;
|
|
247
|
+
while (true) {
|
|
248
|
+
const { rows } = await client.execute({
|
|
249
|
+
sql: `SELECT id, thread_data, message_count FROM chat_threads
|
|
250
|
+
WHERE message_count = 0
|
|
251
|
+
AND thread_data LIKE '%"messages"%'
|
|
252
|
+
AND id > ?
|
|
253
|
+
ORDER BY id
|
|
254
|
+
LIMIT ?`,
|
|
255
|
+
args: [afterId, batchSize],
|
|
263
256
|
});
|
|
257
|
+
if (rows.length === 0) break;
|
|
258
|
+
for (const row of rows) {
|
|
259
|
+
afterId = String(row.id);
|
|
260
|
+
scanned++;
|
|
261
|
+
const count = deriveMessageCount(row.thread_data, 0);
|
|
262
|
+
if (count <= 0) continue;
|
|
263
|
+
const result = await client.execute({
|
|
264
|
+
sql: `UPDATE chat_threads SET message_count = ? WHERE id = ? AND message_count = 0`,
|
|
265
|
+
args: [count, afterId],
|
|
266
|
+
});
|
|
267
|
+
if (result.rowsAffected > 0) updated++;
|
|
268
|
+
}
|
|
269
|
+
if (rows.length < batchSize) break;
|
|
264
270
|
}
|
|
271
|
+
return { scanned, updated };
|
|
265
272
|
}
|
|
266
273
|
|
|
267
274
|
function generateId(): string {
|
|
@@ -407,8 +414,8 @@ function rowToThread(r: Record<string, unknown>): ChatThread {
|
|
|
407
414
|
|
|
408
415
|
function rowToSummary(r: Record<string, unknown>): ChatThreadSummary | null {
|
|
409
416
|
// The summary path never loads `thread_data`; the count comes from the
|
|
410
|
-
// dedicated `message_count` column
|
|
411
|
-
//
|
|
417
|
+
// dedicated `message_count` column maintained on write. Empty threads are
|
|
418
|
+
// filtered out of the list.
|
|
412
419
|
const messageCount = Number(r.message_count);
|
|
413
420
|
if (!Number.isFinite(messageCount) || messageCount <= 0) return null;
|
|
414
421
|
return {
|
|
@@ -475,9 +482,8 @@ const THREAD_COLUMNS = `id, owner_email, title, preview, thread_data, message_co
|
|
|
475
482
|
// message-history JSON blob and selecting it for every row turns "open the
|
|
476
483
|
// sidebar" into "download every conversation". The summary derives nothing
|
|
477
484
|
// from the blob anymore — preview and message_count are dedicated columns
|
|
478
|
-
// (message_count is maintained on write
|
|
479
|
-
//
|
|
480
|
-
// the full blob.
|
|
485
|
+
// (message_count is maintained on write). The detail path (`THREAD_COLUMNS` /
|
|
486
|
+
// `getThread`) still returns the full blob.
|
|
481
487
|
const SUMMARY_COLUMNS = `id, title, preview, message_count, created_at, updated_at, scope_type, scope_id, scope_label, pinned_at, archived_at, org_id, visibility`;
|
|
482
488
|
|
|
483
489
|
export function registerChatThreadsShareable(): void {
|
|
@@ -684,10 +690,9 @@ export async function listThreads(
|
|
|
684
690
|
const limit = opts.limit ?? 50;
|
|
685
691
|
const offset = opts.offset ?? 0;
|
|
686
692
|
const client = getDbExec();
|
|
687
|
-
// `message_count > 0` is the authoritative "has messages" signal
|
|
688
|
-
//
|
|
689
|
-
//
|
|
690
|
-
// full blob is no longer needed here.
|
|
693
|
+
// `message_count > 0` is the authoritative "has messages" signal maintained
|
|
694
|
+
// on every write, so the old `OR thread_data LIKE '%"messages"%'` substring
|
|
695
|
+
// scan over the full blob is no longer needed here.
|
|
691
696
|
const access = chatThreadAccessSql(
|
|
692
697
|
ownerEmail,
|
|
693
698
|
opts.orgId ?? getRequestOrgId(),
|
|
@@ -731,9 +736,9 @@ export async function searchThreads(
|
|
|
731
736
|
await ensureTable();
|
|
732
737
|
const client = getDbExec();
|
|
733
738
|
const pattern = `%${escapeLike(query)}%`;
|
|
734
|
-
// The count-guard uses the maintained
|
|
735
|
-
//
|
|
736
|
-
//
|
|
739
|
+
// The count-guard uses the maintained `message_count` column (same as
|
|
740
|
+
// listThreads). The content match still scans `thread_data` — search
|
|
741
|
+
// legitimately needs to look inside message history.
|
|
737
742
|
const access = chatThreadAccessSql(
|
|
738
743
|
ownerEmail,
|
|
739
744
|
options.orgId ?? getRequestOrgId(),
|
|
@@ -25,6 +25,32 @@ hosted Design MCP connector together. The open Skills CLI path
|
|
|
25
25
|
(\`npx skills@latest add BuilderIO/agent-native --skill visual-edit\`) installs
|
|
26
26
|
exported instructions only, with no MCP connector registration.
|
|
27
27
|
|
|
28
|
+
## Put Design Beside The Chat
|
|
29
|
+
|
|
30
|
+
After \`open-visual-edit\` returns \`openUrl\`, open that URL in the coding host's
|
|
31
|
+
inline browser when one is available. This is the preferred working surface:
|
|
32
|
+
the user can keep Design's canvas beside the conversation, inspect the same
|
|
33
|
+
screens as the agent, and iterate without switching apps.
|
|
34
|
+
|
|
35
|
+
- In Codex Desktop, use the in-app Browser tool to open \`openUrl\`. The built-in
|
|
36
|
+
browser is the right surface for localhost and public pages that should stay
|
|
37
|
+
inside the app.
|
|
38
|
+
- In Claude Code Desktop's Code tab, open or preview \`openUrl\` in the Browser
|
|
39
|
+
pane. Ask Claude to preview it rather than opening the system browser.
|
|
40
|
+
- In VS Code, use the Agent Native Design webview/deep link described below.
|
|
41
|
+
- Inline browser availability is host-dependent. CLI, remote, or restricted
|
|
42
|
+
sessions may not expose one. If the inline surface is unavailable or disabled,
|
|
43
|
+
return the normal **Open design** link instead of claiming it opened.
|
|
44
|
+
|
|
45
|
+
Prefer the host's browser/preview tool over telling the user to press a keyboard
|
|
46
|
+
shortcut. Keep the canvas pane beside chat when the host supports rearrangeable
|
|
47
|
+
panes.
|
|
48
|
+
|
|
49
|
+
Inside Design, use **Show/Hide UI** from the \`Cmd+K\` menu or press
|
|
50
|
+
\`Cmd+Shift+\\\` on Apple platforms / \`Ctrl+Shift+\\\` elsewhere to toggle all
|
|
51
|
+
editing chrome so only the canvas remains. The same action is available from
|
|
52
|
+
Design's empty-canvas context menu.
|
|
53
|
+
|
|
28
54
|
## Core Model
|
|
29
55
|
|
|
30
56
|
- Each screen is a URL-backed iframe, not copied HTML.
|
|
@@ -54,6 +80,23 @@ exported instructions only, with no MCP connector registration.
|
|
|
54
80
|
\`localhost:1234/onboarding/1\` means
|
|
55
81
|
\`http://localhost:1234/onboarding/1\`.
|
|
56
82
|
|
|
83
|
+
## Useful Canvas Sets
|
|
84
|
+
|
|
85
|
+
Translate the user's requested review into the smallest useful set of frames:
|
|
86
|
+
|
|
87
|
+
- **Multi-step flow:** one ordered frame per route or query state, such as cart,
|
|
88
|
+
shipping, payment, and confirmation.
|
|
89
|
+
- **Multiple pages:** one frame per meaningful route, such as home, pricing,
|
|
90
|
+
docs, and account settings.
|
|
91
|
+
- **Responsive comparison:** repeat the same route at the requested desktop,
|
|
92
|
+
tablet, and mobile viewports so they align in one row.
|
|
93
|
+
- **State review:** repeat a route for meaningful URL-addressable states such as
|
|
94
|
+
empty, loading, error, modal-open, or selected-item views.
|
|
95
|
+
|
|
96
|
+
Do not expand every discovered route or every viewport unless the user asks for
|
|
97
|
+
an exhaustive audit. Preserve the user's labels and sequence so the canvas reads
|
|
98
|
+
like the workflow they described.
|
|
99
|
+
|
|
57
100
|
## Select And Reprompt
|
|
58
101
|
|
|
59
102
|
When a chat message begins with \`[Reprompt selection]\`, the selected subtree is
|
|
@@ -275,9 +318,9 @@ Fallback, only when \`open-visual-edit\` is unavailable:
|
|
|
275
318
|
## Open The Design Surface
|
|
276
319
|
|
|
277
320
|
- Use the \`link\`, \`deepLink\`, or MCP App embed returned by Design actions so
|
|
278
|
-
the user sees the canvas.
|
|
279
|
-
|
|
280
|
-
|
|
321
|
+
the user sees the canvas. Follow **Put Design Beside The Chat**: prefer the
|
|
322
|
+
host's inline Browser, preview, or webview panel; otherwise surface the
|
|
323
|
+
**Open design** link.
|
|
281
324
|
- Return or open the \`openUrl\` / action link, not a hand-built
|
|
282
325
|
\`/design/:id?_session=...\` URL.
|
|
283
326
|
- If the user is working in VS Code, the Agent Native extension can open the
|
|
@@ -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;
|