@swarmclawai/swarmclaw 0.8.4 → 0.8.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -9
- package/bin/swarmclaw.js +5 -1
- package/bin/worker-cmd.js +73 -0
- package/package.json +2 -1
- package/src/app/api/agents/[id]/route.ts +17 -7
- package/src/app/api/agents/route.ts +21 -8
- package/src/app/api/approvals/route.test.ts +6 -6
- package/src/app/api/approvals/route.ts +2 -1
- package/src/app/api/auth/route.ts +2 -3
- package/src/app/api/chatrooms/[id]/chat/route.test.ts +299 -0
- package/src/app/api/chatrooms/[id]/chat/route.ts +3 -2
- package/src/app/api/chatrooms/[id]/route.ts +7 -6
- package/src/app/api/chats/[id]/chat/route.test.ts +496 -0
- package/src/app/api/chats/[id]/chat/route.ts +7 -3
- package/src/app/api/chats/[id]/clear/route.ts +9 -9
- package/src/app/api/chats/[id]/devserver/route.ts +2 -1
- package/src/app/api/chats/[id]/edit-resend/route.ts +3 -4
- package/src/app/api/chats/[id]/fork/route.ts +3 -5
- package/src/app/api/chats/[id]/restore/route.ts +6 -7
- package/src/app/api/chats/[id]/retry/route.ts +3 -4
- package/src/app/api/chats/[id]/route.ts +61 -62
- package/src/app/api/chats/route.ts +7 -1
- package/src/app/api/connectors/[id]/route.ts +7 -8
- package/src/app/api/connectors/route.ts +5 -4
- package/src/app/api/eval/run/route.ts +2 -1
- package/src/app/api/eval/suite/route.ts +2 -1
- package/src/app/api/external-agents/route.test.ts +1 -1
- package/src/app/api/external-agents/route.ts +2 -2
- package/src/app/api/files/serve/route.ts +1 -1
- package/src/app/api/gateways/[id]/route.ts +7 -5
- package/src/app/api/gateways/route.ts +1 -1
- package/src/app/api/knowledge/upload/route.ts +1 -1
- package/src/app/api/logs/route.ts +5 -7
- package/src/app/api/memory-images/[filename]/route.ts +2 -3
- package/src/app/api/openclaw/agent-files/route.ts +4 -3
- package/src/app/api/openclaw/approvals/route.ts +3 -4
- package/src/app/api/openclaw/config-sync/route.ts +3 -2
- package/src/app/api/openclaw/cron/route.ts +3 -2
- package/src/app/api/openclaw/dotenv-keys/route.ts +2 -1
- package/src/app/api/openclaw/exec-config/route.ts +3 -2
- package/src/app/api/openclaw/gateway/route.ts +5 -4
- package/src/app/api/openclaw/history/route.ts +3 -2
- package/src/app/api/openclaw/media/route.ts +2 -1
- package/src/app/api/openclaw/permissions/route.ts +3 -2
- package/src/app/api/openclaw/sandbox-env/route.ts +3 -2
- package/src/app/api/openclaw/skills/install/route.ts +2 -1
- package/src/app/api/openclaw/skills/remove/route.ts +2 -1
- package/src/app/api/openclaw/skills/route.ts +3 -2
- package/src/app/api/orchestrator/run/route.ts +5 -14
- package/src/app/api/perf/route.ts +43 -0
- package/src/app/api/plugins/dependencies/route.ts +2 -1
- package/src/app/api/plugins/install/route.ts +2 -1
- package/src/app/api/plugins/marketplace/route.ts +3 -2
- package/src/app/api/plugins/settings/route.ts +2 -1
- package/src/app/api/preview-server/route.ts +11 -10
- package/src/app/api/projects/[id]/route.ts +1 -1
- package/src/app/api/schedules/[id]/route.test.ts +128 -0
- package/src/app/api/schedules/[id]/route.ts +43 -43
- package/src/app/api/schedules/[id]/run/route.ts +11 -62
- package/src/app/api/schedules/route.ts +21 -87
- package/src/app/api/settings/route.ts +2 -0
- package/src/app/api/setup/doctor/route.ts +9 -8
- package/src/app/api/tasks/[id]/approve/route.ts +33 -30
- package/src/app/api/tasks/[id]/route.ts +12 -35
- package/src/app/api/tasks/import/github/route.ts +2 -1
- package/src/app/api/tasks/route.ts +79 -91
- package/src/app/api/wallets/[id]/approve/route.ts +2 -1
- package/src/app/api/wallets/[id]/route.ts +13 -19
- package/src/app/api/wallets/[id]/send/route.ts +2 -1
- package/src/app/api/wallets/route.ts +2 -1
- package/src/app/api/webhooks/[id]/route.ts +2 -1
- package/src/app/api/webhooks/route.test.ts +3 -1
- package/src/app/page.tsx +23 -331
- package/src/cli/index.js +19 -0
- package/src/cli/index.ts +38 -7
- package/src/cli/spec.js +9 -0
- package/src/components/activity/activity-feed.tsx +7 -4
- package/src/components/agents/agent-card.tsx +32 -6
- package/src/components/agents/agent-chat-list.tsx +55 -22
- package/src/components/agents/agent-files-editor.tsx +3 -2
- package/src/components/agents/agent-sheet.tsx +123 -22
- package/src/components/agents/inspector-panel.tsx +1 -1
- package/src/components/agents/openclaw-skills-panel.tsx +2 -1
- package/src/components/agents/trash-list.tsx +1 -1
- package/src/components/auth/access-key-gate.tsx +8 -2
- package/src/components/auth/setup-wizard.tsx +10 -9
- package/src/components/auth/user-picker.tsx +3 -2
- package/src/components/chat/chat-area.tsx +20 -1
- package/src/components/chat/chat-card.tsx +18 -3
- package/src/components/chat/chat-header.tsx +24 -4
- package/src/components/chat/chat-list.tsx +2 -11
- package/src/components/chat/heartbeat-history-panel.tsx +2 -1
- package/src/components/chat/message-bubble.tsx +45 -6
- package/src/components/chat/message-list.tsx +280 -145
- package/src/components/chat/streaming-bubble.tsx +217 -60
- package/src/components/chat/swarm-panel.test.ts +274 -0
- package/src/components/chat/swarm-panel.tsx +410 -0
- package/src/components/chat/swarm-status-card.tsx +346 -0
- package/src/components/chat/tool-call-bubble.tsx +48 -23
- package/src/components/chatrooms/chatroom-list.tsx +8 -5
- package/src/components/chatrooms/chatroom-message.tsx +10 -7
- package/src/components/chatrooms/chatroom-view.tsx +12 -9
- package/src/components/connectors/connector-health.tsx +6 -4
- package/src/components/connectors/connector-list.tsx +16 -11
- package/src/components/connectors/connector-sheet.tsx +12 -6
- package/src/components/home/home-view.tsx +38 -24
- package/src/components/input/chat-input.tsx +10 -1
- package/src/components/layout/app-layout.tsx +2 -38
- package/src/components/layout/sheet-layer.tsx +50 -0
- package/src/components/mcp-servers/mcp-server-list.tsx +37 -5
- package/src/components/mcp-servers/mcp-server-sheet.tsx +12 -2
- package/src/components/plugins/plugin-list.tsx +8 -4
- package/src/components/plugins/plugin-sheet.tsx +2 -1
- package/src/components/providers/provider-list.tsx +3 -2
- package/src/components/providers/provider-sheet.tsx +2 -1
- package/src/components/runs/run-list.tsx +11 -7
- package/src/components/schedules/schedule-card.tsx +5 -3
- package/src/components/shared/agent-switch-dialog.tsx +1 -1
- package/src/components/shared/attachment-chip.tsx +19 -3
- package/src/components/shared/notification-center.tsx +6 -3
- package/src/components/shared/settings/plugin-manager.tsx +3 -2
- package/src/components/shared/settings/section-embedding.tsx +2 -1
- package/src/components/shared/settings/section-orchestrator.tsx +2 -1
- package/src/components/shared/settings/section-user-preferences.tsx +107 -0
- package/src/components/shared/settings/settings-page.tsx +13 -9
- package/src/components/skills/clawhub-browser.tsx +15 -4
- package/src/components/skills/skill-list.tsx +15 -4
- package/src/components/tasks/approvals-panel.tsx +2 -1
- package/src/components/tasks/task-board.tsx +35 -37
- package/src/components/tasks/task-sheet.tsx +4 -3
- package/src/components/ui/full-screen-loader.tsx +164 -0
- package/src/components/wallets/wallet-approval-dialog.tsx +2 -1
- package/src/components/wallets/wallet-panel.tsx +6 -5
- package/src/components/wallets/wallet-section.tsx +3 -2
- package/src/components/webhooks/webhook-list.tsx +4 -5
- package/src/components/webhooks/webhook-sheet.tsx +6 -6
- package/src/hooks/use-app-bootstrap.ts +202 -0
- package/src/hooks/use-mounted-ref.ts +14 -0
- package/src/hooks/use-now.ts +31 -0
- package/src/hooks/use-openclaw-gateway.ts +2 -1
- package/src/instrumentation.ts +20 -8
- package/src/lib/agent-default-tools.test.ts +52 -0
- package/src/lib/agent-default-tools.ts +40 -0
- package/src/lib/api-client.test.ts +21 -0
- package/src/lib/api-client.ts +6 -11
- package/src/lib/canvas-content.test.ts +360 -0
- package/src/lib/chat-streaming-state.test.ts +49 -2
- package/src/lib/chat-streaming-state.ts +26 -10
- package/src/lib/fetch-timeout.test.ts +54 -0
- package/src/lib/fetch-timeout.ts +60 -3
- package/src/lib/live-tool-events.test.ts +77 -0
- package/src/lib/live-tool-events.ts +73 -0
- package/src/lib/local-observability.test.ts +2 -2
- package/src/lib/openclaw-endpoint.test.ts +1 -1
- package/src/lib/providers/anthropic.ts +12 -16
- package/src/lib/providers/index.ts +4 -2
- package/src/lib/providers/ollama.ts +9 -6
- package/src/lib/providers/openai.ts +11 -14
- package/src/lib/runtime-env.test.ts +8 -8
- package/src/lib/schedule-dedupe-advanced.test.ts +2 -2
- package/src/lib/schedule-dedupe.test.ts +1 -1
- package/src/lib/schedule-dedupe.ts +3 -2
- package/src/lib/server/agent-thread-session.test.ts +6 -6
- package/src/lib/server/agent-thread-session.ts +6 -9
- package/src/lib/server/alert-dispatch.ts +2 -1
- package/src/lib/server/api-routes.test.ts +6 -6
- package/src/lib/server/approval-connector-notify.test.ts +4 -4
- package/src/lib/server/approvals-auto-approve.test.ts +29 -29
- package/src/lib/server/approvals.test.ts +317 -0
- package/src/lib/server/approvals.ts +5 -4
- package/src/lib/server/autonomy-runtime.test.ts +11 -11
- package/src/lib/server/browser-state.ts +2 -2
- package/src/lib/server/capability-router.test.ts +1 -1
- package/src/lib/server/capability-router.ts +3 -2
- package/src/lib/server/chat-execution-advanced.test.ts +15 -2
- package/src/lib/server/chat-execution-connector-delivery.ts +67 -0
- package/src/lib/server/chat-execution-disabled.test.ts +3 -3
- package/src/lib/server/chat-execution-eval-history.test.ts +3 -3
- package/src/lib/server/chat-execution-heartbeat.test.ts +42 -1
- package/src/lib/server/chat-execution-session-sync.test.ts +119 -0
- package/src/lib/server/chat-execution-tool-events.ts +116 -0
- package/src/lib/server/chat-execution-utils.test.ts +479 -0
- package/src/lib/server/chat-execution-utils.ts +533 -0
- package/src/lib/server/chat-execution.ts +153 -748
- package/src/lib/server/chat-streaming-utils.ts +174 -0
- package/src/lib/server/chat-turn-tool-routing.ts +310 -0
- package/src/lib/server/chatroom-session-persistence.test.ts +2 -2
- package/src/lib/server/clawhub-client.ts +2 -1
- package/src/lib/server/collection-helpers.test.ts +92 -0
- package/src/lib/server/collection-helpers.ts +25 -3
- package/src/lib/server/connectors/access.ts +146 -0
- package/src/lib/server/connectors/bluebubbles.test.ts +1 -1
- package/src/lib/server/connectors/bluebubbles.ts +4 -4
- package/src/lib/server/connectors/commands.ts +367 -0
- package/src/lib/server/connectors/connector-routing.test.ts +4 -4
- package/src/lib/server/connectors/delivery.ts +142 -0
- package/src/lib/server/connectors/discord.ts +37 -40
- package/src/lib/server/connectors/email.ts +11 -10
- package/src/lib/server/connectors/googlechat.ts +4 -4
- package/src/lib/server/connectors/inbound-audio-transcription.ts +2 -1
- package/src/lib/server/connectors/ingress-delivery.ts +23 -0
- package/src/lib/server/connectors/manager-roundtrip.test.ts +300 -0
- package/src/lib/server/connectors/manager.test.ts +352 -77
- package/src/lib/server/connectors/manager.ts +134 -673
- package/src/lib/server/connectors/matrix.ts +4 -4
- package/src/lib/server/connectors/message-sentinel.ts +7 -0
- package/src/lib/server/connectors/openclaw.test.ts +1 -1
- package/src/lib/server/connectors/openclaw.ts +8 -10
- package/src/lib/server/connectors/outbox.test.ts +192 -0
- package/src/lib/server/connectors/outbox.ts +369 -0
- package/src/lib/server/connectors/pairing.test.ts +18 -1
- package/src/lib/server/connectors/pairing.ts +49 -4
- package/src/lib/server/connectors/policy.ts +9 -3
- package/src/lib/server/connectors/reconnect-state.ts +71 -0
- package/src/lib/server/connectors/response-media.ts +256 -0
- package/src/lib/server/connectors/runtime-state.ts +67 -0
- package/src/lib/server/connectors/session.test.ts +357 -0
- package/src/lib/server/connectors/session.ts +422 -0
- package/src/lib/server/connectors/signal.ts +7 -7
- package/src/lib/server/connectors/slack.ts +43 -43
- package/src/lib/server/connectors/teams.ts +4 -4
- package/src/lib/server/connectors/telegram.ts +37 -43
- package/src/lib/server/connectors/types.ts +31 -1
- package/src/lib/server/connectors/whatsapp.test.ts +108 -0
- package/src/lib/server/connectors/whatsapp.ts +106 -34
- package/src/lib/server/context-manager.test.ts +409 -0
- package/src/lib/server/cost.test.ts +1 -1
- package/src/lib/server/daemon-policy.ts +78 -0
- package/src/lib/server/daemon-state-connectors.test.ts +167 -0
- package/src/lib/server/daemon-state.test.ts +283 -55
- package/src/lib/server/daemon-state.ts +106 -109
- package/src/lib/server/data-dir.test.ts +5 -5
- package/src/lib/server/data-dir.ts +4 -0
- package/src/lib/server/delegation-jobs-advanced.test.ts +1 -1
- package/src/lib/server/delegation-jobs.test.ts +87 -0
- package/src/lib/server/delegation-jobs.ts +42 -48
- package/src/lib/server/devserver-launch.ts +1 -1
- package/src/lib/server/document-utils.ts +7 -9
- package/src/lib/server/elevenlabs.ts +2 -1
- package/src/lib/server/embeddings.test.ts +105 -0
- package/src/lib/server/ethereum.ts +3 -2
- package/src/lib/server/eval/agent-regression.ts +3 -2
- package/src/lib/server/eval/runner.ts +2 -1
- package/src/lib/server/eval/scorer.ts +2 -1
- package/src/lib/server/evm-swap.ts +2 -1
- package/src/lib/server/gateway/protocol.test.ts +1 -1
- package/src/lib/server/guardian.ts +2 -1
- package/src/lib/server/heartbeat-blocked-suppression.test.ts +151 -0
- package/src/lib/server/heartbeat-service-timer.test.ts +6 -6
- package/src/lib/server/heartbeat-service.test.ts +406 -0
- package/src/lib/server/heartbeat-service.ts +54 -7
- package/src/lib/server/heartbeat-wake.test.ts +19 -0
- package/src/lib/server/heartbeat-wake.ts +17 -16
- package/src/lib/server/integrity-monitor.test.ts +149 -0
- package/src/lib/server/json-utils.ts +22 -0
- package/src/lib/server/knowledge-db.test.ts +13 -13
- package/src/lib/server/link-understanding.ts +2 -1
- package/src/lib/server/llm-response-cache.test.ts +1 -1
- package/src/lib/server/main-agent-loop-advanced.test.ts +65 -3
- package/src/lib/server/main-agent-loop.test.ts +6 -6
- package/src/lib/server/main-agent-loop.ts +21 -7
- package/src/lib/server/mcp-client.test.ts +1 -1
- package/src/lib/server/mcp-conformance.test.ts +1 -1
- package/src/lib/server/mcp-conformance.ts +3 -2
- package/src/lib/server/memory-consolidation.ts +2 -1
- package/src/lib/server/memory-db.test.ts +485 -0
- package/src/lib/server/memory-db.ts +39 -26
- package/src/lib/server/memory-graph.test.ts +2 -2
- package/src/lib/server/memory-policy.test.ts +7 -7
- package/src/lib/server/memory-retrieval.test.ts +1 -1
- package/src/lib/server/openclaw-config-sync.ts +2 -1
- package/src/lib/server/openclaw-deploy.test.ts +1 -1
- package/src/lib/server/openclaw-deploy.ts +8 -12
- package/src/lib/server/openclaw-exec-config.ts +2 -1
- package/src/lib/server/openclaw-gateway.ts +6 -7
- package/src/lib/server/openclaw-skills-normalize.ts +2 -1
- package/src/lib/server/openclaw-sync.ts +7 -5
- package/src/lib/server/orchestrator-lg-structure.test.ts +17 -0
- package/src/lib/server/orchestrator-lg.ts +199 -327
- package/src/lib/server/path-utils.ts +31 -0
- package/src/lib/server/perf.ts +161 -0
- package/src/lib/server/plugins-approval-guidance.ts +115 -0
- package/src/lib/server/plugins.test.ts +1 -1
- package/src/lib/server/plugins.ts +22 -132
- package/src/lib/server/process-manager.ts +5 -8
- package/src/lib/server/provider-health.test.ts +137 -0
- package/src/lib/server/provider-health.ts +3 -3
- package/src/lib/server/provider-model-discovery.ts +3 -12
- package/src/lib/server/queue-followups.test.ts +9 -9
- package/src/lib/server/queue-reconcile.test.ts +2 -2
- package/src/lib/server/queue-recovery.test.ts +269 -0
- package/src/lib/server/queue.test.ts +570 -0
- package/src/lib/server/queue.ts +62 -455
- package/src/lib/server/resolve-image.ts +30 -0
- package/src/lib/server/runtime-settings.test.ts +4 -4
- package/src/lib/server/runtime-storage-write-paths.test.ts +60 -0
- package/src/lib/server/schedule-normalization.test.ts +279 -0
- package/src/lib/server/schedule-service.ts +263 -0
- package/src/lib/server/scheduler.ts +17 -74
- package/src/lib/server/session-mailbox.test.ts +191 -0
- package/src/lib/server/session-run-manager.test.ts +640 -0
- package/src/lib/server/session-run-manager.ts +59 -15
- package/src/lib/server/session-tools/autonomy-tools.test.ts +20 -20
- package/src/lib/server/session-tools/calendar.ts +2 -1
- package/src/lib/server/session-tools/canvas.ts +2 -1
- package/src/lib/server/session-tools/chatroom.ts +2 -1
- package/src/lib/server/session-tools/connector.ts +26 -28
- package/src/lib/server/session-tools/context-mgmt.ts +3 -2
- package/src/lib/server/session-tools/crawl.ts +4 -3
- package/src/lib/server/session-tools/crud.ts +105 -324
- package/src/lib/server/session-tools/delegate-fallback.test.ts +9 -9
- package/src/lib/server/session-tools/delegate.ts +6 -8
- package/src/lib/server/session-tools/discovery-approvals.test.ts +15 -15
- package/src/lib/server/session-tools/discovery.ts +4 -3
- package/src/lib/server/session-tools/document.ts +2 -1
- package/src/lib/server/session-tools/email.ts +2 -1
- package/src/lib/server/session-tools/extract.ts +2 -1
- package/src/lib/server/session-tools/file.ts +4 -3
- package/src/lib/server/session-tools/http.ts +2 -1
- package/src/lib/server/session-tools/human-loop.ts +2 -1
- package/src/lib/server/session-tools/image-gen.ts +4 -3
- package/src/lib/server/session-tools/index.ts +26 -30
- package/src/lib/server/session-tools/mailbox.ts +2 -1
- package/src/lib/server/session-tools/manage-connectors.test.ts +4 -4
- package/src/lib/server/session-tools/manage-schedules.test.ts +12 -12
- package/src/lib/server/session-tools/manage-tasks-advanced.test.ts +5 -5
- package/src/lib/server/session-tools/manage-tasks.test.ts +2 -2
- package/src/lib/server/session-tools/monitor.ts +2 -1
- package/src/lib/server/session-tools/platform.ts +2 -1
- package/src/lib/server/session-tools/plugin-creator.ts +2 -1
- package/src/lib/server/session-tools/replicate.ts +3 -2
- package/src/lib/server/session-tools/session-tools-wiring.test.ts +6 -6
- package/src/lib/server/session-tools/shell.ts +4 -9
- package/src/lib/server/session-tools/subagent.ts +322 -170
- package/src/lib/server/session-tools/table.ts +6 -5
- package/src/lib/server/session-tools/wallet-tool.test.ts +3 -3
- package/src/lib/server/session-tools/wallet.ts +7 -6
- package/src/lib/server/session-tools/web-browser-config.test.ts +1 -0
- package/src/lib/server/session-tools/web-utils.ts +317 -0
- package/src/lib/server/session-tools/web.ts +62 -328
- package/src/lib/server/skill-prompt-budget.test.ts +1 -1
- package/src/lib/server/skills-normalize.ts +2 -1
- package/src/lib/server/storage-item-access.test.ts +302 -0
- package/src/lib/server/storage.ts +366 -314
- package/src/lib/server/stream-agent-chat.test.ts +82 -3
- package/src/lib/server/stream-agent-chat.ts +146 -510
- package/src/lib/server/stream-continuation.ts +412 -0
- package/src/lib/server/subagent-lineage.test.ts +647 -0
- package/src/lib/server/subagent-lineage.ts +435 -0
- package/src/lib/server/subagent-runtime.test.ts +484 -0
- package/src/lib/server/subagent-runtime.ts +419 -0
- package/src/lib/server/subagent-swarm.test.ts +391 -0
- package/src/lib/server/subagent-swarm.ts +564 -0
- package/src/lib/server/system-events.ts +3 -3
- package/src/lib/server/task-followups.test.ts +491 -0
- package/src/lib/server/task-followups.ts +391 -0
- package/src/lib/server/task-lifecycle.test.ts +205 -0
- package/src/lib/server/task-lifecycle.ts +200 -0
- package/src/lib/server/task-quality-gate.test.ts +1 -1
- package/src/lib/server/task-resume.ts +208 -0
- package/src/lib/server/task-service.test.ts +108 -0
- package/src/lib/server/task-service.ts +264 -0
- package/src/lib/server/task-validation.test.ts +1 -1
- package/src/lib/server/test-utils/run-with-temp-data-dir.ts +42 -0
- package/src/lib/server/tool-capability-policy.test.ts +2 -2
- package/src/lib/server/tool-capability-policy.ts +3 -2
- package/src/lib/server/tool-planning.ts +2 -1
- package/src/lib/server/tool-retry.ts +2 -3
- package/src/lib/server/wake-dispatcher.test.ts +303 -0
- package/src/lib/server/wake-dispatcher.ts +318 -0
- package/src/lib/server/wake-mode.test.ts +161 -0
- package/src/lib/server/wake-mode.ts +174 -0
- package/src/lib/server/wallet-service.ts +8 -9
- package/src/lib/server/watch-jobs.ts +2 -1
- package/src/lib/server/workspace-context.ts +2 -2
- package/src/lib/shared-utils.test.ts +142 -0
- package/src/lib/shared-utils.ts +62 -0
- package/src/lib/tool-event-summary.ts +2 -1
- package/src/lib/view-routes.test.ts +100 -0
- package/src/lib/wallet.test.ts +322 -6
- package/src/proxy.test.ts +4 -4
- package/src/proxy.ts +2 -3
- package/src/stores/set-if-changed.ts +40 -0
- package/src/stores/slices/agent-slice.ts +111 -0
- package/src/stores/slices/auth-slice.ts +25 -0
- package/src/stores/slices/data-slice.ts +301 -0
- package/src/stores/slices/index.ts +7 -0
- package/src/stores/slices/session-slice.ts +112 -0
- package/src/stores/slices/task-slice.ts +63 -0
- package/src/stores/slices/ui-slice.ts +192 -0
- package/src/stores/use-app-store.ts +17 -822
- package/src/stores/use-approval-store.ts +2 -1
- package/src/stores/use-chat-store.ts +8 -1
- package/src/types/index.ts +10 -0
|
@@ -50,7 +50,19 @@ export function ChatArea() {
|
|
|
50
50
|
const removeSessionFromStore = useAppStore((s) => s.removeSession)
|
|
51
51
|
const refreshSession = useAppStore((s) => s.refreshSession)
|
|
52
52
|
const appSettings = useAppStore((s) => s.appSettings)
|
|
53
|
-
const
|
|
53
|
+
const messages = useChatStore((s) => s.messages)
|
|
54
|
+
const setMessages = useChatStore((s) => s.setMessages)
|
|
55
|
+
const streaming = useChatStore((s) => s.streaming)
|
|
56
|
+
const streamingSessionId = useChatStore((s) => s.streamingSessionId)
|
|
57
|
+
const sendMessage = useChatStore((s) => s.sendMessage)
|
|
58
|
+
const stopStreaming = useChatStore((s) => s.stopStreaming)
|
|
59
|
+
const devServerStatus = useChatStore((s) => s.devServer)
|
|
60
|
+
const setDevServer = useChatStore((s) => s.setDevServer)
|
|
61
|
+
const debugOpen = useChatStore((s) => s.debugOpen)
|
|
62
|
+
const setDebugOpen = useChatStore((s) => s.setDebugOpen)
|
|
63
|
+
const ttsEnabled = useChatStore((s) => s.ttsEnabled)
|
|
64
|
+
const previewContent = useChatStore((s) => s.previewContent)
|
|
65
|
+
const setPreviewContent = useChatStore((s) => s.setPreviewContent)
|
|
54
66
|
const isDesktop = useMediaQuery('(min-width: 768px)')
|
|
55
67
|
|
|
56
68
|
const agents = useAppStore((s) => s.agents)
|
|
@@ -218,6 +230,12 @@ export function ChatArea() {
|
|
|
218
230
|
|
|
219
231
|
const refreshMessages = useCallback(async () => {
|
|
220
232
|
if (!sessionId) return
|
|
233
|
+
// Skip message refresh while we're locally streaming this session —
|
|
234
|
+
// the SSE stream already handles the live display via StreamingBubble.
|
|
235
|
+
// Fetching messages here would replace the array with new objects on every
|
|
236
|
+
// WS notification, causing the full MessageList to re-render and flash.
|
|
237
|
+
const chatState = useChatStore.getState()
|
|
238
|
+
if (chatState.streaming && chatState.streamingSessionId === sessionId) return
|
|
221
239
|
try {
|
|
222
240
|
const msgs = await fetchMessages(sessionId)
|
|
223
241
|
const previous = messagesRef.current
|
|
@@ -357,6 +375,7 @@ export function ChatArea() {
|
|
|
357
375
|
return (
|
|
358
376
|
<div className="flex-1 flex h-full min-h-0 min-w-0">
|
|
359
377
|
<div
|
|
378
|
+
data-testid="chat-area"
|
|
360
379
|
className="flex-1 flex flex-col h-full min-h-0 min-w-0 relative"
|
|
361
380
|
onDragOver={handleDragOver}
|
|
362
381
|
onDragEnter={handleDragEnter}
|
|
@@ -4,6 +4,7 @@ import { useState } from 'react'
|
|
|
4
4
|
import { DEFAULT_HEARTBEAT_INTERVAL_SEC } from '@/lib/heartbeat-defaults'
|
|
5
5
|
import type { Session } from '@/types'
|
|
6
6
|
import { api } from '@/lib/api-client'
|
|
7
|
+
import { useNow } from '@/hooks/use-now'
|
|
7
8
|
import { getSessionLastAssistantAt, getSessionLastMessage } from '@/lib/session-summary'
|
|
8
9
|
import { useAppStore } from '@/stores/use-app-store'
|
|
9
10
|
import { useChatStore } from '@/stores/use-chat-store'
|
|
@@ -12,9 +13,10 @@ import { ConnectorPlatformBadge, getSessionConnector } from '@/components/shared
|
|
|
12
13
|
import { AgentAvatar } from '@/components/agents/agent-avatar'
|
|
13
14
|
import { toast } from 'sonner'
|
|
14
15
|
|
|
15
|
-
function timeAgo(ts: number): string {
|
|
16
|
+
function timeAgo(ts: number, now: number | null): string {
|
|
16
17
|
if (!ts) return ''
|
|
17
|
-
|
|
18
|
+
if (!now) return 'recently'
|
|
19
|
+
const s = Math.floor((now - ts) / 1000)
|
|
18
20
|
if (s < 60) return 'now'
|
|
19
21
|
if (s < 3600) return Math.floor(s / 60) + 'm'
|
|
20
22
|
if (s < 86400) return Math.floor(s / 3600) + 'h'
|
|
@@ -39,6 +41,7 @@ interface Props {
|
|
|
39
41
|
}
|
|
40
42
|
|
|
41
43
|
export function ChatCard({ session, active, onClick }: Props) {
|
|
44
|
+
const now = useNow({ enabled: false })
|
|
42
45
|
const removeSession = useAppStore((s) => s.removeSession)
|
|
43
46
|
const appSettings = useAppStore((s) => s.appSettings)
|
|
44
47
|
const agents = useAppStore((s) => s.agents)
|
|
@@ -96,6 +99,18 @@ export function ChatCard({ session, active, onClick }: Props) {
|
|
|
96
99
|
<>
|
|
97
100
|
<div
|
|
98
101
|
onClick={onClick}
|
|
102
|
+
onKeyDown={(event) => {
|
|
103
|
+
if (event.key === 'Enter' || event.key === ' ') {
|
|
104
|
+
event.preventDefault()
|
|
105
|
+
onClick()
|
|
106
|
+
}
|
|
107
|
+
}}
|
|
108
|
+
role="button"
|
|
109
|
+
tabIndex={0}
|
|
110
|
+
aria-label={`Open chat ${displayName}`}
|
|
111
|
+
data-testid="chat-row"
|
|
112
|
+
data-session-id={session.id}
|
|
113
|
+
data-agent-id={session.agentId || undefined}
|
|
99
114
|
className={`group/card relative py-3.5 px-4 cursor-pointer rounded-[14px]
|
|
100
115
|
transition-all duration-200 active:scale-[0.98]
|
|
101
116
|
${active
|
|
@@ -139,7 +154,7 @@ export function ChatCard({ session, active, onClick }: Props) {
|
|
|
139
154
|
) : null
|
|
140
155
|
})()}
|
|
141
156
|
<span className="text-[11px] text-text-3/70 shrink-0 tabular-nums font-mono">
|
|
142
|
-
{timeAgo(session.lastActiveAt)}
|
|
157
|
+
{timeAgo(session.lastActiveAt, now)}
|
|
143
158
|
</span>
|
|
144
159
|
<button
|
|
145
160
|
onClick={handleDeleteClick}
|
|
@@ -3,8 +3,10 @@
|
|
|
3
3
|
import { DEFAULT_HEARTBEAT_INTERVAL_SEC } from '@/lib/heartbeat-defaults'
|
|
4
4
|
import { useEffect, useState, useMemo, useRef, useCallback, type ReactNode } from 'react'
|
|
5
5
|
import type { Session } from '@/types'
|
|
6
|
+
import { dedup } from '@/lib/shared-utils'
|
|
6
7
|
import { useAppStore } from '@/stores/use-app-store'
|
|
7
8
|
import { useChatStore } from '@/stores/use-chat-store'
|
|
9
|
+
import { useNow } from '@/hooks/use-now'
|
|
8
10
|
import { IconButton } from '@/components/shared/icon-button'
|
|
9
11
|
import { ChatToolToggles } from './chat-tool-toggles'
|
|
10
12
|
import { api } from '@/lib/api-client'
|
|
@@ -41,7 +43,7 @@ function getAgentWalletIds(agent: { walletIds?: string[]; walletId?: string | nu
|
|
|
41
43
|
const legacy = typeof agent?.walletId === 'string' && agent.walletId.trim()
|
|
42
44
|
? [agent.walletId.trim()]
|
|
43
45
|
: []
|
|
44
|
-
return
|
|
46
|
+
return dedup([...ids, ...legacy])
|
|
45
47
|
}
|
|
46
48
|
|
|
47
49
|
function getAgentActiveWalletId(agent: { activeWalletId?: string | null; walletIds?: string[]; walletId?: string | null } | null | undefined): string | null {
|
|
@@ -127,6 +129,7 @@ interface Props {
|
|
|
127
129
|
}
|
|
128
130
|
|
|
129
131
|
export function ChatHeader({ session, streaming, onStop, onMenuToggle, onBack, mobile, browserActive, onStopBrowser, onVoiceToggle, voiceActive, voiceSupported, heartbeatHistoryOpen, onToggleHeartbeatHistory, connectorSources, connectorFilter, onConnectorFilterChange, hasMultipleSources }: Props) {
|
|
132
|
+
const now = useNow()
|
|
130
133
|
const ttsEnabled = useChatStore((s) => s.ttsEnabled)
|
|
131
134
|
const toggleTts = useChatStore((s) => s.toggleTts)
|
|
132
135
|
const soundEnabled = useChatStore((s) => s.soundEnabled)
|
|
@@ -171,9 +174,14 @@ export function ChatHeader({ session, streaming, onStop, onMenuToggle, onBack, m
|
|
|
171
174
|
const setWalletPanelAgentId = useAppStore((s) => s.setWalletPanelAgentId)
|
|
172
175
|
const [walletBalance, setWalletBalance] = useState<{ formatted: string; symbol: string; assets?: number } | null>(null)
|
|
173
176
|
const [headerWidgets, setHeaderWidgets] = useState<Array<{ id: string; label: string; icon?: string }>>([])
|
|
177
|
+
const [localhostBrowser, setLocalhostBrowser] = useState(false)
|
|
174
178
|
const agentWalletIds = useMemo(() => getAgentWalletIds(agent), [agent])
|
|
175
179
|
const activeWalletId = useMemo(() => getAgentActiveWalletId(agent), [agent])
|
|
176
180
|
|
|
181
|
+
useEffect(() => {
|
|
182
|
+
setLocalhostBrowser(window.location.hostname === 'localhost')
|
|
183
|
+
}, [])
|
|
184
|
+
|
|
177
185
|
const refreshHeaderWidgets = useCallback(() => {
|
|
178
186
|
api<Array<{ id: string; label: string; icon?: string }>>('GET', '/plugins/ui?type=header').then((widgets) => {
|
|
179
187
|
if (Array.isArray(widgets)) setHeaderWidgets(widgets)
|
|
@@ -231,7 +239,14 @@ export function ChatHeader({ session, streaming, onStop, onMenuToggle, onBack, m
|
|
|
231
239
|
textClass: 'text-text-3/45',
|
|
232
240
|
}
|
|
233
241
|
}
|
|
234
|
-
|
|
242
|
+
if (!now) {
|
|
243
|
+
return {
|
|
244
|
+
label: 'Idle',
|
|
245
|
+
dotClass: 'bg-text-3/30',
|
|
246
|
+
textClass: 'text-text-3/45',
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
const ago = now - lastAt
|
|
235
250
|
if (ago < 5 * 60_000) {
|
|
236
251
|
return {
|
|
237
252
|
label: 'Active',
|
|
@@ -251,7 +266,7 @@ export function ChatHeader({ session, streaming, onStop, onMenuToggle, onBack, m
|
|
|
251
266
|
dotClass: 'bg-text-3/30',
|
|
252
267
|
textClass: 'text-text-3/45',
|
|
253
268
|
}
|
|
254
|
-
}, [connector, connectorPresence?.lastMessageAt])
|
|
269
|
+
}, [connector, connectorPresence?.lastMessageAt, now])
|
|
255
270
|
|
|
256
271
|
const visibleHeaderWidgets = useMemo(() => {
|
|
257
272
|
const seen = new Set<string>()
|
|
@@ -263,6 +278,11 @@ export function ChatHeader({ session, streaming, onStop, onMenuToggle, onBack, m
|
|
|
263
278
|
})
|
|
264
279
|
}, [headerWidgets])
|
|
265
280
|
|
|
281
|
+
const heartbeatIntervalOptions = useMemo(
|
|
282
|
+
() => [...(localhostBrowser ? [60, 300] : []), 1800, 3600, 7200, 21600, 43200],
|
|
283
|
+
[localhostBrowser],
|
|
284
|
+
)
|
|
285
|
+
|
|
266
286
|
const walletHeaderMeta = useMemo(() => {
|
|
267
287
|
if (!agent?.id) {
|
|
268
288
|
return {
|
|
@@ -869,7 +889,7 @@ export function ChatHeader({ session, streaming, onStop, onMenuToggle, onBack, m
|
|
|
869
889
|
</Tip>
|
|
870
890
|
{hbDropdownOpen && (
|
|
871
891
|
<div className="absolute top-full right-0 mt-1 py-1 rounded-[10px] border border-white/[0.06] bg-bg/95 backdrop-blur-md shadow-lg z-50 min-w-[88px]">
|
|
872
|
-
{
|
|
892
|
+
{heartbeatIntervalOptions.map((sec) => (
|
|
873
893
|
<button
|
|
874
894
|
key={sec}
|
|
875
895
|
onClick={() => handleSelectHeartbeatInterval(sec)}
|
|
@@ -2,9 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import { useEffect, useMemo, useState } from 'react'
|
|
4
4
|
import { useAppStore } from '@/stores/use-app-store'
|
|
5
|
-
import { useChatStore } from '@/stores/use-chat-store'
|
|
6
5
|
import { ChatCard } from './chat-card'
|
|
7
|
-
import { fetchMessages } from '@/lib/chats'
|
|
8
6
|
import { getSessionLastAssistantAt, getSessionLastMessage, getSessionMessageCount } from '@/lib/session-summary'
|
|
9
7
|
import { isLocalhostBrowser, isVisibleSessionForViewer } from '@/lib/local-observability'
|
|
10
8
|
import { toast } from 'sonner'
|
|
@@ -34,7 +32,6 @@ export function ChatList({ inSidebar, onSelect }: Props) {
|
|
|
34
32
|
const lastReadTimestamps = useAppStore((s) => s.lastReadTimestamps)
|
|
35
33
|
const agents = useAppStore((s) => s.agents)
|
|
36
34
|
const connectors = useAppStore((s) => s.connectors)
|
|
37
|
-
const setMessages = useChatStore((s) => s.setMessages)
|
|
38
35
|
const [search, setSearch] = useState('')
|
|
39
36
|
const [typeFilter, setTypeFilter] = useState<SessionFilter>('all')
|
|
40
37
|
const [sortMode, setSortMode] = useState<SortMode>('lastActive')
|
|
@@ -111,14 +108,6 @@ export function ChatList({ inSidebar, onSelect }: Props) {
|
|
|
111
108
|
if (typeof window !== 'undefined') {
|
|
112
109
|
window.dispatchEvent(new CustomEvent('swarmclaw:scroll-bottom'))
|
|
113
110
|
}
|
|
114
|
-
try {
|
|
115
|
-
const msgs = await fetchMessages(id)
|
|
116
|
-
setMessages(msgs)
|
|
117
|
-
} catch {
|
|
118
|
-
const fallback = sessions[id]
|
|
119
|
-
const fallbackLastMessage = fallback ? getSessionLastMessage(fallback) : null
|
|
120
|
-
setMessages(fallback?.messages?.length ? fallback.messages : (fallbackLastMessage ? [fallbackLastMessage] : []))
|
|
121
|
-
}
|
|
122
111
|
onSelect?.()
|
|
123
112
|
}
|
|
124
113
|
|
|
@@ -214,6 +203,8 @@ export function ChatList({ inSidebar, onSelect }: Props) {
|
|
|
214
203
|
value={search}
|
|
215
204
|
onChange={(e) => setSearch(e.target.value)}
|
|
216
205
|
placeholder="Search..."
|
|
206
|
+
aria-label="Search chats"
|
|
207
|
+
data-testid="chat-search"
|
|
217
208
|
className="flex-1 px-4 py-2.5 rounded-[12px] border border-white/[0.04] bg-surface text-text
|
|
218
209
|
text-[13px] outline-none transition-all duration-200 placeholder:text-text-3/70 focus-glow"
|
|
219
210
|
style={{ fontFamily: 'inherit' }}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import { useEffect, useRef, useState, useMemo } from 'react'
|
|
4
4
|
import type { Message } from '@/types'
|
|
5
|
+
import { dedup } from '@/lib/shared-utils'
|
|
5
6
|
|
|
6
7
|
/* ─── Heartbeat meta parsing (shared with message-bubble) ─── */
|
|
7
8
|
|
|
@@ -203,7 +204,7 @@ export function HeartbeatHistoryPanel({ messages, agentHeartbeatGoal, onClose }:
|
|
|
203
204
|
const goal = entry.meta?.goal || agentHeartbeatGoal
|
|
204
205
|
const isExpanded = expandedIdx === i
|
|
205
206
|
const toolNames = entry.msg.toolEvents?.map((te) => te.name).filter(Boolean) ?? []
|
|
206
|
-
const uniqueTools =
|
|
207
|
+
const uniqueTools = dedup(toolNames)
|
|
207
208
|
|
|
208
209
|
return (
|
|
209
210
|
<button
|
|
@@ -5,6 +5,7 @@ import ReactMarkdown from 'react-markdown'
|
|
|
5
5
|
import remarkGfm from 'remark-gfm'
|
|
6
6
|
import rehypeHighlight from 'rehype-highlight'
|
|
7
7
|
import type { Message } from '@/types'
|
|
8
|
+
import { useMediaQuery } from '@/hooks/use-media-query'
|
|
8
9
|
import { useAppStore } from '@/stores/use-app-store'
|
|
9
10
|
import { useChatStore } from '@/stores/use-chat-store'
|
|
10
11
|
import { AiAvatar } from '@/components/shared/avatar'
|
|
@@ -17,6 +18,8 @@ import { isStructuredMarkdown } from './markdown-utils'
|
|
|
17
18
|
import { FilePathChip, FILE_PATH_RE, DIR_PATH_RE } from './file-path-chip'
|
|
18
19
|
import { TransferAgentPicker } from './transfer-agent-picker'
|
|
19
20
|
import { DelegationBanner, DelegationSourceBanner, TaskCompletionCard, parseTaskCompletion } from './delegation-banner'
|
|
21
|
+
import { SwarmPanel, parseSwarmOutput, parseSwarmStatusOutput } from './swarm-panel'
|
|
22
|
+
import { SwarmStatusCard, SwarmStatusStyles } from './swarm-status-card'
|
|
20
23
|
import { ConnectorPlatformIcon, getConnectorPlatformLabel } from '@/components/shared/connector-platform-icon'
|
|
21
24
|
import { copyTextToClipboard } from '@/lib/clipboard'
|
|
22
25
|
import { formatMessageTimestamp } from '@/lib/chat-display'
|
|
@@ -93,7 +96,10 @@ const emptyToolEvents: NonNullable<Message['toolEvents']> = []
|
|
|
93
96
|
// AttachmentChip, parseAttachmentUrl, regex constants, and FILE_TYPE_COLORS
|
|
94
97
|
// are now imported from @/components/shared/attachment-chip
|
|
95
98
|
|
|
96
|
-
function renderAttachments(
|
|
99
|
+
function renderAttachments(
|
|
100
|
+
message: Message,
|
|
101
|
+
onOpenImage?: (image: { url: string; filename: string }) => void,
|
|
102
|
+
) {
|
|
97
103
|
const isUser = message.role === 'user'
|
|
98
104
|
const seen = new Set<string>()
|
|
99
105
|
const chips: { url: string; filename: string }[] = []
|
|
@@ -121,7 +127,15 @@ function renderAttachments(message: Message) {
|
|
|
121
127
|
if (!chips.length) return null
|
|
122
128
|
return (
|
|
123
129
|
<div className="flex flex-col">
|
|
124
|
-
{chips.map((c) =>
|
|
130
|
+
{chips.map((c) => (
|
|
131
|
+
<AttachmentChip
|
|
132
|
+
key={c.url}
|
|
133
|
+
url={c.url}
|
|
134
|
+
filename={c.filename}
|
|
135
|
+
isUserMsg={isUser}
|
|
136
|
+
onOpenImage={onOpenImage}
|
|
137
|
+
/>
|
|
138
|
+
))}
|
|
125
139
|
</div>
|
|
126
140
|
)
|
|
127
141
|
}
|
|
@@ -182,6 +196,8 @@ export const MessageBubble = memo(function MessageBubble({ message, assistantNam
|
|
|
182
196
|
return null
|
|
183
197
|
}, [message.text, isUser])
|
|
184
198
|
const currentUser = useAppStore((s) => s.currentUser)
|
|
199
|
+
const isDesktop = useMediaQuery('(min-width: 768px)')
|
|
200
|
+
const setPreviewContent = useChatStore((s) => s.setPreviewContent)
|
|
185
201
|
const [copied, setCopied] = useState(false)
|
|
186
202
|
const [heartbeatExpanded, setHeartbeatExpanded] = useState(false)
|
|
187
203
|
const [toolEventsExpanded, setToolEventsExpanded] = useState(false)
|
|
@@ -254,6 +270,10 @@ export const MessageBubble = memo(function MessageBubble({ message, assistantNam
|
|
|
254
270
|
? rawDisplayText.split('\n').filter((l) => !/\[(MAIN_LOOP_META|MAIN_LOOP_PLAN|MAIN_LOOP_REVIEW|AGENT_HEARTBEAT_META)\]/.test(l)).join('\n').trim()
|
|
255
271
|
: ''
|
|
256
272
|
|
|
273
|
+
const handleOpenAttachmentImage = useCallback(({ url, filename }: { url: string; filename: string }) => {
|
|
274
|
+
setPreviewContent({ type: 'image', url, title: filename })
|
|
275
|
+
}, [setPreviewContent])
|
|
276
|
+
|
|
257
277
|
const handleCopy = useCallback(() => {
|
|
258
278
|
void copyTextToClipboard(message.text).then((copiedText) => {
|
|
259
279
|
if (!copiedText) return
|
|
@@ -266,6 +286,11 @@ export const MessageBubble = memo(function MessageBubble({ message, assistantNam
|
|
|
266
286
|
|
|
267
287
|
return (
|
|
268
288
|
<div
|
|
289
|
+
data-testid="message-bubble"
|
|
290
|
+
data-message-role={message.role}
|
|
291
|
+
data-message-kind={message.kind || 'chat'}
|
|
292
|
+
data-message-time={message.time || undefined}
|
|
293
|
+
data-message-has-tools={hasToolEvents || undefined}
|
|
269
294
|
className={`group ${isUser ? 'flex flex-col items-end' : 'flex flex-col items-start relative pl-[44px]'}`}
|
|
270
295
|
>
|
|
271
296
|
{/* Avatar on spine (assistant) */}
|
|
@@ -305,7 +330,7 @@ export const MessageBubble = memo(function MessageBubble({ message, assistantNam
|
|
|
305
330
|
|
|
306
331
|
{/* Tool call events (assistant messages only) */}
|
|
307
332
|
{hasToolEvents && (
|
|
308
|
-
<div className="max-w-[85%] md:max-w-[72%] flex flex-col gap-2 mb-2">
|
|
333
|
+
<div className="max-w-[85%] md:max-w-[72%] flex flex-col gap-2 mb-2" data-testid="message-tool-events">
|
|
309
334
|
{nonSendFileEvents.length > 1 && (
|
|
310
335
|
<button
|
|
311
336
|
type="button"
|
|
@@ -317,7 +342,20 @@ export const MessageBubble = memo(function MessageBubble({ message, assistantNam
|
|
|
317
342
|
)}
|
|
318
343
|
<div className={`${toolEventsExpanded ? 'max-h-[320px] overflow-y-auto pr-1 flex flex-col gap-2' : 'flex flex-col gap-2'}`}>
|
|
319
344
|
{visibleToolEvents.map((event, i) => {
|
|
320
|
-
const
|
|
345
|
+
const eventKey = event.toolCallId || `${message.time}-${event.name}-${event.input}`
|
|
346
|
+
const key = `${message.time}-tool-${toolEventsExpanded ? `all-${eventKey}` : `latest-${eventKey}`}`
|
|
347
|
+
|
|
348
|
+
if (event.name === 'spawn_subagent' && event.output) {
|
|
349
|
+
// Prefer rich SwarmStatusCard when snapshot data is available
|
|
350
|
+
const statusData = parseSwarmStatusOutput(event.name, event.output)
|
|
351
|
+
if (statusData) {
|
|
352
|
+
return <div key={key}><SwarmStatusStyles /><SwarmStatusCard data={statusData} /></div>
|
|
353
|
+
}
|
|
354
|
+
const swarmData = parseSwarmOutput(event.name, event.output)
|
|
355
|
+
if (swarmData) {
|
|
356
|
+
return <SwarmPanel key={key} data={swarmData} />
|
|
357
|
+
}
|
|
358
|
+
}
|
|
321
359
|
|
|
322
360
|
if (event.name === 'delegate_to_agent') {
|
|
323
361
|
const inp = tryParseJson(event.input || '{}')
|
|
@@ -356,11 +394,12 @@ export const MessageBubble = memo(function MessageBubble({ message, assistantNam
|
|
|
356
394
|
<ToolCallBubble
|
|
357
395
|
key={key}
|
|
358
396
|
event={{
|
|
359
|
-
id: `${message.time}-${toolEventsExpanded ? i : toolEvents.length - 1}`,
|
|
397
|
+
id: event.toolCallId || `${message.time}-${toolEventsExpanded ? i : toolEvents.length - 1}`,
|
|
360
398
|
name: event.name,
|
|
361
399
|
input: event.input,
|
|
362
400
|
output: event.output,
|
|
363
401
|
status: event.error ? 'error' : 'done',
|
|
402
|
+
|
|
364
403
|
}}
|
|
365
404
|
/>
|
|
366
405
|
)
|
|
@@ -417,7 +456,7 @@ export const MessageBubble = memo(function MessageBubble({ message, assistantNam
|
|
|
417
456
|
) : (
|
|
418
457
|
/* Message bubble */
|
|
419
458
|
<div className={`${isStructured ? 'max-w-[92%] md:max-w-[85%]' : 'max-w-[85%] md:max-w-[72%]'} ${isUser ? 'bubble-user px-5 py-3.5' : isHeartbeat ? 'bubble-ai px-4 py-3' : 'bubble-ai px-5 py-3.5'}`}>
|
|
420
|
-
{renderAttachments(message)}
|
|
459
|
+
{renderAttachments(message, isDesktop ? handleOpenAttachmentImage : undefined)}
|
|
421
460
|
|
|
422
461
|
{walletRequest ? (
|
|
423
462
|
<div className="flex flex-col gap-3 p-4 rounded-[18px] bg-sky-500/[0.03] border border-sky-500/20 shadow-[0_0_20px_rgba(14,165,233,0.05)]">
|