@vellumai/assistant 0.8.3 → 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/docker-entrypoint.sh +0 -1
- package/docs/browser-use-architecture-phase2.md +1 -1
- package/knip.json +2 -1
- package/node_modules/@vellumai/gateway-client/src/types.ts +2 -0
- package/openapi.yaml +1492 -100
- package/package.json +1 -1
- package/src/__tests__/agent-loop-exit-reason.test.ts +4 -5
- package/src/__tests__/agent-loop-override-profile.test.ts +1 -1
- package/src/__tests__/agent-loop.test.ts +88 -3
- package/src/__tests__/anthropic-provider.test.ts +302 -33
- package/src/__tests__/approval-cascade.test.ts +1 -1
- 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 +4 -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-delivery-store.test.ts +193 -0
- package/src/__tests__/channel-guardian.test.ts +3 -3
- package/src/__tests__/channel-reply-delivery.test.ts +284 -5
- package/src/__tests__/channel-retry-sweep.test.ts +274 -1
- package/src/__tests__/checker.test.ts +6 -15
- package/src/__tests__/compaction-events.test.ts +2 -1
- package/src/__tests__/compactor-call-site-logging.test.ts +214 -0
- package/src/__tests__/compactor-preserved-tail-count.test.ts +110 -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__/config-watcher.test.ts +1 -1
- package/src/__tests__/confirmation-request-guardian-bridge.test.ts +0 -1
- package/src/__tests__/context-token-estimator.test.ts +91 -1
- package/src/__tests__/conversation-abort-tool-results.test.ts +1 -1
- package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +1 -1
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +55 -4
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +228 -8
- package/src/__tests__/conversation-agent-loop.test.ts +188 -129
- package/src/__tests__/conversation-app-control-instantiation.test.ts +2 -5
- package/src/__tests__/conversation-app-control-lifecycle.test.ts +1 -1
- package/src/__tests__/conversation-clean-command.test.ts +137 -0
- package/src/__tests__/conversation-clear-safety.test.ts +25 -25
- package/src/__tests__/conversation-confirmation-signals.test.ts +1 -1
- 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 +324 -0
- package/src/__tests__/conversation-lifecycle.test.ts +53 -12
- package/src/__tests__/conversation-load-history-repair.test.ts +1 -1
- package/src/__tests__/conversation-load-history-stripped.test.ts +279 -0
- package/src/__tests__/conversation-pairing.test.ts +2 -2
- package/src/__tests__/conversation-process-callsite.test.ts +1 -1
- package/src/__tests__/conversation-provider-retry-repair.test.ts +2 -1
- package/src/__tests__/conversation-queue.test.ts +1 -1
- 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-runtime-assembly.test.ts +264 -81
- package/src/__tests__/conversation-seed-composer.test.ts +66 -4
- package/src/__tests__/conversation-skill-tools.test.ts +2 -5
- package/src/__tests__/conversation-slash-commands.test.ts +36 -8
- package/src/__tests__/conversation-slash-queue.test.ts +1 -1
- package/src/__tests__/conversation-slash-unknown.test.ts +1 -1
- package/src/__tests__/conversation-speed-override.test.ts +1 -1
- package/src/__tests__/conversation-store.test.ts +1 -1
- package/src/__tests__/conversation-surfaces-task-progress.test.ts +220 -0
- package/src/__tests__/conversation-sync-tags.test.ts +99 -32
- package/src/__tests__/conversation-workspace-cache-state.test.ts +2 -1
- package/src/__tests__/conversation-workspace-injection.test.ts +5 -1
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +5 -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 +7 -0
- package/src/__tests__/credential-vault-unit.test.ts +2 -2
- package/src/__tests__/cu-unified-flow.test.ts +10 -1
- package/src/__tests__/dm-backfill.test.ts +64 -0
- package/src/__tests__/dm-persistence.test.ts +33 -0
- package/src/__tests__/document-find-replace.test.ts +501 -0
- package/src/__tests__/dynamic-page-surface.test.ts +2 -2
- package/src/__tests__/email-html-renderer.test.ts +12 -0
- package/src/__tests__/first-greeting.test.ts +23 -2
- 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__/headless-browser-navigate.test.ts +172 -0
- package/src/__tests__/heartbeat-disk-pressure.test.ts +4 -0
- package/src/__tests__/heartbeat-service.test.ts +4 -0
- package/src/__tests__/host-bash-proxy.test.ts +6 -0
- package/src/__tests__/host-browser-proxy.test.ts +10 -0
- package/src/__tests__/host-cu-proxy.test.ts +8 -1
- package/src/__tests__/host-file-proxy.test.ts +8 -1
- package/src/__tests__/host-shell-tool.test.ts +1 -1
- package/src/__tests__/host-transfer-proxy.test.ts +8 -1
- package/src/__tests__/identity-routes.test.ts +57 -0
- package/src/__tests__/inbound-slack-persistence.test.ts +3 -0
- package/src/__tests__/init-feature-flag-overrides.test.ts +5 -6
- package/src/__tests__/injector-chain.test.ts +2 -0
- package/src/__tests__/injector-document-comments.test.ts +378 -0
- package/src/__tests__/injector-pkb-v2-silenced.test.ts +4 -25
- package/src/__tests__/list-messages-attachments.test.ts +21 -17
- package/src/__tests__/list-messages-hidden-metadata.test.ts +217 -0
- package/src/__tests__/list-messages-page-latest.test.ts +130 -14
- package/src/__tests__/list-messages-tool-merge.test.ts +77 -17
- package/src/__tests__/llm-context-normalization.test.ts +0 -2
- 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 +161 -9
- package/src/__tests__/llm-usage-store.test.ts +66 -0
- package/src/__tests__/log-export-routes.test.ts +99 -2
- 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__/message-queue-steer.test.ts +114 -0
- 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 +151 -0
- package/src/__tests__/openai-responses-provider.test.ts +118 -16
- package/src/__tests__/outbound-slack-persistence.test.ts +187 -20
- package/src/__tests__/pending-interactions-resolved-event.test.ts +189 -0
- package/src/__tests__/platform-bash-auto-approve.test.ts +2 -2
- package/src/__tests__/platform.test.ts +2 -5
- package/src/__tests__/plugin-api-tool-definition.test.ts +92 -0
- package/src/__tests__/plugin-bootstrap.test.ts +2 -2
- package/src/__tests__/plugin-source-watcher.test.ts +302 -0
- 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__/process-message-background-slack.test.ts +1 -51
- package/src/__tests__/process-message-display-content.test.ts +21 -16
- 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__/server-history-render.test.ts +83 -4
- 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__/steer-tool-repair.test.ts +249 -0
- 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 +161 -124
- package/src/__tests__/terminal-tools.test.ts +12 -2
- package/src/__tests__/thinking-block-replay.test.ts +113 -0
- package/src/__tests__/thread-backfill.test.ts +370 -22
- 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 +89 -53
- package/src/__tests__/tool-grant-request-escalation.test.ts +1 -6
- package/src/__tests__/tool-result-metadata-plumbing.test.ts +167 -0
- 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__/twilio-routes.test.ts +1 -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__/web-fetch.test.ts +2 -2
- package/src/__tests__/workspace-git-service.test.ts +94 -10
- package/src/__tests__/workspace-migration-088-deprecate-background-conversation-override.test.ts +158 -0
- 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/attachments.ts +1 -0
- package/src/agent/loop.ts +65 -20
- 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/next-wake.test.ts +289 -0
- package/src/background-wake/next-wake.ts +172 -0
- package/src/background-wake/runtime-registry.ts +24 -0
- package/src/browser/operations.ts +15 -0
- package/src/cli/commands/__tests__/browser.test.ts +23 -5
- package/src/cli/commands/__tests__/conversations-slack.test.ts +572 -0
- 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 +10 -12
- package/src/cli/commands/__tests__/memory-v3-render.test.ts +340 -0
- package/src/cli/commands/browser.ts +247 -0
- package/src/cli/commands/conversations.ts +128 -1
- package/src/cli/commands/domain.ts +91 -41
- package/src/cli/commands/inference-providers.ts +147 -1
- 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 +483 -0
- package/src/cli/commands/memory-v3-render.ts +344 -0
- package/src/cli/commands/memory-v3.ts +316 -0
- package/src/cli/commands/notifications.ts +24 -2
- package/src/cli/program.ts +2 -0
- package/src/cli/utils/conversation-id.ts +17 -5
- package/src/config/assistant-feature-flags.ts +21 -9
- package/src/config/bundled-skills/app-builder/SKILL.md +2 -2
- package/src/config/bundled-skills/document-editor/SKILL.md +124 -0
- package/src/config/bundled-skills/document-editor/TOOLS.json +258 -0
- package/src/config/bundled-skills/document-editor/tools/comment-list.ts +12 -0
- package/src/config/bundled-skills/document-editor/tools/comment-reply.ts +12 -0
- package/src/config/bundled-skills/document-editor/tools/comment-resolve.ts +12 -0
- package/src/config/bundled-skills/document-editor/tools/document-find.ts +12 -0
- package/src/config/bundled-skills/document-editor/tools/document-open.ts +12 -0
- package/src/config/bundled-skills/document-editor/tools/document-replace-text.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/SKILL.md +8 -0
- 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-skills/schedule/SKILL.md +8 -0
- package/src/config/bundled-tool-registry.ts +24 -12
- package/src/config/call-site-defaults.ts +20 -0
- package/src/config/feature-flag-registry.json +115 -3
- package/src/config/llm-resolver.ts +16 -2
- package/src/config/schemas/__tests__/memory-v2.test.ts +217 -1
- package/src/config/schemas/call-site-catalog.ts +35 -0
- package/src/config/schemas/llm.ts +14 -0
- package/src/config/schemas/memory-v2.ts +294 -1
- package/src/config/schemas/memory.ts +2 -1
- package/src/context/compactor.ts +60 -1
- package/src/context/token-estimator.ts +47 -4
- package/src/context/window-manager.ts +25 -0
- package/src/conversations/__tests__/message-consolidation.test.ts +350 -0
- package/src/conversations/message-consolidation.ts +404 -0
- package/src/credential-health/credential-health-service.ts +34 -19
- package/src/daemon/__tests__/conversation-tool-setup-exclude.test.ts +1 -1
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +66 -6
- package/src/daemon/__tests__/meet-manifest-loader.test.ts +1 -1
- package/src/daemon/__tests__/native-web-search-metadata.test.ts +357 -0
- package/src/daemon/__tests__/web-search-status-text.test.ts +287 -0
- package/src/daemon/conversation-agent-loop-handlers.ts +155 -36
- package/src/daemon/conversation-agent-loop.ts +307 -88
- package/src/daemon/conversation-error.ts +31 -1
- package/src/daemon/conversation-lifecycle.ts +149 -118
- package/src/daemon/conversation-messaging.ts +3 -0
- package/src/daemon/conversation-process.ts +273 -0
- package/src/daemon/conversation-queue-manager.ts +14 -0
- package/src/daemon/conversation-runtime-assembly.ts +145 -84
- package/src/daemon/conversation-slash.ts +37 -5
- package/src/daemon/conversation-surfaces.ts +45 -2
- package/src/daemon/conversation-tool-setup.ts +70 -3
- package/src/daemon/conversation-usage.ts +2 -0
- package/src/daemon/conversation.ts +54 -32
- package/src/daemon/disk-pressure-guard.ts +14 -2
- package/src/daemon/first-greeting.ts +10 -0
- package/src/daemon/handlers/__tests__/config-a2a-accept.test.ts +498 -0
- package/src/daemon/handlers/config-a2a.ts +160 -0
- package/src/daemon/handlers/config-model.test.ts +2 -0
- package/src/daemon/handlers/conversations.ts +90 -3
- package/src/daemon/handlers/shared.ts +92 -29
- package/src/daemon/host-bash-proxy.ts +1 -1
- package/src/daemon/host-browser-proxy.ts +5 -5
- package/src/daemon/host-cu-proxy.ts +5 -5
- package/src/daemon/host-file-proxy.ts +5 -5
- package/src/daemon/host-proxy-base.ts +4 -4
- package/src/daemon/host-transfer-proxy.ts +11 -11
- package/src/daemon/lifecycle.ts +40 -23
- package/src/daemon/meet-manifest-loader.ts +1 -7
- package/src/daemon/message-protocol.ts +4 -0
- package/src/daemon/message-types/conversations.ts +14 -9
- package/src/daemon/message-types/document-comments.ts +50 -0
- package/src/daemon/message-types/home.ts +1 -13
- package/src/daemon/message-types/messages.ts +66 -7
- package/src/daemon/message-types/surfaces.ts +3 -1
- package/src/daemon/message-types/sync.ts +14 -0
- package/src/daemon/message-types/web-activity.ts +57 -0
- package/src/daemon/plugin-source-watcher.ts +135 -3
- package/src/daemon/process-message.ts +69 -12
- 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/daemon/trust-context.ts +6 -0
- package/src/documents/document-comments-store.test.ts +338 -0
- package/src/documents/document-comments-store.ts +237 -0
- package/src/documents/document-store.ts +202 -0
- package/src/events/relationship-state-updated.ts +25 -0
- package/src/heartbeat/__tests__/heartbeat-service.test.ts +1 -2
- package/src/heartbeat/heartbeat-service.ts +1 -0
- package/src/home/__tests__/suggested-prompts.test.ts +33 -2
- package/src/home/feed-types.ts +6 -1
- package/src/home/home-content-refresh.ts +52 -0
- package/src/home/home-greeting-cache.ts +69 -0
- package/src/home/home-greeting.ts +85 -0
- package/src/home/suggested-prompts.ts +168 -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__/jobs-worker-v2-schedule.test.ts +135 -2
- package/src/memory/__tests__/memory-retrospective-job.test.ts +327 -6
- package/src/memory/auto-analysis-enqueue.ts +5 -1
- package/src/memory/conversation-crud.ts +191 -100
- 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 +26 -0
- package/src/memory/db-maintenance.ts +30 -21
- package/src/memory/delivery-crud.ts +41 -0
- package/src/memory/delivery-status.ts +141 -15
- package/src/memory/external-conversation-store.ts +32 -1
- 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 +68 -15
- 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-constants.ts +28 -0
- package/src/memory/memory-retrospective-enqueue.ts +11 -3
- package/src/memory/memory-retrospective-job.ts +413 -18
- package/src/memory/memory-retrospective-startup-cleanup.ts +3 -3
- package/src/memory/memory-v2-activation-log-store.ts +41 -14
- package/src/memory/migrations/100-core-tables.ts +1 -0
- package/src/memory/migrations/109-external-conversation-bindings.ts +1 -0
- package/src/memory/migrations/253-conversation-last-notified-profile.ts +15 -0
- package/src/memory/migrations/253-document-comments.ts +47 -0
- package/src/memory/migrations/254-external-conversation-binding-chat-name.ts +43 -0
- package/src/memory/migrations/255-channel-inbound-delivery-attempts.ts +24 -0
- package/src/memory/migrations/256-memory-v2-injection-events.ts +113 -0
- package/src/memory/migrations/257-strip-base-url-non-openai-compatible.ts +22 -0
- package/src/memory/migrations/258-onboarding-events-prior-assistants.ts +13 -0
- package/src/memory/migrations/259-conversation-cleaned-at.ts +33 -0
- 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 +34 -0
- package/src/memory/migrations/registry.ts +58 -0
- package/src/memory/onboarding-events-store.ts +7 -0
- package/src/memory/schema/calls.ts +1 -0
- package/src/memory/schema/conversations.ts +3 -0
- package/src/memory/schema/infrastructure.ts +22 -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-events.test.ts +318 -0
- package/src/memory/v2/__tests__/injection.test.ts +158 -112
- package/src/memory/v2/__tests__/page-index.test.ts +365 -1
- package/src/memory/v2/__tests__/qdrant.test.ts +36 -0
- package/src/memory/v2/__tests__/router.test.ts +660 -4
- package/src/memory/v2/consolidation-job.ts +14 -0
- 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-events.ts +101 -0
- package/src/memory/v2/injection.ts +42 -25
- package/src/memory/v2/page-index.ts +209 -7
- package/src/memory/v2/page-store.ts +18 -0
- package/src/memory/v2/prompts/router.ts +26 -1
- package/src/memory/v2/qdrant.ts +14 -2
- package/src/memory/v2/router.ts +369 -62
- 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/messaging/providers/index.ts +7 -1
- package/src/messaging/providers/slack/__tests__/adapter-mention-rendering.test.ts +329 -3
- package/src/messaging/providers/slack/__tests__/adapter-token-routing.test.ts +34 -1
- package/src/messaging/providers/slack/adapter.ts +178 -25
- package/src/messaging/providers/slack/api.test.ts +54 -0
- package/src/messaging/providers/slack/api.ts +119 -3
- package/src/messaging/providers/slack/client.ts +12 -0
- package/src/messaging/providers/slack/deep-link.ts +20 -1
- package/src/messaging/providers/slack/message-metadata.test.ts +48 -0
- package/src/messaging/providers/slack/message-metadata.ts +156 -0
- package/src/messaging/providers/slack/render-transcript.test.ts +107 -75
- package/src/messaging/providers/slack/render-transcript.ts +176 -49
- package/src/messaging/providers/slack/send.test.ts +77 -0
- package/src/messaging/providers/slack/send.ts +8 -2
- package/src/messaging/providers/slack/types.ts +14 -0
- package/src/notifications/__tests__/emit-signal-home-feed.test.ts +4 -1
- package/src/notifications/__tests__/home-feed-side-effect.test.ts +116 -54
- package/src/notifications/adapters/macos.ts +18 -1
- package/src/notifications/adapters/platform.ts +1 -1
- package/src/notifications/conversation-seed-composer.ts +14 -2
- package/src/notifications/decision-engine.ts +1 -4
- package/src/notifications/deferred-emit.ts +135 -0
- package/src/notifications/emit-signal.ts +38 -50
- package/src/notifications/home-feed-side-effect.ts +60 -30
- package/src/oauth/connect-orchestrator.ts +3 -0
- package/src/oauth/credential-token-resolver.ts +2 -0
- package/src/oauth/manual-token-connection.ts +19 -0
- package/src/oauth/oauth-store.ts +12 -0
- package/src/oauth/seed-providers.ts +22 -0
- package/src/permissions/prompter.ts +8 -5
- package/src/permissions/question-prompter.ts +5 -2
- package/src/permissions/secret-prompter.ts +6 -3
- 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 +100 -20
- 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__/system-prompt.test.ts +46 -2
- package/src/prompts/__tests__/task-progress-hint-section.test.ts +3 -9
- package/src/prompts/normalize-onboarding.ts +40 -0
- package/src/prompts/persona-resolver.ts +36 -21
- package/src/prompts/sections.ts +69 -19
- package/src/prompts/system-prompt.ts +118 -216
- package/src/prompts/template-detection.ts +37 -0
- package/src/prompts/templates/BOOTSTRAP-CONTENT-AUTOMATION.md +141 -0
- package/src/prompts/templates/BOOTSTRAP.md +10 -2
- package/src/prompts/templates/VOICE.md +3 -0
- package/src/prompts/templates/system-sections.ts +281 -9
- 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 +159 -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/fireworks/client.ts +20 -2
- package/src/providers/gemini/client.ts +49 -6
- package/src/providers/inference/__tests__/base-url-route-validation.test.ts +342 -0
- package/src/providers/inference/__tests__/base-url-security.test.ts +189 -0
- package/src/providers/inference/__tests__/codex-token-refresh.test.ts +254 -0
- package/src/providers/inference/adapter-factory.ts +18 -1
- package/src/providers/inference/auth.ts +3 -3
- package/src/providers/inference/codex-token-refresh.ts +128 -0
- package/src/providers/inference/resolve-auth.ts +49 -6
- package/src/providers/minimax/client.ts +106 -0
- package/src/providers/model-catalog.ts +91 -1
- package/src/providers/model-intents.ts +1 -1
- package/src/providers/openai/chat-completions-provider.ts +63 -23
- package/src/providers/openai/codex-models.ts +18 -0
- package/src/providers/openai/responses-provider.ts +86 -23
- package/src/providers/openrouter/client.ts +5 -1
- 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/types.ts +25 -0
- package/src/providers/usage-tracking.ts +2 -0
- package/src/runtime/AGENTS.md +2 -2
- package/src/runtime/__tests__/agent-wake.test.ts +214 -0
- package/src/runtime/__tests__/background-job-runner.test.ts +128 -0
- package/src/runtime/agent-wake.ts +152 -56
- package/src/runtime/assistant-event-hub.ts +76 -6
- package/src/runtime/auth/route-policy.ts +43 -3
- package/src/runtime/background-job-runner.ts +26 -0
- package/src/runtime/btw-sidechain.ts +0 -6
- package/src/runtime/channel-reply-delivery.ts +182 -47
- package/src/runtime/channel-retry-sweep.ts +141 -16
- package/src/runtime/http-types.ts +7 -6
- package/src/runtime/migrations/vbundle-builder.ts +10 -3
- package/src/runtime/pending-interactions.ts +50 -8
- package/src/runtime/routes/__tests__/content-source-routes.test.ts +162 -0
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +161 -1
- package/src/runtime/routes/__tests__/memory-v2-routes.test.ts +14 -0
- package/src/runtime/routes/__tests__/memory-v2-simulate-route.test.ts +290 -0
- package/src/runtime/routes/__tests__/plugins-routes.test.ts +512 -0
- package/src/runtime/routes/__tests__/sanity-routes.test.ts +280 -0
- package/src/runtime/routes/__tests__/slack-channel-routes.test.ts +266 -0
- package/src/runtime/routes/acp-routes.test.ts +255 -6
- package/src/runtime/routes/acp-routes.ts +8 -1
- package/src/runtime/routes/approval-routes.ts +4 -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/chatgpt-subscription-auth-routes.ts +246 -0
- package/src/runtime/routes/content-source-routes.ts +78 -0
- package/src/runtime/routes/conversation-cli-routes.ts +147 -2
- 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 +196 -31
- package/src/runtime/routes/conversation-routes.ts +472 -425
- package/src/runtime/routes/conversation-starter-routes.ts +6 -3
- package/src/runtime/routes/disk-pressure-routes.ts +1 -1
- package/src/runtime/routes/document-comments-routes.ts +287 -0
- package/src/runtime/routes/documents-routes.ts +33 -0
- 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/home-feed-routes.ts +6 -3
- package/src/runtime/routes/host-app-control-routes.ts +1 -1
- package/src/runtime/routes/host-browser-routes.ts +17 -2
- package/src/runtime/routes/host-cu-routes.ts +2 -2
- package/src/runtime/routes/identity-routes.ts +21 -0
- package/src/runtime/routes/inbound-message-handler.ts +288 -58
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +96 -3
- package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +365 -6
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +283 -82
- package/src/runtime/routes/index.ts +20 -4
- 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/inference-provider-connection-routes.ts +63 -7
- package/src/runtime/routes/integrations/a2a.ts +60 -1
- package/src/runtime/routes/llm-call-sites-routes.ts +32 -5
- package/src/runtime/routes/log-export-routes.ts +39 -0
- package/src/runtime/routes/memory-item-routes.ts +8 -3
- package/src/runtime/routes/memory-v2-routes.ts +427 -0
- package/src/runtime/routes/memory-v3-routes.ts +316 -0
- package/src/runtime/routes/migration-routes.ts +21 -24
- package/src/runtime/routes/notification-routes.ts +19 -2
- package/src/runtime/routes/plugins-routes.ts +337 -0
- package/src/runtime/routes/question-routes.ts +4 -1
- package/src/runtime/routes/rename-conversation-routes.ts +6 -2
- package/src/runtime/routes/sanity-routes.ts +159 -0
- 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 +188 -0
- package/src/runtime/routes/workspace-routes.ts +25 -10
- package/src/runtime/services/conversation-serializer.ts +30 -4
- 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/schedule/integration-status.ts +3 -1
- package/src/security/__tests__/oauth2-device-code.test.ts +479 -0
- package/src/security/oauth2-device-code.ts +307 -0
- package/src/security/oauth2.ts +26 -9
- package/src/security/secure-keys.ts +5 -0
- package/src/skills/catalog-install.ts +6 -2
- 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 +150 -0
- package/src/tools/browser/browser-execution.ts +106 -0
- package/src/tools/browser/cdp-client/__tests__/browser-tabs-factory.test.ts +402 -0
- package/src/tools/browser/cdp-client/__tests__/factory.test.ts +28 -0
- package/src/tools/browser/cdp-client/__tests__/types.test.ts +4 -0
- package/src/tools/browser/cdp-client/cdp-inspect-client.ts +22 -0
- package/src/tools/browser/cdp-client/extension-cdp-client.ts +42 -2
- package/src/tools/browser/cdp-client/factory.ts +171 -4
- package/src/tools/browser/cdp-client/local-cdp-client.ts +21 -0
- package/src/tools/browser/cdp-client/types.ts +101 -0
- package/src/tools/browser/pinned-tabs.ts +146 -0
- 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-comment-tool.test.ts +379 -0
- package/src/tools/document/document-comment-tool.ts +156 -0
- package/src/tools/document/document-tool.ts +187 -2
- 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/__tests__/web-fetch-metadata.test.ts +229 -0
- package/src/tools/network/__tests__/web-search-metadata.test.ts +346 -0
- package/src/tools/network/domain-normalize.ts +17 -0
- package/src/tools/network/web-fetch.ts +216 -73
- package/src/tools/network/web-search.ts +216 -98
- 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/safe-env.ts +3 -2
- package/src/tools/terminal/shell.ts +3 -9
- package/src/tools/tool-approval-handler.ts +19 -12
- package/src/tools/tool-defaults.ts +94 -0
- package/src/tools/types.ts +31 -98
- package/src/tools/ui-surface/definitions.ts +9 -23
- package/src/types/onboarding-context.ts +4 -0
- package/src/usage/pricing.ts +23 -0
- package/src/usage/types.ts +12 -0
- package/src/util/__tests__/favicon.test.ts +84 -0
- package/src/util/favicon.ts +40 -0
- package/src/util/logger.ts +16 -7
- package/src/util/platform.ts +7 -7
- package/src/util/sqlite3-runtime.ts +65 -0
- package/src/workspace/git-service.ts +75 -4
- package/src/workspace/migrations/086-revert-stale-gemini-mis-rewrites.ts +1 -0
- package/src/workspace/migrations/088-deprecate-background-conversation-override.ts +103 -0
- package/src/workspace/migrations/089-move-memory-tree-out-of-v3.ts +86 -0
- package/src/workspace/migrations/registry.ts +4 -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/config/bundled-skills/document/SKILL.md +0 -54
- package/src/config/bundled-skills/document/TOOLS.json +0 -106
- package/src/daemon/seed-files.ts +0 -18
- package/src/prompts/cache-boundary.ts +0 -8
- package/src/runtime/routes/interface-routes.ts +0 -43
- /package/src/config/bundled-skills/{document → document-editor}/tools/document-create.ts +0 -0
- /package/src/config/bundled-skills/{document → document-editor}/tools/document-delete.ts +0 -0
- /package/src/config/bundled-skills/{document → document-editor}/tools/document-list.ts +0 -0
- /package/src/config/bundled-skills/{document → document-editor}/tools/document-read.ts +0 -0
- /package/src/config/bundled-skills/{document → document-editor}/tools/document-update.ts +0 -0
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { RenderedHistoryContent } from "../daemon/handlers/shared.js";
|
|
1
2
|
import { renderHistoryContent } from "../daemon/handlers/shared.js";
|
|
2
3
|
import { getAttachmentMetadataForMessage } from "../memory/attachments-store.js";
|
|
3
4
|
import {
|
|
@@ -76,6 +77,18 @@ function toDeliverableTextSegments(
|
|
|
76
77
|
return [];
|
|
77
78
|
}
|
|
78
79
|
|
|
80
|
+
function hasDeliverableReply(
|
|
81
|
+
rendered: RenderedHistoryContent,
|
|
82
|
+
attachments: RuntimeAttachmentMetadata[],
|
|
83
|
+
): boolean {
|
|
84
|
+
return (
|
|
85
|
+
toDeliverableTextSegments(rendered.textSegments, rendered.text).length >
|
|
86
|
+
0 ||
|
|
87
|
+
attachments.length > 0 ||
|
|
88
|
+
hasNoResponseMarker(rendered.textSegments)
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
|
|
79
92
|
export async function deliverRenderedReplyViaCallback(
|
|
80
93
|
params: DeliverRenderedReplyParams,
|
|
81
94
|
): Promise<void> {
|
|
@@ -169,6 +182,13 @@ export async function deliverRenderedReplyViaCallback(
|
|
|
169
182
|
}
|
|
170
183
|
|
|
171
184
|
export type DeliverReplyOptions = {
|
|
185
|
+
/** Persisted assistant message row to deliver; defaults to latest assistant. */
|
|
186
|
+
messageId?: string;
|
|
187
|
+
/**
|
|
188
|
+
* Internal conversation message id for the user row that started this
|
|
189
|
+
* delivery. When set, fallback scans never cross into older turns.
|
|
190
|
+
*/
|
|
191
|
+
sinceMessageId?: string;
|
|
172
192
|
startFromSegment?: number;
|
|
173
193
|
onSegmentDelivered?: (deliveredCount: number) => void;
|
|
174
194
|
/** Deliver as ephemeral (visible only to `user`). Fire-and-forget. */
|
|
@@ -181,6 +201,125 @@ export type DeliverReplyOptions = {
|
|
|
181
201
|
onMessageTs?: (ts: string) => void;
|
|
182
202
|
};
|
|
183
203
|
|
|
204
|
+
type PersistedMessage = ReturnType<typeof getMessages>[number];
|
|
205
|
+
|
|
206
|
+
function readPersistedAssistantReply(msg: PersistedMessage): {
|
|
207
|
+
rendered: RenderedHistoryContent;
|
|
208
|
+
replyAttachments: RuntimeAttachmentMetadata[];
|
|
209
|
+
} {
|
|
210
|
+
let parsed: unknown;
|
|
211
|
+
try {
|
|
212
|
+
parsed = JSON.parse(msg.content);
|
|
213
|
+
} catch {
|
|
214
|
+
parsed = msg.content;
|
|
215
|
+
}
|
|
216
|
+
const rendered = renderHistoryContent(parsed);
|
|
217
|
+
|
|
218
|
+
const linked = getAttachmentMetadataForMessage(msg.id);
|
|
219
|
+
const replyAttachments: RuntimeAttachmentMetadata[] = linked.map((a) => ({
|
|
220
|
+
id: a.id,
|
|
221
|
+
filename: a.originalFilename,
|
|
222
|
+
mimeType: a.mimeType,
|
|
223
|
+
sizeBytes: a.sizeBytes,
|
|
224
|
+
kind: a.kind,
|
|
225
|
+
}));
|
|
226
|
+
|
|
227
|
+
return { rendered, replyAttachments };
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
function isToolResultUserMessage(msg: PersistedMessage): boolean {
|
|
231
|
+
if (msg.role !== "user") return false;
|
|
232
|
+
try {
|
|
233
|
+
const parsed = JSON.parse(msg.content) as unknown;
|
|
234
|
+
return (
|
|
235
|
+
Array.isArray(parsed) &&
|
|
236
|
+
parsed.length > 0 &&
|
|
237
|
+
parsed.every(
|
|
238
|
+
(block) =>
|
|
239
|
+
block !== null &&
|
|
240
|
+
typeof block === "object" &&
|
|
241
|
+
(block as Record<string, unknown>).type === "tool_result",
|
|
242
|
+
)
|
|
243
|
+
);
|
|
244
|
+
} catch {
|
|
245
|
+
return false;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
export function findAssistantReplyMessageIdForTurn(
|
|
250
|
+
conversationId: string,
|
|
251
|
+
userMessageId: string,
|
|
252
|
+
): string | undefined {
|
|
253
|
+
const msgs = getMessages(conversationId);
|
|
254
|
+
const userIndex = msgs.findIndex((msg) => msg.id === userMessageId);
|
|
255
|
+
if (userIndex === -1) return undefined;
|
|
256
|
+
|
|
257
|
+
let turnEndIndex = msgs.length;
|
|
258
|
+
for (let i = userIndex + 1; i < msgs.length; i++) {
|
|
259
|
+
const msg = msgs[i];
|
|
260
|
+
if (msg.role === "user" && !isToolResultUserMessage(msg)) {
|
|
261
|
+
turnEndIndex = i;
|
|
262
|
+
break;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
for (let i = turnEndIndex - 1; i > userIndex; i--) {
|
|
267
|
+
const msg = msgs[i];
|
|
268
|
+
if (msg.role === "assistant") {
|
|
269
|
+
const { rendered, replyAttachments } = readPersistedAssistantReply(msg);
|
|
270
|
+
if (hasDeliverableReply(rendered, replyAttachments)) {
|
|
271
|
+
return msg.id;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
return undefined;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
async function deliverPersistedAssistantMessageViaCallback(
|
|
279
|
+
msg: PersistedMessage,
|
|
280
|
+
externalChatId: string,
|
|
281
|
+
callbackUrl: string,
|
|
282
|
+
assistantId: string | undefined,
|
|
283
|
+
options: DeliverReplyOptions | undefined,
|
|
284
|
+
): Promise<boolean> {
|
|
285
|
+
const { rendered, replyAttachments } = readPersistedAssistantReply(msg);
|
|
286
|
+
if (!hasDeliverableReply(rendered, replyAttachments)) {
|
|
287
|
+
return false;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// Compose an `onMessageTs` that reconciles `slackMeta.channelTs` on the
|
|
291
|
+
// persisted assistant row once Slack returns the authoritative ts. The
|
|
292
|
+
// assistant row was written BEFORE the gateway POST in
|
|
293
|
+
// `handleMessageComplete`, so the partial `slackMeta` it carries is
|
|
294
|
+
// missing `channelTs` and would otherwise be rejected by
|
|
295
|
+
// `readSlackMetadata`, dropping the row out of chronological/thread-tag
|
|
296
|
+
// rendering. We only act on the FIRST ts (top-level segment); any
|
|
297
|
+
// subsequent split segments become independent Slack messages with
|
|
298
|
+
// their own ts and are not represented as separate DB rows.
|
|
299
|
+
const reconcileOnMessageTs = makeChannelTsReconciler(msg.id);
|
|
300
|
+
const callerOnMessageTs = options?.onMessageTs;
|
|
301
|
+
const composedOnMessageTs = (ts: string): void => {
|
|
302
|
+
reconcileOnMessageTs(ts);
|
|
303
|
+
callerOnMessageTs?.(ts);
|
|
304
|
+
};
|
|
305
|
+
|
|
306
|
+
await deliverRenderedReplyViaCallback({
|
|
307
|
+
callbackUrl,
|
|
308
|
+
chatId: externalChatId,
|
|
309
|
+
textSegments: rendered.textSegments,
|
|
310
|
+
fallbackText: rendered.text,
|
|
311
|
+
attachments: replyAttachments,
|
|
312
|
+
assistantId,
|
|
313
|
+
startFromSegment: options?.startFromSegment,
|
|
314
|
+
onSegmentDelivered: options?.onSegmentDelivered,
|
|
315
|
+
ephemeral: options?.ephemeral,
|
|
316
|
+
user: options?.user,
|
|
317
|
+
messageTs: options?.messageTs,
|
|
318
|
+
onMessageTs: composedOnMessageTs,
|
|
319
|
+
});
|
|
320
|
+
return true;
|
|
321
|
+
}
|
|
322
|
+
|
|
184
323
|
export async function deliverReplyViaCallback(
|
|
185
324
|
conversationId: string,
|
|
186
325
|
externalChatId: string,
|
|
@@ -188,58 +327,54 @@ export async function deliverReplyViaCallback(
|
|
|
188
327
|
assistantId?: string,
|
|
189
328
|
options?: DeliverReplyOptions,
|
|
190
329
|
): Promise<void> {
|
|
330
|
+
if (options?.messageId) {
|
|
331
|
+
const msg = getMessageById(options.messageId, conversationId);
|
|
332
|
+
if (!msg || msg.role !== "assistant") {
|
|
333
|
+
throw new Error(
|
|
334
|
+
`Target assistant reply message not found: ${options.messageId}`,
|
|
335
|
+
);
|
|
336
|
+
}
|
|
337
|
+
await deliverPersistedAssistantMessageViaCallback(
|
|
338
|
+
msg,
|
|
339
|
+
externalChatId,
|
|
340
|
+
callbackUrl,
|
|
341
|
+
assistantId,
|
|
342
|
+
options,
|
|
343
|
+
);
|
|
344
|
+
return;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
if (options?.sinceMessageId) {
|
|
348
|
+
const replyMessageId = findAssistantReplyMessageIdForTurn(
|
|
349
|
+
conversationId,
|
|
350
|
+
options.sinceMessageId,
|
|
351
|
+
);
|
|
352
|
+
if (replyMessageId) {
|
|
353
|
+
const msg = getMessageById(replyMessageId, conversationId);
|
|
354
|
+
if (msg && msg.role === "assistant") {
|
|
355
|
+
await deliverPersistedAssistantMessageViaCallback(
|
|
356
|
+
msg,
|
|
357
|
+
externalChatId,
|
|
358
|
+
callbackUrl,
|
|
359
|
+
assistantId,
|
|
360
|
+
options,
|
|
361
|
+
);
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
return;
|
|
365
|
+
}
|
|
366
|
+
|
|
191
367
|
const msgs = getMessages(conversationId);
|
|
192
368
|
for (let i = msgs.length - 1; i >= 0; i--) {
|
|
193
369
|
if (msgs[i].role !== "assistant") continue;
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
parsed = JSON.parse(msgs[i].content);
|
|
198
|
-
} catch {
|
|
199
|
-
parsed = msgs[i].content;
|
|
200
|
-
}
|
|
201
|
-
const rendered = renderHistoryContent(parsed);
|
|
202
|
-
|
|
203
|
-
const linked = getAttachmentMetadataForMessage(msgs[i].id);
|
|
204
|
-
const replyAttachments: RuntimeAttachmentMetadata[] = linked.map((a) => ({
|
|
205
|
-
id: a.id,
|
|
206
|
-
filename: a.originalFilename,
|
|
207
|
-
mimeType: a.mimeType,
|
|
208
|
-
sizeBytes: a.sizeBytes,
|
|
209
|
-
kind: a.kind,
|
|
210
|
-
}));
|
|
211
|
-
|
|
212
|
-
// Compose an `onMessageTs` that reconciles `slackMeta.channelTs` on the
|
|
213
|
-
// persisted assistant row once Slack returns the authoritative ts. The
|
|
214
|
-
// assistant row was written BEFORE the gateway POST in
|
|
215
|
-
// `handleMessageComplete`, so the partial `slackMeta` it carries is
|
|
216
|
-
// missing `channelTs` and would otherwise be rejected by
|
|
217
|
-
// `readSlackMetadata`, dropping the row out of chronological/thread-tag
|
|
218
|
-
// rendering. We only act on the FIRST ts (top-level segment); any
|
|
219
|
-
// subsequent split segments become independent Slack messages with
|
|
220
|
-
// their own ts and are not represented as separate DB rows.
|
|
221
|
-
const reconcileOnMessageTs = makeChannelTsReconciler(msgs[i].id);
|
|
222
|
-
const callerOnMessageTs = options?.onMessageTs;
|
|
223
|
-
const composedOnMessageTs = (ts: string): void => {
|
|
224
|
-
reconcileOnMessageTs(ts);
|
|
225
|
-
callerOnMessageTs?.(ts);
|
|
226
|
-
};
|
|
227
|
-
|
|
228
|
-
await deliverRenderedReplyViaCallback({
|
|
370
|
+
const delivered = await deliverPersistedAssistantMessageViaCallback(
|
|
371
|
+
msgs[i],
|
|
372
|
+
externalChatId,
|
|
229
373
|
callbackUrl,
|
|
230
|
-
chatId: externalChatId,
|
|
231
|
-
textSegments: rendered.textSegments,
|
|
232
|
-
fallbackText: rendered.text,
|
|
233
|
-
attachments: replyAttachments,
|
|
234
374
|
assistantId,
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
user: options?.user,
|
|
239
|
-
messageTs: options?.messageTs,
|
|
240
|
-
onMessageTs: composedOnMessageTs,
|
|
241
|
-
});
|
|
242
|
-
break;
|
|
375
|
+
options,
|
|
376
|
+
);
|
|
377
|
+
if (delivered) break;
|
|
243
378
|
}
|
|
244
379
|
}
|
|
245
380
|
|
|
@@ -9,17 +9,28 @@ import {
|
|
|
9
9
|
} from "../channels/types.js";
|
|
10
10
|
import { getDiskPressureStatus } from "../daemon/disk-pressure-guard.js";
|
|
11
11
|
import { classifyDiskPressureTurnPolicy } from "../daemon/disk-pressure-policy.js";
|
|
12
|
+
import type { ServerMessage } from "../daemon/message-protocol.js";
|
|
12
13
|
import type { TrustContext } from "../daemon/trust-context.js";
|
|
13
14
|
import { updateDeliveredSegmentCount } from "../memory/delivery-channels.js";
|
|
14
|
-
import { clearPayload, linkMessage } from "../memory/delivery-crud.js";
|
|
15
15
|
import {
|
|
16
|
+
clearPayload,
|
|
17
|
+
linkMessage,
|
|
18
|
+
storeReplyMessageId,
|
|
19
|
+
} from "../memory/delivery-crud.js";
|
|
20
|
+
import {
|
|
21
|
+
getRetryableDeliveryEvents,
|
|
16
22
|
getRetryableEvents,
|
|
23
|
+
markDeliveryDelivered,
|
|
17
24
|
markProcessed,
|
|
18
25
|
markRetryableFailure,
|
|
26
|
+
recordDeliveryFailure,
|
|
19
27
|
recordProcessingFailure,
|
|
20
28
|
} from "../memory/delivery-status.js";
|
|
21
29
|
import { getLogger } from "../util/logger.js";
|
|
22
|
-
import {
|
|
30
|
+
import {
|
|
31
|
+
deliverReplyViaCallback,
|
|
32
|
+
findAssistantReplyMessageIdForTurn,
|
|
33
|
+
} from "./channel-reply-delivery.js";
|
|
23
34
|
import { deliverChannelReply } from "./gateway-client.js";
|
|
24
35
|
import type { MessageProcessor } from "./http-types.js";
|
|
25
36
|
import { resolveRoutingStateFromRuntime } from "./trust-context-resolver.js";
|
|
@@ -91,9 +102,13 @@ export async function sweepFailedEvents(
|
|
|
91
102
|
processMessage: MessageProcessor,
|
|
92
103
|
): Promise<void> {
|
|
93
104
|
const events = getRetryableEvents();
|
|
94
|
-
|
|
105
|
+
const deliveryEvents = getRetryableDeliveryEvents();
|
|
106
|
+
if (events.length === 0 && deliveryEvents.length === 0) return;
|
|
95
107
|
|
|
96
|
-
log.info(
|
|
108
|
+
log.info(
|
|
109
|
+
{ processingCount: events.length, deliveryCount: deliveryEvents.length },
|
|
110
|
+
"Retrying failed channel inbound events",
|
|
111
|
+
);
|
|
97
112
|
|
|
98
113
|
for (const event of events) {
|
|
99
114
|
if (!event.rawPayload) {
|
|
@@ -243,9 +258,20 @@ export async function sweepFailedEvents(
|
|
|
243
258
|
sourceMetadata.chatType.trim().length > 0
|
|
244
259
|
? sourceMetadata.chatType.trim()
|
|
245
260
|
: undefined;
|
|
261
|
+
let replyMessageId: string | undefined;
|
|
262
|
+
const observeAgentEvent = (msg: ServerMessage): void => {
|
|
263
|
+
if (
|
|
264
|
+
msg.type === "message_complete" &&
|
|
265
|
+
(msg.source === undefined || msg.source === "main") &&
|
|
266
|
+
typeof msg.messageId === "string"
|
|
267
|
+
) {
|
|
268
|
+
replyMessageId = msg.messageId;
|
|
269
|
+
}
|
|
270
|
+
};
|
|
246
271
|
|
|
272
|
+
let userMessageId: string | undefined;
|
|
247
273
|
try {
|
|
248
|
-
const
|
|
274
|
+
const result = await processMessage(
|
|
249
275
|
event.conversationId,
|
|
250
276
|
content,
|
|
251
277
|
attachmentIds,
|
|
@@ -260,27 +286,39 @@ export async function sweepFailedEvents(
|
|
|
260
286
|
trustContext,
|
|
261
287
|
isInteractive:
|
|
262
288
|
resolveRoutingStateFromRuntime(trustContext).promptWaitingAllowed,
|
|
289
|
+
onEvent: observeAgentEvent,
|
|
263
290
|
},
|
|
264
291
|
sourceChannel,
|
|
265
292
|
sourceInterface,
|
|
266
293
|
);
|
|
294
|
+
userMessageId = result.messageId;
|
|
267
295
|
linkMessage(event.id, userMessageId);
|
|
268
296
|
markProcessed(event.id);
|
|
297
|
+
replyMessageId ??= result.assistantMessageId;
|
|
298
|
+
if (replyMessageId) {
|
|
299
|
+
storeReplyMessageId(event.id, replyMessageId);
|
|
300
|
+
}
|
|
269
301
|
log.info(
|
|
270
302
|
{ eventId: event.id },
|
|
271
303
|
"Successfully replayed failed channel event",
|
|
272
304
|
);
|
|
305
|
+
} catch (err) {
|
|
306
|
+
log.error({ err, eventId: event.id }, "Retry failed for channel event");
|
|
307
|
+
recordProcessingFailure(event.id, err);
|
|
308
|
+
continue;
|
|
309
|
+
}
|
|
273
310
|
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
311
|
+
const replyCallbackUrl =
|
|
312
|
+
typeof payload.replyCallbackUrl === "string"
|
|
313
|
+
? payload.replyCallbackUrl
|
|
314
|
+
: undefined;
|
|
315
|
+
if (replyCallbackUrl) {
|
|
316
|
+
const externalChatId =
|
|
317
|
+
typeof payload.externalChatId === "string"
|
|
318
|
+
? payload.externalChatId
|
|
277
319
|
: undefined;
|
|
278
|
-
if (
|
|
279
|
-
|
|
280
|
-
typeof payload.externalChatId === "string"
|
|
281
|
-
? payload.externalChatId
|
|
282
|
-
: undefined;
|
|
283
|
-
if (externalChatId) {
|
|
320
|
+
if (externalChatId) {
|
|
321
|
+
try {
|
|
284
322
|
// processMessage above generated a fresh assistant response, so any
|
|
285
323
|
// previously tracked segment progress belongs to the old response and
|
|
286
324
|
// must not carry over. Reset to 0 so we deliver all segments of the
|
|
@@ -292,16 +330,103 @@ export async function sweepFailedEvents(
|
|
|
292
330
|
replyCallbackUrl,
|
|
293
331
|
assistantId,
|
|
294
332
|
{
|
|
333
|
+
messageId: replyMessageId,
|
|
334
|
+
sinceMessageId: userMessageId,
|
|
295
335
|
startFromSegment: 0,
|
|
296
336
|
onSegmentDelivered: (count) =>
|
|
297
337
|
updateDeliveredSegmentCount(event.id, count),
|
|
298
338
|
},
|
|
299
339
|
);
|
|
340
|
+
markDeliveryDelivered(event.id);
|
|
341
|
+
} catch (err) {
|
|
342
|
+
log.error(
|
|
343
|
+
{ err, eventId: event.id },
|
|
344
|
+
"Retry delivery failed for channel event",
|
|
345
|
+
);
|
|
346
|
+
recordDeliveryFailure(event.id, err);
|
|
300
347
|
}
|
|
301
348
|
}
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
for (const event of deliveryEvents) {
|
|
353
|
+
if (!event.rawPayload) {
|
|
354
|
+
recordDeliveryFailure(
|
|
355
|
+
event.id,
|
|
356
|
+
new Error("No raw payload stored for delivery retry"),
|
|
357
|
+
);
|
|
358
|
+
continue;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
let payload: Record<string, unknown>;
|
|
362
|
+
try {
|
|
363
|
+
payload = JSON.parse(event.rawPayload) as Record<string, unknown>;
|
|
364
|
+
} catch {
|
|
365
|
+
recordDeliveryFailure(
|
|
366
|
+
event.id,
|
|
367
|
+
new Error("Failed to parse stored raw payload for delivery retry"),
|
|
368
|
+
);
|
|
369
|
+
continue;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
const replyCallbackUrl =
|
|
373
|
+
typeof payload.replyCallbackUrl === "string"
|
|
374
|
+
? payload.replyCallbackUrl
|
|
375
|
+
: undefined;
|
|
376
|
+
const externalChatId =
|
|
377
|
+
typeof payload.externalChatId === "string"
|
|
378
|
+
? payload.externalChatId
|
|
379
|
+
: undefined;
|
|
380
|
+
let replyMessageId =
|
|
381
|
+
typeof payload.replyMessageId === "string"
|
|
382
|
+
? payload.replyMessageId
|
|
383
|
+
: undefined;
|
|
384
|
+
const assistantId =
|
|
385
|
+
typeof payload.assistantId === "string" ? payload.assistantId : undefined;
|
|
386
|
+
if (!replyCallbackUrl || !externalChatId) {
|
|
387
|
+
recordDeliveryFailure(
|
|
388
|
+
event.id,
|
|
389
|
+
new Error("Stored payload is missing delivery callback details"),
|
|
390
|
+
);
|
|
391
|
+
continue;
|
|
392
|
+
}
|
|
393
|
+
if (!replyMessageId && event.messageId) {
|
|
394
|
+
replyMessageId = findAssistantReplyMessageIdForTurn(
|
|
395
|
+
event.conversationId,
|
|
396
|
+
event.messageId,
|
|
397
|
+
);
|
|
398
|
+
if (replyMessageId) {
|
|
399
|
+
storeReplyMessageId(event.id, replyMessageId);
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
if (!replyMessageId) {
|
|
403
|
+
recordDeliveryFailure(
|
|
404
|
+
event.id,
|
|
405
|
+
new Error("Stored payload is missing assistant reply message id"),
|
|
406
|
+
);
|
|
407
|
+
continue;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
try {
|
|
411
|
+
await deliverReplyViaCallback(
|
|
412
|
+
event.conversationId,
|
|
413
|
+
externalChatId,
|
|
414
|
+
replyCallbackUrl,
|
|
415
|
+
assistantId,
|
|
416
|
+
{
|
|
417
|
+
messageId: replyMessageId,
|
|
418
|
+
startFromSegment: event.deliveredSegmentCount,
|
|
419
|
+
onSegmentDelivered: (count) =>
|
|
420
|
+
updateDeliveredSegmentCount(event.id, count),
|
|
421
|
+
},
|
|
422
|
+
);
|
|
423
|
+
markDeliveryDelivered(event.id);
|
|
302
424
|
} catch (err) {
|
|
303
|
-
log.error(
|
|
304
|
-
|
|
425
|
+
log.error(
|
|
426
|
+
{ err, eventId: event.id },
|
|
427
|
+
"Retry delivery failed for processed channel event",
|
|
428
|
+
);
|
|
429
|
+
recordDeliveryFailure(event.id, err);
|
|
305
430
|
}
|
|
306
431
|
}
|
|
307
432
|
}
|
|
@@ -63,6 +63,7 @@ export interface RuntimeMessageConversationOptions {
|
|
|
63
63
|
hints?: string[];
|
|
64
64
|
uxBrief?: string;
|
|
65
65
|
chatType?: string;
|
|
66
|
+
clientTimezone?: string;
|
|
66
67
|
};
|
|
67
68
|
assistantId?: string;
|
|
68
69
|
trustContext?: TrustContext;
|
|
@@ -74,8 +75,6 @@ export interface RuntimeMessageConversationOptions {
|
|
|
74
75
|
isInteractive?: boolean;
|
|
75
76
|
/** Channel command intent metadata (e.g. Telegram /start). */
|
|
76
77
|
commandIntent?: { type: string; payload?: string; languageCode?: string };
|
|
77
|
-
/** Slack-only non-persisted notice injected into the active model turn. */
|
|
78
|
-
slackRuntimeContextNotice?: string;
|
|
79
78
|
/**
|
|
80
79
|
* Persisted user-facing content. When present, storage/UI use this value
|
|
81
80
|
* while the model-facing turn continues to use `content`.
|
|
@@ -106,7 +105,7 @@ export type MessageProcessor = (
|
|
|
106
105
|
options?: RuntimeMessageConversationOptions,
|
|
107
106
|
sourceChannel?: ChannelId,
|
|
108
107
|
sourceInterface?: InterfaceId,
|
|
109
|
-
) => Promise<{ messageId: string }>;
|
|
108
|
+
) => Promise<{ messageId: string; assistantMessageId?: string }>;
|
|
110
109
|
|
|
111
110
|
/**
|
|
112
111
|
* Dependencies for the POST /v1/messages handler.
|
|
@@ -149,8 +148,6 @@ export interface RuntimeAttachmentMetadata {
|
|
|
149
148
|
|
|
150
149
|
export interface RuntimeMessagePayload {
|
|
151
150
|
id: string;
|
|
152
|
-
/** Concrete persisted assistant row id for row-scoped actions. */
|
|
153
|
-
daemonMessageId?: string;
|
|
154
151
|
role: string;
|
|
155
152
|
content: string;
|
|
156
153
|
timestamp: string;
|
|
@@ -167,7 +164,6 @@ export interface RuntimeMessagePayload {
|
|
|
167
164
|
approvalReason?: string;
|
|
168
165
|
riskThreshold?: string;
|
|
169
166
|
}>;
|
|
170
|
-
interfaces?: string[];
|
|
171
167
|
surfaces?: Array<{
|
|
172
168
|
surfaceId: string;
|
|
173
169
|
surfaceType: string;
|
|
@@ -189,8 +185,13 @@ export interface RuntimeMessagePayload {
|
|
|
189
185
|
};
|
|
190
186
|
slackMessage?: {
|
|
191
187
|
channelId: string;
|
|
188
|
+
channelName?: string;
|
|
192
189
|
channelTs: string;
|
|
193
190
|
threadTs?: string;
|
|
191
|
+
sender?: {
|
|
192
|
+
displayName?: string;
|
|
193
|
+
externalUserId?: string;
|
|
194
|
+
};
|
|
194
195
|
messageLink?: {
|
|
195
196
|
appUrl?: string;
|
|
196
197
|
webUrl?: string;
|
|
@@ -681,8 +681,13 @@ export interface BuildExportVBundleOptions {
|
|
|
681
681
|
* flushed to the main .db file. Callers should pass a function that runs
|
|
682
682
|
* PRAGMA wal_checkpoint(TRUNCATE) on the live database connection.
|
|
683
683
|
* Called before the workspace walk so the DB file is up to date.
|
|
684
|
+
*
|
|
685
|
+
* May return a Promise — `streamExportVBundle` awaits the result so an
|
|
686
|
+
* async-dispatched checkpoint (e.g. via `runAsyncSqlite`) does not race
|
|
687
|
+
* with the file walk. The synchronous `buildExportVBundle` path does
|
|
688
|
+
* not await; pass a sync callback there.
|
|
684
689
|
*/
|
|
685
|
-
checkpoint?: () => void
|
|
690
|
+
checkpoint?: () => void | Promise<void>;
|
|
686
691
|
/** Optional credential entries to include in the archive under credentials/ prefix. */
|
|
687
692
|
credentials?: Array<{ account: string; value: string }>;
|
|
688
693
|
}
|
|
@@ -1120,9 +1125,11 @@ export async function streamExportVBundle(
|
|
|
1120
1125
|
credentials,
|
|
1121
1126
|
} = options;
|
|
1122
1127
|
|
|
1123
|
-
// Flush WAL to the main database file before reading
|
|
1128
|
+
// Flush WAL to the main database file before reading. Awaiting allows
|
|
1129
|
+
// the callback to dispatch the checkpoint via `runAsyncSqlite` so the
|
|
1130
|
+
// daemon event loop stays responsive while SQLite truncates the WAL.
|
|
1124
1131
|
if (checkpoint) {
|
|
1125
|
-
checkpoint();
|
|
1132
|
+
await checkpoint();
|
|
1126
1133
|
}
|
|
1127
1134
|
|
|
1128
1135
|
const allFileMetadata: FileMetadata[] = [];
|
|
@@ -18,7 +18,14 @@
|
|
|
18
18
|
* resolve the interaction.
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
|
+
import type { InteractionResolutionState } from "../daemon/message-types/messages.js";
|
|
21
22
|
import type { UserDecision } from "../permissions/types.js";
|
|
23
|
+
import { getLogger } from "../util/logger.js";
|
|
24
|
+
import { broadcastMessage } from "./assistant-event-hub.js";
|
|
25
|
+
|
|
26
|
+
const log = getLogger("pending-interactions");
|
|
27
|
+
|
|
28
|
+
export type { InteractionResolutionState } from "../daemon/message-types/messages.js";
|
|
22
29
|
|
|
23
30
|
export interface ConfirmationDetails {
|
|
24
31
|
toolName: string;
|
|
@@ -98,17 +105,49 @@ export function register(
|
|
|
98
105
|
* Remove and return the pending interaction for the given requestId.
|
|
99
106
|
* Auto-clears the proxy timer and detaches the abort listener if present.
|
|
100
107
|
* Returns undefined if no interaction is registered.
|
|
108
|
+
*
|
|
109
|
+
* Emits `interaction_resolved` on the event hub when an interaction is
|
|
110
|
+
* actually removed (no-op when the entry was already consumed by another
|
|
111
|
+
* path). Callers pass `state` to communicate the lifecycle outcome
|
|
112
|
+
* — defaults to `"cancelled"`, the safest value when the call site has
|
|
113
|
+
* no extra context.
|
|
101
114
|
*/
|
|
102
|
-
export function resolve(
|
|
115
|
+
export function resolve(
|
|
116
|
+
requestId: string,
|
|
117
|
+
state: InteractionResolutionState = "cancelled",
|
|
118
|
+
): PendingInteraction | undefined {
|
|
103
119
|
const interaction = pending.get(requestId);
|
|
104
|
-
if (interaction)
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
120
|
+
if (!interaction) return undefined;
|
|
121
|
+
pending.delete(requestId);
|
|
122
|
+
if (interaction.timer != null) clearTimeout(interaction.timer);
|
|
123
|
+
interaction.detachAbort?.();
|
|
124
|
+
emitResolved(requestId, interaction, state);
|
|
109
125
|
return interaction;
|
|
110
126
|
}
|
|
111
127
|
|
|
128
|
+
function emitResolved(
|
|
129
|
+
requestId: string,
|
|
130
|
+
interaction: PendingInteraction,
|
|
131
|
+
state: InteractionResolutionState,
|
|
132
|
+
): void {
|
|
133
|
+
log.info(
|
|
134
|
+
{
|
|
135
|
+
requestId,
|
|
136
|
+
conversationId: interaction.conversationId,
|
|
137
|
+
kind: interaction.kind,
|
|
138
|
+
state,
|
|
139
|
+
},
|
|
140
|
+
"Pending interaction resolved",
|
|
141
|
+
);
|
|
142
|
+
broadcastMessage({
|
|
143
|
+
type: "interaction_resolved",
|
|
144
|
+
requestId,
|
|
145
|
+
conversationId: interaction.conversationId,
|
|
146
|
+
kind: interaction.kind,
|
|
147
|
+
state,
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
|
|
112
151
|
/**
|
|
113
152
|
* Return the pending interaction without removing it.
|
|
114
153
|
* Used by trust-rule endpoint which doesn't resolve the confirmation itself.
|
|
@@ -146,7 +185,10 @@ export function getByConversation(
|
|
|
146
185
|
* /v1/host-transfer-result after completing the operation, get a 404, and the
|
|
147
186
|
* proxy timer would fire with a spurious timeout error.
|
|
148
187
|
*/
|
|
149
|
-
export function removeByConversation(
|
|
188
|
+
export function removeByConversation(
|
|
189
|
+
conversationId: string,
|
|
190
|
+
state: InteractionResolutionState = "superseded",
|
|
191
|
+
): void {
|
|
150
192
|
// Snapshot keys to avoid mutation-during-iteration.
|
|
151
193
|
for (const [requestId, interaction] of [...pending]) {
|
|
152
194
|
if (
|
|
@@ -160,7 +202,7 @@ export function removeByConversation(conversationId: string): void {
|
|
|
160
202
|
interaction.kind !== "acp_confirmation"
|
|
161
203
|
) {
|
|
162
204
|
// resolve() clears the stored timer and detaches abort listeners.
|
|
163
|
-
resolve(requestId);
|
|
205
|
+
resolve(requestId, state);
|
|
164
206
|
}
|
|
165
207
|
}
|
|
166
208
|
}
|