@agent-native/core 0.4.5 → 0.5.0-dev.b51eaae
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/dist/a2a/client.d.ts +7 -0
- package/dist/a2a/client.d.ts.map +1 -1
- package/dist/a2a/client.js +24 -3
- package/dist/a2a/client.js.map +1 -1
- package/dist/a2a/handlers.d.ts +6 -3
- package/dist/a2a/handlers.d.ts.map +1 -1
- package/dist/a2a/handlers.js +45 -39
- package/dist/a2a/handlers.js.map +1 -1
- package/dist/a2a/index.d.ts +1 -1
- package/dist/a2a/index.d.ts.map +1 -1
- package/dist/a2a/index.js +2 -2
- package/dist/a2a/index.js.map +1 -1
- package/dist/a2a/server.d.ts +7 -2
- package/dist/a2a/server.d.ts.map +1 -1
- package/dist/a2a/server.js +54 -14
- package/dist/a2a/server.js.map +1 -1
- package/dist/a2a/task-store.d.ts +6 -6
- package/dist/a2a/task-store.d.ts.map +1 -1
- package/dist/a2a/task-store.js +102 -42
- package/dist/a2a/task-store.js.map +1 -1
- package/dist/a2a/types.d.ts +2 -0
- package/dist/a2a/types.d.ts.map +1 -1
- package/dist/action.d.ts +46 -0
- package/dist/action.d.ts.map +1 -0
- package/dist/action.js +35 -0
- package/dist/action.js.map +1 -0
- package/dist/adapters/sync/file-sync.js +1 -1
- package/dist/agent/index.d.ts +2 -2
- package/dist/agent/index.d.ts.map +1 -1
- package/dist/agent/index.js.map +1 -1
- package/dist/agent/production-agent.d.ts +22 -6
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +336 -123
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/agent/run-manager.d.ts +43 -0
- package/dist/agent/run-manager.d.ts.map +1 -0
- package/dist/agent/run-manager.js +358 -0
- package/dist/agent/run-manager.js.map +1 -0
- package/dist/agent/run-store.d.ts +26 -0
- package/dist/agent/run-store.d.ts.map +1 -0
- package/dist/agent/run-store.js +145 -0
- package/dist/agent/run-store.js.map +1 -0
- package/dist/agent/thread-data-builder.d.ts +30 -0
- package/dist/agent/thread-data-builder.d.ts.map +1 -0
- package/dist/agent/thread-data-builder.js +88 -0
- package/dist/agent/thread-data-builder.js.map +1 -0
- package/dist/agent/types.d.ts +52 -1
- package/dist/agent/types.d.ts.map +1 -1
- package/dist/application-state/emitter.d.ts +3 -2
- package/dist/application-state/emitter.d.ts.map +1 -1
- package/dist/application-state/emitter.js +14 -4
- package/dist/application-state/emitter.js.map +1 -1
- package/dist/application-state/handlers.d.ts.map +1 -1
- package/dist/application-state/handlers.js +13 -16
- package/dist/application-state/handlers.js.map +1 -1
- package/dist/application-state/script-helpers.d.ts +1 -1
- package/dist/application-state/script-helpers.d.ts.map +1 -1
- package/dist/application-state/script-helpers.js +15 -5
- package/dist/application-state/script-helpers.js.map +1 -1
- package/dist/application-state/store.d.ts +4 -3
- package/dist/application-state/store.d.ts.map +1 -1
- package/dist/application-state/store.js +31 -59
- package/dist/application-state/store.js.map +1 -1
- package/dist/chat-threads/emitter.d.ts +9 -0
- package/dist/chat-threads/emitter.d.ts.map +1 -0
- package/dist/chat-threads/emitter.js +14 -0
- package/dist/chat-threads/emitter.js.map +1 -0
- package/dist/chat-threads/store.d.ts +28 -0
- package/dist/chat-threads/store.d.ts.map +1 -0
- package/dist/chat-threads/store.js +124 -0
- package/dist/chat-threads/store.js.map +1 -0
- package/dist/cli/create.d.ts.map +1 -1
- package/dist/cli/create.js +4 -18
- package/dist/cli/create.js.map +1 -1
- package/dist/cli/index.js +30 -3
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/setup-agents.d.ts +11 -0
- package/dist/cli/setup-agents.d.ts.map +1 -0
- package/dist/cli/setup-agents.js +123 -0
- package/dist/cli/setup-agents.js.map +1 -0
- package/dist/client/AgentPanel.d.ts +9 -2
- package/dist/client/AgentPanel.d.ts.map +1 -1
- package/dist/client/AgentPanel.js +466 -29
- package/dist/client/AgentPanel.js.map +1 -1
- package/dist/client/AssistantChat.d.ts +25 -3
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +613 -83
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/ClientOnly.d.ts +14 -0
- package/dist/client/ClientOnly.d.ts.map +1 -0
- package/dist/client/ClientOnly.js +17 -0
- package/dist/client/ClientOnly.js.map +1 -0
- package/dist/client/CommandMenu.d.ts +71 -0
- package/dist/client/CommandMenu.d.ts.map +1 -0
- package/dist/client/CommandMenu.js +257 -0
- package/dist/client/CommandMenu.js.map +1 -0
- package/dist/client/DefaultSpinner.d.ts +7 -0
- package/dist/client/DefaultSpinner.d.ts.map +1 -0
- package/dist/client/DefaultSpinner.js +28 -0
- package/dist/client/DefaultSpinner.js.map +1 -0
- package/dist/client/MultiTabAssistantChat.d.ts +34 -2
- package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
- package/dist/client/MultiTabAssistantChat.js +346 -57
- package/dist/client/MultiTabAssistantChat.js.map +1 -1
- package/dist/client/PoweredByBadge.d.ts.map +1 -1
- package/dist/client/PoweredByBadge.js +2 -1
- package/dist/client/PoweredByBadge.js.map +1 -1
- package/dist/client/active-run-state.d.ts +10 -0
- package/dist/client/active-run-state.d.ts.map +1 -0
- package/dist/client/active-run-state.js +32 -0
- package/dist/client/active-run-state.js.map +1 -0
- package/dist/client/agent-chat-adapter.d.ts +2 -1
- package/dist/client/agent-chat-adapter.d.ts.map +1 -1
- package/dist/client/agent-chat-adapter.js +83 -129
- package/dist/client/agent-chat-adapter.js.map +1 -1
- package/dist/client/agent-chat.js +2 -2
- package/dist/client/agent-chat.js.map +1 -1
- package/dist/client/components/ApiKeySettings.d.ts +2 -2
- package/dist/client/components/ApiKeySettings.js +4 -4
- package/dist/client/components/ApiKeySettings.js.map +1 -1
- package/dist/client/components/CodeRequiredDialog.d.ts.map +1 -1
- package/dist/client/components/CodeRequiredDialog.js +4 -3
- package/dist/client/components/CodeRequiredDialog.js.map +1 -1
- package/dist/client/composer/MentionPopover.d.ts +26 -0
- package/dist/client/composer/MentionPopover.d.ts.map +1 -0
- package/dist/client/composer/MentionPopover.js +130 -0
- package/dist/client/composer/MentionPopover.js.map +1 -0
- package/dist/client/composer/TiptapComposer.d.ts +19 -0
- package/dist/client/composer/TiptapComposer.d.ts.map +1 -0
- package/dist/client/composer/TiptapComposer.js +415 -0
- package/dist/client/composer/TiptapComposer.js.map +1 -0
- package/dist/client/composer/extensions/FileReference.d.ts +3 -0
- package/dist/client/composer/extensions/FileReference.d.ts.map +1 -0
- package/dist/client/composer/extensions/FileReference.js +36 -0
- package/dist/client/composer/extensions/FileReference.js.map +1 -0
- package/dist/client/composer/extensions/MentionReference.d.ts +3 -0
- package/dist/client/composer/extensions/MentionReference.d.ts.map +1 -0
- package/dist/client/composer/extensions/MentionReference.js +63 -0
- package/dist/client/composer/extensions/MentionReference.js.map +1 -0
- package/dist/client/composer/extensions/SkillReference.d.ts +3 -0
- package/dist/client/composer/extensions/SkillReference.d.ts.map +1 -0
- package/dist/client/composer/extensions/SkillReference.js +40 -0
- package/dist/client/composer/extensions/SkillReference.js.map +1 -0
- package/dist/client/composer/index.d.ts +8 -0
- package/dist/client/composer/index.d.ts.map +1 -0
- package/dist/client/composer/index.js +7 -0
- package/dist/client/composer/index.js.map +1 -0
- package/dist/client/composer/types.d.ts +32 -0
- package/dist/client/composer/types.d.ts.map +1 -0
- package/dist/client/composer/types.js +2 -0
- package/dist/client/composer/types.js.map +1 -0
- package/dist/client/composer/use-file-search.d.ts +6 -0
- package/dist/client/composer/use-file-search.d.ts.map +1 -0
- package/dist/client/composer/use-file-search.js +40 -0
- package/dist/client/composer/use-file-search.js.map +1 -0
- package/dist/client/composer/use-mention-search.d.ts +6 -0
- package/dist/client/composer/use-mention-search.d.ts.map +1 -0
- package/dist/client/composer/use-mention-search.js +39 -0
- package/dist/client/composer/use-mention-search.js.map +1 -0
- package/dist/client/composer/use-skills.d.ts +7 -0
- package/dist/client/composer/use-skills.d.ts.map +1 -0
- package/dist/client/composer/use-skills.js +38 -0
- package/dist/client/composer/use-skills.js.map +1 -0
- package/dist/client/index.d.ts +9 -4
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +8 -3
- package/dist/client/index.js.map +1 -1
- package/dist/client/resources/ResourceEditor.d.ts +7 -0
- package/dist/client/resources/ResourceEditor.d.ts.map +1 -0
- package/dist/client/resources/ResourceEditor.js +851 -0
- package/dist/client/resources/ResourceEditor.js.map +1 -0
- package/dist/client/resources/ResourceTree.d.ts +13 -0
- package/dist/client/resources/ResourceTree.d.ts.map +1 -0
- package/dist/client/resources/ResourceTree.js +122 -0
- package/dist/client/resources/ResourceTree.js.map +1 -0
- package/dist/client/resources/ResourcesPanel.d.ts +2 -0
- package/dist/client/resources/ResourcesPanel.d.ts.map +1 -0
- package/dist/client/resources/ResourcesPanel.js +341 -0
- package/dist/client/resources/ResourcesPanel.js.map +1 -0
- package/dist/client/resources/index.d.ts +5 -0
- package/dist/client/resources/index.d.ts.map +1 -0
- package/dist/client/resources/index.js +5 -0
- package/dist/client/resources/index.js.map +1 -0
- package/dist/client/resources/use-resources.d.ts +45 -0
- package/dist/client/resources/use-resources.d.ts.map +1 -0
- package/dist/client/resources/use-resources.js +102 -0
- package/dist/client/resources/use-resources.js.map +1 -0
- package/dist/client/sse-event-processor.d.ts +50 -0
- package/dist/client/sse-event-processor.d.ts.map +1 -0
- package/dist/client/sse-event-processor.js +267 -0
- package/dist/client/sse-event-processor.js.map +1 -0
- package/dist/client/terminal/AgentTerminal.d.ts +1 -1
- package/dist/client/terminal/AgentTerminal.d.ts.map +1 -1
- package/dist/client/terminal/AgentTerminal.js +11 -6
- package/dist/client/terminal/AgentTerminal.js.map +1 -1
- package/dist/client/use-agent-chat.d.ts +1 -1
- package/dist/client/use-agent-chat.d.ts.map +1 -1
- package/dist/client/use-agent-chat.js +3 -3
- package/dist/client/use-agent-chat.js.map +1 -1
- package/dist/client/use-chat-threads.d.ts +36 -0
- package/dist/client/use-chat-threads.d.ts.map +1 -0
- package/dist/client/use-chat-threads.js +175 -0
- package/dist/client/use-chat-threads.js.map +1 -0
- package/dist/client/use-db-sync.d.ts +35 -0
- package/dist/client/use-db-sync.d.ts.map +1 -0
- package/dist/client/use-db-sync.js +74 -0
- package/dist/client/use-db-sync.js.map +1 -0
- package/dist/client/use-dev-mode.d.ts +4 -2
- package/dist/client/use-dev-mode.d.ts.map +1 -1
- package/dist/client/use-dev-mode.js +39 -12
- package/dist/client/use-dev-mode.js.map +1 -1
- package/dist/client/use-file-sync-status.d.ts +1 -1
- package/dist/client/use-file-sync-status.js +3 -3
- package/dist/client/use-file-sync-status.js.map +1 -1
- package/dist/client/use-session.d.ts +1 -1
- package/dist/client/use-session.js +2 -2
- package/dist/client/use-session.js.map +1 -1
- package/dist/client/useProductionAgent.d.ts +1 -1
- package/dist/client/useProductionAgent.d.ts.map +1 -1
- package/dist/client/useProductionAgent.js +38 -3
- package/dist/client/useProductionAgent.js.map +1 -1
- package/dist/credentials/index.d.ts +18 -0
- package/dist/credentials/index.d.ts.map +1 -0
- package/dist/credentials/index.js +32 -0
- package/dist/credentials/index.js.map +1 -0
- package/dist/db/client.d.ts +35 -0
- package/dist/db/client.d.ts.map +1 -0
- package/dist/db/client.js +248 -0
- package/dist/db/client.js.map +1 -0
- package/dist/db/create-get-db.d.ts.map +1 -1
- package/dist/db/create-get-db.js +103 -16
- package/dist/db/create-get-db.js.map +1 -1
- package/dist/db/index.d.ts +10 -6
- package/dist/db/index.d.ts.map +1 -1
- package/dist/db/index.js +10 -4
- package/dist/db/index.js.map +1 -1
- package/dist/db/migrations.d.ts.map +1 -1
- package/dist/db/migrations.js +31 -30
- package/dist/db/migrations.js.map +1 -1
- package/dist/db/schema.d.ts +45 -0
- package/dist/db/schema.d.ts.map +1 -0
- package/dist/db/schema.js +61 -0
- package/dist/db/schema.js.map +1 -0
- package/dist/deploy/build.js +35 -6
- package/dist/deploy/build.js.map +1 -1
- package/dist/deploy/route-discovery.d.ts +9 -0
- package/dist/deploy/route-discovery.d.ts.map +1 -1
- package/dist/deploy/route-discovery.js +30 -1
- package/dist/deploy/route-discovery.js.map +1 -1
- package/dist/index.browser.d.ts +1 -1
- package/dist/index.browser.d.ts.map +1 -1
- package/dist/index.browser.js +1 -1
- package/dist/index.browser.js.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/oauth-tokens/store.d.ts.map +1 -1
- package/dist/oauth-tokens/store.js +43 -81
- package/dist/oauth-tokens/store.js.map +1 -1
- package/dist/resources/emitter.d.ts +13 -0
- package/dist/resources/emitter.d.ts.map +1 -0
- package/dist/resources/emitter.js +32 -0
- package/dist/resources/emitter.js.map +1 -0
- package/dist/resources/handlers.d.ts +45 -0
- package/dist/resources/handlers.d.ts.map +1 -0
- package/dist/resources/handlers.js +219 -0
- package/dist/resources/handlers.js.map +1 -0
- package/dist/resources/index.d.ts +5 -0
- package/dist/resources/index.d.ts.map +1 -0
- package/dist/resources/index.js +5 -0
- package/dist/resources/index.js.map +1 -0
- package/dist/resources/script-helpers.d.ts +24 -0
- package/dist/resources/script-helpers.d.ts.map +1 -0
- package/dist/resources/script-helpers.js +36 -0
- package/dist/resources/script-helpers.js.map +1 -0
- package/dist/resources/store.d.ts +35 -0
- package/dist/resources/store.d.ts.map +1 -0
- package/dist/resources/store.js +453 -0
- package/dist/resources/store.js.map +1 -0
- package/dist/scripts/call-agent.d.ts +5 -0
- package/dist/scripts/call-agent.d.ts.map +1 -0
- package/dist/scripts/call-agent.js +107 -0
- package/dist/scripts/call-agent.js.map +1 -0
- package/dist/scripts/core-scripts.d.ts.map +1 -1
- package/dist/scripts/core-scripts.js +2 -0
- package/dist/scripts/core-scripts.js.map +1 -1
- package/dist/scripts/db/exec.d.ts +6 -2
- package/dist/scripts/db/exec.d.ts.map +1 -1
- package/dist/scripts/db/exec.js +127 -36
- package/dist/scripts/db/exec.js.map +1 -1
- package/dist/scripts/db/query.d.ts +7 -2
- package/dist/scripts/db/query.d.ts.map +1 -1
- package/dist/scripts/db/query.js +89 -45
- package/dist/scripts/db/query.js.map +1 -1
- package/dist/scripts/db/schema.d.ts +2 -2
- package/dist/scripts/db/schema.d.ts.map +1 -1
- package/dist/scripts/db/schema.js +145 -6
- package/dist/scripts/db/schema.js.map +1 -1
- package/dist/scripts/db/scoping.d.ts +36 -0
- package/dist/scripts/db/scoping.d.ts.map +1 -0
- package/dist/scripts/db/scoping.js +198 -0
- package/dist/scripts/db/scoping.js.map +1 -0
- package/dist/scripts/dev/index.d.ts +2 -2
- package/dist/scripts/dev/index.js +1 -1
- package/dist/scripts/dev/list-files.d.ts +2 -2
- package/dist/scripts/dev/read-file.d.ts +2 -2
- package/dist/scripts/dev/read-file.js +1 -1
- package/dist/scripts/dev/read-file.js.map +1 -1
- package/dist/scripts/dev/search-files.d.ts +2 -2
- package/dist/scripts/dev/search-files.js +1 -1
- package/dist/scripts/dev/search-files.js.map +1 -1
- package/dist/scripts/dev/shell.d.ts +2 -2
- package/dist/scripts/dev/shell.js +1 -1
- package/dist/scripts/dev/shell.js.map +1 -1
- package/dist/scripts/dev/write-file.d.ts +2 -2
- package/dist/scripts/dev/write-file.js +1 -1
- package/dist/scripts/dev/write-file.js.map +1 -1
- package/dist/scripts/resources/delete.d.ts +10 -0
- package/dist/scripts/resources/delete.d.ts.map +1 -0
- package/dist/scripts/resources/delete.js +38 -0
- package/dist/scripts/resources/delete.js.map +1 -0
- package/dist/scripts/resources/index.d.ts +2 -0
- package/dist/scripts/resources/index.d.ts.map +1 -0
- package/dist/scripts/resources/index.js +8 -0
- package/dist/scripts/resources/index.js.map +1 -0
- package/dist/scripts/resources/list.d.ts +10 -0
- package/dist/scripts/resources/list.d.ts.map +1 -0
- package/dist/scripts/resources/list.js +57 -0
- package/dist/scripts/resources/list.js.map +1 -0
- package/dist/scripts/resources/migrate-learnings.d.ts +10 -0
- package/dist/scripts/resources/migrate-learnings.d.ts.map +1 -0
- package/dist/scripts/resources/migrate-learnings.js +23 -0
- package/dist/scripts/resources/migrate-learnings.js.map +1 -0
- package/dist/scripts/resources/read.d.ts +10 -0
- package/dist/scripts/resources/read.d.ts.map +1 -0
- package/dist/scripts/resources/read.js +59 -0
- package/dist/scripts/resources/read.js.map +1 -0
- package/dist/scripts/resources/write.d.ts +10 -0
- package/dist/scripts/resources/write.d.ts.map +1 -0
- package/dist/scripts/resources/write.js +67 -0
- package/dist/scripts/resources/write.js.map +1 -0
- package/dist/scripts/runner.d.ts +7 -7
- package/dist/scripts/runner.d.ts.map +1 -1
- package/dist/scripts/runner.js +68 -27
- package/dist/scripts/runner.js.map +1 -1
- package/dist/scripts/utils.d.ts +4 -1
- package/dist/scripts/utils.d.ts.map +1 -1
- package/dist/scripts/utils.js +5 -3
- package/dist/scripts/utils.js.map +1 -1
- package/dist/server/action-discovery.d.ts +40 -0
- package/dist/server/action-discovery.d.ts.map +1 -0
- package/dist/server/action-discovery.js +189 -0
- package/dist/server/action-discovery.js.map +1 -0
- package/dist/server/agent-chat-plugin.d.ts +12 -23
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +1087 -36
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/agent-discovery.d.ts +16 -0
- package/dist/server/agent-discovery.d.ts.map +1 -0
- package/dist/server/agent-discovery.js +136 -0
- package/dist/server/agent-discovery.js.map +1 -0
- package/dist/server/auth-plugin.d.ts +5 -0
- package/dist/server/auth-plugin.d.ts.map +1 -1
- package/dist/server/auth-plugin.js +12 -1
- package/dist/server/auth-plugin.js.map +1 -1
- package/dist/server/auth.d.ts +3 -1
- package/dist/server/auth.d.ts.map +1 -1
- package/dist/server/auth.js +576 -117
- package/dist/server/auth.js.map +1 -1
- package/dist/server/core-routes-plugin.d.ts +57 -0
- package/dist/server/core-routes-plugin.d.ts.map +1 -0
- package/dist/server/core-routes-plugin.js +125 -0
- package/dist/server/core-routes-plugin.js.map +1 -0
- package/dist/server/create-server.d.ts +4 -4
- package/dist/server/create-server.d.ts.map +1 -1
- package/dist/server/create-server.js +5 -5
- package/dist/server/create-server.js.map +1 -1
- package/dist/server/default-watcher.d.ts +9 -3
- package/dist/server/default-watcher.d.ts.map +1 -1
- package/dist/server/default-watcher.js +26 -6
- package/dist/server/default-watcher.js.map +1 -1
- package/dist/server/google-auth-plugin.js +3 -3
- package/dist/server/google-auth-plugin.js.map +1 -1
- package/dist/server/google-oauth.d.ts +72 -0
- package/dist/server/google-oauth.d.ts.map +1 -0
- package/dist/server/google-oauth.js +187 -0
- package/dist/server/google-oauth.js.map +1 -0
- package/dist/server/index.d.ts +9 -2
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +8 -1
- package/dist/server/index.js.map +1 -1
- package/dist/server/oauth-helpers.d.ts +16 -0
- package/dist/server/oauth-helpers.d.ts.map +1 -0
- package/dist/server/oauth-helpers.js +25 -0
- package/dist/server/oauth-helpers.js.map +1 -0
- package/dist/server/poll.d.ts +40 -0
- package/dist/server/poll.d.ts.map +1 -0
- package/dist/server/poll.js +49 -0
- package/dist/server/poll.js.map +1 -0
- package/dist/server/resources-plugin.d.ts +27 -0
- package/dist/server/resources-plugin.d.ts.map +1 -0
- package/dist/server/resources-plugin.js +74 -0
- package/dist/server/resources-plugin.js.map +1 -0
- package/dist/server/script-discovery.d.ts +6 -0
- package/dist/server/script-discovery.d.ts.map +1 -0
- package/dist/server/script-discovery.js +6 -0
- package/dist/server/script-discovery.js.map +1 -0
- package/dist/server/sse.d.ts +1 -1
- package/dist/server/sse.js +1 -1
- package/dist/settings/handlers.d.ts +3 -3
- package/dist/settings/handlers.d.ts.map +1 -1
- package/dist/settings/handlers.js +8 -6
- package/dist/settings/handlers.js.map +1 -1
- package/dist/settings/index.d.ts +1 -1
- package/dist/settings/index.d.ts.map +1 -1
- package/dist/settings/index.js.map +1 -1
- package/dist/settings/store.d.ts +6 -2
- package/dist/settings/store.d.ts.map +1 -1
- package/dist/settings/store.js +26 -63
- package/dist/settings/store.js.map +1 -1
- package/dist/settings/user-settings.d.ts +3 -2
- package/dist/settings/user-settings.d.ts.map +1 -1
- package/dist/settings/user-settings.js +5 -5
- package/dist/settings/user-settings.js.map +1 -1
- package/dist/tailwind.preset.d.ts +7 -6
- package/dist/tailwind.preset.d.ts.map +1 -1
- package/dist/tailwind.preset.js +18 -1
- package/dist/tailwind.preset.js.map +1 -1
- package/dist/terminal/cli-registry.d.ts +1 -1
- package/dist/terminal/cli-registry.js +3 -3
- package/dist/terminal/cli-registry.js.map +1 -1
- package/dist/terminal/pty-server.d.ts.map +1 -1
- package/dist/terminal/pty-server.js +65 -11
- package/dist/terminal/pty-server.js.map +1 -1
- package/dist/terminal/terminal-plugin.d.ts +2 -2
- package/dist/terminal/terminal-plugin.d.ts.map +1 -1
- package/dist/terminal/terminal-plugin.js +27 -21
- package/dist/terminal/terminal-plugin.js.map +1 -1
- package/dist/vite/client.d.ts.map +1 -1
- package/dist/vite/client.js +114 -8
- package/dist/vite/client.js.map +1 -1
- package/dist/vite/dev-api-server.d.ts +1 -1
- package/dist/vite/dev-api-server.d.ts.map +1 -1
- package/dist/vite/dev-api-server.js +105 -22
- package/dist/vite/dev-api-server.js.map +1 -1
- package/package.json +22 -6
- package/src/templates/default/.agents/skills/actions/SKILL.md +136 -0
- package/src/templates/default/.agents/skills/create-skill/SKILL.md +1 -1
- package/src/templates/default/.agents/skills/delegate-to-agent/SKILL.md +1 -1
- package/src/templates/default/.agents/skills/files-as-database/SKILL.md +2 -2
- package/src/templates/default/.agents/skills/real-time-sync/SKILL.md +112 -0
- package/src/templates/default/AGENTS.md +56 -164
- package/src/templates/default/DEVELOPING.md +117 -0
- package/src/templates/default/{scripts → actions}/hello.ts +1 -1
- package/src/templates/default/actions/navigate.ts +53 -0
- package/src/templates/default/actions/view-screen.ts +39 -0
- package/src/templates/default/app/global.css +2 -2
- package/src/templates/default/app/root.tsx +19 -16
- package/src/templates/default/app/routes/_index.tsx +1 -1
- package/src/templates/default/package.json +4 -0
- package/src/templates/default/server/plugins/.gitkeep +0 -0
- package/dist/a2a/middleware.d.ts +0 -3
- package/dist/a2a/middleware.d.ts.map +0 -1
- package/dist/a2a/middleware.js +0 -36
- package/dist/a2a/middleware.js.map +0 -1
- package/dist/client/use-file-watcher.d.ts +0 -23
- package/dist/client/use-file-watcher.d.ts.map +0 -1
- package/dist/client/use-file-watcher.js +0 -50
- package/dist/client/use-file-watcher.js.map +0 -1
- package/src/templates/default/.agents/skills/scripts/SKILL.md +0 -121
- package/src/templates/default/.agents/skills/sse-file-watcher/SKILL.md +0 -80
- package/src/templates/default/server/plugins/agent-chat.ts +0 -1
- package/src/templates/default/server/plugins/auth.ts +0 -1
- package/src/templates/default/server/plugins/file-sync.ts +0 -1
- package/src/templates/default/server/plugins/terminal.ts +0 -1
- package/src/templates/default/server/routes/api/events.get.ts +0 -3
- package/src/templates/default/server/routes/api/file-sync/status.get.ts +0 -4
- /package/src/templates/default/{scripts → actions}/run.ts +0 -0
|
@@ -1,55 +1,298 @@
|
|
|
1
|
-
import { jsx as _jsx,
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useState, useRef, useEffect, useCallback, useMemo, forwardRef, useImperativeHandle, } from "react";
|
|
3
|
-
import { AssistantRuntimeProvider, useLocalRuntime, useThreadRuntime, useThread, useMessageRuntime, ThreadPrimitive, ComposerPrimitive, MessagePrimitive, } from "@assistant-ui/react";
|
|
3
|
+
import { AssistantRuntimeProvider, useLocalRuntime, useThreadRuntime, useThread, useAui, useComposer, useMessageRuntime, ThreadPrimitive, ComposerPrimitive, MessagePrimitive, } from "@assistant-ui/react";
|
|
4
|
+
import { SimpleImageAttachmentAdapter, SimpleTextAttachmentAdapter, CompositeAttachmentAdapter, } from "@assistant-ui/react";
|
|
5
|
+
import { MarkdownTextPrimitive } from "@assistant-ui/react-markdown";
|
|
6
|
+
import ReactMarkdown from "react-markdown";
|
|
4
7
|
import { createAgentChatAdapter } from "./agent-chat-adapter.js";
|
|
8
|
+
import { readSSEStreamRaw } from "./sse-event-processor.js";
|
|
5
9
|
import { cn } from "./utils.js";
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
10
|
+
import { TiptapComposer, } from "./composer/TiptapComposer.js";
|
|
11
|
+
import { IconSparkles, IconX, IconPlayerStop, IconCheck, IconChevronDown, IconCopy, IconTerminal, IconLoader2, IconCircleX, IconSquareFilled, IconClock, IconFile, IconFolder, IconFileText, IconCheckbox, IconMail, IconUser, IconPresentation, IconStack2, IconMessageChatbot, } from "@tabler/icons-react";
|
|
12
|
+
// ─── Markdown Text ──────────────────────────────────────────────────────────
|
|
13
|
+
const markdownStyles = `
|
|
14
|
+
.agent-markdown > :first-child { margin-top: 0; }
|
|
15
|
+
.agent-markdown > :last-child { margin-bottom: 0; }
|
|
16
|
+
.agent-markdown p { margin: 0.5em 0; }
|
|
17
|
+
.agent-markdown ul, .agent-markdown ol { margin: 0.5em 0; padding-left: 1.5em; }
|
|
18
|
+
.agent-markdown li { margin: 0.2em 0; }
|
|
19
|
+
.agent-markdown li > p { margin: 0; }
|
|
20
|
+
.agent-markdown h1 { font-size: 1.25em; font-weight: 600; margin: 0.75em 0 0.25em; }
|
|
21
|
+
.agent-markdown h2 { font-size: 1.125em; font-weight: 600; margin: 0.75em 0 0.25em; }
|
|
22
|
+
.agent-markdown h3 { font-size: 1em; font-weight: 600; margin: 0.75em 0 0.25em; }
|
|
23
|
+
.agent-markdown strong { font-weight: 600; }
|
|
24
|
+
.agent-markdown em { font-style: italic; }
|
|
25
|
+
.agent-markdown code { font-size: 0.875em; padding: 0.15em 0.35em; border-radius: 0.25em; background: var(--color-muted, hsl(0 0% 15%)); }
|
|
26
|
+
.agent-markdown pre { margin: 0.5em 0; padding: 0.75em 1em; border-radius: 0.375em; background: var(--color-muted, hsl(0 0% 15%)); overflow-x: auto; }
|
|
27
|
+
.agent-markdown pre code { padding: 0; background: transparent; font-size: 0.8125em; }
|
|
28
|
+
.agent-markdown hr { border: none; border-top: 1px solid var(--color-border, hsl(0 0% 20%)); margin: 0.75em 0; }
|
|
29
|
+
.agent-markdown a { text-decoration: underline; text-underline-offset: 2px; }
|
|
30
|
+
.agent-markdown blockquote { border-left: 2px solid var(--color-border, hsl(0 0% 20%)); padding-left: 0.75em; margin: 0.5em 0; opacity: 0.8; }
|
|
31
|
+
.agent-markdown table { border-collapse: collapse; margin: 0.5em 0; font-size: 0.875em; }
|
|
32
|
+
.agent-markdown th, .agent-markdown td { border: 1px solid var(--color-border, hsl(0 0% 20%)); padding: 0.35em 0.65em; text-align: left; }
|
|
33
|
+
.agent-markdown th { font-weight: 600; background: var(--color-muted, hsl(0 0% 15%)); }
|
|
34
|
+
`;
|
|
35
|
+
let stylesInjected = false;
|
|
36
|
+
function injectMarkdownStyles() {
|
|
37
|
+
if (stylesInjected || typeof document === "undefined")
|
|
38
|
+
return;
|
|
39
|
+
stylesInjected = true;
|
|
40
|
+
const style = document.createElement("style");
|
|
41
|
+
style.textContent = markdownStyles;
|
|
42
|
+
document.head.appendChild(style);
|
|
9
43
|
}
|
|
10
|
-
function
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
return (_jsx(
|
|
15
|
-
}
|
|
16
|
-
function CheckIcon({ className }) {
|
|
17
|
-
return (_jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", className: className, children: _jsx("path", { d: "M20 6L9 17l-5-5" }) }));
|
|
44
|
+
function MarkdownText() {
|
|
45
|
+
useEffect(() => {
|
|
46
|
+
injectMarkdownStyles();
|
|
47
|
+
}, []);
|
|
48
|
+
return (_jsx(MarkdownTextPrimitive, { smooth: true, className: "agent-markdown break-words" }));
|
|
18
49
|
}
|
|
19
|
-
|
|
20
|
-
|
|
50
|
+
// ─── Composer Attachment Preview ─────────────────────────────────────────────
|
|
51
|
+
function getImageAttachmentSrc(attachment) {
|
|
52
|
+
if (attachment.type !== "image")
|
|
53
|
+
return null;
|
|
54
|
+
if ("file" in attachment && attachment.file) {
|
|
55
|
+
return URL.createObjectURL(attachment.file);
|
|
56
|
+
}
|
|
57
|
+
const imagePart = attachment.content?.find((part) => part.type === "image");
|
|
58
|
+
return imagePart && "image" in imagePart ? imagePart.image : null;
|
|
21
59
|
}
|
|
22
|
-
function
|
|
23
|
-
|
|
60
|
+
function ComposerAttachmentPreviewCard({ attachment, onRemove, }) {
|
|
61
|
+
const [imageSrc, setImageSrc] = useState(null);
|
|
62
|
+
useEffect(() => {
|
|
63
|
+
const nextSrc = getImageAttachmentSrc(attachment);
|
|
64
|
+
setImageSrc(nextSrc);
|
|
65
|
+
return () => {
|
|
66
|
+
if (nextSrc?.startsWith("blob:")) {
|
|
67
|
+
URL.revokeObjectURL(nextSrc);
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
}, [attachment]);
|
|
71
|
+
const isImage = !!imageSrc;
|
|
72
|
+
return (_jsxs("div", { className: cn("group relative overflow-hidden border border-border/70 bg-muted/50 text-foreground", isImage
|
|
73
|
+
? "h-20 w-20 rounded-xl shadow-[0_12px_30px_-18px_rgba(0,0,0,0.7)]"
|
|
74
|
+
: "inline-flex max-w-[220px] items-center gap-2 rounded-lg px-2.5 py-2 text-xs"), children: [isImage ? (_jsxs(_Fragment, { children: [_jsx("img", { src: imageSrc, alt: attachment.name, className: "h-full w-full object-cover" }), _jsx("div", { className: "pointer-events-none absolute inset-x-0 bottom-0 bg-gradient-to-t from-black/80 via-black/30 to-transparent px-2 py-1.5", children: _jsx("div", { className: "truncate text-[10px] font-medium text-white/95", children: attachment.name }) })] })) : (_jsxs(_Fragment, { children: [_jsx("div", { className: "flex h-8 w-8 shrink-0 items-center justify-center rounded-md bg-background text-[10px] font-semibold uppercase tracking-[0.12em] text-muted-foreground", children: attachment.name.split(".").pop() || "file" }), _jsxs("div", { className: "min-w-0", children: [_jsx("div", { className: "truncate font-medium", children: attachment.name }), _jsx("div", { className: "text-[11px] text-muted-foreground", children: attachment.contentType || attachment.type })] })] })), _jsx("button", { type: "button", onClick: () => onRemove(attachment.id), className: cn("absolute flex h-6 w-6 items-center justify-center rounded-full border border-border/60 bg-background/95 text-muted-foreground shadow-sm transition hover:text-foreground", isImage
|
|
75
|
+
? "right-1.5 top-1.5 opacity-100 md:opacity-0 md:group-hover:opacity-100"
|
|
76
|
+
: "right-1.5 top-1.5"), "aria-label": `Remove ${attachment.name}`, children: _jsx(IconX, { className: "h-3 w-3" }) })] }));
|
|
24
77
|
}
|
|
25
|
-
function
|
|
26
|
-
|
|
78
|
+
function ComposerAttachmentPreviewStrip() {
|
|
79
|
+
const attachments = useComposer((state) => state.attachments);
|
|
80
|
+
const aui = useAui();
|
|
81
|
+
const handleRemove = useCallback((id) => {
|
|
82
|
+
void aui.composer().attachment({ id }).remove();
|
|
83
|
+
}, [aui]);
|
|
84
|
+
if (attachments.length === 0)
|
|
85
|
+
return null;
|
|
86
|
+
return (_jsx("div", { className: "flex flex-wrap gap-2 px-2 pt-2", children: attachments.map((attachment) => (_jsx(ComposerAttachmentPreviewCard, { attachment: attachment, onRemove: handleRemove }, attachment.id))) }));
|
|
27
87
|
}
|
|
28
88
|
// ─── Tool Call Fallback ─────────────────────────────────────────────────────
|
|
29
|
-
function ToolCallFallback({ toolName, args, result, }) {
|
|
30
|
-
const
|
|
89
|
+
function ToolCallFallback({ toolName, args, argsText, result, }) {
|
|
90
|
+
const streamRef = useRef(null);
|
|
91
|
+
const thread = useThread();
|
|
92
|
+
const isRunning = result === undefined && thread.isRunning;
|
|
93
|
+
const isAgentCall = toolName.startsWith("agent:");
|
|
94
|
+
// Agent calls default to expanded; regular tools default to collapsed
|
|
95
|
+
const [expanded, setExpanded] = useState(isAgentCall);
|
|
96
|
+
const agentName = isAgentCall ? toolName.slice(6) : null;
|
|
97
|
+
const isAgentError = isAgentCall && result === "Error calling agent";
|
|
98
|
+
// For agent calls, argsText holds the streaming response text
|
|
99
|
+
const agentStreamText = isAgentCall ? (argsText ?? "") : "";
|
|
100
|
+
const hasStreamText = agentStreamText.length > 0;
|
|
101
|
+
const argsStr = isAgentCall
|
|
102
|
+
? ""
|
|
103
|
+
: Object.entries(args)
|
|
104
|
+
.map(([k, v]) => `${k}=${typeof v === "string" ? v : JSON.stringify(v)}`)
|
|
105
|
+
.join(", ");
|
|
106
|
+
const displayName = isAgentCall
|
|
107
|
+
? isRunning
|
|
108
|
+
? `Asking ${agentName}...`
|
|
109
|
+
: isAgentError
|
|
110
|
+
? `Error asking ${agentName}`
|
|
111
|
+
: `Asked ${agentName}`
|
|
112
|
+
: toolName;
|
|
113
|
+
// Agent calls expand only when there's text to show, toggleable when done
|
|
114
|
+
const canExpand = isAgentCall ? hasStreamText : result !== undefined;
|
|
115
|
+
const isExpanded = isAgentCall ? hasStreamText && expanded : expanded;
|
|
116
|
+
// Auto-scroll streaming text to bottom as new content arrives
|
|
117
|
+
useEffect(() => {
|
|
118
|
+
if (isAgentCall && isRunning && streamRef.current) {
|
|
119
|
+
streamRef.current.scrollTop = streamRef.current.scrollHeight;
|
|
120
|
+
}
|
|
121
|
+
}, [agentStreamText, isAgentCall, isRunning]);
|
|
122
|
+
return (_jsxs("div", { className: "my-1 overflow-hidden", children: [_jsxs("button", { onClick: () => canExpand && setExpanded(!isExpanded), 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
|
|
123
|
+
? "bg-muted text-muted-foreground"
|
|
124
|
+
: "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 && !isRunning && (_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, { children: agentStreamText }) })), isExpanded && !isAgentCall && result !== undefined && (_jsx("div", { className: "mt-1 rounded-md bg-muted/50 px-3 py-2 text-xs font-mono text-muted-foreground whitespace-pre-wrap break-all max-h-48 overflow-y-auto", children: typeof result === "string"
|
|
125
|
+
? result
|
|
126
|
+
: JSON.stringify(result, null, 2) }))] }));
|
|
127
|
+
}
|
|
128
|
+
// ─── Reconnect Stream Message ───────────────────────────────────────────────
|
|
129
|
+
// Renders the agent's in-progress response during reconnection (outside
|
|
130
|
+
// assistant-ui's runtime). Uses the same visual styling as normal messages.
|
|
131
|
+
function ReconnectStreamToolCall({ toolName, argsText, args, result, }) {
|
|
132
|
+
const streamRef = useRef(null);
|
|
31
133
|
const isRunning = result === undefined;
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
134
|
+
const isAgentCall = toolName.startsWith("agent:");
|
|
135
|
+
const [expanded, setExpanded] = useState(isAgentCall);
|
|
136
|
+
const agentName = isAgentCall ? toolName.slice(6) : null;
|
|
137
|
+
const isAgentError = isAgentCall && result === "Error calling agent";
|
|
138
|
+
const agentStreamText = isAgentCall ? (argsText ?? "") : "";
|
|
139
|
+
const hasStreamText = agentStreamText.length > 0;
|
|
140
|
+
const argsStr = isAgentCall
|
|
141
|
+
? ""
|
|
142
|
+
: Object.entries(args)
|
|
143
|
+
.map(([k, v]) => `${k}=${typeof v === "string" ? v : JSON.stringify(v)}`)
|
|
144
|
+
.join(", ");
|
|
145
|
+
const displayName = isAgentCall
|
|
146
|
+
? isRunning
|
|
147
|
+
? `Asking ${agentName}...`
|
|
148
|
+
: isAgentError
|
|
149
|
+
? `Error asking ${agentName}`
|
|
150
|
+
: `Asked ${agentName}`
|
|
151
|
+
: toolName;
|
|
152
|
+
const canExpand = isAgentCall ? hasStreamText : result !== undefined;
|
|
153
|
+
const isExpanded = isAgentCall ? hasStreamText && expanded : expanded;
|
|
154
|
+
useEffect(() => {
|
|
155
|
+
if (isAgentCall && isRunning && streamRef.current) {
|
|
156
|
+
streamRef.current.scrollTop = streamRef.current.scrollHeight;
|
|
157
|
+
}
|
|
158
|
+
}, [agentStreamText, isAgentCall, isRunning]);
|
|
159
|
+
return (_jsxs("div", { className: "my-1 overflow-hidden", children: [_jsxs("button", { onClick: () => canExpand && setExpanded(!isExpanded), 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
|
|
160
|
+
? "bg-muted text-muted-foreground"
|
|
161
|
+
: "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" })) : (_jsx(IconCheck, { className: "h-3 w-3 text-emerald-500" })) }), _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 && !isRunning && (_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, { children: agentStreamText }) })), isExpanded && !isAgentCall && result !== undefined && (_jsx("div", { className: "mt-1 rounded-md bg-muted/50 px-3 py-2 text-xs font-mono text-muted-foreground whitespace-pre-wrap break-all max-h-48 overflow-y-auto", children: typeof result === "string"
|
|
38
162
|
? result
|
|
39
163
|
: JSON.stringify(result, null, 2) }))] }));
|
|
40
164
|
}
|
|
165
|
+
function ReconnectStreamMessage({ content }) {
|
|
166
|
+
const endRef = useRef(null);
|
|
167
|
+
useEffect(() => {
|
|
168
|
+
endRef.current?.scrollIntoView({ behavior: "smooth", block: "end" });
|
|
169
|
+
}, [content]);
|
|
170
|
+
return (_jsx("div", { className: "flex justify-start px-4 py-2", children: _jsxs("div", { className: "max-w-[85%] space-y-1", children: [_jsxs("div", { className: "flex items-center gap-1.5 mb-1", children: [_jsx(IconSparkles, { className: "h-3.5 w-3.5 text-muted-foreground" }), _jsx("span", { className: "text-[10px] text-muted-foreground font-medium uppercase tracking-wide", children: "Agent" })] }), content.map((part, i) => {
|
|
171
|
+
if (part.type === "text") {
|
|
172
|
+
return (_jsx("div", { className: "text-sm leading-relaxed whitespace-pre-wrap break-words", children: part.text }, `reconnect-text-${i}`));
|
|
173
|
+
}
|
|
174
|
+
if (part.type === "tool-call") {
|
|
175
|
+
return (_jsx(ReconnectStreamToolCall, { toolName: part.toolName, argsText: part.argsText, args: part.args, result: part.result }, `reconnect-tool-${i}`));
|
|
176
|
+
}
|
|
177
|
+
return null;
|
|
178
|
+
}), _jsx("div", { ref: endRef })] }) }));
|
|
179
|
+
}
|
|
41
180
|
// ─── Message Components ─────────────────────────────────────────────────────
|
|
181
|
+
const mentionIconProps = {
|
|
182
|
+
size: 14,
|
|
183
|
+
className: "shrink-0 text-muted-foreground",
|
|
184
|
+
};
|
|
185
|
+
function MentionChipIcon({ icon }) {
|
|
186
|
+
switch (icon) {
|
|
187
|
+
case "folder":
|
|
188
|
+
return _jsx(IconFolder, { ...mentionIconProps });
|
|
189
|
+
case "document":
|
|
190
|
+
return _jsx(IconFileText, { ...mentionIconProps });
|
|
191
|
+
case "form":
|
|
192
|
+
return _jsx(IconCheckbox, { ...mentionIconProps });
|
|
193
|
+
case "email":
|
|
194
|
+
return _jsx(IconMail, { ...mentionIconProps });
|
|
195
|
+
case "user":
|
|
196
|
+
return _jsx(IconUser, { ...mentionIconProps });
|
|
197
|
+
case "deck":
|
|
198
|
+
return _jsx(IconPresentation, { ...mentionIconProps });
|
|
199
|
+
case "agent":
|
|
200
|
+
return _jsx(IconMessageChatbot, { ...mentionIconProps });
|
|
201
|
+
case "file":
|
|
202
|
+
return _jsx(IconFile, { ...mentionIconProps });
|
|
203
|
+
default:
|
|
204
|
+
return _jsx(IconStack2, { ...mentionIconProps });
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
// Matches rich mention format: @[label|icon] or plain @word
|
|
208
|
+
const richMentionPattern = /@\[([^\]|]+)\|([^\]]+)\]/g;
|
|
209
|
+
const plainMentionPattern = /((?:^|(?<=\s))@(\w+))/g;
|
|
210
|
+
function UserMessageText({ text }) {
|
|
211
|
+
const parts = [];
|
|
212
|
+
let lastIndex = 0;
|
|
213
|
+
let match;
|
|
214
|
+
let hasRichMentions = false;
|
|
215
|
+
// First try rich mentions (@[label|icon])
|
|
216
|
+
richMentionPattern.lastIndex = 0;
|
|
217
|
+
while ((match = richMentionPattern.exec(text)) !== null) {
|
|
218
|
+
hasRichMentions = true;
|
|
219
|
+
const matchStart = match.index;
|
|
220
|
+
if (matchStart > lastIndex) {
|
|
221
|
+
parts.push(text.slice(lastIndex, matchStart));
|
|
222
|
+
}
|
|
223
|
+
const label = match[1];
|
|
224
|
+
const icon = match[2];
|
|
225
|
+
parts.push(_jsxs("span", { className: "inline-flex items-center gap-1 rounded-md border border-input bg-muted/50 px-1.5 py-0.5 text-xs font-medium text-foreground align-middle mx-0.5 max-w-[200px] select-all", "data-mention-label": label, children: [_jsx(MentionChipIcon, { icon: icon }), _jsx("span", { className: "truncate", children: label })] }, matchStart));
|
|
226
|
+
lastIndex = matchStart + match[0].length;
|
|
227
|
+
}
|
|
228
|
+
if (hasRichMentions) {
|
|
229
|
+
if (lastIndex < text.length) {
|
|
230
|
+
parts.push(text.slice(lastIndex));
|
|
231
|
+
}
|
|
232
|
+
return _jsx(_Fragment, { children: parts });
|
|
233
|
+
}
|
|
234
|
+
// Fallback: plain @word mentions (for older messages)
|
|
235
|
+
plainMentionPattern.lastIndex = 0;
|
|
236
|
+
while ((match = plainMentionPattern.exec(text)) !== null) {
|
|
237
|
+
const matchStart = match.index;
|
|
238
|
+
if (matchStart > lastIndex) {
|
|
239
|
+
parts.push(text.slice(lastIndex, matchStart));
|
|
240
|
+
}
|
|
241
|
+
const mentionName = match[2];
|
|
242
|
+
parts.push(_jsxs("span", { className: "inline-flex items-center gap-1 rounded-md border border-input bg-muted/50 px-1.5 py-0.5 text-xs font-medium text-foreground align-middle mx-0.5 select-all", "data-mention-label": mentionName, children: ["@", mentionName] }, matchStart));
|
|
243
|
+
lastIndex = matchStart + match[0].length;
|
|
244
|
+
}
|
|
245
|
+
if (lastIndex < text.length) {
|
|
246
|
+
parts.push(text.slice(lastIndex));
|
|
247
|
+
}
|
|
248
|
+
return _jsx(_Fragment, { children: parts.length > 0 ? parts : text });
|
|
249
|
+
}
|
|
42
250
|
function UserMessage() {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
251
|
+
const [expanded, setExpanded] = useState(false);
|
|
252
|
+
const [isExpandable, setIsExpandable] = useState(false);
|
|
253
|
+
const contentRef = useRef(null);
|
|
254
|
+
useEffect(() => {
|
|
255
|
+
const el = contentRef.current;
|
|
256
|
+
if (!el)
|
|
257
|
+
return;
|
|
258
|
+
const measure = () => {
|
|
259
|
+
setIsExpandable(el.scrollHeight > 200);
|
|
260
|
+
};
|
|
261
|
+
measure();
|
|
262
|
+
const observer = new ResizeObserver(measure);
|
|
263
|
+
observer.observe(el);
|
|
264
|
+
return () => observer.disconnect();
|
|
265
|
+
}, []);
|
|
266
|
+
return (_jsx("div", { className: "flex justify-end", style: { contentVisibility: "auto" }, children: _jsxs("div", { className: "max-w-[85%]", children: [_jsxs("div", { className: "relative rounded-lg bg-accent px-3 py-2 text-sm leading-relaxed text-foreground", onCopy: (e) => {
|
|
267
|
+
const selection = window.getSelection();
|
|
268
|
+
if (!selection || selection.rangeCount === 0)
|
|
269
|
+
return;
|
|
270
|
+
const fragment = selection.getRangeAt(0).cloneContents();
|
|
271
|
+
const mentions = fragment.querySelectorAll("[data-mention-label]");
|
|
272
|
+
if (mentions.length === 0)
|
|
273
|
+
return;
|
|
274
|
+
e.preventDefault();
|
|
275
|
+
mentions.forEach((el) => {
|
|
276
|
+
el.textContent = `@${el.getAttribute("data-mention-label")}`;
|
|
277
|
+
});
|
|
278
|
+
const div = document.createElement("div");
|
|
279
|
+
div.appendChild(fragment);
|
|
280
|
+
e.clipboardData.setData("text/plain", div.textContent || "");
|
|
281
|
+
}, children: [_jsx("div", { ref: contentRef, className: cn("whitespace-pre-wrap break-words", !expanded && isExpandable && "max-h-[200px] overflow-hidden"), children: _jsx(MessagePrimitive.Parts, { components: {
|
|
282
|
+
Text: UserMessageText,
|
|
283
|
+
} }) }), !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"] }))] }) }));
|
|
46
284
|
}
|
|
47
285
|
function AssistantMessage() {
|
|
48
286
|
const [copied, setCopied] = useState(false);
|
|
49
287
|
const messageRuntime = useMessageRuntime();
|
|
288
|
+
const thread = useThread();
|
|
289
|
+
const msg = messageRuntime.getState();
|
|
290
|
+
const isLast = thread.messages.length > 0 &&
|
|
291
|
+
thread.messages[thread.messages.length - 1].id === msg.id;
|
|
292
|
+
const isComplete = !isLast || !thread.isRunning;
|
|
50
293
|
const handleCopy = useCallback(() => {
|
|
51
|
-
const
|
|
52
|
-
const text =
|
|
294
|
+
const m = messageRuntime.getState();
|
|
295
|
+
const text = m.content
|
|
53
296
|
.filter((p) => p.type === "text")
|
|
54
297
|
.map((p) => p.text)
|
|
55
298
|
.join("\n");
|
|
@@ -57,16 +300,23 @@ function AssistantMessage() {
|
|
|
57
300
|
setCopied(true);
|
|
58
301
|
setTimeout(() => setCopied(false), 2000);
|
|
59
302
|
}, [messageRuntime]);
|
|
60
|
-
return (_jsxs("div", { className: "group relative", children: [_jsx("div", { className: "max-w-[95%] text-sm leading-relaxed text-foreground", children: _jsx(MessagePrimitive.Parts, { components: {
|
|
61
|
-
Text:
|
|
303
|
+
return (_jsxs("div", { className: "group relative", style: { contentVisibility: isComplete ? "auto" : "visible" }, children: [_jsx("div", { className: "max-w-[95%] text-sm leading-relaxed text-foreground", children: _jsx(MessagePrimitive.Parts, { components: {
|
|
304
|
+
Text: MarkdownText,
|
|
62
305
|
tools: {
|
|
63
306
|
Fallback: ToolCallFallback,
|
|
64
307
|
},
|
|
65
|
-
} }) }), _jsx("div", { className: "mt-1 flex items-center gap-0.5 opacity-0 group-hover:opacity-100", children: _jsx("button", { onClick: handleCopy, className: "flex h-
|
|
308
|
+
} }) }), isComplete && (_jsx("div", { className: "mt-1 flex items-center gap-0.5 opacity-0 group-hover:opacity-100", children: _jsx("button", { onClick: handleCopy, className: "flex h-6 w-6 items-center justify-center rounded-md text-muted-foreground hover:bg-accent hover:text-foreground", children: copied ? (_jsx(IconCheck, { className: "h-3 w-3" })) : (_jsx(IconCopy, { className: "h-3 w-3" })) }) }))] }));
|
|
66
309
|
}
|
|
67
310
|
// ─── Thinking Indicator ─────────────────────────────────────────────────────
|
|
68
311
|
function ThinkingIndicator() {
|
|
69
|
-
|
|
312
|
+
const [dots, setDots] = useState(1);
|
|
313
|
+
useEffect(() => {
|
|
314
|
+
const interval = setInterval(() => {
|
|
315
|
+
setDots((d) => (d % 3) + 1);
|
|
316
|
+
}, 400);
|
|
317
|
+
return () => clearInterval(interval);
|
|
318
|
+
}, []);
|
|
319
|
+
return (_jsx("div", { className: "flex items-center text-muted-foreground", children: _jsxs("span", { className: "text-xs", children: ["Thinking", ".".repeat(dots)] }) }));
|
|
70
320
|
}
|
|
71
321
|
// ─── API Key Setup Card ─────────────────────────────────────────────────────
|
|
72
322
|
function ApiKeySetupCard({ apiUrl }) {
|
|
@@ -100,9 +350,9 @@ function ApiKeySetupCard({ apiUrl }) {
|
|
|
100
350
|
}
|
|
101
351
|
};
|
|
102
352
|
if (saved) {
|
|
103
|
-
return (_jsx("div", { className: "mx-4 my-6 rounded-lg border border-emerald-500/30 bg-emerald-500/5 p-4", children: _jsxs("div", { className: "flex items-center gap-2 text-sm text-emerald-400", children: [_jsx(
|
|
353
|
+
return (_jsx("div", { className: "mx-4 my-6 rounded-lg border border-emerald-500/30 bg-emerald-500/5 p-4", children: _jsxs("div", { className: "flex items-center gap-2 text-sm text-emerald-400", children: [_jsx(IconCheck, { className: "h-4 w-4" }), "API key saved. Reloading..."] }) }));
|
|
104
354
|
}
|
|
105
|
-
return (_jsxs("div", { className: "mx-4 my-6 rounded-lg border border-border bg-card p-5", children: [_jsxs("div", { className: "flex items-center gap-3 mb-3", children: [_jsx("div", { className: "flex h-9 w-9 shrink-0 items-center justify-center rounded-full bg-muted", children: _jsx(
|
|
355
|
+
return (_jsxs("div", { className: "mx-4 my-6 rounded-lg border border-border bg-card p-5", children: [_jsxs("div", { className: "flex items-center gap-3 mb-3", children: [_jsx("div", { className: "flex h-9 w-9 shrink-0 items-center justify-center rounded-full bg-muted", children: _jsx(IconSparkles, { className: "h-4.5 w-4.5 text-muted-foreground" }) }), _jsxs("div", { children: [_jsx("h3", { className: "text-sm font-medium text-foreground", children: "Connect your AI" }), _jsx("p", { className: "text-xs text-muted-foreground mt-0.5", children: "Add an Anthropic API key to enable the agent" })] })] }), _jsxs("div", { className: "space-y-3", children: [_jsxs("div", { className: "rounded-md bg-muted/50 px-3 py-2.5 text-xs text-muted-foreground leading-relaxed", children: [_jsxs("p", { children: ["1. Go to", " ", _jsx("a", { href: "https://console.anthropic.com/settings/keys", target: "_blank", rel: "noopener noreferrer", className: "underline text-foreground/80 hover:text-foreground", children: "console.anthropic.com/settings/keys" })] }), _jsx("p", { className: "mt-1", children: "2. Create a new API key and paste it below" })] }), _jsx("input", { type: "password", value: apiKey, onChange: (e) => {
|
|
106
356
|
setApiKey(e.target.value);
|
|
107
357
|
setError(null);
|
|
108
358
|
}, onKeyDown: (e) => {
|
|
@@ -110,35 +360,18 @@ function ApiKeySetupCard({ apiUrl }) {
|
|
|
110
360
|
handleSave();
|
|
111
361
|
}, placeholder: "sk-ant-...", className: "w-full rounded-md border border-input bg-background px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground/50 outline-none focus:ring-1 focus:ring-ring", autoComplete: "off" }), error && _jsx("p", { className: "text-xs text-destructive", children: error }), _jsx("button", { onClick: handleSave, disabled: saving || !apiKey.trim(), className: "w-full rounded-md bg-primary px-3 py-2 text-sm font-medium text-primary-foreground hover:opacity-90 disabled:opacity-40 disabled:cursor-not-allowed", children: saving ? "Saving..." : "Save API key" })] })] }));
|
|
112
362
|
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
function
|
|
116
|
-
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
// (not ComposerPrimitive) so we can submit without interrupting the active run.
|
|
121
|
-
function QueueComposer({ composerRef, addToQueue, queuedCount, }) {
|
|
122
|
-
const [value, setValue] = useState("");
|
|
123
|
-
const handleSubmit = useCallback(() => {
|
|
124
|
-
const text = value.trim();
|
|
125
|
-
if (!text)
|
|
126
|
-
return;
|
|
127
|
-
addToQueue(text);
|
|
128
|
-
setValue("");
|
|
129
|
-
// Re-focus after submit
|
|
130
|
-
setTimeout(() => composerRef.current?.focus(), 0);
|
|
131
|
-
}, [value, addToQueue, composerRef]);
|
|
132
|
-
return (_jsxs("div", { className: "flex items-center gap-2 rounded-lg border border-input bg-background px-3 py-2 focus-within:ring-1 focus-within:ring-ring", children: [_jsx("textarea", { ref: composerRef, value: value, onChange: (e) => setValue(e.target.value), onKeyDown: (e) => {
|
|
133
|
-
if (e.key === "Enter" && !e.shiftKey) {
|
|
134
|
-
e.preventDefault();
|
|
135
|
-
handleSubmit();
|
|
136
|
-
}
|
|
137
|
-
}, placeholder: queuedCount > 0
|
|
138
|
-
? `${queuedCount} queued — type another...`
|
|
139
|
-
: "Queue a message...", className: "flex-1 resize-none bg-transparent text-sm text-foreground placeholder:text-muted-foreground outline-none leading-relaxed min-h-[24px] max-h-[120px]", rows: 1 }), _jsx("button", { onClick: handleSubmit, disabled: !value.trim(), className: "shrink-0 flex h-8 w-8 items-center justify-center rounded-md bg-primary/70 text-primary-foreground hover:bg-primary disabled:opacity-30 disabled:cursor-not-allowed", title: "Queue message", children: _jsx(SendIcon, { className: "h-3.5 w-3.5" }) })] }));
|
|
363
|
+
export const CHAT_STORAGE_PREFIX = "agent-chat:";
|
|
364
|
+
/** Remove persisted chat for a given tabId (or "default"). */
|
|
365
|
+
export function clearChatStorage(tabId) {
|
|
366
|
+
try {
|
|
367
|
+
sessionStorage.removeItem(`${CHAT_STORAGE_PREFIX}${tabId || "default"}`);
|
|
368
|
+
}
|
|
369
|
+
catch { }
|
|
140
370
|
}
|
|
141
|
-
|
|
371
|
+
// Re-export for backwards compatibility
|
|
372
|
+
import { extractThreadMeta } from "../agent/thread-data-builder.js";
|
|
373
|
+
export { extractThreadMeta };
|
|
374
|
+
const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateText, suggestions, showHeader = true, onSwitchToCli, className, apiUrl, tabId, threadId, onMessageCountChange, onSaveThread, onGenerateTitle, composerSlot, isNewThread, }, ref) {
|
|
142
375
|
const scrollRef = useRef(null);
|
|
143
376
|
const thread = useThread();
|
|
144
377
|
const threadRuntime = useThreadRuntime();
|
|
@@ -146,14 +379,230 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
146
379
|
const messages = thread.messages;
|
|
147
380
|
const [missingApiKey, setMissingApiKey] = useState(false);
|
|
148
381
|
const [queuedMessages, setQueuedMessages] = useState([]);
|
|
382
|
+
const [showContinue, setShowContinue] = useState(false);
|
|
383
|
+
const [isReconnecting, setIsReconnecting] = useState(false);
|
|
384
|
+
const [reconnectContent, setReconnectContent] = useState([]);
|
|
149
385
|
const wasRunningRef = useRef(false);
|
|
150
|
-
const
|
|
386
|
+
const tiptapRef = useRef(null);
|
|
387
|
+
// ─── Chat persistence ──────────────────────────────────────────────
|
|
388
|
+
const hasRestoredRef = useRef(false);
|
|
389
|
+
const [isRestoring, setIsRestoring] = useState(!!threadId && !isNewThread);
|
|
390
|
+
const onSaveThreadRef = useRef(onSaveThread);
|
|
391
|
+
onSaveThreadRef.current = onSaveThread;
|
|
392
|
+
const onGenerateTitleRef = useRef(onGenerateTitle);
|
|
393
|
+
onGenerateTitleRef.current = onGenerateTitle;
|
|
394
|
+
const titleGeneratedRef = useRef(false);
|
|
395
|
+
// Restore messages from server on mount (when threadId is set)
|
|
396
|
+
useEffect(() => {
|
|
397
|
+
if (hasRestoredRef.current)
|
|
398
|
+
return;
|
|
399
|
+
hasRestoredRef.current = true;
|
|
400
|
+
if (threadId) {
|
|
401
|
+
// Load from server
|
|
402
|
+
(async () => {
|
|
403
|
+
try {
|
|
404
|
+
const res = await fetch(`${apiUrl}/threads/${encodeURIComponent(threadId)}`);
|
|
405
|
+
if (!res.ok)
|
|
406
|
+
return;
|
|
407
|
+
const data = await res.json();
|
|
408
|
+
if (data.threadData) {
|
|
409
|
+
const repo = typeof data.threadData === "string"
|
|
410
|
+
? JSON.parse(data.threadData)
|
|
411
|
+
: data.threadData;
|
|
412
|
+
if (repo?.messages?.length > 0) {
|
|
413
|
+
titleGeneratedRef.current = true; // Don't re-generate for restored threads
|
|
414
|
+
threadRuntime.import(repo);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
// Also skip title generation if thread already has a title
|
|
418
|
+
if (data.title) {
|
|
419
|
+
titleGeneratedRef.current = true;
|
|
420
|
+
}
|
|
421
|
+
// Check if there's an active run for this thread (e.g. after hot reload)
|
|
422
|
+
try {
|
|
423
|
+
const runRes = await fetch(`${apiUrl}/runs/active?threadId=${encodeURIComponent(threadId)}`);
|
|
424
|
+
if (runRes.ok) {
|
|
425
|
+
const runInfo = await runRes.json();
|
|
426
|
+
// Agent is still running — subscribe to live SSE stream
|
|
427
|
+
setIsReconnecting(true);
|
|
428
|
+
setReconnectContent([]);
|
|
429
|
+
const streamReconnect = async () => {
|
|
430
|
+
try {
|
|
431
|
+
const sseRes = await fetch(`${apiUrl}/runs/${encodeURIComponent(runInfo.runId)}/events?after=0`);
|
|
432
|
+
if (sseRes.ok && sseRes.body) {
|
|
433
|
+
const content = [];
|
|
434
|
+
const toolCallCounter = { value: 0 };
|
|
435
|
+
// Throttle React state updates via requestAnimationFrame
|
|
436
|
+
let rafPending = false;
|
|
437
|
+
let latestSnapshot = [];
|
|
438
|
+
const scheduleUpdate = (snapshot) => {
|
|
439
|
+
latestSnapshot = snapshot;
|
|
440
|
+
if (!rafPending) {
|
|
441
|
+
rafPending = true;
|
|
442
|
+
requestAnimationFrame(() => {
|
|
443
|
+
rafPending = false;
|
|
444
|
+
setReconnectContent(latestSnapshot);
|
|
445
|
+
});
|
|
446
|
+
}
|
|
447
|
+
};
|
|
448
|
+
await readSSEStreamRaw(sseRes.body, content, toolCallCounter, tabId, scheduleUpdate);
|
|
449
|
+
// Final update with complete content
|
|
450
|
+
setReconnectContent([...content]);
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
catch {
|
|
454
|
+
// Stream error — fall through to re-fetch
|
|
455
|
+
}
|
|
456
|
+
// Run finished — re-fetch thread data from server
|
|
457
|
+
// (server now persists assistant response on completion)
|
|
458
|
+
try {
|
|
459
|
+
const refreshRes = await fetch(`${apiUrl}/threads/${encodeURIComponent(threadId)}`);
|
|
460
|
+
if (refreshRes.ok) {
|
|
461
|
+
const refreshData = await refreshRes.json();
|
|
462
|
+
if (refreshData.threadData) {
|
|
463
|
+
const repo = typeof refreshData.threadData === "string"
|
|
464
|
+
? JSON.parse(refreshData.threadData)
|
|
465
|
+
: refreshData.threadData;
|
|
466
|
+
if (repo?.messages?.length > 0) {
|
|
467
|
+
threadRuntime.import(repo);
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
catch { }
|
|
473
|
+
setReconnectContent([]);
|
|
474
|
+
setIsReconnecting(false);
|
|
475
|
+
};
|
|
476
|
+
streamReconnect();
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
catch {
|
|
480
|
+
// No active run — nothing to reconnect to
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
catch {
|
|
484
|
+
// Start fresh
|
|
485
|
+
}
|
|
486
|
+
finally {
|
|
487
|
+
setIsRestoring(false);
|
|
488
|
+
}
|
|
489
|
+
})();
|
|
490
|
+
}
|
|
491
|
+
else {
|
|
492
|
+
// Legacy: restore from sessionStorage
|
|
493
|
+
const storageKey = `${CHAT_STORAGE_PREFIX}${tabId || "default"}`;
|
|
494
|
+
try {
|
|
495
|
+
const saved = sessionStorage.getItem(storageKey);
|
|
496
|
+
if (saved) {
|
|
497
|
+
const repo = JSON.parse(saved);
|
|
498
|
+
if (repo?.messages?.length > 0) {
|
|
499
|
+
threadRuntime.import(repo);
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
catch { }
|
|
504
|
+
setIsRestoring(false);
|
|
505
|
+
}
|
|
506
|
+
}, [threadId, tabId, apiUrl, threadRuntime]);
|
|
507
|
+
// Generate a title when the first user message is sent
|
|
508
|
+
useEffect(() => {
|
|
509
|
+
if (!hasRestoredRef.current)
|
|
510
|
+
return;
|
|
511
|
+
if (titleGeneratedRef.current)
|
|
512
|
+
return;
|
|
513
|
+
if (messages.length === 0)
|
|
514
|
+
return;
|
|
515
|
+
const firstUserMsg = messages.find((m) => m.role === "user");
|
|
516
|
+
if (!firstUserMsg)
|
|
517
|
+
return;
|
|
518
|
+
// Extract text from the first user message
|
|
519
|
+
const text = "content" in firstUserMsg
|
|
520
|
+
? Array.isArray(firstUserMsg.content)
|
|
521
|
+
? firstUserMsg.content
|
|
522
|
+
.filter((p) => p.type === "text")
|
|
523
|
+
.map((p) => p.text)
|
|
524
|
+
.join(" ")
|
|
525
|
+
: typeof firstUserMsg.content === "string"
|
|
526
|
+
? firstUserMsg.content
|
|
527
|
+
: ""
|
|
528
|
+
: "";
|
|
529
|
+
if (!text.trim())
|
|
530
|
+
return;
|
|
531
|
+
titleGeneratedRef.current = true;
|
|
532
|
+
onGenerateTitleRef.current?.(text.trim());
|
|
533
|
+
}, [messages]);
|
|
534
|
+
// Save title/preview eagerly when messages change (even while agent is running)
|
|
535
|
+
// so that the history popover shows meaningful labels immediately.
|
|
536
|
+
const savedTitleRef = useRef("");
|
|
537
|
+
useEffect(() => {
|
|
538
|
+
if (!hasRestoredRef.current)
|
|
539
|
+
return;
|
|
540
|
+
if (messages.length === 0)
|
|
541
|
+
return;
|
|
542
|
+
if (!threadId || !onSaveThreadRef.current)
|
|
543
|
+
return;
|
|
544
|
+
const repo = threadRuntime.export();
|
|
545
|
+
const { title, preview } = extractThreadMeta(repo);
|
|
546
|
+
// Save full thread data while running so hot reloads don't lose messages
|
|
547
|
+
if (isRunning && title && title !== savedTitleRef.current) {
|
|
548
|
+
savedTitleRef.current = title;
|
|
549
|
+
onSaveThreadRef.current({
|
|
550
|
+
threadData: JSON.stringify(repo),
|
|
551
|
+
title,
|
|
552
|
+
preview,
|
|
553
|
+
messageCount: messages.length,
|
|
554
|
+
});
|
|
555
|
+
}
|
|
556
|
+
}, [messages, isRunning, threadId, threadRuntime]);
|
|
557
|
+
// Persist full thread data after each completed response
|
|
558
|
+
useEffect(() => {
|
|
559
|
+
if (!hasRestoredRef.current)
|
|
560
|
+
return;
|
|
561
|
+
if (isRunning)
|
|
562
|
+
return;
|
|
563
|
+
if (messages.length === 0)
|
|
564
|
+
return;
|
|
565
|
+
const repo = threadRuntime.export();
|
|
566
|
+
if (threadId && onSaveThreadRef.current) {
|
|
567
|
+
// Save to server via the hook callback
|
|
568
|
+
const { title, preview } = extractThreadMeta(repo);
|
|
569
|
+
savedTitleRef.current = title;
|
|
570
|
+
onSaveThreadRef.current({
|
|
571
|
+
threadData: JSON.stringify(repo),
|
|
572
|
+
title,
|
|
573
|
+
preview,
|
|
574
|
+
messageCount: messages.length,
|
|
575
|
+
});
|
|
576
|
+
}
|
|
577
|
+
else {
|
|
578
|
+
// Legacy: save to sessionStorage
|
|
579
|
+
const storageKey = `${CHAT_STORAGE_PREFIX}${tabId || "default"}`;
|
|
580
|
+
try {
|
|
581
|
+
sessionStorage.setItem(storageKey, JSON.stringify(repo));
|
|
582
|
+
}
|
|
583
|
+
catch { }
|
|
584
|
+
}
|
|
585
|
+
}, [messages, isRunning, threadId, tabId, threadRuntime]);
|
|
586
|
+
useEffect(() => {
|
|
587
|
+
onMessageCountChange?.(messages.length);
|
|
588
|
+
}, [messages.length, onMessageCountChange]);
|
|
151
589
|
// Listen for missing API key events from the adapter
|
|
152
590
|
useEffect(() => {
|
|
153
591
|
const handler = () => setMissingApiKey(true);
|
|
154
592
|
window.addEventListener("agent-chat:missing-api-key", handler);
|
|
155
593
|
return () => window.removeEventListener("agent-chat:missing-api-key", handler);
|
|
156
594
|
}, []);
|
|
595
|
+
// Listen for loop-limit events from the adapter
|
|
596
|
+
useEffect(() => {
|
|
597
|
+
const handler = (e) => {
|
|
598
|
+
const detail = e.detail;
|
|
599
|
+
if (!tabId || detail?.tabId === tabId) {
|
|
600
|
+
setShowContinue(true);
|
|
601
|
+
}
|
|
602
|
+
};
|
|
603
|
+
window.addEventListener("agent-chat:loop-limit", handler);
|
|
604
|
+
return () => window.removeEventListener("agent-chat:loop-limit", handler);
|
|
605
|
+
}, [tabId]);
|
|
157
606
|
// Auto-dequeue: when agent finishes running, send the next queued message
|
|
158
607
|
useEffect(() => {
|
|
159
608
|
if (wasRunningRef.current && !isRunning && queuedMessages.length > 0) {
|
|
@@ -161,23 +610,36 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
161
610
|
setQueuedMessages(rest);
|
|
162
611
|
// Small delay to let the runtime settle after completion
|
|
163
612
|
setTimeout(() => {
|
|
613
|
+
const content = [{ type: "text", text: next.text }];
|
|
614
|
+
if (next.images) {
|
|
615
|
+
for (const img of next.images) {
|
|
616
|
+
content.push({ type: "image", image: img });
|
|
617
|
+
}
|
|
618
|
+
}
|
|
164
619
|
threadRuntime.append({
|
|
165
620
|
role: "user",
|
|
166
|
-
content
|
|
621
|
+
content,
|
|
622
|
+
...(next.references && next.references.length > 0
|
|
623
|
+
? { runConfig: { custom: { references: next.references } } }
|
|
624
|
+
: {}),
|
|
167
625
|
});
|
|
168
626
|
}, 100);
|
|
169
627
|
}
|
|
170
628
|
wasRunningRef.current = isRunning;
|
|
171
629
|
}, [isRunning, queuedMessages, threadRuntime]);
|
|
172
|
-
const addToQueue = useCallback((text) => {
|
|
630
|
+
const addToQueue = useCallback((text, images, references) => {
|
|
631
|
+
setShowContinue(false);
|
|
173
632
|
if (isRunning) {
|
|
174
|
-
setQueuedMessages((prev) => [...prev, text]);
|
|
633
|
+
setQueuedMessages((prev) => [...prev, { text, images, references }]);
|
|
175
634
|
}
|
|
176
635
|
else {
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
636
|
+
const content = [{ type: "text", text }];
|
|
637
|
+
if (images) {
|
|
638
|
+
for (const img of images) {
|
|
639
|
+
content.push({ type: "image", image: img });
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
threadRuntime.append({ role: "user", content });
|
|
181
643
|
}
|
|
182
644
|
}, [isRunning, threadRuntime]);
|
|
183
645
|
// Expose imperative handle
|
|
@@ -191,27 +653,95 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
191
653
|
isRunning() {
|
|
192
654
|
return thread.isRunning;
|
|
193
655
|
},
|
|
656
|
+
focusComposer() {
|
|
657
|
+
tiptapRef.current?.focus();
|
|
658
|
+
},
|
|
194
659
|
}), [addToQueue, thread.isRunning]);
|
|
195
|
-
//
|
|
660
|
+
// Track whether user has scrolled away from bottom
|
|
661
|
+
const isNearBottomRef = useRef(true);
|
|
662
|
+
const [showScrollToBottom, setShowScrollToBottom] = useState(false);
|
|
196
663
|
useEffect(() => {
|
|
664
|
+
const el = scrollRef.current;
|
|
665
|
+
if (!el)
|
|
666
|
+
return;
|
|
667
|
+
function onScroll() {
|
|
668
|
+
if (!el)
|
|
669
|
+
return;
|
|
670
|
+
const threshold = 40;
|
|
671
|
+
const nearBottom = el.scrollHeight - el.scrollTop - el.clientHeight < threshold;
|
|
672
|
+
isNearBottomRef.current = nearBottom;
|
|
673
|
+
setShowScrollToBottom(!nearBottom && messages.length > 0);
|
|
674
|
+
}
|
|
675
|
+
el.addEventListener("scroll", onScroll, { passive: true });
|
|
676
|
+
return () => el.removeEventListener("scroll", onScroll);
|
|
677
|
+
}, [messages.length]);
|
|
678
|
+
const scrollToBottom = useCallback(() => {
|
|
197
679
|
const el = scrollRef.current;
|
|
198
680
|
if (el) {
|
|
199
681
|
el.scrollTop = el.scrollHeight;
|
|
682
|
+
isNearBottomRef.current = true;
|
|
683
|
+
setShowScrollToBottom(false);
|
|
684
|
+
}
|
|
685
|
+
}, []);
|
|
686
|
+
// Scroll to bottom when a restored thread finishes loading
|
|
687
|
+
const wasRestoringRef = useRef(isRestoring);
|
|
688
|
+
useEffect(() => {
|
|
689
|
+
if (wasRestoringRef.current && !isRestoring) {
|
|
690
|
+
requestAnimationFrame(() => {
|
|
691
|
+
scrollToBottom();
|
|
692
|
+
});
|
|
693
|
+
}
|
|
694
|
+
wasRestoringRef.current = isRestoring;
|
|
695
|
+
}, [isRestoring, scrollToBottom]);
|
|
696
|
+
// Auto-scroll on new messages or queued messages (only if near bottom)
|
|
697
|
+
useEffect(() => {
|
|
698
|
+
const el = scrollRef.current;
|
|
699
|
+
if (el && isNearBottomRef.current) {
|
|
700
|
+
el.scrollTop = el.scrollHeight;
|
|
200
701
|
}
|
|
201
|
-
}, [messages,
|
|
202
|
-
|
|
702
|
+
}, [messages, queuedMessages]);
|
|
703
|
+
// Continuous auto-scroll while streaming (only if near bottom)
|
|
704
|
+
useEffect(() => {
|
|
705
|
+
if (!isRunning)
|
|
706
|
+
return;
|
|
707
|
+
const el = scrollRef.current;
|
|
708
|
+
if (!el)
|
|
709
|
+
return;
|
|
710
|
+
const interval = setInterval(() => {
|
|
711
|
+
if (isNearBottomRef.current) {
|
|
712
|
+
el.scrollTop = el.scrollHeight;
|
|
713
|
+
}
|
|
714
|
+
}, 100);
|
|
715
|
+
return () => clearInterval(interval);
|
|
716
|
+
}, [isRunning]);
|
|
717
|
+
return (_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 && (_jsxs("button", { onClick: onSwitchToCli, className: "flex items-center gap-1 text-[12px] text-muted-foreground hover:text-foreground px-2 py-1 rounded-md hover:bg-accent", title: "Switch to CLI", children: [_jsx(IconTerminal, { className: "h-3.5 w-3.5" }), "CLI"] })) })] })), _jsx("div", { ref: scrollRef, className: "flex-1 overflow-y-auto overflow-x-hidden min-h-0", children: missingApiKey ? (_jsx("div", { className: "flex flex-col items-center justify-center h-full px-2", children: _jsx(ApiKeySetupCard, { apiUrl: apiUrl }) })) : 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(IconSparkles, { 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: () => {
|
|
203
718
|
threadRuntime.append({
|
|
204
719
|
role: "user",
|
|
205
720
|
content: [{ type: "text", text: suggestion }],
|
|
206
721
|
});
|
|
207
|
-
}, 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))) }))
|
|
722
|
+
}, 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: "flex flex-col gap-4 px-4 py-4", children: [_jsx(ThreadPrimitive.Messages, { components: {
|
|
208
723
|
UserMessage,
|
|
209
724
|
AssistantMessage,
|
|
210
|
-
} }),
|
|
725
|
+
} }), showContinue && !isRunning && (_jsx("div", { className: "flex justify-center py-2", children: _jsx("button", { type: "button", onClick: () => {
|
|
726
|
+
setShowContinue(false);
|
|
727
|
+
addToQueue("Continue from where you left off.");
|
|
728
|
+
}, className: "rounded-lg border border-border bg-background px-4 py-2 text-sm font-medium text-foreground hover:bg-accent", children: "Continue" }) })), isRunning && _jsx(ThinkingIndicator, {}), isReconnecting && !isRunning && reconnectContent.length > 0 && (_jsx(ReconnectStreamMessage, { content: reconnectContent })), isReconnecting && !isRunning && reconnectContent.length === 0 && (_jsx(ThinkingIndicator, {})), queuedMessages.map((msg, i) => (_jsx("div", { className: "flex justify-end", children: _jsxs("div", { className: "max-w-[85%] rounded-lg bg-accent/50 text-foreground/60 px-3 py-2 text-sm leading-relaxed whitespace-pre-wrap break-words", children: [_jsxs("div", { className: "flex items-center gap-1.5 text-[10px] text-muted-foreground mb-1 font-medium uppercase tracking-wide", children: [_jsx(IconClock, { className: "h-3 w-3" }), "Queued"] }), msg.text, msg.images && msg.images.length > 0 && (_jsx("div", { className: "flex flex-wrap gap-1.5 mt-1.5", children: msg.images.map((img, j) => (_jsx("img", { src: img, alt: "", className: "h-12 w-12 rounded object-cover border border-border/50" }, j))) }))] }) }, `queued-${i}`)))] })) }), showScrollToBottom && (_jsx("div", { className: "shrink-0 flex justify-center -mb-1", children: _jsx("button", { type: "button", onClick: scrollToBottom, className: "flex h-7 w-7 items-center justify-center rounded-full border border-border bg-background shadow-sm hover:bg-accent", "aria-label": "Scroll to bottom", children: _jsx(IconChevronDown, { className: "h-3.5 w-3.5 text-muted-foreground" }) }) })), composerSlot, _jsx("div", { className: "shrink-0 px-3 py-2", children: _jsxs(ComposerPrimitive.Root, { className: "flex flex-col rounded-lg border border-input bg-background focus-within:ring-1 focus-within:ring-ring", children: [_jsx(ComposerAttachmentPreviewStrip, {}), _jsx(TiptapComposer, { focusRef: tiptapRef, placeholder: isRunning
|
|
729
|
+
? queuedMessages.length > 0
|
|
730
|
+
? `${queuedMessages.length} queued — type another...`
|
|
731
|
+
: "Queue a message..."
|
|
732
|
+
: undefined, onSubmit: isRunning
|
|
733
|
+
? (text, references) => addToQueue(text, undefined, references.length > 0 ? references : undefined)
|
|
734
|
+
: undefined, actionButton: isRunning ? (_jsx("button", { onClick: () => threadRuntime.cancelRun(), className: "shrink-0 flex h-7 w-7 items-center justify-center rounded-md bg-primary text-primary-foreground hover:opacity-90", title: "Stop generating", children: _jsx(IconPlayerStop, { className: "h-3.5 w-3.5" }) })) : undefined })] }) })] }));
|
|
211
735
|
});
|
|
212
|
-
export const AssistantChat = forwardRef(function AssistantChat({ apiUrl, tabId, ...props }, ref) {
|
|
213
|
-
const adapter = useMemo(() => createAgentChatAdapter({ apiUrl, tabId }), [apiUrl, tabId]);
|
|
214
|
-
const
|
|
215
|
-
|
|
736
|
+
export const AssistantChat = forwardRef(function AssistantChat({ apiUrl = "/_agent-native/agent-chat", tabId, threadId, ...props }, ref) {
|
|
737
|
+
const adapter = useMemo(() => createAgentChatAdapter({ apiUrl, tabId, threadId }), [apiUrl, tabId, threadId]);
|
|
738
|
+
const attachmentAdapter = useMemo(() => new CompositeAttachmentAdapter([
|
|
739
|
+
new SimpleImageAttachmentAdapter(),
|
|
740
|
+
new SimpleTextAttachmentAdapter(),
|
|
741
|
+
]), []);
|
|
742
|
+
const runtime = useLocalRuntime(adapter, {
|
|
743
|
+
adapters: { attachments: attachmentAdapter },
|
|
744
|
+
});
|
|
745
|
+
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 }) }) }));
|
|
216
746
|
});
|
|
217
747
|
//# sourceMappingURL=AssistantChat.js.map
|