@agent-native/core 0.4.4 → 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 +326 -107
- 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 -38
- 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 +42 -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 +14 -3
- package/dist/client/AgentPanel.d.ts.map +1 -1
- package/dist/client/AgentPanel.js +492 -21
- package/dist/client/AgentPanel.js.map +1 -1
- package/dist/client/AssistantChat.d.ts +27 -3
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +639 -57
- 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 -67
- 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.d.ts +2 -0
- package/dist/client/agent-chat.d.ts.map +1 -1
- package/dist/client/agent-chat.js +2 -2
- package/dist/client/agent-chat.js.map +1 -1
- package/dist/client/analytics.d.ts +16 -0
- package/dist/client/analytics.d.ts.map +1 -0
- package/dist/client/analytics.js +17 -0
- package/dist/client/analytics.js.map +1 -0
- 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 +13 -0
- package/dist/client/components/CodeRequiredDialog.d.ts.map +1 -0
- package/dist/client/components/CodeRequiredDialog.js +160 -0
- package/dist/client/components/CodeRequiredDialog.js.map +1 -0
- 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 +13 -4
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +12 -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 +12 -7
- 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 +11 -0
- package/dist/client/use-dev-mode.d.ts.map +1 -0
- package/dist/client/use-dev-mode.js +71 -0
- package/dist/client/use-dev-mode.js.map +1 -0
- 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-send-to-agent-chat.d.ts +17 -0
- package/dist/client/use-send-to-agent-chat.d.ts.map +1 -0
- package/dist/client/use-send-to-agent-chat.js +40 -0
- package/dist/client/use-send-to-agent-chat.js.map +1 -0
- package/dist/client/use-session.d.ts +1 -1
- package/dist/client/use-session.d.ts.map +1 -1
- package/dist/client/use-session.js +13 -4
- 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 +108 -12
- 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 +52 -21
- 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.d.ts +16 -0
- package/dist/deploy/build.d.ts.map +1 -0
- package/dist/deploy/build.js +453 -0
- package/dist/deploy/build.js.map +1 -0
- package/dist/deploy/route-discovery.d.ts +43 -0
- package/dist/deploy/route-discovery.d.ts.map +1 -0
- package/dist/deploy/route-discovery.js +115 -0
- package/dist/deploy/route-discovery.js.map +1 -0
- 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/index.d.ts +1 -1
- package/dist/oauth-tokens/index.d.ts.map +1 -1
- package/dist/oauth-tokens/index.js +1 -1
- package/dist/oauth-tokens/index.js.map +1 -1
- package/dist/oauth-tokens/store.d.ts +18 -1
- package/dist/oauth-tokens/store.d.ts.map +1 -1
- package/dist/oauth-tokens/store.js +81 -40
- 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 +1102 -39
- 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/analytics.d.ts +19 -0
- package/dist/server/analytics.d.ts.map +1 -0
- package/dist/server/analytics.js +61 -0
- package/dist/server/analytics.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 +598 -104
- 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.d.ts.map +1 -1
- package/dist/server/google-auth-plugin.js +4 -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 +10 -2
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +9 -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 -36
- package/dist/settings/store.js.map +1 -1
- package/dist/settings/user-settings.d.ts +6 -10
- package/dist/settings/user-settings.d.ts.map +1 -1
- package/dist/settings/user-settings.js +9 -18
- 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 +3 -1
- package/dist/terminal/cli-registry.d.ts.map +1 -1
- package/dist/terminal/cli-registry.js +10 -5
- 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 -8
- 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 +23 -7
- 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/entry.server.tsx +2 -1
- package/src/templates/default/app/global.css +2 -2
- package/src/templates/default/app/root.tsx +27 -15
- package/src/templates/default/app/routes/_index.tsx +1 -1
- package/src/templates/default/package.json +4 -0
- package/src/templates/default/public/icon-180.svg +4 -0
- package/src/templates/default/public/icon-192.svg +4 -0
- package/src/templates/default/public/icon-512.svg +4 -0
- package/src/templates/default/public/manifest.json +13 -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,56 +360,388 @@ 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
|
-
|
|
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 { }
|
|
117
370
|
}
|
|
118
|
-
|
|
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) {
|
|
119
375
|
const scrollRef = useRef(null);
|
|
120
376
|
const thread = useThread();
|
|
121
377
|
const threadRuntime = useThreadRuntime();
|
|
122
378
|
const isRunning = thread.isRunning;
|
|
123
379
|
const messages = thread.messages;
|
|
124
380
|
const [missingApiKey, setMissingApiKey] = useState(false);
|
|
381
|
+
const [queuedMessages, setQueuedMessages] = useState([]);
|
|
382
|
+
const [showContinue, setShowContinue] = useState(false);
|
|
383
|
+
const [isReconnecting, setIsReconnecting] = useState(false);
|
|
384
|
+
const [reconnectContent, setReconnectContent] = useState([]);
|
|
385
|
+
const wasRunningRef = useRef(false);
|
|
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]);
|
|
125
589
|
// Listen for missing API key events from the adapter
|
|
126
590
|
useEffect(() => {
|
|
127
591
|
const handler = () => setMissingApiKey(true);
|
|
128
592
|
window.addEventListener("agent-chat:missing-api-key", handler);
|
|
129
593
|
return () => window.removeEventListener("agent-chat:missing-api-key", handler);
|
|
130
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]);
|
|
606
|
+
// Auto-dequeue: when agent finishes running, send the next queued message
|
|
607
|
+
useEffect(() => {
|
|
608
|
+
if (wasRunningRef.current && !isRunning && queuedMessages.length > 0) {
|
|
609
|
+
const [next, ...rest] = queuedMessages;
|
|
610
|
+
setQueuedMessages(rest);
|
|
611
|
+
// Small delay to let the runtime settle after completion
|
|
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
|
+
}
|
|
619
|
+
threadRuntime.append({
|
|
620
|
+
role: "user",
|
|
621
|
+
content,
|
|
622
|
+
...(next.references && next.references.length > 0
|
|
623
|
+
? { runConfig: { custom: { references: next.references } } }
|
|
624
|
+
: {}),
|
|
625
|
+
});
|
|
626
|
+
}, 100);
|
|
627
|
+
}
|
|
628
|
+
wasRunningRef.current = isRunning;
|
|
629
|
+
}, [isRunning, queuedMessages, threadRuntime]);
|
|
630
|
+
const addToQueue = useCallback((text, images, references) => {
|
|
631
|
+
setShowContinue(false);
|
|
632
|
+
if (isRunning) {
|
|
633
|
+
setQueuedMessages((prev) => [...prev, { text, images, references }]);
|
|
634
|
+
}
|
|
635
|
+
else {
|
|
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 });
|
|
643
|
+
}
|
|
644
|
+
}, [isRunning, threadRuntime]);
|
|
131
645
|
// Expose imperative handle
|
|
132
646
|
useImperativeHandle(ref, () => ({
|
|
133
647
|
sendMessage(text) {
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
648
|
+
addToQueue(text);
|
|
649
|
+
},
|
|
650
|
+
queueMessage(text) {
|
|
651
|
+
addToQueue(text);
|
|
138
652
|
},
|
|
139
653
|
isRunning() {
|
|
140
654
|
return thread.isRunning;
|
|
141
655
|
},
|
|
142
|
-
|
|
143
|
-
|
|
656
|
+
focusComposer() {
|
|
657
|
+
tiptapRef.current?.focus();
|
|
658
|
+
},
|
|
659
|
+
}), [addToQueue, thread.isRunning]);
|
|
660
|
+
// Track whether user has scrolled away from bottom
|
|
661
|
+
const isNearBottomRef = useRef(true);
|
|
662
|
+
const [showScrollToBottom, setShowScrollToBottom] = useState(false);
|
|
144
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(() => {
|
|
145
679
|
const el = scrollRef.current;
|
|
146
680
|
if (el) {
|
|
147
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;
|
|
148
701
|
}
|
|
149
|
-
}, [messages,
|
|
150
|
-
|
|
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: () => {
|
|
151
718
|
threadRuntime.append({
|
|
152
719
|
role: "user",
|
|
153
720
|
content: [{ type: "text", text: suggestion }],
|
|
154
721
|
});
|
|
155
|
-
}, 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: {
|
|
156
723
|
UserMessage,
|
|
157
724
|
AssistantMessage,
|
|
158
|
-
} }), isRunning &&
|
|
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 })] }) })] }));
|
|
159
735
|
});
|
|
160
|
-
export const AssistantChat = forwardRef(function AssistantChat({ apiUrl, tabId, ...props }, ref) {
|
|
161
|
-
const adapter = useMemo(() => createAgentChatAdapter({ apiUrl, tabId }), [apiUrl, tabId]);
|
|
162
|
-
const
|
|
163
|
-
|
|
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 }) }) }));
|
|
164
746
|
});
|
|
165
747
|
//# sourceMappingURL=AssistantChat.js.map
|