@vellumai/assistant 0.8.4 → 0.8.5
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/ARCHITECTURE.md +2 -2
- package/docs/browser-use-architecture-phase2.md +1 -1
- package/knip.json +2 -1
- package/openapi.yaml +809 -11
- package/package.json +1 -1
- package/src/__tests__/anthropic-provider.test.ts +34 -37
- package/src/__tests__/assistant-event-hub-self-exclusion.test.ts +293 -0
- package/src/__tests__/assistant-feature-flags-integration.test.ts +3 -3
- package/src/__tests__/audit-log-rotation.test.ts +70 -16
- package/src/__tests__/background-workers-disk-pressure.test.ts +3 -3
- package/src/__tests__/btw-routes.test.ts +2 -3
- package/src/__tests__/call-controller.test.ts +0 -1
- package/src/__tests__/cancel-resolves-conversation-key.test.ts +1 -1
- package/src/__tests__/channel-guardian.test.ts +3 -3
- package/src/__tests__/checker.test.ts +6 -15
- package/src/__tests__/compaction-events.test.ts +1 -0
- package/src/__tests__/compactor-call-site-logging.test.ts +214 -0
- package/src/__tests__/computer-use-skill-manifest-regression.test.ts +5 -11
- package/src/__tests__/computer-use-tools.test.ts +2 -4
- package/src/__tests__/confirmation-request-guardian-bridge.test.ts +0 -1
- package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +1 -1
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +1 -1
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +197 -2
- package/src/__tests__/conversation-agent-loop.test.ts +163 -122
- package/src/__tests__/conversation-app-control-instantiation.test.ts +2 -5
- package/src/__tests__/conversation-clear-safety.test.ts +25 -25
- package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +1 -1
- package/src/__tests__/conversation-disk-view-integration.test.ts +2 -2
- package/src/__tests__/conversation-error.test.ts +31 -0
- package/src/__tests__/conversation-fork-crud.test.ts +178 -15
- package/src/__tests__/conversation-lifecycle.test.ts +52 -11
- package/src/__tests__/{conversation-load-cleaned-at.test.ts → conversation-load-history-stripped.test.ts} +13 -13
- package/src/__tests__/conversation-provider-retry-repair.test.ts +1 -0
- package/src/__tests__/conversation-routes-disk-view.test.ts +109 -0
- package/src/__tests__/conversation-routes-slash-commands.test.ts +35 -0
- package/src/__tests__/conversation-skill-tools.test.ts +2 -5
- package/src/__tests__/conversation-store.test.ts +1 -1
- package/src/__tests__/conversation-sync-tags.test.ts +99 -32
- package/src/__tests__/conversation-workspace-cache-state.test.ts +1 -0
- package/src/__tests__/conversation-workspace-injection.test.ts +1 -1
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +1 -1
- package/src/__tests__/credential-execution-feature-gates.test.ts +9 -7
- package/src/__tests__/credential-execution-tools.test.ts +6 -6
- package/src/__tests__/credential-security-invariants.test.ts +1 -0
- package/src/__tests__/credential-vault-unit.test.ts +2 -2
- package/src/__tests__/dynamic-page-surface.test.ts +2 -2
- package/src/__tests__/email-html-renderer.test.ts +12 -0
- package/src/__tests__/gateway-flag-listener.test.ts +237 -0
- package/src/__tests__/gemini-provider.test.ts +78 -0
- package/src/__tests__/guardian-dispatch.test.ts +0 -1
- package/src/__tests__/guardian-outbound-http.test.ts +7 -5
- package/src/__tests__/handlers-user-message-approval-consumption.test.ts +1 -1
- package/src/__tests__/heartbeat-disk-pressure.test.ts +4 -0
- package/src/__tests__/heartbeat-service.test.ts +4 -0
- package/src/__tests__/host-shell-tool.test.ts +1 -1
- package/src/__tests__/init-feature-flag-overrides.test.ts +5 -6
- package/src/__tests__/list-messages-tool-merge.test.ts +70 -11
- package/src/__tests__/llm-request-log-call-site.test.ts +136 -0
- package/src/__tests__/llm-request-log-source-clickhouse.test.ts +26 -0
- package/src/__tests__/llm-resolver.test.ts +77 -9
- package/src/__tests__/llm-usage-store.test.ts +66 -0
- package/src/__tests__/logger.test.ts +89 -0
- package/src/__tests__/mcp-abort-signal.test.ts +2 -2
- package/src/__tests__/media-generate-image.test.ts +31 -0
- package/src/__tests__/memory-v2-static-injector.test.ts +7 -7
- package/src/__tests__/model-intents.test.ts +2 -4
- package/src/__tests__/notification-guardian-path.test.ts +0 -1
- package/src/__tests__/onboarding-template-contract.test.ts +1 -1
- package/src/__tests__/openai-provider.test.ts +46 -0
- package/src/__tests__/openai-responses-provider.test.ts +114 -12
- package/src/__tests__/pending-interactions-resolved-event.test.ts +0 -1
- package/src/__tests__/platform-bash-auto-approve.test.ts +2 -2
- package/src/__tests__/platform.test.ts +2 -2
- package/src/__tests__/plugin-api-tool-definition.test.ts +92 -0
- package/src/__tests__/plugin-bootstrap.test.ts +2 -2
- package/src/__tests__/plugin-tool-contribution.test.ts +13 -6
- package/src/__tests__/plugin-types.test.ts +3 -2
- package/src/__tests__/prechat-onboarding-contract.test.ts +131 -98
- package/src/__tests__/pricing.test.ts +12 -0
- package/src/__tests__/prune-jobs-changes-parser.test.ts +61 -0
- package/src/__tests__/registry.test.ts +2 -8
- package/src/__tests__/require-fresh-approval.test.ts +2 -2
- package/src/__tests__/runtime-events-sse-bilingual.test.ts +154 -0
- package/src/__tests__/shell-tool-proxy-mode.test.ts +1 -1
- package/src/__tests__/skill-feature-flags.test.ts +2 -2
- package/src/__tests__/skill-projection-feature-flag.test.ts +4 -7
- package/src/__tests__/skill-projection.benchmark.test.ts +2 -6
- package/src/__tests__/skill-tool-factory.test.ts +1 -1
- package/src/__tests__/subagent-notify-parent.test.ts +1 -1
- package/src/__tests__/suggestion-routes.test.ts +1 -0
- package/src/__tests__/sync-message-contract.test.ts +59 -0
- package/src/__tests__/system-prompt.test.ts +145 -131
- package/src/__tests__/terminal-tools.test.ts +1 -1
- package/src/__tests__/tool-approval-handler.test.ts +1 -5
- package/src/__tests__/tool-execute-pipeline.test.ts +2 -2
- package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +2 -5
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +15 -5
- package/src/__tests__/tool-executor.test.ts +9 -62
- package/src/__tests__/tool-grant-request-escalation.test.ts +1 -6
- package/src/__tests__/trusted-contact-approval-notifier.test.ts +0 -1
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +1 -6
- package/src/__tests__/trusted-contact-multichannel.test.ts +0 -1
- package/src/__tests__/ui-file-upload-surface.test.ts +2 -2
- package/src/__tests__/usage-routes.test.ts +3 -0
- package/src/__tests__/verification-control-plane-policy.test.ts +2 -2
- package/src/__tests__/workspace-git-service.test.ts +6 -5
- package/src/__tests__/workspace-migration-089-move-memory-tree-out-of-v3.test.ts +86 -0
- package/src/acp/__tests__/prepare-agent-env.test.ts +146 -0
- package/src/acp/prepare-agent-env.ts +78 -0
- package/src/acp/session-manager.ts +1 -1
- package/src/agent/loop.ts +8 -0
- package/src/api/README.md +5 -0
- package/src/api/index.ts +4 -0
- package/src/api/package.json +10 -0
- package/src/background-wake/background-wake-routes.test.ts +233 -0
- package/src/background-wake/runtime-registry.ts +24 -0
- package/src/cli/commands/__tests__/browser.test.ts +23 -5
- package/src/cli/commands/__tests__/domain-register.test.ts +110 -0
- package/src/cli/commands/__tests__/domain-status.test.ts +33 -33
- package/src/cli/commands/__tests__/inference-send.test.ts +108 -5
- package/src/cli/commands/__tests__/memory-v2-compare-render.test.ts +98 -0
- package/src/cli/commands/__tests__/memory-v2.test.ts +1 -0
- package/src/cli/commands/__tests__/memory-v3-render.test.ts +340 -0
- package/src/cli/commands/browser.ts +247 -0
- package/src/cli/commands/domain.ts +91 -41
- package/src/cli/commands/inference.ts +93 -40
- package/src/cli/commands/memory-v2-compare-render.ts +115 -0
- package/src/cli/commands/memory-v2.ts +176 -1
- package/src/cli/commands/memory-v3-render.ts +344 -0
- package/src/cli/commands/memory-v3.ts +316 -0
- package/src/cli/program.ts +2 -0
- package/src/config/assistant-feature-flags.ts +21 -9
- package/src/config/bundled-skills/document-editor/SKILL.md +11 -2
- package/src/config/bundled-skills/document-editor/TOOLS.json +18 -0
- package/src/config/bundled-skills/document-editor/tools/document-open.ts +12 -0
- package/src/config/bundled-skills/image-studio/SKILL.md +4 -0
- package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +2 -2
- package/src/config/bundled-skills/media-processing/tools/ingest-media.ts +13 -8
- package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +10 -3
- package/src/config/bundled-skills/phone-calls/references/TRANSCRIPTS.md +16 -14
- package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +7 -2
- package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +7 -2
- package/src/config/bundled-tool-registry.ts +2 -0
- package/src/config/call-site-defaults.ts +7 -6
- package/src/config/feature-flag-registry.json +16 -0
- package/src/config/schemas/__tests__/memory-v2.test.ts +213 -1
- package/src/config/schemas/call-site-catalog.ts +21 -7
- package/src/config/schemas/llm.ts +12 -1
- package/src/config/schemas/memory-v2.ts +246 -0
- package/src/config/schemas/memory.ts +2 -1
- package/src/context/compactor.ts +52 -0
- package/src/conversations/__tests__/message-consolidation.test.ts +350 -0
- package/src/conversations/message-consolidation.ts +404 -0
- package/src/daemon/__tests__/conversation-tool-setup-exclude.test.ts +1 -1
- package/src/daemon/__tests__/meet-manifest-loader.test.ts +1 -1
- package/src/daemon/conversation-agent-loop-handlers.ts +2 -13
- package/src/daemon/conversation-agent-loop.ts +126 -76
- package/src/daemon/conversation-error.ts +31 -1
- package/src/daemon/conversation-lifecycle.ts +27 -22
- package/src/daemon/conversation-runtime-assembly.ts +10 -9
- package/src/daemon/conversation-tool-setup.ts +63 -3
- package/src/daemon/conversation-usage.ts +2 -0
- package/src/daemon/conversation.ts +14 -29
- package/src/daemon/disk-pressure-guard.ts +14 -2
- package/src/daemon/handlers/config-model.test.ts +1 -0
- package/src/daemon/handlers/conversations.ts +11 -3
- package/src/daemon/host-browser-proxy.ts +5 -5
- package/src/daemon/host-cu-proxy.ts +4 -4
- package/src/daemon/host-file-proxy.ts +4 -4
- package/src/daemon/host-proxy-base.ts +4 -4
- package/src/daemon/host-transfer-proxy.ts +10 -10
- package/src/daemon/lifecycle.ts +23 -20
- package/src/daemon/meet-manifest-loader.ts +1 -7
- package/src/daemon/message-types/conversations.ts +6 -9
- package/src/daemon/message-types/home.ts +1 -13
- package/src/daemon/message-types/messages.ts +6 -14
- package/src/daemon/message-types/sync.ts +14 -0
- package/src/daemon/shutdown-handlers.ts +24 -5
- package/src/daemon/switch-inference-profile-tool.ts +52 -0
- package/src/daemon/tool-setup-types.ts +13 -0
- package/src/events/relationship-state-updated.ts +25 -0
- package/src/heartbeat/__tests__/heartbeat-service.test.ts +1 -1
- package/src/home/home-greeting.ts +0 -9
- package/src/home/suggested-prompts.ts +0 -9
- package/src/ipc/gateway-flag-listener.ts +123 -0
- package/src/ipc/skill-routes/registries.ts +8 -12
- package/src/memory/__tests__/db-async-query.test.ts +165 -0
- package/src/memory/__tests__/db-maintenance.test.ts +115 -0
- package/src/memory/__tests__/jobs-store-enqueue-gate.test.ts +241 -0
- package/src/memory/__tests__/jobs-store-job-classes.test.ts +28 -1
- package/src/memory/__tests__/memory-retrospective-job.test.ts +7 -0
- package/src/memory/auto-analysis-enqueue.ts +5 -1
- package/src/memory/conversation-crud.ts +71 -70
- package/src/memory/conversation-starters-cadence.ts +3 -1
- package/src/memory/conversation-title-service.ts +19 -3
- package/src/memory/db-async-query.ts +214 -0
- package/src/memory/db-init.ts +10 -0
- package/src/memory/db-maintenance.ts +30 -21
- package/src/memory/graph/bootstrap.ts +8 -1
- package/src/memory/graph/capability-seed.ts +7 -3
- package/src/memory/graph/conversation-graph-memory.ts +100 -17
- package/src/memory/graph/extraction.ts +1 -5
- package/src/memory/graph/graph-search.ts +7 -1
- package/src/memory/indexer.ts +28 -18
- package/src/memory/job-handlers/cleanup.ts +76 -18
- package/src/memory/job-handlers/conversation-starters.ts +1 -4
- package/src/memory/jobs/embed-pkb-file.ts +6 -1
- package/src/memory/jobs-store.ts +14 -0
- package/src/memory/jobs-worker.ts +55 -22
- package/src/memory/llm-request-log-source-clickhouse.ts +42 -2
- package/src/memory/llm-request-log-source-local.ts +7 -0
- package/src/memory/llm-request-log-source.ts +9 -2
- package/src/memory/llm-request-log-store.ts +43 -1
- package/src/memory/llm-usage-store.ts +24 -0
- package/src/memory/memory-retrospective-enqueue.ts +8 -1
- package/src/memory/memory-retrospective-job.ts +5 -0
- package/src/memory/memory-v2-activation-log-store.ts +15 -6
- package/src/memory/migrations/260-rename-cleaned-at.ts +44 -0
- package/src/memory/migrations/261-llm-usage-add-raw-usage.ts +36 -0
- package/src/memory/migrations/262-memory-v3-coactivation.ts +57 -0
- package/src/memory/migrations/263-memory-v3-auto-edges.ts +50 -0
- package/src/memory/migrations/264-llm-request-log-call-site.ts +29 -0
- package/src/memory/migrations/index.ts +17 -0
- package/src/memory/migrations/registry.ts +33 -0
- package/src/memory/schema/conversations.ts +1 -1
- package/src/memory/schema/infrastructure.ts +21 -0
- package/src/memory/tool-usage-store.ts +36 -8
- package/src/memory/v2/__tests__/consolidation-job.test.ts +1 -0
- package/src/memory/v2/__tests__/harness-compare.test.ts +186 -0
- package/src/memory/v2/__tests__/harness-metrics.test.ts +74 -0
- package/src/memory/v2/__tests__/harness-oracle.test.ts +257 -0
- package/src/memory/v2/__tests__/harness-replay-input.test.ts +225 -0
- package/src/memory/v2/__tests__/harness-runner.test.ts +109 -0
- package/src/memory/v2/__tests__/injection.test.ts +127 -98
- package/src/memory/v2/__tests__/qdrant.test.ts +36 -0
- package/src/memory/v2/__tests__/router.test.ts +171 -3
- package/src/memory/v2/harness/compare.ts +57 -0
- package/src/memory/v2/harness/metrics.ts +124 -0
- package/src/memory/v2/harness/oracle.ts +145 -0
- package/src/memory/v2/harness/replay-input.ts +224 -0
- package/src/memory/v2/harness/retriever.ts +74 -0
- package/src/memory/v2/harness/router-retriever.ts +43 -0
- package/src/memory/v2/harness/runner.ts +106 -0
- package/src/memory/v2/harness/trace.ts +58 -0
- package/src/memory/v2/injection.ts +21 -15
- package/src/memory/v2/prompts/router.ts +26 -1
- package/src/memory/v2/qdrant.ts +14 -2
- package/src/memory/v2/router.ts +171 -18
- package/src/memory/v3/__tests__/coactivation-store.test.ts +422 -0
- package/src/memory/v3/__tests__/consolidation-job.test.ts +468 -0
- package/src/memory/v3/__tests__/edge-learning-job.test.ts +324 -0
- package/src/memory/v3/__tests__/edges.test.ts +563 -0
- package/src/memory/v3/__tests__/filter.test.ts +512 -0
- package/src/memory/v3/__tests__/gate.test.ts +574 -0
- package/src/memory/v3/__tests__/index-composition.test.ts +233 -0
- package/src/memory/v3/__tests__/loop.test.ts +530 -0
- package/src/memory/v3/__tests__/retriever.test.ts +226 -0
- package/src/memory/v3/__tests__/scouts.test.ts +440 -0
- package/src/memory/v3/__tests__/shadow-middleware.test.ts +312 -0
- package/src/memory/v3/__tests__/system-prompts.test.ts +154 -0
- package/src/memory/v3/__tests__/traversal.test.ts +469 -0
- package/src/memory/v3/__tests__/tree-index.test.ts +280 -0
- package/src/memory/v3/__tests__/tree-store.test.ts +529 -0
- package/src/memory/v3/__tests__/tree-walk.test.ts +707 -0
- package/src/memory/v3/__tests__/validate.test.ts +245 -0
- package/src/memory/v3/auto-edges.ts +223 -0
- package/src/memory/v3/coactivation-store.ts +124 -0
- package/src/memory/v3/consolidation-job.ts +323 -0
- package/src/memory/v3/edge-learning-job.ts +160 -0
- package/src/memory/v3/edges.ts +249 -0
- package/src/memory/v3/filter.ts +281 -0
- package/src/memory/v3/gate.ts +334 -0
- package/src/memory/v3/index-composition.ts +113 -0
- package/src/memory/v3/llm-capture.ts +46 -0
- package/src/memory/v3/loop.ts +382 -0
- package/src/memory/v3/maintenance.ts +144 -0
- package/src/memory/v3/prompt-context.ts +33 -0
- package/src/memory/v3/prompts/consolidation.ts +458 -0
- package/src/memory/v3/prompts/system-prompts.ts +196 -0
- package/src/memory/v3/retriever.ts +33 -0
- package/src/memory/v3/scouts.ts +420 -0
- package/src/memory/v3/shadow-middleware.ts +305 -0
- package/src/memory/v3/traversal.ts +206 -0
- package/src/memory/v3/tree-index.ts +237 -0
- package/src/memory/v3/tree-store.ts +394 -0
- package/src/memory/v3/tree-walk.ts +351 -0
- package/src/memory/v3/types.ts +65 -0
- package/src/memory/v3/validate.ts +300 -0
- package/src/notifications/adapters/macos.ts +18 -1
- package/src/notifications/adapters/platform.ts +1 -1
- package/src/notifications/decision-engine.ts +1 -4
- package/src/notifications/emit-signal.ts +29 -49
- package/src/permissions/prompter.ts +3 -3
- package/src/permissions/question-prompter.ts +5 -2
- package/src/permissions/secret-prompter.ts +2 -2
- package/src/plugin-api/index.ts +4 -0
- package/src/plugin-api/types.ts +7 -33
- package/src/plugins/defaults/index.ts +6 -0
- package/src/plugins/defaults/injectors.ts +18 -11
- package/src/plugins/external-plugin-loader.ts +5 -68
- package/src/plugins/types.ts +11 -16
- package/src/proactive-artifact/aux-message-injector.ts +17 -4
- package/src/prompts/__tests__/task-progress-hint-section.test.ts +3 -9
- package/src/prompts/persona-resolver.ts +36 -21
- package/src/prompts/sections.ts +39 -7
- package/src/prompts/system-prompt.ts +50 -185
- package/src/prompts/templates/BOOTSTRAP.md +2 -2
- package/src/prompts/templates/system-sections.ts +230 -8
- package/src/providers/__tests__/connection-model-compat.test.ts +234 -0
- package/src/providers/__tests__/retry-callsite.test.ts +85 -5
- package/src/providers/anthropic/client.ts +32 -66
- package/src/providers/call-site-routing.ts +14 -2
- package/src/providers/connection-model-compat.ts +38 -0
- package/src/providers/connection-resolution.ts +16 -2
- package/src/providers/gemini/client.ts +49 -6
- package/src/providers/inference/adapter-factory.ts +3 -0
- package/src/providers/minimax/client.ts +106 -0
- package/src/providers/model-catalog.ts +43 -0
- package/src/providers/model-intents.ts +1 -1
- package/src/providers/openai/chat-completions-provider.ts +6 -3
- package/src/providers/openai/codex-models.ts +18 -0
- package/src/providers/openai/responses-provider.ts +78 -21
- package/src/providers/provider-send-message.ts +7 -1
- package/src/providers/retry.ts +34 -3
- package/src/providers/thinking-config.ts +26 -1
- package/src/providers/usage-tracking.ts +2 -0
- package/src/runtime/AGENTS.md +2 -2
- package/src/runtime/agent-wake.ts +1 -0
- package/src/runtime/assistant-event-hub.ts +76 -6
- package/src/runtime/auth/route-policy.ts +36 -0
- package/src/runtime/btw-sidechain.ts +0 -6
- package/src/runtime/http-types.ts +0 -2
- package/src/runtime/migrations/vbundle-builder.ts +10 -3
- package/src/runtime/pending-interactions.ts +0 -1
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +106 -0
- package/src/runtime/routes/__tests__/memory-v2-simulate-route.test.ts +25 -6
- package/src/runtime/routes/__tests__/plugins-routes.test.ts +512 -0
- package/src/runtime/routes/acp-routes.test.ts +255 -6
- package/src/runtime/routes/acp-routes.ts +8 -1
- package/src/runtime/routes/avatar-routes.ts +10 -10
- package/src/runtime/routes/background-wake-routes.ts +188 -0
- package/src/runtime/routes/browser-tabs-routes.ts +200 -0
- package/src/runtime/routes/btw-routes.ts +0 -6
- package/src/runtime/routes/conversation-cli-routes.ts +1 -1
- package/src/runtime/routes/conversation-list-routes.ts +12 -4
- package/src/runtime/routes/conversation-management-routes.ts +77 -20
- package/src/runtime/routes/conversation-query-routes.ts +142 -36
- package/src/runtime/routes/conversation-routes.ts +252 -410
- package/src/runtime/routes/conversation-starter-routes.ts +6 -3
- package/src/runtime/routes/disk-pressure-routes.ts +1 -1
- package/src/runtime/routes/domain-routes.ts +60 -10
- package/src/runtime/routes/email-routes.ts +5 -2
- package/src/runtime/routes/events-routes.ts +54 -10
- package/src/runtime/routes/group-routes.ts +24 -8
- package/src/runtime/routes/host-browser-routes.ts +10 -2
- package/src/runtime/routes/host-cu-routes.ts +2 -2
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +96 -3
- package/src/runtime/routes/index.ts +8 -0
- package/src/runtime/routes/inference-profile-session-handler.ts +22 -12
- package/src/runtime/routes/inference-profile-session-routes.ts +7 -1
- package/src/runtime/routes/llm-call-sites-routes.ts +32 -5
- package/src/runtime/routes/memory-item-routes.ts +8 -3
- package/src/runtime/routes/memory-v2-routes.ts +215 -5
- package/src/runtime/routes/memory-v3-routes.ts +316 -0
- package/src/runtime/routes/migration-routes.ts +21 -24
- package/src/runtime/routes/plugins-routes.ts +337 -0
- package/src/runtime/routes/rename-conversation-routes.ts +6 -2
- package/src/runtime/routes/secret-routes.ts +25 -5
- package/src/runtime/routes/settings-routes.ts +12 -11
- package/src/runtime/routes/slack-channel-routes.ts +5 -4
- package/src/runtime/routes/workspace-routes.ts +25 -10
- package/src/runtime/sync/resource-sync-events.ts +106 -38
- package/src/runtime/sync/sync-publisher.test.ts +49 -0
- package/src/runtime/sync/sync-publisher.ts +2 -1
- package/src/runtime/verification-outbound-actions.ts +73 -1
- package/src/telemetry/types.ts +12 -0
- package/src/telemetry/usage-telemetry-reporter.test.ts +48 -0
- package/src/telemetry/usage-telemetry-reporter.ts +1 -0
- package/src/tools/acp/spawn.test.ts +119 -0
- package/src/tools/acp/spawn.ts +15 -2
- package/src/tools/apps/definitions.ts +2 -8
- package/src/tools/ask-question/ask-question-tool.test.ts +3 -3
- package/src/tools/ask-question/ask-question-tool.ts +38 -45
- package/src/tools/browser/__tests__/pinned-tabs.test.ts +70 -0
- package/src/tools/browser/browser-execution.ts +16 -3
- package/src/tools/browser/cdp-client/__tests__/browser-tabs-factory.test.ts +402 -0
- package/src/tools/browser/cdp-client/__tests__/types.test.ts +3 -0
- package/src/tools/browser/cdp-client/cdp-inspect-client.ts +12 -0
- package/src/tools/browser/cdp-client/extension-cdp-client.ts +27 -1
- package/src/tools/browser/cdp-client/factory.ts +100 -17
- package/src/tools/browser/cdp-client/local-cdp-client.ts +12 -0
- package/src/tools/browser/cdp-client/types.ts +65 -0
- package/src/tools/browser/pinned-tabs.ts +96 -40
- package/src/tools/computer-use/definitions.ts +22 -78
- package/src/tools/credential-execution/make-authenticated-request.ts +3 -9
- package/src/tools/credential-execution/manage-secure-command-tool.ts +3 -9
- package/src/tools/credential-execution/run-authenticated-command.ts +3 -9
- package/src/tools/credentials/vault.ts +3 -9
- package/src/tools/document/document-tool.ts +59 -0
- package/src/tools/execution-target.ts +21 -23
- package/src/tools/executor.ts +6 -1
- package/src/tools/filesystem/edit.ts +3 -9
- package/src/tools/filesystem/list.ts +3 -9
- package/src/tools/filesystem/read.ts +3 -9
- package/src/tools/filesystem/write.ts +3 -9
- package/src/tools/host-filesystem/edit.ts +3 -9
- package/src/tools/host-filesystem/read.ts +3 -9
- package/src/tools/host-filesystem/transfer.ts +3 -9
- package/src/tools/host-filesystem/write.ts +3 -9
- package/src/tools/host-terminal/host-shell.ts +3 -9
- package/src/tools/mcp/mcp-tool-factory.ts +1 -8
- package/src/tools/memory/register.test.ts +1 -1
- package/src/tools/memory/register.ts +4 -9
- package/src/tools/network/web-fetch.ts +3 -9
- package/src/tools/network/web-search.ts +25 -32
- package/src/tools/registry.ts +7 -23
- package/src/tools/schema-transforms.ts +1 -1
- package/src/tools/skills/execute.ts +3 -9
- package/src/tools/skills/load.ts +3 -9
- package/src/tools/skills/skill-tool-factory.ts +1 -8
- package/src/tools/subagent/notify-parent.ts +3 -9
- package/src/tools/system/request-permission.ts +3 -9
- package/src/tools/terminal/shell.ts +3 -9
- package/src/tools/tool-defaults.ts +94 -0
- package/src/tools/types.ts +27 -98
- package/src/tools/ui-surface/definitions.ts +6 -22
- package/src/usage/pricing.ts +23 -0
- package/src/usage/types.ts +12 -0
- package/src/util/logger.ts +16 -7
- package/src/util/platform.ts +7 -2
- package/src/util/sqlite3-runtime.ts +65 -0
- package/src/workspace/migrations/086-revert-stale-gemini-mis-rewrites.ts +1 -0
- package/src/workspace/migrations/089-move-memory-tree-out-of-v3.ts +86 -0
- package/src/workspace/migrations/registry.ts +2 -0
- package/src/__tests__/compaction-strip-metadata-clear.test.ts +0 -206
- package/src/__tests__/message-complete-display-id.test.ts +0 -175
- package/src/daemon/query-complexity-router.ts +0 -75
- package/src/prompts/cache-boundary.ts +0 -8
|
@@ -0,0 +1,404 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Message consolidation — shared logic that maps the raw DB row sequence
|
|
3
|
+
* onto the displayed transcript.
|
|
4
|
+
*
|
|
5
|
+
* A single "display turn" in the UI can span multiple DB rows. During
|
|
6
|
+
* streaming the agent loop persists each API call as a separate
|
|
7
|
+
* assistant row (deferred consolidation, for prefix-cache stability),
|
|
8
|
+
* and intervening user rows often carry only tool_result blocks that
|
|
9
|
+
* are suppressed at display time. The two-pass collapse here is what
|
|
10
|
+
* turns the raw sequence into the rows the user actually sees.
|
|
11
|
+
*
|
|
12
|
+
* Pass 1 — `mergeToolResultsIntoAssistantMessages`
|
|
13
|
+
* For each user row, lift its `tool_result` (and `web_search_tool_result`)
|
|
14
|
+
* blocks onto the preceding assistant row. If the user row had
|
|
15
|
+
* nothing else (only tool_result + system_notice blocks), drop the
|
|
16
|
+
* row entirely. Otherwise keep its non-tool-result content as a
|
|
17
|
+
* real user message.
|
|
18
|
+
*
|
|
19
|
+
* Pass 2 — `mergeConsecutiveAssistantMessages`
|
|
20
|
+
* After pass 1 removes tool-result-only user separators, fold runs
|
|
21
|
+
* of adjacent assistant rows onto the first row of the run
|
|
22
|
+
* ("anchor"). Anchors keep their id, createdAt, and metadata;
|
|
23
|
+
* subagent-notification metadata is promoted from later rows when
|
|
24
|
+
* the anchor lacks it.
|
|
25
|
+
*
|
|
26
|
+
* `findDisplayTurnEndIndex` is the primitive any write-path needs when
|
|
27
|
+
* it has a single DB-row id and wants to know "which DB rows make up
|
|
28
|
+
* the display turn that this row anchors". It uses the same
|
|
29
|
+
* `isToolResultOnlyUserMessage` predicate that pass 1 uses to decide
|
|
30
|
+
* which user rows are suppressed, so the read-path and write-path
|
|
31
|
+
* agree on cluster boundaries without duplicating the merge code.
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
import type { MessageRow } from "../memory/conversation-crud.js";
|
|
35
|
+
import { getLogger } from "../util/logger.js";
|
|
36
|
+
|
|
37
|
+
const log = getLogger("message-consolidation");
|
|
38
|
+
|
|
39
|
+
// ── Block predicates ────────────────────────────────────────────────
|
|
40
|
+
|
|
41
|
+
function isToolResultType(type: string): boolean {
|
|
42
|
+
return type === "tool_result" || type === "web_search_tool_result";
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function isSystemNoticeText(block: Record<string, unknown>): boolean {
|
|
46
|
+
if (block.type !== "text") return false;
|
|
47
|
+
const text = typeof block.text === "string" ? block.text : "";
|
|
48
|
+
return (
|
|
49
|
+
text.startsWith("<system_notice>") && text.endsWith("</system_notice>")
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* True when a user row's content is exclusively tool_result blocks
|
|
55
|
+
* (and optional system_notice text). Such rows are suppressed by the
|
|
56
|
+
* read-path collapse — they exist in the DB to satisfy the LLM's
|
|
57
|
+
* tool_use ↔ tool_result pairing requirement but are never displayed
|
|
58
|
+
* to the user. Any write-path that walks DB rows in display order
|
|
59
|
+
* must treat them as part of the surrounding assistant turn.
|
|
60
|
+
*/
|
|
61
|
+
export function isToolResultOnlyUserMessage(msg: MessageRow): boolean {
|
|
62
|
+
if (msg.role !== "user") return false;
|
|
63
|
+
let blocks: unknown[];
|
|
64
|
+
try {
|
|
65
|
+
const parsed = JSON.parse(msg.content);
|
|
66
|
+
if (!Array.isArray(parsed)) return false;
|
|
67
|
+
blocks = parsed;
|
|
68
|
+
} catch {
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
let sawToolResult = false;
|
|
73
|
+
for (const block of blocks) {
|
|
74
|
+
if (
|
|
75
|
+
typeof block !== "object" ||
|
|
76
|
+
block === null ||
|
|
77
|
+
typeof (block as Record<string, unknown>).type !== "string"
|
|
78
|
+
) {
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
const rec = block as Record<string, unknown>;
|
|
82
|
+
if (isToolResultType(rec.type as string)) {
|
|
83
|
+
sawToolResult = true;
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
if (isSystemNoticeText(rec)) {
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
return sawToolResult;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// ── Display-turn boundary lookup ────────────────────────────────────
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Returns the inclusive DB-row index where the display turn that
|
|
98
|
+
* contains `messages[startIdx]` ends.
|
|
99
|
+
*
|
|
100
|
+
* For non-assistant rows, returns `startIdx` unchanged — only assistant
|
|
101
|
+
* turns can span multiple rows.
|
|
102
|
+
*
|
|
103
|
+
* For assistant rows, advances past any consecutive rows that the
|
|
104
|
+
* read-path collapse would fold into the same display turn:
|
|
105
|
+
* - another assistant row → part of the consecutive-assistant run, OR
|
|
106
|
+
* - a tool-result-only user row → suppressed at display time, sits
|
|
107
|
+
* between two halves of the same assistant turn.
|
|
108
|
+
*
|
|
109
|
+
* Stops at the first real user message (or any non-collapsible row),
|
|
110
|
+
* end-of-array, or invalid index.
|
|
111
|
+
*
|
|
112
|
+
* Mirror of the cluster boundary that `mergeConsecutiveAssistantMessages`
|
|
113
|
+
* (post pass-1) would produce — without paying the cost of parsing
|
|
114
|
+
* every content block.
|
|
115
|
+
*/
|
|
116
|
+
export function findDisplayTurnEndIndex(
|
|
117
|
+
messages: MessageRow[],
|
|
118
|
+
startIdx: number,
|
|
119
|
+
): number {
|
|
120
|
+
if (startIdx < 0 || startIdx >= messages.length) return startIdx;
|
|
121
|
+
if (messages[startIdx]?.role !== "assistant") return startIdx;
|
|
122
|
+
|
|
123
|
+
let endIdx = startIdx;
|
|
124
|
+
while (endIdx + 1 < messages.length) {
|
|
125
|
+
const next = messages[endIdx + 1];
|
|
126
|
+
if (!next) break;
|
|
127
|
+
if (next.role === "assistant") {
|
|
128
|
+
endIdx += 1;
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
if (next.role === "user" && isToolResultOnlyUserMessage(next)) {
|
|
132
|
+
endIdx += 1;
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
break;
|
|
136
|
+
}
|
|
137
|
+
return endIdx;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// ── Pass 1: tool-result merging ─────────────────────────────────────
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Merge tool_result blocks from user messages into the preceding assistant
|
|
144
|
+
* message's content array. This lets renderHistoryContent's pendingToolUses
|
|
145
|
+
* map pair tool_use and tool_result blocks, preventing "unknown" tool names.
|
|
146
|
+
*
|
|
147
|
+
* User messages that consist entirely of tool_result blocks (and optional
|
|
148
|
+
* system_notice text) are removed from the output. Mixed messages (tool_result
|
|
149
|
+
* + real user text) keep only the non-tool-result blocks.
|
|
150
|
+
*/
|
|
151
|
+
export function mergeToolResultsIntoAssistantMessages(
|
|
152
|
+
messages: MessageRow[],
|
|
153
|
+
): MessageRow[] {
|
|
154
|
+
// Index of the most recent assistant message in the output array.
|
|
155
|
+
let lastAssistantIdx = -1;
|
|
156
|
+
// Parsed content caches — lazily populated per assistant message.
|
|
157
|
+
const parsedAssistantContent = new Map<number, unknown[]>();
|
|
158
|
+
|
|
159
|
+
const result: MessageRow[] = [];
|
|
160
|
+
|
|
161
|
+
for (const msg of messages) {
|
|
162
|
+
if (msg.role === "assistant") {
|
|
163
|
+
lastAssistantIdx = result.length;
|
|
164
|
+
result.push(msg);
|
|
165
|
+
continue;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Only process user messages — other roles pass through.
|
|
169
|
+
if (msg.role !== "user") {
|
|
170
|
+
result.push(msg);
|
|
171
|
+
continue;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
let blocks: unknown[];
|
|
175
|
+
try {
|
|
176
|
+
const parsed = JSON.parse(msg.content);
|
|
177
|
+
if (!Array.isArray(parsed)) {
|
|
178
|
+
result.push(msg);
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
blocks = parsed;
|
|
182
|
+
} catch {
|
|
183
|
+
result.push(msg);
|
|
184
|
+
continue;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// Separate tool-result blocks from real user content.
|
|
188
|
+
const toolResultBlocks: unknown[] = [];
|
|
189
|
+
const otherBlocks: unknown[] = [];
|
|
190
|
+
for (const block of blocks) {
|
|
191
|
+
if (
|
|
192
|
+
typeof block === "object" &&
|
|
193
|
+
block !== null &&
|
|
194
|
+
typeof (block as Record<string, unknown>).type === "string"
|
|
195
|
+
) {
|
|
196
|
+
const rec = block as Record<string, unknown>;
|
|
197
|
+
if (isToolResultType(rec.type as string)) {
|
|
198
|
+
toolResultBlocks.push(block);
|
|
199
|
+
} else if (isSystemNoticeText(rec)) {
|
|
200
|
+
// System notices don't count as user content — drop them when
|
|
201
|
+
// the message is otherwise tool-result-only.
|
|
202
|
+
otherBlocks.push(block);
|
|
203
|
+
} else {
|
|
204
|
+
otherBlocks.push(block);
|
|
205
|
+
}
|
|
206
|
+
} else {
|
|
207
|
+
otherBlocks.push(block);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// No tool results → pass through unchanged. System notices are only
|
|
212
|
+
// injected alongside tool results in the agent loop, so a pure user
|
|
213
|
+
// message (no tool_result blocks) should never be filtered — even if
|
|
214
|
+
// the user's text happens to look like a system_notice tag.
|
|
215
|
+
if (toolResultBlocks.length === 0) {
|
|
216
|
+
result.push(msg);
|
|
217
|
+
continue;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// Append tool_result blocks to the preceding assistant message's content.
|
|
221
|
+
// No-op at pagination boundaries (lastAssistantIdx < 0); orphan tool_results
|
|
222
|
+
// are silently dropped by renderHistoryContent downstream either way.
|
|
223
|
+
if (lastAssistantIdx >= 0) {
|
|
224
|
+
const assistant = result[lastAssistantIdx];
|
|
225
|
+
let assistantContent = parsedAssistantContent.get(lastAssistantIdx);
|
|
226
|
+
if (!assistantContent) {
|
|
227
|
+
try {
|
|
228
|
+
const parsed = JSON.parse(assistant.content);
|
|
229
|
+
assistantContent = Array.isArray(parsed) ? parsed : [parsed];
|
|
230
|
+
} catch {
|
|
231
|
+
assistantContent = [];
|
|
232
|
+
}
|
|
233
|
+
parsedAssistantContent.set(lastAssistantIdx, assistantContent);
|
|
234
|
+
}
|
|
235
|
+
assistantContent.push(...toolResultBlocks);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// If the user message had only tool_result (+ system_notice) blocks,
|
|
239
|
+
// suppress it entirely. Otherwise keep the non-tool-result content.
|
|
240
|
+
const realUserContent = otherBlocks.filter(
|
|
241
|
+
(b) =>
|
|
242
|
+
!(
|
|
243
|
+
typeof b === "object" &&
|
|
244
|
+
b !== null &&
|
|
245
|
+
isSystemNoticeText(b as Record<string, unknown>)
|
|
246
|
+
),
|
|
247
|
+
);
|
|
248
|
+
if (realUserContent.length > 0) {
|
|
249
|
+
result.push({ ...msg, content: JSON.stringify(otherBlocks) });
|
|
250
|
+
}
|
|
251
|
+
// else: tool-result-only → suppressed
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// Write back any modified assistant message content.
|
|
255
|
+
for (const [idx, content] of parsedAssistantContent) {
|
|
256
|
+
result[idx] = { ...result[idx], content: JSON.stringify(content) };
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
return result;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// ── Pass 2: consecutive-assistant merging ───────────────────────────
|
|
263
|
+
|
|
264
|
+
/** Parse a message's JSON content into an array of content blocks. */
|
|
265
|
+
function parseContentBlocks(content: string): unknown[] {
|
|
266
|
+
try {
|
|
267
|
+
const parsed = JSON.parse(content);
|
|
268
|
+
return Array.isArray(parsed) ? parsed : [parsed];
|
|
269
|
+
} catch (err) {
|
|
270
|
+
log.warn(
|
|
271
|
+
{ err },
|
|
272
|
+
"Failed to parse content blocks during assistant message merge",
|
|
273
|
+
);
|
|
274
|
+
return [];
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Append content blocks from a donor message onto a target block array.
|
|
280
|
+
* Parses the donor's JSON content and pushes each block into `target`.
|
|
281
|
+
*/
|
|
282
|
+
function appendContentBlocks(target: unknown[], donorContent: string): void {
|
|
283
|
+
try {
|
|
284
|
+
const parsed = JSON.parse(donorContent);
|
|
285
|
+
if (Array.isArray(parsed)) {
|
|
286
|
+
target.push(...parsed);
|
|
287
|
+
} else {
|
|
288
|
+
target.push(parsed);
|
|
289
|
+
}
|
|
290
|
+
} catch (err) {
|
|
291
|
+
log.warn(
|
|
292
|
+
{ err },
|
|
293
|
+
"Failed to parse donor content blocks during assistant message merge",
|
|
294
|
+
);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* Promote metadata fields from a donor message to the surviving message
|
|
300
|
+
* when the survivor lacks them. Currently promotes `subagentNotification`.
|
|
301
|
+
* Returns a new MessageRow if promotion occurred, otherwise the original.
|
|
302
|
+
*/
|
|
303
|
+
function promoteMetadata(survivor: MessageRow, donor: MessageRow): MessageRow {
|
|
304
|
+
if (donor.metadata && survivor.metadata) {
|
|
305
|
+
try {
|
|
306
|
+
const survivorMeta = JSON.parse(survivor.metadata);
|
|
307
|
+
const donorMeta = JSON.parse(donor.metadata);
|
|
308
|
+
if (
|
|
309
|
+
!survivorMeta.subagentNotification &&
|
|
310
|
+
donorMeta.subagentNotification
|
|
311
|
+
) {
|
|
312
|
+
survivorMeta.subagentNotification = donorMeta.subagentNotification;
|
|
313
|
+
return { ...survivor, metadata: JSON.stringify(survivorMeta) };
|
|
314
|
+
}
|
|
315
|
+
} catch (err) {
|
|
316
|
+
log.warn(
|
|
317
|
+
{ err },
|
|
318
|
+
"Failed to parse metadata during assistant message merge",
|
|
319
|
+
);
|
|
320
|
+
}
|
|
321
|
+
} else if (donor.metadata && !survivor.metadata) {
|
|
322
|
+
return { ...survivor, metadata: donor.metadata };
|
|
323
|
+
}
|
|
324
|
+
return survivor;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
/**
|
|
328
|
+
* Merge consecutive assistant messages into a single message at query time.
|
|
329
|
+
*
|
|
330
|
+
* During streaming, all assistant turns within one agent loop accumulate on
|
|
331
|
+
* a single client-side message. In the DB, each API turn is stored as a
|
|
332
|
+
* separate assistant row (consolidation is deferred to compaction for
|
|
333
|
+
* prefix-cache stability). This produces N separate assistant messages that
|
|
334
|
+
* the client would otherwise render as N individual rows — each showing
|
|
335
|
+
* "Completed 1 step" instead of one grouped "Completed N steps" accordion.
|
|
336
|
+
*
|
|
337
|
+
* This function concatenates the content block arrays of consecutive
|
|
338
|
+
* assistant messages (no intervening user messages after tool-result
|
|
339
|
+
* merging) into the first message of each run. The merged messages are
|
|
340
|
+
* removed from the output. This is query-time only — the DB is not
|
|
341
|
+
* modified.
|
|
342
|
+
*
|
|
343
|
+
* The first message in each run keeps its id, createdAt, and metadata so
|
|
344
|
+
* that attachment lookups, display timestamps, and subagent notifications
|
|
345
|
+
* continue to work. Metadata from later messages in the run (e.g.
|
|
346
|
+
* subagentNotification) is preserved by promoting it to the surviving
|
|
347
|
+
* message when the surviving message has no metadata of its own for that
|
|
348
|
+
* field.
|
|
349
|
+
*/
|
|
350
|
+
export function mergeConsecutiveAssistantMessages(messages: MessageRow[]): {
|
|
351
|
+
messages: MessageRow[];
|
|
352
|
+
/** Maps each surviving message ID → all original message IDs merged into it. */
|
|
353
|
+
mergedIdMap: Map<string, string[]>;
|
|
354
|
+
} {
|
|
355
|
+
const result: MessageRow[] = [];
|
|
356
|
+
// Key = index in `result`, value = accumulated content blocks.
|
|
357
|
+
const pendingMerges = new Map<number, unknown[]>();
|
|
358
|
+
// Key = index in `result`, value = IDs of messages merged into the target.
|
|
359
|
+
const mergedIds = new Map<number, string[]>();
|
|
360
|
+
|
|
361
|
+
for (const msg of messages) {
|
|
362
|
+
const lastIdx = result.length - 1;
|
|
363
|
+
const isConsecutiveAssistant =
|
|
364
|
+
msg.role === "assistant" &&
|
|
365
|
+
lastIdx >= 0 &&
|
|
366
|
+
result[lastIdx].role === "assistant";
|
|
367
|
+
|
|
368
|
+
if (!isConsecutiveAssistant) {
|
|
369
|
+
result.push(msg);
|
|
370
|
+
continue;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
// Track the donor message ID.
|
|
374
|
+
let ids = mergedIds.get(lastIdx);
|
|
375
|
+
if (!ids) {
|
|
376
|
+
ids = [];
|
|
377
|
+
mergedIds.set(lastIdx, ids);
|
|
378
|
+
}
|
|
379
|
+
ids.push(msg.id);
|
|
380
|
+
|
|
381
|
+
// Lazily parse the target's content on first merge.
|
|
382
|
+
let targetContent = pendingMerges.get(lastIdx);
|
|
383
|
+
if (!targetContent) {
|
|
384
|
+
targetContent = parseContentBlocks(result[lastIdx].content);
|
|
385
|
+
pendingMerges.set(lastIdx, targetContent);
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
appendContentBlocks(targetContent, msg.content);
|
|
389
|
+
result[lastIdx] = promoteMetadata(result[lastIdx], msg);
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
// Write back merged content for any messages that were targets.
|
|
393
|
+
for (const [idx, content] of pendingMerges) {
|
|
394
|
+
result[idx] = { ...result[idx], content: JSON.stringify(content) };
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
// Build the merged ID map keyed by surviving message ID.
|
|
398
|
+
const mergedIdMap = new Map<string, string[]>();
|
|
399
|
+
for (const [idx, ids] of mergedIds) {
|
|
400
|
+
mergedIdMap.set(result[idx].id, ids);
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
return { messages: result, mergedIdMap };
|
|
404
|
+
}
|
|
@@ -183,7 +183,7 @@ describe("loadMeetManifestProxies", () => {
|
|
|
183
183
|
expect(t.ownerSkillId).toBe("meet-join");
|
|
184
184
|
expect(t.ownerSkillBundled).toBe(true);
|
|
185
185
|
expect(t.ownerSkillVersionHash).toBe(FIXTURE_MANIFEST.sourceHash);
|
|
186
|
-
expect(t.
|
|
186
|
+
expect(t.input_schema).toEqual(
|
|
187
187
|
FIXTURE_MANIFEST.tools[0]!.input_schema,
|
|
188
188
|
);
|
|
189
189
|
});
|
|
@@ -144,11 +144,6 @@ export interface EventHandlerState {
|
|
|
144
144
|
*/
|
|
145
145
|
contextTooLargeError: unknown;
|
|
146
146
|
providerErrorUserMessage: string | null;
|
|
147
|
-
/**
|
|
148
|
-
* First persisted assistant row in this run; history keeps this id when it
|
|
149
|
-
* merges tool-turn rows into one display bubble.
|
|
150
|
-
*/
|
|
151
|
-
firstAssistantMessageId: string | undefined;
|
|
152
147
|
lastAssistantMessageId: string | undefined;
|
|
153
148
|
readonly pendingToolResults: Map<string, PendingToolResult>;
|
|
154
149
|
readonly persistedToolUseIds: Set<string>;
|
|
@@ -249,7 +244,6 @@ export function createEventHandlerState(): EventHandlerState {
|
|
|
249
244
|
imageTooLargeDetected: false,
|
|
250
245
|
contextTooLargeError: null,
|
|
251
246
|
providerErrorUserMessage: null,
|
|
252
|
-
firstAssistantMessageId: undefined,
|
|
253
247
|
lastAssistantMessageId: undefined,
|
|
254
248
|
pendingToolResults: new Map(),
|
|
255
249
|
persistedToolUseIds: new Set(),
|
|
@@ -275,12 +269,6 @@ export function createEventHandlerState(): EventHandlerState {
|
|
|
275
269
|
};
|
|
276
270
|
}
|
|
277
271
|
|
|
278
|
-
export function getClientDisplayMessageId(
|
|
279
|
-
state: EventHandlerState,
|
|
280
|
-
): string | undefined {
|
|
281
|
-
return state.firstAssistantMessageId ?? state.lastAssistantMessageId;
|
|
282
|
-
}
|
|
283
|
-
|
|
284
272
|
// ── Shared Helper ────────────────────────────────────────────────────
|
|
285
273
|
|
|
286
274
|
// providerNameOverride should be supplied when the caller already knows the
|
|
@@ -1111,7 +1099,6 @@ export async function handleMessageComplete(
|
|
|
1111
1099
|
DEFAULT_TIMEOUTS.persistence,
|
|
1112
1100
|
)) as PersistAddResult;
|
|
1113
1101
|
const assistantMsg = assistantPersistResult.message;
|
|
1114
|
-
state.firstAssistantMessageId ??= assistantMsg.id;
|
|
1115
1102
|
state.lastAssistantMessageId = assistantMsg.id;
|
|
1116
1103
|
|
|
1117
1104
|
// Backfill message_id on all LLM request logs from this turn.
|
|
@@ -1222,6 +1209,7 @@ function handleUsage(
|
|
|
1222
1209
|
JSON.stringify(event.rawResponse),
|
|
1223
1210
|
undefined,
|
|
1224
1211
|
providerName,
|
|
1212
|
+
"mainAgent",
|
|
1225
1213
|
);
|
|
1226
1214
|
} catch (err) {
|
|
1227
1215
|
deps.rlog.warn({ err }, "Failed to persist LLM request log (non-fatal)");
|
|
@@ -1287,6 +1275,7 @@ function handleProviderError(
|
|
|
1287
1275
|
JSON.stringify(buildProviderErrorResponsePayload(event.error)),
|
|
1288
1276
|
undefined,
|
|
1289
1277
|
event.actualProvider,
|
|
1278
|
+
"mainAgent",
|
|
1290
1279
|
);
|
|
1291
1280
|
} catch (err) {
|
|
1292
1281
|
deps.rlog.warn(
|