@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
|
@@ -0,0 +1,412 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Continuation logic for stream-agent-chat.
|
|
3
|
+
*
|
|
4
|
+
* Determines whether an LLM iteration should continue (and why),
|
|
5
|
+
* builds the appropriate follow-up prompts, and resolves final
|
|
6
|
+
* response text from tool-heavy turns.
|
|
7
|
+
*/
|
|
8
|
+
import type { MessageToolEvent } from '@/types'
|
|
9
|
+
import { extractSuggestions } from './suggestions'
|
|
10
|
+
|
|
11
|
+
// ---------------------------------------------------------------------------
|
|
12
|
+
// Types
|
|
13
|
+
// ---------------------------------------------------------------------------
|
|
14
|
+
|
|
15
|
+
export type ContinuationType =
|
|
16
|
+
| 'recursion'
|
|
17
|
+
| 'transient'
|
|
18
|
+
| 'required_tool'
|
|
19
|
+
| 'attachment_followthrough'
|
|
20
|
+
| 'execution_followthrough'
|
|
21
|
+
| 'deliverable_followthrough'
|
|
22
|
+
| 'tool_summary'
|
|
23
|
+
| false
|
|
24
|
+
|
|
25
|
+
// ---------------------------------------------------------------------------
|
|
26
|
+
// Message classification helpers
|
|
27
|
+
// ---------------------------------------------------------------------------
|
|
28
|
+
|
|
29
|
+
export function isBroadGoal(text: string): boolean {
|
|
30
|
+
if (text.length < 50) return false
|
|
31
|
+
if (/```/.test(text)) return false
|
|
32
|
+
if (/\/(src|lib|app|pages|components|api)\//.test(text)) return false
|
|
33
|
+
if (/^\s*\d+[.)]\s/m.test(text)) return false
|
|
34
|
+
if (text.length < 80 && text.endsWith('?')) return false
|
|
35
|
+
return true
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function looksLikeExternalWalletTask(text: string): boolean {
|
|
39
|
+
const normalized = text.toLowerCase()
|
|
40
|
+
if (!normalized.trim()) return false
|
|
41
|
+
return /\b(wallet|wallet connect|walletconnect|trade|trading|exchange|dex|bridge|swap|deposit|withdraw|onchain|token|gas|hyperliquid|arbitrum|ethereum|solana|base|usdc|eth|sol)\b/.test(normalized)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function looksLikeBoundedExternalExecutionTask(text: string): boolean {
|
|
45
|
+
const normalized = text.toLowerCase()
|
|
46
|
+
if (!looksLikeExternalWalletTask(text)) return false
|
|
47
|
+
return /\b(live|swap|trade|buy|purchase|sell|mint|claim|execute|transact|transaction|approve|broadcast)\b/.test(normalized)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function looksLikeOpenEndedDeliverableTask(text: string): boolean {
|
|
51
|
+
const normalized = text.toLowerCase()
|
|
52
|
+
if (!normalized.trim()) return false
|
|
53
|
+
if (/```|package\.json|tsconfig|\btsx?\b|\bjsx?\b|pytest|vitest|npm run|src\/|components\/|api\//.test(normalized)) return false
|
|
54
|
+
if (/\b(revise|revision|iterate|iteration|draft|deliverable|deliverables|offer|brief|copy|proposal|landing|outreach|plan|strategy|report|memo|document|docs?)\b/.test(normalized)) return true
|
|
55
|
+
if (
|
|
56
|
+
/\b(create|build|generate|make|write|produce)\b/.test(normalized)
|
|
57
|
+
&& /\b(save|write|output|export)\b[^.!?\n]{0,60}\b(to|as|in)\b[^.!?\n]{0,40}(\/|~\/|\.\/|\.[a-z]{2,5}\b)/.test(normalized)
|
|
58
|
+
) {
|
|
59
|
+
return true
|
|
60
|
+
}
|
|
61
|
+
if (
|
|
62
|
+
isBroadGoal(text)
|
|
63
|
+
&& /\b(create|build|generate|make|write|research|capture|take|start|produce)\b/.test(normalized)
|
|
64
|
+
&& /\b(screenshot|screenshots|image|images|markdown|\.md\b|md\b|md files?|pdf|pdf files?|html|html\s+(?:page|file)|dashboard|site|sites|website|web page|webpage|dev server|dev servers|artifact|artifacts|topic|topics)\b/.test(normalized)
|
|
65
|
+
) {
|
|
66
|
+
return true
|
|
67
|
+
}
|
|
68
|
+
return isBroadGoal(text) && /(\.md\b|\.txt\b|\.html\b|\.json\b|copy|brief|proposal|plan|report|draft|document|dashboard)/.test(normalized)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function looksLikeIncompleteDeliverableResponse(text: string): boolean {
|
|
72
|
+
const trimmed = text.trim()
|
|
73
|
+
if (!trimmed) return true
|
|
74
|
+
if (trimmed.endsWith(':') || trimmed.endsWith('...') || trimmed.endsWith('…')) return true
|
|
75
|
+
const lastChunk = trimmed.slice(-400).toLowerCase()
|
|
76
|
+
return /\b(?:next|now|then|after that|moving on to|proceeding to)\b[^.!?\n]{0,120}\b(?:i(?:'ll| will)|create|build|write|capture|take|start|finish|generate)\b/.test(lastChunk)
|
|
77
|
+
|| /\b(?:i(?:'ll| will)|let me)\s+(?:now|next)?\s*(?:create|build|write|capture|take|start|finish|generate|continue)\b/.test(lastChunk)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// ---------------------------------------------------------------------------
|
|
81
|
+
// Tool evidence analysis
|
|
82
|
+
// ---------------------------------------------------------------------------
|
|
83
|
+
|
|
84
|
+
export function hasStateChangingWalletEvidence(toolEvents: MessageToolEvent[]): boolean {
|
|
85
|
+
return toolEvents.some((event) => {
|
|
86
|
+
const input = `${event.input || ''}\n${event.output || ''}`
|
|
87
|
+
return event.name === 'wallet_tool' && (
|
|
88
|
+
/"action":"send_transaction"/.test(input)
|
|
89
|
+
|| /"action":"send"/.test(input)
|
|
90
|
+
|| /"action":"sign_transaction"/.test(input)
|
|
91
|
+
|| /"type":"plugin_wallet_action_request"/.test(input)
|
|
92
|
+
|| /"type":"plugin_wallet_transfer_request"/.test(input)
|
|
93
|
+
|| /"status":"broadcast"/.test(input)
|
|
94
|
+
)
|
|
95
|
+
})
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export function countExternalExecutionResearchSteps(toolEvents: MessageToolEvent[]): number {
|
|
99
|
+
return toolEvents.filter((event) => {
|
|
100
|
+
if (['http_request', 'web', 'web_search', 'web_fetch', 'browser'].includes(event.name)) return true
|
|
101
|
+
if (event.name !== 'wallet_tool') return false
|
|
102
|
+
return /"action":"(balance|address|transactions|call_contract|encode_contract_call)"/.test(event.input || '')
|
|
103
|
+
}).length
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export function countDistinctExternalResearchHosts(toolEvents: MessageToolEvent[]): number {
|
|
107
|
+
const hosts = new Set<string>()
|
|
108
|
+
for (const event of toolEvents) {
|
|
109
|
+
const candidates = [event.input || '', event.output || '']
|
|
110
|
+
for (const candidate of candidates) {
|
|
111
|
+
const matches = candidate.match(/https?:\/\/[^"'\\\s)]+/g) || []
|
|
112
|
+
for (const match of matches) {
|
|
113
|
+
try {
|
|
114
|
+
hosts.add(new URL(match).host.toLowerCase())
|
|
115
|
+
} catch {
|
|
116
|
+
// Ignore malformed URLs in model/tool text.
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return hosts.size
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// ---------------------------------------------------------------------------
|
|
125
|
+
// Continuation decision helpers
|
|
126
|
+
// ---------------------------------------------------------------------------
|
|
127
|
+
|
|
128
|
+
export function shouldForceExternalExecutionFollowthrough(params: {
|
|
129
|
+
userMessage: string
|
|
130
|
+
finalResponse: string
|
|
131
|
+
hasToolCalls: boolean
|
|
132
|
+
toolEvents: MessageToolEvent[]
|
|
133
|
+
}): boolean {
|
|
134
|
+
if (!looksLikeBoundedExternalExecutionTask(params.userMessage)) return false
|
|
135
|
+
if (!params.hasToolCalls || params.toolEvents.length < 4) return false
|
|
136
|
+
if (hasStateChangingWalletEvidence(params.toolEvents)) return false
|
|
137
|
+
const distinctHosts = countDistinctExternalResearchHosts(params.toolEvents)
|
|
138
|
+
const trimmed = params.finalResponse.trim()
|
|
139
|
+
if (!trimmed) return countExternalExecutionResearchSteps(params.toolEvents) >= 4 || distinctHosts >= 3
|
|
140
|
+
if (/\b(last reversible step|exact blocker|safest next action|blocked|cannot|can't|missing capability|no-key route unavailable)\b/i.test(trimmed)) {
|
|
141
|
+
return false
|
|
142
|
+
}
|
|
143
|
+
if (countExternalExecutionResearchSteps(params.toolEvents) < 4 && distinctHosts < 3) return false
|
|
144
|
+
return /(let me|i'll|i will|trying|research|query|check|look|promising|now let me|good -|good,)/i.test(trimmed) || trimmed.length < 500
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export function shouldForceDeliverableFollowthrough(params: {
|
|
148
|
+
userMessage: string
|
|
149
|
+
finalResponse: string
|
|
150
|
+
hasToolCalls: boolean
|
|
151
|
+
toolEvents: MessageToolEvent[]
|
|
152
|
+
}): boolean {
|
|
153
|
+
if (!looksLikeOpenEndedDeliverableTask(params.userMessage)) return false
|
|
154
|
+
if (!params.hasToolCalls || params.toolEvents.length === 0) return false
|
|
155
|
+
const trimmed = params.finalResponse.trim()
|
|
156
|
+
if (!trimmed) return params.toolEvents.length >= 2
|
|
157
|
+
if (
|
|
158
|
+
/\b(task complete|completed|finished|done|delivered|shared|sent|uploaded|attached)\b/i.test(trimmed)
|
|
159
|
+
&& /(?:\/api\/uploads\/|https?:\/\/|`[^`\n]+\.(?:md|pdf|png|jpe?g|webp|gif|html|txt|zip)`)/i.test(trimmed)
|
|
160
|
+
) {
|
|
161
|
+
return false
|
|
162
|
+
}
|
|
163
|
+
const userNormalized = params.userMessage.toLowerCase()
|
|
164
|
+
if (/\b(save|write|output)\b[^.!?\n]{0,60}\b(to|as)\b[^.!?\n]{0,40}(\/|~\/|\.[a-z]{2,5}\b)/.test(userNormalized)) {
|
|
165
|
+
const usedFileWriteTools = params.toolEvents.some((e) => {
|
|
166
|
+
if (!e.name) return false
|
|
167
|
+
if (['write_file', 'edit_file'].includes(e.name)) return true
|
|
168
|
+
if (e.name === 'shell' || e.name === 'execute_command') return true
|
|
169
|
+
if (e.name === 'files') {
|
|
170
|
+
const input = e.input || ''
|
|
171
|
+
return /"action"\s*:\s*"write"/i.test(input)
|
|
172
|
+
}
|
|
173
|
+
return false
|
|
174
|
+
})
|
|
175
|
+
if (!usedFileWriteTools) return true
|
|
176
|
+
}
|
|
177
|
+
if (looksLikeIncompleteDeliverableResponse(trimmed)) return true
|
|
178
|
+
return trimmed.length < 120 && params.toolEvents.length >= 3
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// ---------------------------------------------------------------------------
|
|
182
|
+
// Tool evidence rendering (shared with buildForcedExternalServiceSummary)
|
|
183
|
+
// ---------------------------------------------------------------------------
|
|
184
|
+
|
|
185
|
+
export function renderToolEvidence(events: MessageToolEvent[]): string {
|
|
186
|
+
return events
|
|
187
|
+
.slice(-10)
|
|
188
|
+
.map((event, index) => [
|
|
189
|
+
`Tool ${index + 1}: ${event.name}`,
|
|
190
|
+
event.input ? `Input: ${event.input}` : '',
|
|
191
|
+
event.output ? `Output: ${event.output.slice(0, 1200)}` : '',
|
|
192
|
+
].filter(Boolean).join('\n'))
|
|
193
|
+
.join('\n\n')
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// ---------------------------------------------------------------------------
|
|
197
|
+
// Continuation prompt builders
|
|
198
|
+
// ---------------------------------------------------------------------------
|
|
199
|
+
|
|
200
|
+
function buildExternalExecutionFollowthroughPrompt(params: {
|
|
201
|
+
userMessage: string
|
|
202
|
+
fullText: string
|
|
203
|
+
toolEvents: MessageToolEvent[]
|
|
204
|
+
}): string {
|
|
205
|
+
return [
|
|
206
|
+
'You are in a bounded external execution task and have already done enough research.',
|
|
207
|
+
'Do not restart broad discovery. Do not ask the user for another prompt.',
|
|
208
|
+
'Do not spend this continuation on more venue shopping. Use the already confirmed route unless one last fetch is strictly required to prepare execution.',
|
|
209
|
+
'If several venue or aggregator APIs already failed, stop searching for more venues. Either use a direct onchain read path with the available wallet tools, or state the blocker.',
|
|
210
|
+
'A prose approval request does not count as completion. If the next step is a sign/send/approve action, call the real wallet tool action so the runtime can create the approval request.',
|
|
211
|
+
'Do not mutate already confirmed token addresses, router addresses, spender addresses, or network identifiers unless newer tool evidence proves the earlier value was wrong.',
|
|
212
|
+
'Within this continuation, do exactly one of the following:',
|
|
213
|
+
'1. Take the next concrete execution step now using the existing tools and stop at the first approval boundary for a state-changing action.',
|
|
214
|
+
'2. If no safe executable step exists with the current tools, state the exact blocker with evidence.',
|
|
215
|
+
'A successful continuation ends with one of these outcomes only: an approval request, a broadcast transaction, or a final blocker summary.',
|
|
216
|
+
'Prefer the route sources and facts already confirmed in the tool evidence below. Do not keep shopping for new venues unless the current options are clearly unusable.',
|
|
217
|
+
'If the tool evidence already includes enough information to prepare a contract call, approval, quote read, or transaction simulation, do that now instead of making another search or HTTP request.',
|
|
218
|
+
'',
|
|
219
|
+
`Objective:\n${params.userMessage}`,
|
|
220
|
+
'',
|
|
221
|
+
`Current partial response:\n${params.fullText || '(none)'}`,
|
|
222
|
+
'',
|
|
223
|
+
`Recent tool evidence:\n${renderToolEvidence(params.toolEvents) || '(none)'}`,
|
|
224
|
+
].join('\n')
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
function buildDeliverableFollowthroughPrompt(params: {
|
|
228
|
+
userMessage: string
|
|
229
|
+
fullText: string
|
|
230
|
+
toolEvents: MessageToolEvent[]
|
|
231
|
+
}): string {
|
|
232
|
+
const lines = [
|
|
233
|
+
'You are in the middle of a multi-step deliverable and stopped after only a partial batch of work.',
|
|
234
|
+
'Continue from the existing workspace and artifacts. Do not restart from scratch and do not ask the user to restate the request.',
|
|
235
|
+
'Do not stop after one partial batch. Finish every requested deliverable that is still outstanding before concluding.',
|
|
236
|
+
'If a requested artifact cannot be produced, say exactly which artifact is missing, what blocked it, and what you already completed.',
|
|
237
|
+
'Use the existing files, screenshots, and generated outputs first. Inspect them if needed, then complete the remaining work.',
|
|
238
|
+
'Preserve hard structural constraints from the original request: exact counts stay exact, required titled sections stay present, and source coverage gaps should be filled instead of skipped.',
|
|
239
|
+
'End with a concise grouped completion summary that lists exact file paths, upload URLs, localhost URLs/ports, and screenshots you produced.',
|
|
240
|
+
]
|
|
241
|
+
|
|
242
|
+
const userNormalized = params.userMessage.toLowerCase()
|
|
243
|
+
const fileOutputMatch = userNormalized.match(/\b(?:save|write|output|export)\b[^.!?\n]{0,80}\b(?:to|as|at|in)\b[^.!?\n]{0,60}(\/[^\s,'"]+|~\/[^\s,'"]+|\.\/[^\s,'"]+)/i)
|
|
244
|
+
if (fileOutputMatch) {
|
|
245
|
+
const fileToolNames = ['write_file', 'edit_file', 'files', 'shell', 'execute_command']
|
|
246
|
+
const usedFileTools = params.toolEvents.some((e) => e.name && fileToolNames.includes(e.name))
|
|
247
|
+
if (!usedFileTools) {
|
|
248
|
+
lines.push(
|
|
249
|
+
'',
|
|
250
|
+
`CRITICAL: The user asked you to save output to a file path (${fileOutputMatch[1] || 'see objective'}). You have NOT used any file-writing tool yet.`,
|
|
251
|
+
'You MUST use the `files` or `write_file` tool to write the content to the requested path. Do not just include the content in your text response — actually write the file.',
|
|
252
|
+
)
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
lines.push(
|
|
257
|
+
'',
|
|
258
|
+
`Objective:\n${params.userMessage}`,
|
|
259
|
+
'',
|
|
260
|
+
`Current partial response:\n${params.fullText || '(none)'}`,
|
|
261
|
+
'',
|
|
262
|
+
`Recent tool evidence:\n${renderToolEvidence(params.toolEvents) || '(none)'}`,
|
|
263
|
+
)
|
|
264
|
+
return lines.join('\n')
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
function buildAttachmentFollowthroughPrompt(params: {
|
|
268
|
+
message: string
|
|
269
|
+
fullText: string
|
|
270
|
+
}): string {
|
|
271
|
+
return [
|
|
272
|
+
'The current thread already includes user attachments as inline context.',
|
|
273
|
+
'Image attachments are directly visible to you in the message content. Text and PDF attachments are also available inline when present.',
|
|
274
|
+
'Do not claim that you cannot use images, attachments, or external tools when they are available in this session.',
|
|
275
|
+
'If the user wants you to look something up from an attachment, first extract the identifier or details from the attachment/history, then use the enabled tools to continue.',
|
|
276
|
+
'Only state a blocker if the attachment is genuinely unreadable or a needed tool is actually unavailable after a real attempt.',
|
|
277
|
+
'',
|
|
278
|
+
`Original request:\n${params.message}`,
|
|
279
|
+
'',
|
|
280
|
+
`Your previous response:\n${params.fullText || '(none)'}`,
|
|
281
|
+
'',
|
|
282
|
+
'Now continue and handle the attachment-aware task correctly.',
|
|
283
|
+
].join('\n')
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
function buildToolSummaryPrompt(params: {
|
|
287
|
+
message: string
|
|
288
|
+
fullText: string
|
|
289
|
+
toolEvents: MessageToolEvent[]
|
|
290
|
+
}): string {
|
|
291
|
+
const toolSummaryLines = params.toolEvents
|
|
292
|
+
.filter((e) => e.output)
|
|
293
|
+
.map((e) => `[${e.name}]: ${(e.output || '').slice(0, 500)}`)
|
|
294
|
+
.slice(0, 6)
|
|
295
|
+
const preambleNote = params.fullText.trim()
|
|
296
|
+
? `You started with "${params.fullText.trim().slice(0, 100)}..." but did not follow through with actual results.`
|
|
297
|
+
: 'Your tool calls completed but you did not provide a response.'
|
|
298
|
+
return [
|
|
299
|
+
preambleNote,
|
|
300
|
+
'Here are the tool results:',
|
|
301
|
+
...toolSummaryLines,
|
|
302
|
+
'',
|
|
303
|
+
`Original request: ${params.message.slice(0, 500)}`,
|
|
304
|
+
'',
|
|
305
|
+
'Now answer the original request using these tool results. Be concise and direct. Present the findings clearly.',
|
|
306
|
+
].join('\n')
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
// ---------------------------------------------------------------------------
|
|
310
|
+
// buildContinuationPrompt — unified prompt builder for all continuation types
|
|
311
|
+
// ---------------------------------------------------------------------------
|
|
312
|
+
|
|
313
|
+
/**
|
|
314
|
+
* Returns the human-message prompt for a given continuation type,
|
|
315
|
+
* or `null` for types that don't push a message (e.g. `transient`).
|
|
316
|
+
*/
|
|
317
|
+
export function buildContinuationPrompt(params: {
|
|
318
|
+
type: ContinuationType
|
|
319
|
+
message: string
|
|
320
|
+
fullText: string
|
|
321
|
+
toolEvents: MessageToolEvent[]
|
|
322
|
+
requiredToolReminderNames: string[]
|
|
323
|
+
}): string | null {
|
|
324
|
+
switch (params.type) {
|
|
325
|
+
case 'recursion':
|
|
326
|
+
return 'Continue where you left off. Complete the remaining steps of the objective.'
|
|
327
|
+
|
|
328
|
+
case 'required_tool':
|
|
329
|
+
return `You have not yet completed the required explicit tool step(s): ${params.requiredToolReminderNames.join(', ')}. Use those enabled tools now before declaring success. Do not replace ask_human with a plain-text request, do not replace outbound delivery tools with prose, and do not replace screenshot requests with text-only summaries.`
|
|
330
|
+
|
|
331
|
+
case 'attachment_followthrough':
|
|
332
|
+
return buildAttachmentFollowthroughPrompt({
|
|
333
|
+
message: params.message,
|
|
334
|
+
fullText: params.fullText,
|
|
335
|
+
})
|
|
336
|
+
|
|
337
|
+
case 'execution_followthrough':
|
|
338
|
+
return buildExternalExecutionFollowthroughPrompt({
|
|
339
|
+
userMessage: params.message,
|
|
340
|
+
fullText: params.fullText,
|
|
341
|
+
toolEvents: params.toolEvents,
|
|
342
|
+
})
|
|
343
|
+
|
|
344
|
+
case 'deliverable_followthrough':
|
|
345
|
+
return buildDeliverableFollowthroughPrompt({
|
|
346
|
+
userMessage: params.message,
|
|
347
|
+
fullText: params.fullText,
|
|
348
|
+
toolEvents: params.toolEvents,
|
|
349
|
+
})
|
|
350
|
+
|
|
351
|
+
case 'tool_summary':
|
|
352
|
+
return buildToolSummaryPrompt({
|
|
353
|
+
message: params.message,
|
|
354
|
+
fullText: params.fullText,
|
|
355
|
+
toolEvents: params.toolEvents,
|
|
356
|
+
})
|
|
357
|
+
|
|
358
|
+
case 'transient':
|
|
359
|
+
case false:
|
|
360
|
+
return null
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
// ---------------------------------------------------------------------------
|
|
365
|
+
// Response text resolution
|
|
366
|
+
// ---------------------------------------------------------------------------
|
|
367
|
+
|
|
368
|
+
function resolveToolOnlyFinalResponse(toolEvents: MessageToolEvent[] | undefined): string {
|
|
369
|
+
const events = Array.isArray(toolEvents) ? toolEvents : []
|
|
370
|
+
for (let index = events.length - 1; index >= 0; index--) {
|
|
371
|
+
const event = events[index]
|
|
372
|
+
const output = typeof event?.output === 'string'
|
|
373
|
+
? extractSuggestions(event.output).clean.trim()
|
|
374
|
+
: ''
|
|
375
|
+
if (!output) continue
|
|
376
|
+
if (/^error[:\s]/i.test(output)) continue
|
|
377
|
+
if (output.startsWith('{') || output.startsWith('[')) continue
|
|
378
|
+
return output
|
|
379
|
+
}
|
|
380
|
+
return ''
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
export function resolveFinalStreamResponseText(params: {
|
|
384
|
+
fullText: string
|
|
385
|
+
lastSegment: string
|
|
386
|
+
lastSettledSegment: string
|
|
387
|
+
hasToolCalls: boolean
|
|
388
|
+
toolEvents?: MessageToolEvent[]
|
|
389
|
+
}): string {
|
|
390
|
+
const fullText = params.fullText || ''
|
|
391
|
+
if (!params.hasToolCalls) return fullText
|
|
392
|
+
|
|
393
|
+
const candidates = [
|
|
394
|
+
extractSuggestions(params.lastSegment || '').clean.trim(),
|
|
395
|
+
extractSuggestions(params.lastSettledSegment || '').clean.trim(),
|
|
396
|
+
extractSuggestions(fullText).clean.trim(),
|
|
397
|
+
resolveToolOnlyFinalResponse(params.toolEvents),
|
|
398
|
+
]
|
|
399
|
+
|
|
400
|
+
return candidates.find((candidate) => candidate.length > 0) || ''
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
export function resolveContinuationAssistantText(params: {
|
|
404
|
+
iterationText: string
|
|
405
|
+
lastSegment: string
|
|
406
|
+
}): string {
|
|
407
|
+
const candidates = [
|
|
408
|
+
extractSuggestions(params.iterationText || '').clean.trim(),
|
|
409
|
+
extractSuggestions(params.lastSegment || '').clean.trim(),
|
|
410
|
+
]
|
|
411
|
+
return candidates.find((candidate) => candidate.length > 0) || ''
|
|
412
|
+
}
|