@agent-native/core 0.14.8 → 0.15.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/README.md +1 -1
- package/dist/agent/engine/builder-engine.d.ts.map +1 -1
- package/dist/agent/engine/builder-engine.js +30 -9
- package/dist/agent/engine/builder-engine.js.map +1 -1
- package/dist/agent/engine/registry.d.ts.map +1 -1
- package/dist/agent/engine/registry.js +14 -4
- package/dist/agent/engine/registry.js.map +1 -1
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +71 -4
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/agent/types.d.ts +9 -0
- package/dist/agent/types.d.ts.map +1 -1
- package/dist/agent/types.js.map +1 -1
- package/dist/appearance/actions/change-appearance.d.ts +3 -0
- package/dist/appearance/actions/change-appearance.d.ts.map +1 -0
- package/dist/appearance/actions/change-appearance.js +29 -0
- package/dist/appearance/actions/change-appearance.js.map +1 -0
- package/dist/chat-threads/store.d.ts +53 -2
- package/dist/chat-threads/store.d.ts.map +1 -1
- package/dist/chat-threads/store.js +172 -12
- package/dist/chat-threads/store.js.map +1 -1
- package/dist/cli/create.d.ts.map +1 -1
- package/dist/cli/create.js +114 -37
- package/dist/cli/create.js.map +1 -1
- package/dist/cli/index.js +30 -4
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/workspace-dev.d.ts +25 -1
- package/dist/cli/workspace-dev.d.ts.map +1 -1
- package/dist/cli/workspace-dev.js +275 -49
- package/dist/cli/workspace-dev.js.map +1 -1
- package/dist/client/AgentPanel.d.ts +23 -4
- package/dist/client/AgentPanel.d.ts.map +1 -1
- package/dist/client/AgentPanel.js +276 -53
- package/dist/client/AgentPanel.js.map +1 -1
- package/dist/client/AppearancePicker.d.ts +11 -0
- package/dist/client/AppearancePicker.d.ts.map +1 -0
- package/dist/client/AppearancePicker.js +16 -0
- package/dist/client/AppearancePicker.js.map +1 -0
- package/dist/client/AssistantChat.d.ts +35 -0
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +315 -32
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/ConnectBuilderCard.d.ts.map +1 -1
- package/dist/client/ConnectBuilderCard.js +5 -2
- package/dist/client/ConnectBuilderCard.js.map +1 -1
- package/dist/client/ErrorBoundary.d.ts.map +1 -1
- package/dist/client/ErrorBoundary.js +8 -10
- package/dist/client/ErrorBoundary.js.map +1 -1
- package/dist/client/FeedbackButton.d.ts.map +1 -1
- package/dist/client/FeedbackButton.js +1 -1
- package/dist/client/FeedbackButton.js.map +1 -1
- package/dist/client/MultiTabAssistantChat.d.ts +13 -1
- package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
- package/dist/client/MultiTabAssistantChat.js +217 -38
- package/dist/client/MultiTabAssistantChat.js.map +1 -1
- package/dist/client/NewWorkspaceAppFlow.d.ts.map +1 -1
- package/dist/client/NewWorkspaceAppFlow.js +37 -14
- package/dist/client/NewWorkspaceAppFlow.js.map +1 -1
- package/dist/client/agent-chat-adapter.d.ts +5 -0
- package/dist/client/agent-chat-adapter.d.ts.map +1 -1
- package/dist/client/agent-chat-adapter.js +4 -0
- package/dist/client/agent-chat-adapter.js.map +1 -1
- package/dist/client/agent-sidebar-state.d.ts +12 -0
- package/dist/client/agent-sidebar-state.d.ts.map +1 -1
- package/dist/client/agent-sidebar-state.js +8 -0
- package/dist/client/agent-sidebar-state.js.map +1 -1
- package/dist/client/analytics.d.ts.map +1 -1
- package/dist/client/analytics.js +175 -3
- package/dist/client/analytics.js.map +1 -1
- package/dist/client/appearance.d.ts +40 -0
- package/dist/client/appearance.d.ts.map +1 -0
- package/dist/client/appearance.js +114 -0
- package/dist/client/appearance.js.map +1 -0
- package/dist/client/builder-frame.d.ts +1 -0
- package/dist/client/builder-frame.d.ts.map +1 -1
- package/dist/client/builder-frame.js +19 -9
- package/dist/client/builder-frame.js.map +1 -1
- package/dist/client/components/CodeRequiredDialog.d.ts.map +1 -1
- package/dist/client/components/CodeRequiredDialog.js +10 -2
- package/dist/client/components/CodeRequiredDialog.js.map +1 -1
- package/dist/client/components/ui/dropdown-menu.js +2 -2
- package/dist/client/components/ui/dropdown-menu.js.map +1 -1
- package/dist/client/components/ui/hover-card.js +1 -1
- package/dist/client/components/ui/hover-card.js.map +1 -1
- package/dist/client/components/ui/popover.js +1 -1
- package/dist/client/components/ui/popover.js.map +1 -1
- package/dist/client/composer/PromptComposer.d.ts +7 -0
- package/dist/client/composer/PromptComposer.d.ts.map +1 -1
- package/dist/client/composer/PromptComposer.js +63 -32
- package/dist/client/composer/PromptComposer.js.map +1 -1
- package/dist/client/composer/TiptapComposer.d.ts +5 -0
- package/dist/client/composer/TiptapComposer.d.ts.map +1 -1
- package/dist/client/composer/TiptapComposer.js +36 -6
- package/dist/client/composer/TiptapComposer.js.map +1 -1
- package/dist/client/composer/useVoiceDictation.d.ts.map +1 -1
- package/dist/client/composer/useVoiceDictation.js +13 -1
- package/dist/client/composer/useVoiceDictation.js.map +1 -1
- package/dist/client/error-format.d.ts +3 -2
- package/dist/client/error-format.d.ts.map +1 -1
- package/dist/client/error-format.js +9 -2
- package/dist/client/error-format.js.map +1 -1
- package/dist/client/extensions/ExtensionViewer.d.ts.map +1 -1
- package/dist/client/extensions/ExtensionViewer.js +24 -2
- package/dist/client/extensions/ExtensionViewer.js.map +1 -1
- package/dist/client/index.d.ts +8 -1
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +7 -0
- package/dist/client/index.js.map +1 -1
- package/dist/client/onboarding/OnboardingPanel.js +1 -0
- package/dist/client/onboarding/OnboardingPanel.js.map +1 -1
- package/dist/client/org/InvitationBanner.d.ts.map +1 -1
- package/dist/client/org/InvitationBanner.js +23 -2
- package/dist/client/org/InvitationBanner.js.map +1 -1
- package/dist/client/org/OrgSwitcher.d.ts +5 -4
- package/dist/client/org/OrgSwitcher.d.ts.map +1 -1
- package/dist/client/org/OrgSwitcher.js +57 -9
- package/dist/client/org/OrgSwitcher.js.map +1 -1
- package/dist/client/org/hooks.d.ts.map +1 -1
- package/dist/client/org/hooks.js +10 -6
- package/dist/client/org/hooks.js.map +1 -1
- package/dist/client/org/workspace-app-links.d.ts +31 -0
- package/dist/client/org/workspace-app-links.d.ts.map +1 -0
- package/dist/client/org/workspace-app-links.js +268 -0
- package/dist/client/org/workspace-app-links.js.map +1 -0
- package/dist/client/resources/ResourcesPanel.d.ts.map +1 -1
- package/dist/client/resources/ResourcesPanel.js +18 -5
- package/dist/client/resources/ResourcesPanel.js.map +1 -1
- package/dist/client/resources/use-resources.d.ts +18 -13
- package/dist/client/resources/use-resources.d.ts.map +1 -1
- package/dist/client/resources/use-resources.js +24 -6
- package/dist/client/resources/use-resources.js.map +1 -1
- package/dist/client/settings/BackgroundAgentSection.d.ts.map +1 -1
- package/dist/client/settings/BackgroundAgentSection.js +9 -1
- package/dist/client/settings/BackgroundAgentSection.js.map +1 -1
- package/dist/client/settings/BrowserSection.d.ts.map +1 -1
- package/dist/client/settings/BrowserSection.js +16 -1
- package/dist/client/settings/BrowserSection.js.map +1 -1
- package/dist/client/settings/SettingsPanel.d.ts.map +1 -1
- package/dist/client/settings/SettingsPanel.js +4 -1
- package/dist/client/settings/SettingsPanel.js.map +1 -1
- package/dist/client/settings/VoiceTranscriptionSection.d.ts.map +1 -1
- package/dist/client/settings/VoiceTranscriptionSection.js +5 -5
- package/dist/client/settings/VoiceTranscriptionSection.js.map +1 -1
- package/dist/client/settings/useBuilderStatus.d.ts +8 -0
- package/dist/client/settings/useBuilderStatus.d.ts.map +1 -1
- package/dist/client/settings/useBuilderStatus.js +50 -13
- package/dist/client/settings/useBuilderStatus.js.map +1 -1
- package/dist/client/settings/useBuilderStatus.spec.d.ts +2 -0
- package/dist/client/settings/useBuilderStatus.spec.d.ts.map +1 -0
- package/dist/client/settings/useBuilderStatus.spec.js +64 -0
- package/dist/client/settings/useBuilderStatus.spec.js.map +1 -0
- package/dist/client/sharing/ShareButton.d.ts +5 -0
- package/dist/client/sharing/ShareButton.d.ts.map +1 -1
- package/dist/client/sharing/ShareButton.js +60 -6
- package/dist/client/sharing/ShareButton.js.map +1 -1
- package/dist/client/theme.js +1 -1
- package/dist/client/theme.js.map +1 -1
- package/dist/client/transcription/BuilderTranscriptionCta.d.ts.map +1 -1
- package/dist/client/transcription/BuilderTranscriptionCta.js +2 -3
- package/dist/client/transcription/BuilderTranscriptionCta.js.map +1 -1
- package/dist/client/use-change-version.d.ts +46 -0
- package/dist/client/use-change-version.d.ts.map +1 -0
- package/dist/client/use-change-version.js +135 -0
- package/dist/client/use-change-version.js.map +1 -0
- package/dist/client/use-chat-threads.d.ts +16 -2
- package/dist/client/use-chat-threads.d.ts.map +1 -1
- package/dist/client/use-chat-threads.js +87 -12
- package/dist/client/use-chat-threads.js.map +1 -1
- package/dist/client/use-chat-threads.spec.d.ts +2 -0
- package/dist/client/use-chat-threads.spec.d.ts.map +1 -0
- package/dist/client/use-chat-threads.spec.js +85 -0
- package/dist/client/use-chat-threads.spec.js.map +1 -0
- package/dist/client/use-db-sync.d.ts +5 -2
- package/dist/client/use-db-sync.d.ts.map +1 -1
- package/dist/client/use-db-sync.js +41 -16
- package/dist/client/use-db-sync.js.map +1 -1
- package/dist/client/use-pinch-zoom.d.ts +35 -0
- package/dist/client/use-pinch-zoom.d.ts.map +1 -0
- package/dist/client/use-pinch-zoom.js +105 -0
- package/dist/client/use-pinch-zoom.js.map +1 -0
- package/dist/deploy/workspace-deploy.d.ts.map +1 -1
- package/dist/deploy/workspace-deploy.js +99 -5
- package/dist/deploy/workspace-deploy.js.map +1 -1
- package/dist/extensions/actions.d.ts.map +1 -1
- package/dist/extensions/actions.js +3 -0
- package/dist/extensions/actions.js.map +1 -1
- package/dist/extensions/store.d.ts +5 -0
- package/dist/extensions/store.d.ts.map +1 -1
- package/dist/extensions/store.js +16 -1
- package/dist/extensions/store.js.map +1 -1
- package/dist/file-upload/actions/upload-image.d.ts +3 -0
- package/dist/file-upload/actions/upload-image.d.ts.map +1 -0
- package/dist/file-upload/actions/upload-image.js +145 -0
- package/dist/file-upload/actions/upload-image.js.map +1 -0
- package/dist/file-upload/builder.d.ts.map +1 -1
- package/dist/file-upload/builder.js +31 -11
- package/dist/file-upload/builder.js.map +1 -1
- package/dist/file-upload/index.d.ts +1 -0
- package/dist/file-upload/index.d.ts.map +1 -1
- package/dist/file-upload/index.js +1 -0
- package/dist/file-upload/index.js.map +1 -1
- package/dist/file-upload/pre-upload-attachments.d.ts +39 -0
- package/dist/file-upload/pre-upload-attachments.d.ts.map +1 -0
- package/dist/file-upload/pre-upload-attachments.js +110 -0
- package/dist/file-upload/pre-upload-attachments.js.map +1 -0
- package/dist/file-upload/registry.d.ts.map +1 -1
- package/dist/file-upload/registry.js +8 -7
- package/dist/file-upload/registry.js.map +1 -1
- package/dist/onboarding/default-steps.js +1 -1
- package/dist/onboarding/default-steps.js.map +1 -1
- package/dist/org/context.d.ts +15 -1
- package/dist/org/context.d.ts.map +1 -1
- package/dist/org/context.js +25 -0
- package/dist/org/context.js.map +1 -1
- package/dist/org/handlers.d.ts +2 -2
- package/dist/org/handlers.d.ts.map +1 -1
- package/dist/org/handlers.js +3 -17
- package/dist/org/handlers.js.map +1 -1
- package/dist/org/index.d.ts +1 -1
- package/dist/org/index.d.ts.map +1 -1
- package/dist/org/index.js +1 -1
- package/dist/org/index.js.map +1 -1
- package/dist/resources/handlers.d.ts +6 -0
- package/dist/resources/handlers.d.ts.map +1 -1
- package/dist/resources/handlers.js +30 -6
- package/dist/resources/handlers.js.map +1 -1
- package/dist/resources/script-helpers.d.ts +11 -2
- package/dist/resources/script-helpers.d.ts.map +1 -1
- package/dist/resources/script-helpers.js +20 -3
- package/dist/resources/script-helpers.js.map +1 -1
- package/dist/resources/store.d.ts +28 -3
- package/dist/resources/store.d.ts.map +1 -1
- package/dist/resources/store.js +170 -20
- package/dist/resources/store.js.map +1 -1
- package/dist/scripts/resources/list.d.ts +1 -1
- package/dist/scripts/resources/list.d.ts.map +1 -1
- package/dist/scripts/resources/list.js +16 -4
- package/dist/scripts/resources/list.js.map +1 -1
- package/dist/scripts/resources/write.d.ts +1 -1
- package/dist/scripts/resources/write.d.ts.map +1 -1
- package/dist/scripts/resources/write.js +47 -3
- package/dist/scripts/resources/write.js.map +1 -1
- package/dist/server/action-discovery.d.ts.map +1 -1
- package/dist/server/action-discovery.js +8 -3
- package/dist/server/action-discovery.js.map +1 -1
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +214 -25
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/agent-discovery.d.ts +35 -0
- package/dist/server/agent-discovery.d.ts.map +1 -1
- package/dist/server/agent-discovery.js +139 -8
- package/dist/server/agent-discovery.js.map +1 -1
- package/dist/server/app-url.d.ts +12 -6
- package/dist/server/app-url.d.ts.map +1 -1
- package/dist/server/app-url.js +58 -11
- package/dist/server/app-url.js.map +1 -1
- package/dist/server/auth.d.ts +22 -0
- package/dist/server/auth.d.ts.map +1 -1
- package/dist/server/auth.js +272 -59
- package/dist/server/auth.js.map +1 -1
- package/dist/server/better-auth-instance.d.ts +0 -4
- package/dist/server/better-auth-instance.d.ts.map +1 -1
- package/dist/server/better-auth-instance.js +0 -3
- package/dist/server/better-auth-instance.js.map +1 -1
- package/dist/server/builder-browser.d.ts.map +1 -1
- package/dist/server/builder-browser.js +23 -0
- package/dist/server/builder-browser.js.map +1 -1
- package/dist/server/core-routes-plugin.d.ts.map +1 -1
- package/dist/server/core-routes-plugin.js +29 -14
- package/dist/server/core-routes-plugin.js.map +1 -1
- package/dist/server/credential-provider.d.ts +14 -0
- package/dist/server/credential-provider.d.ts.map +1 -1
- package/dist/server/credential-provider.js +88 -11
- package/dist/server/credential-provider.js.map +1 -1
- package/dist/server/google-auth-plugin.d.ts.map +1 -1
- package/dist/server/google-auth-plugin.js +53 -13
- package/dist/server/google-auth-plugin.js.map +1 -1
- package/dist/server/google-oauth.d.ts.map +1 -1
- package/dist/server/google-oauth.js +47 -17
- package/dist/server/google-oauth.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/oauth-public-origin.d.ts.map +1 -1
- package/dist/server/oauth-public-origin.js +19 -1
- package/dist/server/oauth-public-origin.js.map +1 -1
- package/dist/server/onboarding-html.d.ts.map +1 -1
- package/dist/server/onboarding-html.js +62 -15
- package/dist/server/onboarding-html.js.map +1 -1
- package/dist/server/poll.d.ts.map +1 -1
- package/dist/server/poll.js +20 -5
- package/dist/server/poll.js.map +1 -1
- package/dist/server/request-context.d.ts +8 -0
- package/dist/server/request-context.d.ts.map +1 -1
- package/dist/server/request-context.js.map +1 -1
- package/dist/shared/index.d.ts +2 -0
- package/dist/shared/index.d.ts.map +1 -1
- package/dist/shared/index.js +2 -0
- package/dist/shared/index.js.map +1 -1
- package/dist/shared/llm-connection.d.ts +10 -0
- package/dist/shared/llm-connection.d.ts.map +1 -0
- package/dist/shared/llm-connection.js +29 -0
- package/dist/shared/llm-connection.js.map +1 -0
- package/dist/shared/workspace-app-audience.d.ts +25 -0
- package/dist/shared/workspace-app-audience.d.ts.map +1 -0
- package/dist/shared/workspace-app-audience.js +126 -0
- package/dist/shared/workspace-app-audience.js.map +1 -0
- package/dist/shared/workspace-app-id.d.ts +1 -1
- package/dist/shared/workspace-app-id.d.ts.map +1 -1
- package/dist/shared/workspace-app-id.js +1 -0
- package/dist/shared/workspace-app-id.js.map +1 -1
- package/dist/sharing/access.d.ts.map +1 -1
- package/dist/sharing/access.js +46 -5
- package/dist/sharing/access.js.map +1 -1
- package/dist/sharing/actions/list-resource-shares.d.ts.map +1 -1
- package/dist/sharing/actions/list-resource-shares.js +8 -1
- package/dist/sharing/actions/list-resource-shares.js.map +1 -1
- package/dist/sharing/actions/set-resource-visibility.d.ts.map +1 -1
- package/dist/sharing/actions/set-resource-visibility.js +12 -3
- package/dist/sharing/actions/set-resource-visibility.js.map +1 -1
- package/dist/sharing/actions/share-resource.d.ts.map +1 -1
- package/dist/sharing/actions/share-resource.js +50 -1
- package/dist/sharing/actions/share-resource.js.map +1 -1
- package/dist/sharing/registry.d.ts +26 -0
- package/dist/sharing/registry.d.ts.map +1 -1
- package/dist/sharing/registry.js.map +1 -1
- package/dist/styles/agent-native.css +91 -0
- package/dist/templates/default/.agents/skills/adding-a-feature/SKILL.md +72 -0
- package/dist/templates/default/.agents/skills/frontend-design/SKILL.md +60 -37
- package/dist/templates/default/.agents/skills/real-time-sync/SKILL.md +28 -17
- package/dist/templates/default/.agents/skills/shadcn-ui/SKILL.md +79 -0
- package/dist/templates/default/AGENTS.md +22 -19
- package/dist/templates/default/actions/navigate.ts +3 -0
- package/dist/templates/default/app/hooks/use-navigation-state.ts +29 -5
- package/dist/templates/workspace-core/.agents/skills/a2a-protocol/SKILL.md +251 -0
- package/dist/templates/workspace-core/.agents/skills/actions/SKILL.md +264 -0
- package/dist/templates/workspace-core/.agents/skills/adding-a-feature/SKILL.md +130 -0
- package/dist/templates/workspace-core/.agents/skills/address-feedback/SKILL.md +112 -0
- package/dist/templates/workspace-core/.agents/skills/authentication/SKILL.md +88 -0
- package/dist/templates/workspace-core/.agents/skills/automations/SKILL.md +191 -0
- package/dist/templates/workspace-core/.agents/skills/capture-learnings/SKILL.md +74 -0
- package/dist/templates/workspace-core/.agents/skills/client-side-routing/SKILL.md +75 -0
- package/dist/templates/workspace-core/.agents/skills/context-awareness/SKILL.md +190 -0
- package/dist/templates/workspace-core/.agents/skills/create-skill/SKILL.md +168 -0
- package/dist/templates/workspace-core/.agents/skills/delegate-to-agent/SKILL.md +163 -0
- package/dist/templates/workspace-core/.agents/skills/extension-points/SKILL.md +205 -0
- package/dist/templates/workspace-core/.agents/skills/extensions/SKILL.md +720 -0
- package/dist/templates/workspace-core/.agents/skills/frontend-design/SKILL.md +92 -0
- package/dist/templates/workspace-core/.agents/skills/integration-webhooks/SKILL.md +285 -0
- package/dist/templates/workspace-core/.agents/skills/observability/SKILL.md +192 -0
- package/dist/templates/workspace-core/.agents/skills/onboarding/SKILL.md +43 -0
- package/dist/templates/workspace-core/.agents/skills/portability/SKILL.md +84 -0
- package/dist/templates/workspace-core/.agents/skills/qa/SKILL.md +313 -0
- package/dist/templates/workspace-core/.agents/skills/real-time-collab/SKILL.md +112 -0
- package/dist/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +165 -0
- package/dist/templates/workspace-core/.agents/skills/recurring-jobs/SKILL.md +41 -0
- package/dist/templates/workspace-core/.agents/skills/secrets/SKILL.md +239 -0
- package/dist/templates/workspace-core/.agents/skills/security/SKILL.md +191 -0
- package/dist/templates/workspace-core/.agents/skills/self-modifying-code/SKILL.md +79 -0
- package/dist/templates/workspace-core/.agents/skills/server-plugins/SKILL.md +73 -0
- package/dist/templates/workspace-core/.agents/skills/shadcn-ui/SKILL.md +79 -0
- package/dist/templates/workspace-core/.agents/skills/sharing/SKILL.md +217 -0
- package/dist/templates/workspace-core/.agents/skills/storing-data/SKILL.md +132 -0
- package/dist/templates/workspace-core/.agents/skills/tracking/SKILL.md +150 -0
- package/dist/templates/workspace-core/.agents/skills/voice-transcription/SKILL.md +124 -0
- package/dist/templates/workspace-core/AGENTS.md +16 -1
- package/dist/templates/workspace-root/AGENTS.md +35 -0
- package/dist/templates/workspace-root/README.md +7 -0
- package/dist/vite/action-types-plugin.d.ts.map +1 -1
- package/dist/vite/action-types-plugin.js +4 -0
- package/dist/vite/action-types-plugin.js.map +1 -1
- package/docs/content/authentication.md +36 -0
- package/docs/content/creating-templates.md +15 -0
- package/docs/content/dispatch.md +3 -3
- package/docs/content/multi-app-workspace.md +5 -0
- package/docs/content/tracking.md +12 -0
- package/docs/content/workspace-management.md +39 -4
- package/package.json +15 -12
- package/src/templates/default/.agents/skills/adding-a-feature/SKILL.md +72 -0
- package/src/templates/default/.agents/skills/frontend-design/SKILL.md +60 -37
- package/src/templates/default/.agents/skills/real-time-sync/SKILL.md +28 -17
- package/src/templates/default/.agents/skills/shadcn-ui/SKILL.md +79 -0
- package/src/templates/default/AGENTS.md +22 -19
- package/src/templates/default/actions/navigate.ts +3 -0
- package/src/templates/default/app/hooks/use-navigation-state.ts +29 -5
- package/src/templates/workspace-core/.agents/skills/a2a-protocol/SKILL.md +251 -0
- package/src/templates/workspace-core/.agents/skills/actions/SKILL.md +264 -0
- package/src/templates/workspace-core/.agents/skills/adding-a-feature/SKILL.md +130 -0
- package/src/templates/workspace-core/.agents/skills/address-feedback/SKILL.md +112 -0
- package/src/templates/workspace-core/.agents/skills/authentication/SKILL.md +88 -0
- package/src/templates/workspace-core/.agents/skills/automations/SKILL.md +191 -0
- package/src/templates/workspace-core/.agents/skills/capture-learnings/SKILL.md +74 -0
- package/src/templates/workspace-core/.agents/skills/client-side-routing/SKILL.md +75 -0
- package/src/templates/workspace-core/.agents/skills/context-awareness/SKILL.md +190 -0
- package/src/templates/workspace-core/.agents/skills/create-skill/SKILL.md +168 -0
- package/src/templates/workspace-core/.agents/skills/delegate-to-agent/SKILL.md +163 -0
- package/src/templates/workspace-core/.agents/skills/extension-points/SKILL.md +205 -0
- package/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +720 -0
- package/src/templates/workspace-core/.agents/skills/frontend-design/SKILL.md +92 -0
- package/src/templates/workspace-core/.agents/skills/integration-webhooks/SKILL.md +285 -0
- package/src/templates/workspace-core/.agents/skills/observability/SKILL.md +192 -0
- package/src/templates/workspace-core/.agents/skills/onboarding/SKILL.md +43 -0
- package/src/templates/workspace-core/.agents/skills/portability/SKILL.md +84 -0
- package/src/templates/workspace-core/.agents/skills/qa/SKILL.md +313 -0
- package/src/templates/workspace-core/.agents/skills/real-time-collab/SKILL.md +112 -0
- package/src/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +165 -0
- package/src/templates/workspace-core/.agents/skills/recurring-jobs/SKILL.md +41 -0
- package/src/templates/workspace-core/.agents/skills/secrets/SKILL.md +239 -0
- package/src/templates/workspace-core/.agents/skills/security/SKILL.md +191 -0
- package/src/templates/workspace-core/.agents/skills/self-modifying-code/SKILL.md +79 -0
- package/src/templates/workspace-core/.agents/skills/server-plugins/SKILL.md +73 -0
- package/src/templates/workspace-core/.agents/skills/shadcn-ui/SKILL.md +79 -0
- package/src/templates/workspace-core/.agents/skills/sharing/SKILL.md +217 -0
- package/src/templates/workspace-core/.agents/skills/storing-data/SKILL.md +132 -0
- package/src/templates/workspace-core/.agents/skills/tracking/SKILL.md +150 -0
- package/src/templates/workspace-core/.agents/skills/voice-transcription/SKILL.md +124 -0
- package/src/templates/workspace-core/AGENTS.md +16 -1
- package/src/templates/workspace-root/AGENTS.md +35 -0
- package/src/templates/workspace-root/README.md +7 -0
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import React, { useState, useRef, useEffect, useCallback, useMemo, forwardRef, useImperativeHandle, } from "react";
|
|
3
|
-
import { AssistantRuntimeProvider, useLocalRuntime, useThreadRuntime, useThread, useAui, useComposer, useMessageRuntime, ThreadPrimitive, ComposerPrimitive, MessagePrimitive, } from "@assistant-ui/react";
|
|
4
|
-
import {
|
|
3
|
+
import { AssistantRuntimeProvider, useLocalRuntime, useThreadRuntime, useThread, useAui, useComposer, useComposerRuntime, useMessageRuntime, ThreadPrimitive, ComposerPrimitive, MessagePrimitive, } from "@assistant-ui/react";
|
|
4
|
+
import { CompositeAttachmentAdapter } from "@assistant-ui/react";
|
|
5
5
|
import { MarkdownTextPrimitive } from "@assistant-ui/react-markdown";
|
|
6
|
-
import ReactMarkdown from "react-markdown";
|
|
6
|
+
import ReactMarkdown, { defaultUrlTransform } from "react-markdown";
|
|
7
7
|
import remarkGfm from "remark-gfm";
|
|
8
8
|
import { createAgentChatAdapter } from "./agent-chat-adapter.js";
|
|
9
9
|
import { getActiveRun } from "./active-run-state.js";
|
|
10
10
|
import { AgentAutoContinueSignal, readSSEStreamRaw, } from "./sse-event-processor.js";
|
|
11
|
+
import { captureError, trackEvent } from "./analytics.js";
|
|
11
12
|
import { cn } from "./utils.js";
|
|
12
13
|
import { TextAttachmentAdapter } from "./composer/attachment-accept.js";
|
|
13
14
|
import { AgentTaskCard } from "./AgentTaskCard.js";
|
|
@@ -18,12 +19,40 @@ import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel,
|
|
|
18
19
|
import { IframeEmbed, parseEmbedBody } from "./IframeEmbed.js";
|
|
19
20
|
import { useDevMode } from "./use-dev-mode.js";
|
|
20
21
|
import { agentNativePath } from "./api-path.js";
|
|
21
|
-
import { BUILDER_SPACE_SETTINGS_URL } from "./error-format.js";
|
|
22
|
+
import { BUILDER_SPACE_SETTINGS_URL, NEW_CHAT_ACTION_HREF, } from "./error-format.js";
|
|
22
23
|
import { ThumbsFeedback } from "./observability/ThumbsFeedback.js";
|
|
23
24
|
import { TiptapComposer, } from "./composer/TiptapComposer.js";
|
|
24
25
|
import { isPastedTextAttachmentName } from "./composer/pasted-text.js";
|
|
25
26
|
import { PastedTextChip } from "./composer/PastedTextChip.js";
|
|
26
|
-
import { IconMessage, IconX, IconPlayerStop, IconCheck, IconChevronDown, IconCopy, IconTerminal, IconLoader2, IconCircleX, IconSquareFilled, IconClock, IconFile, IconFolder, IconFileText, IconCheckbox, IconMail, IconUser, IconPresentation, IconStack2, IconMessageChatbot, IconLock, IconArrowBackUp, IconExternalLink, IconDots, IconGitFork, IconId, IconQuote, IconGauge, IconArrowRight, IconSettings, IconAlertTriangle, IconRefresh, IconPlayerPlay, IconClipboardList, IconSearch, IconArrowsMaximize, IconArrowsMinimize, } from "@tabler/icons-react";
|
|
27
|
+
import { IconMessage, IconX, IconPlayerStop, IconCheck, IconChevronDown, IconCopy, IconTerminal, IconLoader2, IconCircleX, IconSquareFilled, IconClock, IconFile, IconFolder, IconFileText, IconCheckbox, IconMail, IconUser, IconPresentation, IconStack2, IconMessageChatbot, IconLock, IconArrowBackUp, IconExternalLink, IconDots, IconGitFork, IconId, IconQuote, IconGauge, IconArrowRight, IconSettings, IconAlertTriangle, IconRefresh, IconPlayerPlay, IconClipboardList, IconSearch, IconArrowsMaximize, IconArrowsMinimize, IconPlus, } from "@tabler/icons-react";
|
|
28
|
+
class DownscalingImageAttachmentAdapter {
|
|
29
|
+
accept = "image/*";
|
|
30
|
+
async add(state) {
|
|
31
|
+
return {
|
|
32
|
+
id: state.file.name,
|
|
33
|
+
type: "image",
|
|
34
|
+
name: state.file.name,
|
|
35
|
+
contentType: state.file.type,
|
|
36
|
+
file: state.file,
|
|
37
|
+
status: { type: "requires-action", reason: "composer-send" },
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
async send(attachment) {
|
|
41
|
+
return {
|
|
42
|
+
...attachment,
|
|
43
|
+
status: { type: "complete" },
|
|
44
|
+
content: [
|
|
45
|
+
{
|
|
46
|
+
type: "image",
|
|
47
|
+
image: await getImageFileDataURL(attachment.file),
|
|
48
|
+
},
|
|
49
|
+
],
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
async remove() {
|
|
53
|
+
// noop
|
|
54
|
+
}
|
|
55
|
+
}
|
|
27
56
|
class BinaryDocumentAttachmentAdapter {
|
|
28
57
|
accept = "application/pdf,.pdf";
|
|
29
58
|
async add(state) {
|
|
@@ -69,6 +98,51 @@ function getFileDataURL(file) {
|
|
|
69
98
|
reader.readAsDataURL(file);
|
|
70
99
|
});
|
|
71
100
|
}
|
|
101
|
+
// Anthropic / OpenAI vision inputs choke on multi-megabyte images, and
|
|
102
|
+
// base64-encoding a raw screenshot eats enough heap to crash the composer
|
|
103
|
+
// (PayloadTooLarge / "Maximum call stack" in serializers). Downscale large
|
|
104
|
+
// images on the client before we ever serialize them.
|
|
105
|
+
const MAX_IMAGE_BYTES = 4 * 1024 * 1024;
|
|
106
|
+
const MAX_IMAGE_DIMENSION = 2048;
|
|
107
|
+
function loadImage(url) {
|
|
108
|
+
return new Promise((resolve, reject) => {
|
|
109
|
+
const img = new Image();
|
|
110
|
+
img.onload = () => resolve(img);
|
|
111
|
+
img.onerror = () => reject(new Error("Failed to decode pasted image"));
|
|
112
|
+
img.src = url;
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
async function getImageFileDataURL(file) {
|
|
116
|
+
if (file.size <= MAX_IMAGE_BYTES) {
|
|
117
|
+
return getFileDataURL(file);
|
|
118
|
+
}
|
|
119
|
+
if (typeof document === "undefined" || typeof Image === "undefined") {
|
|
120
|
+
return getFileDataURL(file);
|
|
121
|
+
}
|
|
122
|
+
const objectUrl = URL.createObjectURL(file);
|
|
123
|
+
try {
|
|
124
|
+
const img = await loadImage(objectUrl);
|
|
125
|
+
const ratio = Math.min(MAX_IMAGE_DIMENSION / img.naturalWidth, MAX_IMAGE_DIMENSION / img.naturalHeight, 1);
|
|
126
|
+
const width = Math.max(1, Math.round(img.naturalWidth * ratio));
|
|
127
|
+
const height = Math.max(1, Math.round(img.naturalHeight * ratio));
|
|
128
|
+
const canvas = document.createElement("canvas");
|
|
129
|
+
canvas.width = width;
|
|
130
|
+
canvas.height = height;
|
|
131
|
+
const ctx = canvas.getContext("2d");
|
|
132
|
+
if (!ctx) {
|
|
133
|
+
return getFileDataURL(file);
|
|
134
|
+
}
|
|
135
|
+
ctx.drawImage(img, 0, 0, width, height);
|
|
136
|
+
const useJpeg = file.type !== "image/png" || file.size > MAX_IMAGE_BYTES * 2;
|
|
137
|
+
return canvas.toDataURL(useJpeg ? "image/jpeg" : "image/png", 0.85);
|
|
138
|
+
}
|
|
139
|
+
catch {
|
|
140
|
+
return getFileDataURL(file);
|
|
141
|
+
}
|
|
142
|
+
finally {
|
|
143
|
+
URL.revokeObjectURL(objectUrl);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
72
146
|
function createUserMessageRunConfig(references, requestMode) {
|
|
73
147
|
const custom = {};
|
|
74
148
|
if (references && references.length > 0) {
|
|
@@ -145,7 +219,7 @@ async function serializeQueuedAttachments(attachments) {
|
|
|
145
219
|
name,
|
|
146
220
|
contentType: file.type,
|
|
147
221
|
status: { type: "complete" },
|
|
148
|
-
content: [{ type: "image", image: await
|
|
222
|
+
content: [{ type: "image", image: await getImageFileDataURL(file) }],
|
|
149
223
|
});
|
|
150
224
|
}
|
|
151
225
|
else if (isTextLikeFile(file)) {
|
|
@@ -543,14 +617,23 @@ function HighlightedCodeBlock({ code, lang }) {
|
|
|
543
617
|
}
|
|
544
618
|
return (_jsx("pre", { children: _jsx("code", { className: lang ? `language-${lang}` : undefined, children: code }) }));
|
|
545
619
|
}
|
|
620
|
+
const CTA_BUTTON_CLASSES = "agent-markdown-cta mt-1 inline-flex items-center gap-1.5 rounded-md bg-foreground px-3 py-1.5 text-xs font-medium text-background no-underline shadow-sm transition-colors hover:bg-foreground/90 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background cursor-pointer";
|
|
546
621
|
const markdownComponents = {
|
|
547
622
|
a(props) {
|
|
548
623
|
const { href, children, className, rel: _rel, target: _target, ...rest } = props;
|
|
624
|
+
if (href === NEW_CHAT_ACTION_HREF) {
|
|
625
|
+
// In-app action: dispatch a CustomEvent that MultiTabAssistantChat
|
|
626
|
+
// listens for and opens a new chat tab. Not an external navigation.
|
|
627
|
+
return (_jsxs("button", { type: "button", onClick: (e) => {
|
|
628
|
+
e.preventDefault();
|
|
629
|
+
window.dispatchEvent(new CustomEvent("agent-chat:new-chat"));
|
|
630
|
+
}, className: cn(CTA_BUTTON_CLASSES, className), children: [_jsx(IconPlus, { size: 13, strokeWidth: 2, "aria-hidden": "true" }), _jsx("span", { children: children })] }));
|
|
631
|
+
}
|
|
549
632
|
const isBuilderCta = isBuilderErrorCtaHref(href);
|
|
550
633
|
if (!isBuilderCta) {
|
|
551
634
|
return (_jsx("a", { href: href, className: className, ...rest, children: children }));
|
|
552
635
|
}
|
|
553
|
-
return (_jsxs("a", { href: href, target: "_blank", rel: "noreferrer", className: cn(
|
|
636
|
+
return (_jsxs("a", { href: href, target: "_blank", rel: "noreferrer", className: cn(CTA_BUTTON_CLASSES, className), ...rest, children: [_jsx("span", { children: children }), _jsx(IconExternalLink, { size: 13, strokeWidth: 2, "aria-hidden": "true" })] }));
|
|
554
637
|
},
|
|
555
638
|
pre(props) {
|
|
556
639
|
const { children, ...rest } = props;
|
|
@@ -587,11 +670,20 @@ function isBuilderErrorCtaHref(href) {
|
|
|
587
670
|
return false;
|
|
588
671
|
}
|
|
589
672
|
}
|
|
673
|
+
// react-markdown's defaultUrlTransform strips href values whose protocol
|
|
674
|
+
// isn't on its safe list (https, mailto, etc.). Our in-app pseudo-href
|
|
675
|
+
// `agent-native:new-chat` would be blanked out by that, so let it through
|
|
676
|
+
// while delegating every other URL to the default transform for sanitization.
|
|
677
|
+
function markdownUrlTransform(value) {
|
|
678
|
+
if (value === NEW_CHAT_ACTION_HREF)
|
|
679
|
+
return value;
|
|
680
|
+
return defaultUrlTransform(value);
|
|
681
|
+
}
|
|
590
682
|
function MarkdownText() {
|
|
591
683
|
useEffect(() => {
|
|
592
684
|
injectMarkdownStyles();
|
|
593
685
|
}, []);
|
|
594
|
-
return (_jsx(MarkdownTextPrimitive, { smooth: true, className: "agent-markdown break-words", remarkPlugins: [remarkGfm], components: markdownComponents }));
|
|
686
|
+
return (_jsx(MarkdownTextPrimitive, { smooth: true, className: "agent-markdown break-words", remarkPlugins: [remarkGfm], components: markdownComponents, urlTransform: markdownUrlTransform }));
|
|
595
687
|
}
|
|
596
688
|
// ─── Composer Attachment Preview ─────────────────────────────────────────────
|
|
597
689
|
function getImageAttachmentSrc(attachment) {
|
|
@@ -891,7 +983,7 @@ function ToolCallDisplay({ toolName, argsText, args, result, isRunning, }) {
|
|
|
891
983
|
const isExpanded = isAgentCall ? hasStreamText && expanded : expanded;
|
|
892
984
|
return (_jsxs("div", { className: "my-1 overflow-hidden", children: [_jsxs("button", { onClick: () => canExpand && setExpanded(!isExpanded), "aria-expanded": canExpand ? isExpanded : undefined, className: cn("flex items-center gap-2 rounded-md px-2.5 py-1.5 text-xs font-mono w-full text-left overflow-hidden", isRunning
|
|
893
985
|
? "bg-muted text-muted-foreground"
|
|
894
|
-
: "bg-muted text-muted-foreground hover:bg-accent"), children: [_jsx("span", { className: "shrink-0", children: isRunning ? (_jsx(IconLoader2, { className: "h-3 w-3 animate-spin" })) : isAgentError ? (_jsx(IconCircleX, { className: "h-3 w-3 text-destructive" })) : result !== undefined ? (_jsx(IconCheck, { className: "h-3 w-3 text-emerald-500" })) : (_jsx(IconSquareFilled, { className: "h-3 w-3 text-muted-foreground" })) }), _jsxs("span", { className: "truncate min-w-0", children: [_jsx("span", { className: "font-medium", children: displayName }), argsStr && _jsxs("span", { className: "opacity-60 ml-1", children: ["(", argsStr, ")"] })] }), canExpand && (_jsx(IconChevronDown, { className: cn("ml-auto h-3 w-3 shrink-0 opacity-40", isExpanded && "rotate-180") }))] }), isExpanded && isAgentCall && hasStreamText && (_jsx("div", { ref: streamRef, className: "mt-1 rounded-md bg-muted/50 px-3 py-2 text-xs text-muted-foreground break-words max-h-48 overflow-y-auto agent-markdown prose prose-sm prose-invert max-w-none", children: _jsx(ReactMarkdown, { remarkPlugins: [remarkGfm], components: markdownComponents, children: agentStreamText }) })), isExpanded && !isAgentCall && (hasArgs || result !== undefined) && (_jsxs("div", { className: "mt-1 space-y-2 rounded-md bg-muted/50 px-3 py-2 text-xs text-muted-foreground", children: [inputPayload && _jsx(ToolDetailViewer, { payload: inputPayload }), resultPayload && _jsx(ToolDetailViewer, { payload: resultPayload })] }))] }));
|
|
986
|
+
: "bg-muted text-muted-foreground hover:bg-accent"), children: [_jsx("span", { className: "shrink-0", children: isRunning ? (_jsx(IconLoader2, { className: "h-3 w-3 animate-spin" })) : isAgentError ? (_jsx(IconCircleX, { className: "h-3 w-3 text-destructive" })) : result !== undefined ? (_jsx(IconCheck, { className: "h-3 w-3 text-emerald-500" })) : (_jsx(IconSquareFilled, { className: "h-3 w-3 text-muted-foreground" })) }), _jsxs("span", { className: "truncate min-w-0", children: [_jsx("span", { className: "font-medium", children: displayName }), argsStr && _jsxs("span", { className: "opacity-60 ml-1", children: ["(", argsStr, ")"] })] }), canExpand && (_jsx(IconChevronDown, { className: cn("ml-auto h-3 w-3 shrink-0 opacity-40", isExpanded && "rotate-180") }))] }), isExpanded && isAgentCall && hasStreamText && (_jsx("div", { ref: streamRef, className: "mt-1 rounded-md bg-muted/50 px-3 py-2 text-xs text-muted-foreground break-words max-h-48 overflow-y-auto agent-markdown prose prose-sm prose-invert max-w-none", children: _jsx(ReactMarkdown, { remarkPlugins: [remarkGfm], components: markdownComponents, urlTransform: markdownUrlTransform, children: agentStreamText }) })), isExpanded && !isAgentCall && (hasArgs || result !== undefined) && (_jsxs("div", { className: "mt-1 space-y-2 rounded-md bg-muted/50 px-3 py-2 text-xs text-muted-foreground", children: [inputPayload && _jsx(ToolDetailViewer, { payload: inputPayload }), resultPayload && _jsx(ToolDetailViewer, { payload: resultPayload })] }))] }));
|
|
895
987
|
}
|
|
896
988
|
function ToolCallFallback({ toolName, args, argsText, result, }) {
|
|
897
989
|
const chatRunning = React.useContext(ChatRunningContext);
|
|
@@ -913,7 +1005,7 @@ function ReconnectStreamMessage({ content }) {
|
|
|
913
1005
|
}, [content]);
|
|
914
1006
|
return (_jsx("div", { className: "flex justify-start", children: _jsxs("div", { className: "max-w-[95%] text-sm leading-relaxed text-foreground space-y-1", children: [content.map((part, i) => {
|
|
915
1007
|
if (part.type === "text") {
|
|
916
|
-
return (_jsx("div", { className: "agent-markdown break-words", children: _jsx(ReactMarkdown, { remarkPlugins: [remarkGfm], components: markdownComponents, children: part.text }) }, `reconnect-text-${i}`));
|
|
1008
|
+
return (_jsx("div", { className: "agent-markdown break-words", children: _jsx(ReactMarkdown, { remarkPlugins: [remarkGfm], components: markdownComponents, urlTransform: markdownUrlTransform, children: part.text }) }, `reconnect-text-${i}`));
|
|
917
1009
|
}
|
|
918
1010
|
if (part.type === "tool-call") {
|
|
919
1011
|
return (_jsx(ToolCallDisplay, { toolName: part.toolName, argsText: part.argsText, args: part.args, result: part.result, isRunning: part.result === undefined && chatRunning }, `reconnect-tool-${i}`));
|
|
@@ -953,9 +1045,7 @@ const richMentionPattern = /@\[([^\]|]+)\|([^\]]+)\]/g;
|
|
|
953
1045
|
const plainMentionPattern = /((?:^|(?<=\s))@(\w+))/g;
|
|
954
1046
|
function UserMessageText({ text }) {
|
|
955
1047
|
// Strip injected <context>...</context> blocks before display
|
|
956
|
-
const displayText = text
|
|
957
|
-
.replace(/<context>[\s\S]*?<\/context>\n?/g, "")
|
|
958
|
-
.trim();
|
|
1048
|
+
const displayText = displayableUserMessageText(text);
|
|
959
1049
|
const parts = [];
|
|
960
1050
|
let lastIndex = 0;
|
|
961
1051
|
let match;
|
|
@@ -995,6 +1085,77 @@ function UserMessageText({ text }) {
|
|
|
995
1085
|
}
|
|
996
1086
|
return _jsx(_Fragment, { children: parts.length > 0 ? parts : displayText });
|
|
997
1087
|
}
|
|
1088
|
+
export function displayableUserMessageText(text) {
|
|
1089
|
+
return text.replace(/<context>[\s\S]*?<\/context>\n?/g, "").trim();
|
|
1090
|
+
}
|
|
1091
|
+
export function isAssistantUiStaleIndexError(error) {
|
|
1092
|
+
const message = error instanceof Error ? error.message : String(error ?? "");
|
|
1093
|
+
return /^tapClientLookup: Index \d+ out of bounds \(length: \d+\)$/.test(message);
|
|
1094
|
+
}
|
|
1095
|
+
export class AssistantUiStaleIndexErrorBoundary extends React.Component {
|
|
1096
|
+
state = {
|
|
1097
|
+
error: null,
|
|
1098
|
+
retryToken: 0,
|
|
1099
|
+
};
|
|
1100
|
+
retryTimer = null;
|
|
1101
|
+
static getDerivedStateFromError(error) {
|
|
1102
|
+
return {
|
|
1103
|
+
error: error instanceof Error ? error : new Error(String(error ?? "")),
|
|
1104
|
+
};
|
|
1105
|
+
}
|
|
1106
|
+
componentDidCatch(error, info) {
|
|
1107
|
+
if (!isAssistantUiStaleIndexError(error))
|
|
1108
|
+
return;
|
|
1109
|
+
captureError(error, {
|
|
1110
|
+
tags: {
|
|
1111
|
+
component: this.props.componentName ?? "AssistantChat",
|
|
1112
|
+
recoverable: "assistant-ui-stale-message-index",
|
|
1113
|
+
},
|
|
1114
|
+
extra: {
|
|
1115
|
+
resetKey: this.props.resetKey,
|
|
1116
|
+
componentStack: info.componentStack,
|
|
1117
|
+
},
|
|
1118
|
+
});
|
|
1119
|
+
if (this.retryTimer)
|
|
1120
|
+
return;
|
|
1121
|
+
this.retryTimer = setTimeout(() => {
|
|
1122
|
+
this.retryTimer = null;
|
|
1123
|
+
this.setState((state) => {
|
|
1124
|
+
if (!state.error || !isAssistantUiStaleIndexError(state.error)) {
|
|
1125
|
+
return null;
|
|
1126
|
+
}
|
|
1127
|
+
return { error: null, retryToken: state.retryToken + 1 };
|
|
1128
|
+
});
|
|
1129
|
+
}, 0);
|
|
1130
|
+
}
|
|
1131
|
+
componentDidUpdate(prevProps) {
|
|
1132
|
+
if (this.state.error &&
|
|
1133
|
+
isAssistantUiStaleIndexError(this.state.error) &&
|
|
1134
|
+
prevProps.resetKey !== this.props.resetKey) {
|
|
1135
|
+
this.setState((state) => ({
|
|
1136
|
+
error: null,
|
|
1137
|
+
retryToken: state.retryToken + 1,
|
|
1138
|
+
}));
|
|
1139
|
+
}
|
|
1140
|
+
}
|
|
1141
|
+
componentWillUnmount() {
|
|
1142
|
+
if (this.retryTimer) {
|
|
1143
|
+
clearTimeout(this.retryTimer);
|
|
1144
|
+
}
|
|
1145
|
+
}
|
|
1146
|
+
render() {
|
|
1147
|
+
if (this.state.error) {
|
|
1148
|
+
if (!isAssistantUiStaleIndexError(this.state.error)) {
|
|
1149
|
+
throw this.state.error;
|
|
1150
|
+
}
|
|
1151
|
+
return null;
|
|
1152
|
+
}
|
|
1153
|
+
return (_jsx(React.Fragment, { children: this.props.children }, `${this.props.resetKey}:${this.state.retryToken}`));
|
|
1154
|
+
}
|
|
1155
|
+
}
|
|
1156
|
+
export function AssistantMessageListErrorBoundary({ resetKey, children, }) {
|
|
1157
|
+
return (_jsx(AssistantUiStaleIndexErrorBoundary, { resetKey: resetKey, componentName: "AssistantMessageList", children: children }));
|
|
1158
|
+
}
|
|
998
1159
|
function UserMessageAttachments() {
|
|
999
1160
|
const messageRuntime = useMessageRuntime();
|
|
1000
1161
|
const msg = messageRuntime.getState();
|
|
@@ -1023,10 +1184,17 @@ function UserMessage() {
|
|
|
1023
1184
|
const [isExpandable, setIsExpandable] = useState(false);
|
|
1024
1185
|
const contentRef = useRef(null);
|
|
1025
1186
|
const messageRuntime = useMessageRuntime();
|
|
1026
|
-
const
|
|
1187
|
+
const message = messageRuntime.getState();
|
|
1188
|
+
const timestamp = formatMessageTimestamp(message.createdAt);
|
|
1189
|
+
const hasDisplayableText = message.content
|
|
1190
|
+
?.filter((part) => {
|
|
1191
|
+
return part.type === "text" && typeof part.text === "string";
|
|
1192
|
+
})
|
|
1193
|
+
.some((part) => displayableUserMessageText(part.text).length > 0) ??
|
|
1194
|
+
false;
|
|
1027
1195
|
useEffect(() => {
|
|
1028
1196
|
const el = contentRef.current;
|
|
1029
|
-
if (!el)
|
|
1197
|
+
if (!el || !hasDisplayableText)
|
|
1030
1198
|
return;
|
|
1031
1199
|
const measure = () => {
|
|
1032
1200
|
setIsExpandable(el.scrollHeight > 200);
|
|
@@ -1035,8 +1203,8 @@ function UserMessage() {
|
|
|
1035
1203
|
const observer = new ResizeObserver(measure);
|
|
1036
1204
|
observer.observe(el);
|
|
1037
1205
|
return () => observer.disconnect();
|
|
1038
|
-
}, []);
|
|
1039
|
-
return (_jsx("div", { className: "group flex justify-end", style: { contentVisibility: "auto" }, children: _jsxs("div", { className: "max-w-[85%]", children: [_jsx(UserMessageAttachments, {}), _jsxs("div", { className: "relative rounded-lg bg-accent px-3 py-2 text-sm leading-relaxed text-foreground", onCopy: (e) => {
|
|
1206
|
+
}, [hasDisplayableText]);
|
|
1207
|
+
return (_jsx("div", { className: "group flex justify-end", style: { contentVisibility: "auto" }, children: _jsxs("div", { className: "max-w-[85%]", children: [_jsx(UserMessageAttachments, {}), hasDisplayableText && (_jsxs("div", { className: "relative rounded-lg bg-accent px-3 py-2 text-sm leading-relaxed text-foreground", onCopy: (e) => {
|
|
1040
1208
|
const selection = window.getSelection();
|
|
1041
1209
|
if (!selection || selection.rangeCount === 0)
|
|
1042
1210
|
return;
|
|
@@ -1053,7 +1221,7 @@ function UserMessage() {
|
|
|
1053
1221
|
e.clipboardData.setData("text/plain", div.textContent || "");
|
|
1054
1222
|
}, children: [_jsx("div", { ref: contentRef, className: cn("whitespace-pre-wrap break-words", !expanded && isExpandable && "max-h-[200px] overflow-hidden"), children: _jsx(MessagePrimitive.Parts, { components: {
|
|
1055
1223
|
Text: UserMessageText,
|
|
1056
|
-
} }) }), !expanded && isExpandable && (_jsx("div", { className: "pointer-events-none absolute inset-x-0 bottom-0 h-14 rounded-b-lg bg-gradient-to-t from-accent via-accent/90 to-transparent" }))] }), isExpandable && (_jsxs("button", { type: "button", onClick: () => setExpanded((prev) => !prev), className: "mt-1 inline-flex items-center gap-1 rounded-md px-1.5 py-1 text-[11px] font-medium text-muted-foreground hover:text-foreground", children: [_jsx(IconChevronDown, { className: cn("h-3.5 w-3.5 transition-transform", expanded && "rotate-180") }), expanded ? "Collapse" : "Expand"] })), timestamp && (_jsx("div", { className: "mt-1 flex justify-end", children: _jsx(MessageTimestamp, { timestamp: timestamp, className: "opacity-0 transition-opacity duration-150 group-hover:opacity-100 group-focus-within:opacity-100" }) }))] }) }));
|
|
1224
|
+
} }) }), !expanded && isExpandable && (_jsx("div", { className: "pointer-events-none absolute inset-x-0 bottom-0 h-14 rounded-b-lg bg-gradient-to-t from-accent via-accent/90 to-transparent" }))] })), hasDisplayableText && isExpandable && (_jsxs("button", { type: "button", onClick: () => setExpanded((prev) => !prev), className: "mt-1 inline-flex items-center gap-1 rounded-md px-1.5 py-1 text-[11px] font-medium text-muted-foreground hover:text-foreground", children: [_jsx(IconChevronDown, { className: cn("h-3.5 w-3.5 transition-transform", expanded && "rotate-180") }), expanded ? "Collapse" : "Expand"] })), timestamp && (_jsx("div", { className: "mt-1 flex justify-end", children: _jsx(MessageTimestamp, { timestamp: timestamp, className: "opacity-0 transition-opacity duration-150 group-hover:opacity-100 group-focus-within:opacity-100" }) }))] }) }));
|
|
1057
1225
|
}
|
|
1058
1226
|
const CheckpointContext = React.createContext(null);
|
|
1059
1227
|
const MessageActionsContext = React.createContext(null);
|
|
@@ -1217,6 +1385,7 @@ function ThinkingIndicator({ label = "Thinking" } = {}) {
|
|
|
1217
1385
|
// session. See packages/desktop-app/src/main/index.ts.
|
|
1218
1386
|
function BuilderConnectCta({ variant = "primary", onConnected, }) {
|
|
1219
1387
|
const { configured, orgName, connecting, error, start } = useBuilderConnectFlow({
|
|
1388
|
+
trackingSource: "assistant_chat_builder_cta",
|
|
1220
1389
|
onConnected,
|
|
1221
1390
|
});
|
|
1222
1391
|
const containerClass = variant === "compact"
|
|
@@ -1354,7 +1523,14 @@ function RunErrorRecoveryCard({ info, onContinue, onRetry, onFork, onDismiss, })
|
|
|
1354
1523
|
}, [info]);
|
|
1355
1524
|
return (_jsxs("div", { className: "rounded-lg border border-amber-500/25 bg-amber-500/[0.06] p-3 text-sm", children: [_jsxs("div", { className: "flex items-start gap-2", children: [_jsx("span", { className: "mt-0.5 flex h-6 w-6 shrink-0 items-center justify-center rounded-md bg-amber-500/10 text-amber-700 dark:text-amber-300", children: _jsx(IconAlertTriangle, { size: 14 }) }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("div", { className: "font-medium text-foreground", children: canRecover
|
|
1356
1525
|
? "The agent stopped before finishing"
|
|
1357
|
-
: "The agent hit an error" }), _jsx("p", { className: "mt-1 text-xs leading-relaxed text-muted-foreground", children: info.message }), shouldShowBuilderReconnect && (_jsx("p", { className: "mt-2 text-xs leading-relaxed text-muted-foreground", children: "The current Builder.io or model-provider credential was rejected. Reconnect Builder.io, then retry this message." })), (info.runId || info.errorCode || info.details) && (_jsxs("button", { type: "button", onClick: () => setDetailsOpen((v) => !v), className: "mt-2 inline-flex items-center gap-1 text-[11px] font-medium text-muted-foreground hover:text-foreground", children: [_jsx(IconChevronDown, { size: 12, className: cn("transition-transform", detailsOpen && "rotate-180") }), "Details"] })), detailsOpen && (_jsxs("div", { className: "mt-2 rounded-md border border-border/60 bg-background/70 p-2 font-mono text-[11px] leading-relaxed text-muted-foreground", children: [info.runId && _jsxs("div", { children: ["run: ", info.runId] }), info.errorCode && _jsxs("div", { children: ["code: ", info.errorCode] }), info.details && (_jsx("pre", { className: "mt-2 max-h-28 overflow-auto whitespace-pre-wrap break-words font-mono", children: info.details }))] }))] }), _jsx("button", { type: "button", onClick: onDismiss, "aria-label": "Dismiss", className: "flex h-6 w-6 shrink-0 items-center justify-center rounded-md text-muted-foreground hover:bg-background/80 hover:text-foreground", children: _jsx(IconX, { size: 14 }) })] }), _jsxs("div", { className: "mt-3 flex flex-wrap items-center gap-2", children: [shouldShowBuilderReconnect && (_jsxs("a", { href: agentNativePath("/_agent-native/builder/connect"), target: "_blank", rel: "noreferrer",
|
|
1526
|
+
: "The agent hit an error" }), _jsx("p", { className: "mt-1 text-xs leading-relaxed text-muted-foreground", children: info.message }), shouldShowBuilderReconnect && (_jsx("p", { className: "mt-2 text-xs leading-relaxed text-muted-foreground", children: "The current Builder.io or model-provider credential was rejected. Reconnect Builder.io, then retry this message." })), (info.runId || info.errorCode || info.details) && (_jsxs("button", { type: "button", onClick: () => setDetailsOpen((v) => !v), className: "mt-2 inline-flex items-center gap-1 text-[11px] font-medium text-muted-foreground hover:text-foreground", children: [_jsx(IconChevronDown, { size: 12, className: cn("transition-transform", detailsOpen && "rotate-180") }), "Details"] })), detailsOpen && (_jsxs("div", { className: "mt-2 rounded-md border border-border/60 bg-background/70 p-2 font-mono text-[11px] leading-relaxed text-muted-foreground", children: [info.runId && _jsxs("div", { children: ["run: ", info.runId] }), info.errorCode && _jsxs("div", { children: ["code: ", info.errorCode] }), info.details && (_jsx("pre", { className: "mt-2 max-h-28 overflow-auto whitespace-pre-wrap break-words font-mono", children: info.details }))] }))] }), _jsx("button", { type: "button", onClick: onDismiss, "aria-label": "Dismiss", className: "flex h-6 w-6 shrink-0 items-center justify-center rounded-md text-muted-foreground hover:bg-background/80 hover:text-foreground", children: _jsx(IconX, { size: 14 }) })] }), _jsxs("div", { className: "mt-3 flex flex-wrap items-center gap-2", children: [shouldShowBuilderReconnect && (_jsxs("a", { href: agentNativePath("/_agent-native/builder/connect"), target: "_blank", rel: "noreferrer", onClick: () => {
|
|
1527
|
+
trackEvent("builder connect clicked", {
|
|
1528
|
+
feature: "builder",
|
|
1529
|
+
stage: "client",
|
|
1530
|
+
source: "assistant_chat_reconnect_error",
|
|
1531
|
+
connect_url_kind: "default",
|
|
1532
|
+
});
|
|
1533
|
+
}, className: "inline-flex h-8 items-center gap-1.5 rounded-md bg-foreground px-3 text-xs font-medium text-background hover:opacity-90", children: [_jsx(IconExternalLink, { size: 13 }), "Reconnect Builder.io"] })), canRecover && (_jsxs(_Fragment, { children: [_jsxs("button", { type: "button", onClick: onContinue, className: "inline-flex h-8 items-center gap-1.5 rounded-md bg-foreground px-3 text-xs font-medium text-background hover:opacity-90", children: [_jsx(IconPlayerPlay, { size: 13 }), "Continue"] }), _jsxs("button", { type: "button", onClick: onRetry, className: "inline-flex h-8 items-center gap-1.5 rounded-md border border-border bg-background px-3 text-xs font-medium text-foreground hover:bg-accent", children: [_jsx(IconRefresh, { size: 13 }), isQueryError ? "Diagnose and retry" : "Retry"] })] })), canRecover && onFork && (_jsxs("button", { type: "button", onClick: onFork, title: "Fork this conversation into a separate chat thread.", "aria-label": "Fork this conversation into a separate chat thread", className: "inline-flex h-8 items-center gap-1.5 rounded-md border border-border bg-background px-3 text-xs font-medium text-foreground hover:bg-accent", children: [_jsx(IconGitFork, { size: 13 }), "Fork chat"] })), _jsxs("button", { type: "button", onClick: copyDetails, className: "ml-auto inline-flex h-8 items-center gap-1.5 rounded-md px-2.5 text-xs font-medium text-muted-foreground hover:bg-background/80 hover:text-foreground", children: [copied ? _jsx(IconCheck, { size: 13 }) : _jsx(IconCopy, { size: 13 }), copied ? "Copied" : copyLabel] })] })] }));
|
|
1358
1534
|
}
|
|
1359
1535
|
function LoopLimitContinueCard({ info, onContinue, }) {
|
|
1360
1536
|
const [settings, setSettings] = useState(null);
|
|
@@ -1493,12 +1669,64 @@ function ensureMessageMetadata(repo) {
|
|
|
1493
1669
|
// Re-export for backwards compatibility
|
|
1494
1670
|
import { extractThreadMeta, normalizeThreadRepository, } from "../agent/thread-data-builder.js";
|
|
1495
1671
|
export { extractThreadMeta };
|
|
1496
|
-
const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateText, suggestions, showHeader = true, onSwitchToCli, className, apiUrl, tabId, threadId, onMessageCountChange, onSaveThread, onGenerateTitle, composerSlot, composerDisabled = false, composerDisabledPlaceholder, isNewThread, onSlashCommand, execMode, onExecModeChange, planModeDisabled, planModeDisabledReason, selectedModel, defaultModel, selectedEngine, selectedEffort, availableModels, onModelChange, onEffortChange, onForkChat, }, ref) {
|
|
1672
|
+
const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateText, suggestions, emptyStateAddon, showHeader = true, onSwitchToCli, className, apiUrl, tabId, threadId, onMessageCountChange, onSaveThread, onGenerateTitle, composerSlot, composerDisabled = false, composerDisabledPlaceholder, isNewThread, onSlashCommand, execMode, onExecModeChange, planModeDisabled, planModeDisabledReason, selectedModel, defaultModel, selectedEngine, selectedEffort, availableModels, onModelChange, onEffortChange, onForkChat, }, ref) {
|
|
1497
1673
|
const scrollRef = useRef(null);
|
|
1498
1674
|
const thread = useThread();
|
|
1499
1675
|
const threadRuntime = useThreadRuntime();
|
|
1676
|
+
const composerRuntime = useComposerRuntime();
|
|
1500
1677
|
const isRuntimeRunning = thread.isRunning;
|
|
1501
1678
|
const messages = thread.messages;
|
|
1679
|
+
const messageListResetKey = useMemo(() => messages.map((message) => message.id).join("|"), [messages]);
|
|
1680
|
+
// Chat-wide drag-and-drop: users expect to drop a file anywhere on the agent
|
|
1681
|
+
// sidebar (thread, header, composer) and have it attach — same as ChatGPT,
|
|
1682
|
+
// Claude.ai, Linear, Slack, etc. Tiptap's own `handleDrop` only fires inside
|
|
1683
|
+
// the contenteditable; drops on the message thread or the composer
|
|
1684
|
+
// attachment strip otherwise navigate to the file (browser default), which
|
|
1685
|
+
// is why "upload does nothing" — the chat refreshes to the dropped image.
|
|
1686
|
+
const [dropActive, setDropActive] = useState(false);
|
|
1687
|
+
const dropDepthRef = useRef(0);
|
|
1688
|
+
const handleChatDragEnter = useCallback((e) => {
|
|
1689
|
+
if (!Array.from(e.dataTransfer?.types ?? []).includes("Files"))
|
|
1690
|
+
return;
|
|
1691
|
+
e.preventDefault();
|
|
1692
|
+
dropDepthRef.current += 1;
|
|
1693
|
+
setDropActive(true);
|
|
1694
|
+
}, []);
|
|
1695
|
+
const handleChatDragOver = useCallback((e) => {
|
|
1696
|
+
if (!Array.from(e.dataTransfer?.types ?? []).includes("Files"))
|
|
1697
|
+
return;
|
|
1698
|
+
e.preventDefault();
|
|
1699
|
+
if (e.dataTransfer)
|
|
1700
|
+
e.dataTransfer.dropEffect = "copy";
|
|
1701
|
+
}, []);
|
|
1702
|
+
const handleChatDragLeave = useCallback((e) => {
|
|
1703
|
+
if (!Array.from(e.dataTransfer?.types ?? []).includes("Files"))
|
|
1704
|
+
return;
|
|
1705
|
+
dropDepthRef.current = Math.max(0, dropDepthRef.current - 1);
|
|
1706
|
+
if (dropDepthRef.current === 0)
|
|
1707
|
+
setDropActive(false);
|
|
1708
|
+
}, []);
|
|
1709
|
+
const handleChatDrop = useCallback((e) => {
|
|
1710
|
+
const files = Array.from(e.dataTransfer?.files ?? []);
|
|
1711
|
+
if (files.length === 0)
|
|
1712
|
+
return;
|
|
1713
|
+
e.preventDefault();
|
|
1714
|
+
e.stopPropagation();
|
|
1715
|
+
dropDepthRef.current = 0;
|
|
1716
|
+
setDropActive(false);
|
|
1717
|
+
// Mirror TiptapComposer's paste/drop name-uniqueness so consecutive
|
|
1718
|
+
// screenshots (all named `image.png`) don't collide on the
|
|
1719
|
+
// SimpleImageAttachmentAdapter id.
|
|
1720
|
+
const attachments = files.map((file) => {
|
|
1721
|
+
if (!file.type.startsWith("image/"))
|
|
1722
|
+
return file;
|
|
1723
|
+
const uniqueName = `${Date.now()}-${Math.random().toString(36).slice(2)}-${file.name}`;
|
|
1724
|
+
return new File([file], uniqueName, { type: file.type });
|
|
1725
|
+
});
|
|
1726
|
+
void Promise.all(attachments.map((file) => composerRuntime.addAttachment(file))).catch((error) => {
|
|
1727
|
+
console.error("Error adding dropped chat attachment:", error);
|
|
1728
|
+
});
|
|
1729
|
+
}, [composerRuntime]);
|
|
1502
1730
|
// Patch the underlying assistant-ui MessageRepository so addOrUpdateMessage
|
|
1503
1731
|
// can't throw "Parent message not found" mid-run. assistant-ui calls
|
|
1504
1732
|
// `repository.clear()` from `runtime.import()` and from `resetHead(null)`,
|
|
@@ -1721,6 +1949,19 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
1721
1949
|
clearTimeout(maxReconnectTimer);
|
|
1722
1950
|
}
|
|
1723
1951
|
if (noProgressDuringReconnect && reconnectRunIdRef.current === runId) {
|
|
1952
|
+
captureError(new Error("agent-chat:reconnect_no_progress"), {
|
|
1953
|
+
tags: {
|
|
1954
|
+
context: "agent-native-chat",
|
|
1955
|
+
errorCode: "reconnect_no_progress",
|
|
1956
|
+
reconnectTimedOut: String(reconnectTimedOut),
|
|
1957
|
+
},
|
|
1958
|
+
extra: {
|
|
1959
|
+
runId,
|
|
1960
|
+
threadId: threadId ?? null,
|
|
1961
|
+
tabId: tabId ?? null,
|
|
1962
|
+
contentLength: latestContent.length,
|
|
1963
|
+
},
|
|
1964
|
+
});
|
|
1724
1965
|
try {
|
|
1725
1966
|
await fetch(`${apiUrl}/runs/${encodeURIComponent(runId)}/abort`, {
|
|
1726
1967
|
method: "POST",
|
|
@@ -2093,16 +2334,35 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
2093
2334
|
useEffect(() => {
|
|
2094
2335
|
if (!authError)
|
|
2095
2336
|
return;
|
|
2337
|
+
// Auto-recovery (`checkAuthSession`) runs immediately + at 250ms. If the
|
|
2338
|
+
// card is still showing 3 seconds later, recovery failed and the user
|
|
2339
|
+
// is about to hit "Refresh chat" — that's the "Reload UI required"
|
|
2340
|
+
// symptom we want signal on.
|
|
2341
|
+
const stuckCapture = window.setTimeout(() => {
|
|
2342
|
+
captureError(new Error("agent-chat:auth_error_card_stuck"), {
|
|
2343
|
+
tags: {
|
|
2344
|
+
context: "agent-native-chat",
|
|
2345
|
+
errorCode: "auth_error_card",
|
|
2346
|
+
sessionAvailable: String(authSessionAvailable),
|
|
2347
|
+
sessionExpired: String(!!authError.sessionExpired),
|
|
2348
|
+
},
|
|
2349
|
+
extra: {
|
|
2350
|
+
threadId: threadId ?? null,
|
|
2351
|
+
tabId: tabId ?? null,
|
|
2352
|
+
},
|
|
2353
|
+
});
|
|
2354
|
+
}, 3000);
|
|
2096
2355
|
const handler = () => void checkAuthSession();
|
|
2097
2356
|
const timer = window.setTimeout(handler, 250);
|
|
2098
2357
|
window.addEventListener("focus", handler);
|
|
2099
2358
|
window.addEventListener("agent-engine:configured-changed", handler);
|
|
2100
2359
|
return () => {
|
|
2360
|
+
window.clearTimeout(stuckCapture);
|
|
2101
2361
|
window.clearTimeout(timer);
|
|
2102
2362
|
window.removeEventListener("focus", handler);
|
|
2103
2363
|
window.removeEventListener("agent-engine:configured-changed", handler);
|
|
2104
2364
|
};
|
|
2105
|
-
}, [authError, checkAuthSession]);
|
|
2365
|
+
}, [authError, authSessionAvailable, checkAuthSession, tabId, threadId]);
|
|
2106
2366
|
// Listen for loop-limit events from the adapter
|
|
2107
2367
|
useEffect(() => {
|
|
2108
2368
|
const handler = (e) => {
|
|
@@ -2260,6 +2520,13 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
2260
2520
|
// Selection context attached via Cmd+I is one-shot — clear it as soon
|
|
2261
2521
|
// as the user actually sends a message so it can't be re-used.
|
|
2262
2522
|
clearPendingSelection();
|
|
2523
|
+
// Sending a message is an explicit user action — always anchor to the
|
|
2524
|
+
// bottom so the new message and any reply land in view, even if the
|
|
2525
|
+
// user had scrolled up to read history. The sticky-bottom override
|
|
2526
|
+
// exists to stop streaming from yanking the viewport, not to swallow
|
|
2527
|
+
// direct sends.
|
|
2528
|
+
isNearBottomRef.current = true;
|
|
2529
|
+
setShowScrollToBottom(false);
|
|
2263
2530
|
const queuedAttachments = await serializeQueuedAttachments(attachments);
|
|
2264
2531
|
// Snapshot the exec mode at enqueue time when the caller didn't
|
|
2265
2532
|
// pass an explicit override. Without this, a plan-mode message that
|
|
@@ -2317,7 +2584,19 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
2317
2584
|
focusComposer() {
|
|
2318
2585
|
tiptapRef.current?.focus();
|
|
2319
2586
|
},
|
|
2320
|
-
|
|
2587
|
+
exportThreadSnapshot() {
|
|
2588
|
+
if (messages.length === 0)
|
|
2589
|
+
return null;
|
|
2590
|
+
const repo = threadRuntime.export();
|
|
2591
|
+
const { title, preview } = extractThreadMeta(repo);
|
|
2592
|
+
return {
|
|
2593
|
+
threadData: JSON.stringify(repo),
|
|
2594
|
+
title,
|
|
2595
|
+
preview,
|
|
2596
|
+
messageCount: messages.length,
|
|
2597
|
+
};
|
|
2598
|
+
},
|
|
2599
|
+
}), [addToQueue, messages.length, thread.isRunning, threadRuntime]);
|
|
2321
2600
|
// Track whether user has scrolled away from bottom
|
|
2322
2601
|
const isNearBottomRef = useRef(true);
|
|
2323
2602
|
const [showScrollToBottom, setShowScrollToBottom] = useState(false);
|
|
@@ -2462,7 +2741,7 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
2462
2741
|
(!userStoppedRunRef.current.runId ||
|
|
2463
2742
|
!visibleRunError.runId ||
|
|
2464
2743
|
userStoppedRunRef.current.runId === visibleRunError.runId));
|
|
2465
|
-
return (_jsx(CheckpointContext.Provider, { value: checkpointCtx, children: _jsx(MessageActionsContext.Provider, { value: messageActionsCtx, children: _jsx(ChatRunningContext.Provider, { value: isRunning, children: _jsxs("div", { className: cn("flex flex-1 flex-col h-full min-h-0 text-foreground", className), children: [showHeader && (_jsxs("div", { className: "flex h-11 shrink-0 items-center justify-between border-b border-border px-4", children: [_jsx("span", { className: "text-[13px] font-medium text-muted-foreground", children: "Agent" }), _jsx("div", { className: "flex items-center gap-1", children: onSwitchToCli && (_jsx(TooltipProvider, { delayDuration: 200, children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsxs("button", { onClick: onSwitchToCli, "aria-label": "Switch to CLI", className: "flex items-center gap-1 text-[12px] text-muted-foreground hover:text-foreground px-2 py-1 rounded-md hover:bg-accent", children: [_jsx(IconTerminal, { className: "h-3.5 w-3.5" }), "CLI"] }) }), _jsx(TooltipContent, { children: "Switch to CLI" })] }) })) })] })), _jsx("div", { ref: scrollRef, className: "flex-1 overflow-y-auto overflow-x-hidden min-h-0", children: authError ? (_jsxs("div", { className: "flex flex-col items-center justify-center h-full px-4 gap-3", children: [_jsx("div", { className: "flex h-10 w-10 items-center justify-center rounded-full bg-destructive/10", children: _jsx(IconLock, { className: "h-5 w-5 text-destructive" }) }), _jsxs("div", { className: "text-center max-w-[280px]", children: [_jsx("p", { className: "text-sm font-medium text-foreground mb-1", children: authSessionAvailable
|
|
2744
|
+
return (_jsx(CheckpointContext.Provider, { value: checkpointCtx, children: _jsx(MessageActionsContext.Provider, { value: messageActionsCtx, children: _jsx(ChatRunningContext.Provider, { value: isRunning, children: _jsxs("div", { className: cn("relative flex flex-1 flex-col h-full min-h-0 text-foreground", className), onDragEnter: handleChatDragEnter, onDragOver: handleChatDragOver, onDragLeave: handleChatDragLeave, onDrop: handleChatDrop, children: [dropActive && (_jsx("div", { "aria-hidden": "true", className: "pointer-events-none absolute inset-0 z-50 flex items-center justify-center rounded-md border-2 border-dashed border-primary/70 bg-primary/5 backdrop-blur-[1px]", children: _jsx("span", { className: "rounded-md bg-background/90 px-3 py-1.5 text-xs font-medium text-foreground shadow-sm", children: "Drop to attach" }) })), showHeader && (_jsxs("div", { className: "flex h-11 shrink-0 items-center justify-between border-b border-border px-4", children: [_jsx("span", { className: "text-[13px] font-medium text-muted-foreground", children: "Agent" }), _jsx("div", { className: "flex items-center gap-1", children: onSwitchToCli && (_jsx(TooltipProvider, { delayDuration: 200, children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsxs("button", { onClick: onSwitchToCli, "aria-label": "Switch to CLI", className: "flex items-center gap-1 text-[12px] text-muted-foreground hover:text-foreground px-2 py-1 rounded-md hover:bg-accent", children: [_jsx(IconTerminal, { className: "h-3.5 w-3.5" }), "CLI"] }) }), _jsx(TooltipContent, { children: "Switch to CLI" })] }) })) })] })), _jsx("div", { ref: scrollRef, className: "flex-1 overflow-y-auto overflow-x-hidden min-h-0", children: authError ? (_jsxs("div", { className: "flex flex-col items-center justify-center h-full px-4 gap-3", children: [_jsx("div", { className: "flex h-10 w-10 items-center justify-center rounded-full bg-destructive/10", children: _jsx(IconLock, { className: "h-5 w-5 text-destructive" }) }), _jsxs("div", { className: "text-center max-w-[280px]", children: [_jsx("p", { className: "text-sm font-medium text-foreground mb-1", children: authSessionAvailable
|
|
2466
2745
|
? "Chat session needs refresh"
|
|
2467
2746
|
: authError.sessionExpired
|
|
2468
2747
|
? "Session expired"
|
|
@@ -2488,15 +2767,15 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
2488
2767
|
window.location.reload();
|
|
2489
2768
|
}, className: authSessionAvailable
|
|
2490
2769
|
? "text-xs text-background bg-foreground hover:opacity-90 px-3 py-1.5 rounded-md"
|
|
2491
|
-
: "text-xs text-muted-foreground hover:text-foreground px-3 py-1.5 rounded-md border border-border hover:bg-accent", children: "Refresh chat" })] })] })) : missingApiKey && messages.length === 0 ? (_jsx("div", { className: "flex flex-col items-center justify-center h-full px-2", children: _jsx(BuilderSetupCard, { onConnected: handleBuilderConnected, bouncePulse: missingKeyBouncePulse }) })) : isRestoring ? (_jsxs("div", { className: "flex flex-col gap-3 p-4", children: [_jsx("div", { className: "flex justify-end", children: _jsx("div", { className: "h-8 w-32 rounded-lg bg-muted animate-pulse" }) }), _jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx("div", { className: "h-4 w-48 rounded bg-muted animate-pulse" }), _jsx("div", { className: "h-4 w-64 rounded bg-muted animate-pulse" }), _jsx("div", { className: "h-4 w-40 rounded bg-muted animate-pulse" })] })] })) : messages.length === 0 && !isReconnecting ? (_jsxs("div", { className: "flex flex-col items-center justify-center gap-4 py-16 px-4 h-full", children: [_jsx("div", { className: "flex h-10 w-10 items-center justify-center rounded-full bg-muted", children: _jsx(IconMessage, { className: "h-5 w-5 text-muted-foreground" }) }), _jsx("p", { className: "text-sm text-muted-foreground text-center max-w-[240px]", children: emptyStateText ?? "How can I help you?" }), suggestions && suggestions.length > 0 && (_jsx("div", { className: "flex flex-col gap-1.5 w-full max-w-[280px]", children: suggestions.map((suggestion) => (_jsx("button", { onClick: () => {
|
|
2770
|
+
: "text-xs text-muted-foreground hover:text-foreground px-3 py-1.5 rounded-md border border-border hover:bg-accent", children: "Refresh chat" })] })] })) : missingApiKey && messages.length === 0 ? (_jsx("div", { className: "flex flex-col items-center justify-center h-full px-2", children: _jsx(BuilderSetupCard, { onConnected: handleBuilderConnected, bouncePulse: missingKeyBouncePulse }) })) : isRestoring ? (_jsxs("div", { className: "flex flex-col gap-3 p-4", children: [_jsx("div", { className: "flex justify-end", children: _jsx("div", { className: "h-8 w-32 rounded-lg bg-muted animate-pulse" }) }), _jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx("div", { className: "h-4 w-48 rounded bg-muted animate-pulse" }), _jsx("div", { className: "h-4 w-64 rounded bg-muted animate-pulse" }), _jsx("div", { className: "h-4 w-40 rounded bg-muted animate-pulse" })] })] })) : messages.length === 0 && !isReconnecting ? (_jsxs("div", { className: "flex flex-col items-center justify-center gap-4 py-16 px-4 h-full", children: [_jsx("div", { className: "flex h-10 w-10 items-center justify-center rounded-full bg-muted", children: _jsx(IconMessage, { className: "h-5 w-5 text-muted-foreground" }) }), _jsx("p", { className: "text-sm text-muted-foreground text-center max-w-[240px]", children: emptyStateText ?? "How can I help you?" }), emptyStateAddon, suggestions && suggestions.length > 0 && (_jsx("div", { className: "flex flex-col gap-1.5 w-full max-w-[280px]", children: suggestions.map((suggestion) => (_jsx("button", { onClick: () => {
|
|
2492
2771
|
threadRuntime.append({
|
|
2493
2772
|
role: "user",
|
|
2494
2773
|
content: [{ type: "text", text: suggestion }],
|
|
2495
2774
|
});
|
|
2496
|
-
}, className: "w-full rounded-lg border border-border px-3 py-2 text-left text-[13px] text-muted-foreground hover:bg-accent hover:text-foreground", children: suggestion }, suggestion))) }))] })) : (_jsxs("div", { className: "agent-thread-content flex flex-col gap-4 px-4 py-4", children: [_jsx(ThreadPrimitive.Messages, { components: {
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2775
|
+
}, className: "w-full rounded-lg border border-border px-3 py-2 text-left text-[13px] text-muted-foreground hover:bg-accent hover:text-foreground", children: suggestion }, suggestion))) }))] })) : (_jsxs("div", { className: "agent-thread-content flex flex-col gap-4 px-4 py-4", children: [_jsx(AssistantMessageListErrorBoundary, { resetKey: messageListResetKey, children: _jsx(ThreadPrimitive.Messages, { components: {
|
|
2776
|
+
UserMessage,
|
|
2777
|
+
AssistantMessage,
|
|
2778
|
+
} }) }), missingApiKey && (_jsx(BuilderSetupCard, { onConnected: handleBuilderConnected, bouncePulse: missingKeyBouncePulse })), visibleLoopLimit && !showRunningInUI && (_jsx(LoopLimitContinueCard, { info: visibleLoopLimit, onContinue: () => {
|
|
2500
2779
|
setShowContinue(false);
|
|
2501
2780
|
setLoopLimitInfo(null);
|
|
2502
2781
|
addToQueue("Continue from where you left off.");
|
|
@@ -2568,7 +2847,7 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
2568
2847
|
}));
|
|
2569
2848
|
}, className: "shrink-0 flex h-7 w-7 items-center justify-center rounded-md bg-muted text-foreground hover:bg-muted/80", children: _jsx(IconPlayerStop, { className: "h-3.5 w-3.5" }) }) }), _jsx(TooltipContent, { children: "Stop generating" })] })) : undefined })] }) })] }) }) }) }));
|
|
2570
2849
|
});
|
|
2571
|
-
export const AssistantChat = forwardRef(function AssistantChat({ apiUrl = agentNativePath("/_agent-native/agent-chat"), tabId, threadId, ...props }, ref) {
|
|
2850
|
+
export const AssistantChat = forwardRef(function AssistantChat({ apiUrl = agentNativePath("/_agent-native/agent-chat"), tabId, browserTabId, threadId, contextScope, ...props }, ref) {
|
|
2572
2851
|
const modelRef = useRef(props.selectedModel);
|
|
2573
2852
|
modelRef.current = props.selectedModel;
|
|
2574
2853
|
const engineRef = useRef(props.selectedEngine);
|
|
@@ -2577,6 +2856,8 @@ export const AssistantChat = forwardRef(function AssistantChat({ apiUrl = agentN
|
|
|
2577
2856
|
effortRef.current = props.selectedEffort;
|
|
2578
2857
|
const execModeRef = useRef(props.execMode);
|
|
2579
2858
|
execModeRef.current = props.execMode;
|
|
2859
|
+
const scopeRef = useRef(contextScope);
|
|
2860
|
+
scopeRef.current = contextScope;
|
|
2580
2861
|
const adapter = useMemo(() => createAgentChatAdapter({
|
|
2581
2862
|
apiUrl,
|
|
2582
2863
|
tabId,
|
|
@@ -2585,15 +2866,17 @@ export const AssistantChat = forwardRef(function AssistantChat({ apiUrl = agentN
|
|
|
2585
2866
|
engineRef,
|
|
2586
2867
|
effortRef,
|
|
2587
2868
|
execModeRef,
|
|
2588
|
-
|
|
2869
|
+
browserTabId,
|
|
2870
|
+
scopeRef,
|
|
2871
|
+
}), [apiUrl, tabId, threadId, browserTabId]);
|
|
2589
2872
|
const attachmentAdapter = useMemo(() => new CompositeAttachmentAdapter([
|
|
2590
|
-
new
|
|
2873
|
+
new DownscalingImageAttachmentAdapter(),
|
|
2591
2874
|
new BinaryDocumentAttachmentAdapter(),
|
|
2592
2875
|
new TextAttachmentAdapter(),
|
|
2593
2876
|
]), []);
|
|
2594
2877
|
const runtime = useLocalRuntime(adapter, {
|
|
2595
2878
|
adapters: { attachments: attachmentAdapter },
|
|
2596
2879
|
});
|
|
2597
|
-
return (_jsx(AssistantRuntimeProvider, { runtime: runtime, children: _jsx(ThreadPrimitive.Root, { className: "flex flex-1 flex-col h-full min-h-0 overflow-x-hidden", children: _jsx(AssistantChatInner, { ref: ref, ...props, apiUrl: apiUrl, tabId: tabId, threadId: threadId }) }) }));
|
|
2880
|
+
return (_jsx(AssistantRuntimeProvider, { runtime: runtime, children: _jsx(ThreadPrimitive.Root, { className: "flex flex-1 flex-col h-full min-h-0 overflow-x-hidden", children: _jsx(AssistantUiStaleIndexErrorBoundary, { resetKey: `${tabId ?? ""}:${threadId ?? ""}`, componentName: "AssistantChat", children: _jsx(AssistantChatInner, { ref: ref, ...props, apiUrl: apiUrl, tabId: tabId, threadId: threadId }) }) }) }));
|
|
2598
2881
|
});
|
|
2599
2882
|
//# sourceMappingURL=AssistantChat.js.map
|