@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,10 +1,7 @@
|
|
|
1
1
|
import { writeFileSync } from "node:fs";
|
|
2
2
|
import { afterEach, beforeEach, describe, expect, test } from "bun:test";
|
|
3
3
|
|
|
4
|
-
import {
|
|
5
|
-
invalidateConfigCache,
|
|
6
|
-
loadRawConfig,
|
|
7
|
-
} from "../config/loader.js";
|
|
4
|
+
import { invalidateConfigCache, loadRawConfig } from "../config/loader.js";
|
|
8
5
|
import {
|
|
9
6
|
classifySlash,
|
|
10
7
|
resolveSlash,
|
|
@@ -42,6 +39,7 @@ describe("resolveSlash /commands interface-aware help", () => {
|
|
|
42
39
|
expect(lines).toEqual([
|
|
43
40
|
"/commands — List all available commands",
|
|
44
41
|
"/compact — Force context compaction immediately",
|
|
42
|
+
"/clean — Strip injected runtime context and reset memory injection state (no summarization)",
|
|
45
43
|
"/context — Show conversation context usage",
|
|
46
44
|
"/model — List or switch inference profile",
|
|
47
45
|
"/models — List all available models",
|
|
@@ -58,6 +56,7 @@ describe("resolveSlash /commands interface-aware help", () => {
|
|
|
58
56
|
expect(lines).toEqual([
|
|
59
57
|
"/commands — List all available commands",
|
|
60
58
|
"/compact — Force context compaction immediately",
|
|
59
|
+
"/clean — Strip injected runtime context and reset memory injection state (no summarization)",
|
|
61
60
|
"/context — Show conversation context usage",
|
|
62
61
|
"/model — List or switch inference profile",
|
|
63
62
|
"/models — List all available models",
|
|
@@ -74,6 +73,7 @@ describe("resolveSlash /commands interface-aware help", () => {
|
|
|
74
73
|
expect(lines).toEqual([
|
|
75
74
|
"/commands — List all available commands",
|
|
76
75
|
"/compact — Force context compaction immediately",
|
|
76
|
+
"/clean — Strip injected runtime context and reset memory injection state (no summarization)",
|
|
77
77
|
"/context — Show conversation context usage",
|
|
78
78
|
"/model — List or switch inference profile",
|
|
79
79
|
"/models — List all available models",
|
|
@@ -87,6 +87,7 @@ describe("resolveSlash /commands interface-aware help", () => {
|
|
|
87
87
|
expect(lines).toEqual([
|
|
88
88
|
"/commands — List all available commands",
|
|
89
89
|
"/compact — Force context compaction immediately",
|
|
90
|
+
"/clean — Strip injected runtime context and reset memory injection state (no summarization)",
|
|
90
91
|
"/context — Show conversation context usage",
|
|
91
92
|
"/model — List or switch inference profile",
|
|
92
93
|
"/models — List all available models",
|
|
@@ -99,6 +100,7 @@ describe("resolveSlash /commands interface-aware help", () => {
|
|
|
99
100
|
expect(lines).toEqual([
|
|
100
101
|
"/commands — List all available commands",
|
|
101
102
|
"/compact — Force context compaction immediately",
|
|
103
|
+
"/clean — Strip injected runtime context and reset memory injection state (no summarization)",
|
|
102
104
|
"/model — List or switch inference profile",
|
|
103
105
|
"/models — List all available models",
|
|
104
106
|
]);
|
|
@@ -187,13 +189,38 @@ describe("resolveSlash /compact target override", () => {
|
|
|
187
189
|
});
|
|
188
190
|
});
|
|
189
191
|
|
|
192
|
+
describe("resolveSlash /clean", () => {
|
|
193
|
+
test("plain /clean resolves to kind=clean", async () => {
|
|
194
|
+
const result = await resolveSlash("/clean");
|
|
195
|
+
expect(result).toEqual({ kind: "clean" });
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
test("/clean tolerates surrounding whitespace", async () => {
|
|
199
|
+
const result = await resolveSlash(" /clean ");
|
|
200
|
+
expect(result).toEqual({ kind: "clean" });
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
test("/clean is case-insensitive", async () => {
|
|
204
|
+
const result = await resolveSlash("/CLEAN");
|
|
205
|
+
expect(result).toEqual({ kind: "clean" });
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
test("/clean rejects arguments with usage hint", async () => {
|
|
209
|
+
const result = await resolveSlash("/clean now");
|
|
210
|
+
expect(result.kind).toBe("unknown");
|
|
211
|
+
if (result.kind !== "unknown") throw new Error("expected unknown");
|
|
212
|
+
expect(result.message).toContain("/clean");
|
|
213
|
+
expect(result.message).toContain("does not take arguments");
|
|
214
|
+
});
|
|
215
|
+
});
|
|
216
|
+
|
|
190
217
|
describe("classifySlash is a pure classifier matching resolveSlash kinds", () => {
|
|
191
218
|
// Lookahead in `buildPassthroughBatch` must not run `resolveSlash`'s side
|
|
192
219
|
// effects. The pure classifier is synchronous, takes no side-effecting
|
|
193
220
|
// dependencies, and must agree with resolveSlash's `kind`.
|
|
194
221
|
const cases: Array<{
|
|
195
222
|
input: string;
|
|
196
|
-
kind: "passthrough" | "compact" | "unknown";
|
|
223
|
+
kind: "passthrough" | "compact" | "clean" | "unknown";
|
|
197
224
|
}> = [
|
|
198
225
|
{ input: "/models", kind: "unknown" },
|
|
199
226
|
{ input: "/context", kind: "unknown" },
|
|
@@ -204,6 +231,9 @@ describe("classifySlash is a pure classifier matching resolveSlash kinds", () =>
|
|
|
204
231
|
{ input: "/compact 30k", kind: "compact" },
|
|
205
232
|
{ input: "/compact 1.5M", kind: "compact" },
|
|
206
233
|
{ input: "/compact bogus", kind: "unknown" },
|
|
234
|
+
{ input: "/clean", kind: "clean" },
|
|
235
|
+
{ input: " /clean ", kind: "clean" },
|
|
236
|
+
{ input: "/clean foo", kind: "unknown" },
|
|
207
237
|
{ input: "/model", kind: "unknown" },
|
|
208
238
|
{ input: "/model foo", kind: "unknown" },
|
|
209
239
|
{ input: "/opus", kind: "unknown" },
|
|
@@ -318,9 +348,7 @@ describe("resolveSlash /model — inference profile switcher", () => {
|
|
|
318
348
|
const result = await resolveSlash("/model balanced");
|
|
319
349
|
expect(result.kind).toBe("unknown");
|
|
320
350
|
if (result.kind !== "unknown") throw new Error("expected unknown kind");
|
|
321
|
-
expect(result.message).toBe(
|
|
322
|
-
"Already using profile `balanced` (Balanced).",
|
|
323
|
-
);
|
|
351
|
+
expect(result.message).toBe("Already using profile `balanced` (Balanced).");
|
|
324
352
|
});
|
|
325
353
|
|
|
326
354
|
test("`/model` with no profiles defined points at Settings", async () => {
|
|
@@ -28,7 +28,7 @@ mock.module("../memory/guardian-action-store.js", () => ({
|
|
|
28
28
|
|
|
29
29
|
mock.module("../providers/registry.js", () => ({
|
|
30
30
|
getProvider: () => ({ name: "mock-provider" }),
|
|
31
|
-
initializeProviders: () => {},
|
|
31
|
+
initializeProviders: async () => {},
|
|
32
32
|
}));
|
|
33
33
|
|
|
34
34
|
mock.module("../config/loader.js", () => ({
|
|
@@ -24,7 +24,7 @@ mock.module("../memory/guardian-action-store.js", () => ({
|
|
|
24
24
|
|
|
25
25
|
mock.module("../providers/registry.js", () => ({
|
|
26
26
|
getProvider: () => ({ name: "mock-provider" }),
|
|
27
|
-
initializeProviders: () => {},
|
|
27
|
+
initializeProviders: async () => {},
|
|
28
28
|
}));
|
|
29
29
|
|
|
30
30
|
mock.module("../config/loader.js", () => ({
|
|
@@ -48,7 +48,7 @@ mock.module("../memory/guardian-action-store.js", () => ({
|
|
|
48
48
|
|
|
49
49
|
mock.module("../providers/registry.js", () => ({
|
|
50
50
|
getProvider: () => ({ name: "mock-provider" }),
|
|
51
|
-
initializeProviders: () => {},
|
|
51
|
+
initializeProviders: async () => {},
|
|
52
52
|
}));
|
|
53
53
|
|
|
54
54
|
// Controllable config mock — speed and feature flag behavior are test-specific.
|
|
@@ -334,7 +334,7 @@ describe("attachment orphan cleanup", () => {
|
|
|
334
334
|
const stored = uploadAttachment("doc.pdf", "application/pdf", "JVBER");
|
|
335
335
|
linkAttachmentToMessage(msg.id, stored.id, 0);
|
|
336
336
|
|
|
337
|
-
clearAll();
|
|
337
|
+
await clearAll();
|
|
338
338
|
|
|
339
339
|
const raw = (
|
|
340
340
|
getDb() as unknown as {
|
|
@@ -84,6 +84,95 @@ describe("task_progress surface compatibility", () => {
|
|
|
84
84
|
expect(sent).toHaveLength(0);
|
|
85
85
|
});
|
|
86
86
|
|
|
87
|
+
test("allows Slack ui_show for task_progress card when dynamic UI is otherwise disabled", async () => {
|
|
88
|
+
const sent: ServerMessage[] = [];
|
|
89
|
+
const ctx = makeContext(sent, {
|
|
90
|
+
channel: "slack",
|
|
91
|
+
supportsDynamicUi: false,
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
const result = await surfaceProxyResolver(ctx, "ui_show", {
|
|
95
|
+
surface_type: "card",
|
|
96
|
+
title: "Working",
|
|
97
|
+
template: "task_progress",
|
|
98
|
+
templateData: {
|
|
99
|
+
status: "in_progress",
|
|
100
|
+
steps: [{ label: "Start", status: "in_progress" }],
|
|
101
|
+
},
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
expect(result.isError).toBe(false);
|
|
105
|
+
const showMessage = sent.find(
|
|
106
|
+
(msg): msg is UiSurfaceShow => msg.type === "ui_surface_show",
|
|
107
|
+
);
|
|
108
|
+
expect(showMessage).toBeDefined();
|
|
109
|
+
if (!showMessage || showMessage.surfaceType !== "card") return;
|
|
110
|
+
expect((showMessage.data as CardSurfaceData).template).toBe(
|
|
111
|
+
"task_progress",
|
|
112
|
+
);
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
test("blocks Slack ui_show for non-task_progress card when dynamic UI is disabled", async () => {
|
|
116
|
+
const sent: ServerMessage[] = [];
|
|
117
|
+
const ctx = makeContext(sent, {
|
|
118
|
+
channel: "slack",
|
|
119
|
+
supportsDynamicUi: false,
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
const result = await surfaceProxyResolver(ctx, "ui_show", {
|
|
123
|
+
surface_type: "card",
|
|
124
|
+
title: "Blocked",
|
|
125
|
+
data: { title: "Blocked", body: "not progress" },
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
expect(result.isError).toBe(true);
|
|
129
|
+
expect(result.content).toContain(
|
|
130
|
+
'ui_show is unavailable on channel "slack"',
|
|
131
|
+
);
|
|
132
|
+
expect(sent).toHaveLength(0);
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
test("blocks Slack ui_show when normalized card data is not task_progress", async () => {
|
|
136
|
+
const sent: ServerMessage[] = [];
|
|
137
|
+
const ctx = makeContext(sent, {
|
|
138
|
+
channel: "slack",
|
|
139
|
+
supportsDynamicUi: false,
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
const result = await surfaceProxyResolver(ctx, "ui_show", {
|
|
143
|
+
surface_type: "card",
|
|
144
|
+
title: "Blocked",
|
|
145
|
+
template: "task_progress",
|
|
146
|
+
data: { title: "Blocked", body: "not progress", template: "plain" },
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
expect(result.isError).toBe(true);
|
|
150
|
+
expect(result.content).toContain(
|
|
151
|
+
'ui_show is unavailable on channel "slack"',
|
|
152
|
+
);
|
|
153
|
+
expect(sent).toHaveLength(0);
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
test("blocks Slack ui_show for non-card task_progress input when dynamic UI is disabled", async () => {
|
|
157
|
+
const sent: ServerMessage[] = [];
|
|
158
|
+
const ctx = makeContext(sent, {
|
|
159
|
+
channel: "slack",
|
|
160
|
+
supportsDynamicUi: false,
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
const result = await surfaceProxyResolver(ctx, "ui_show", {
|
|
164
|
+
surface_type: "dynamic_page",
|
|
165
|
+
title: "Blocked",
|
|
166
|
+
data: { template: "task_progress", html: "<p>Blocked</p>" },
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
expect(result.isError).toBe(true);
|
|
170
|
+
expect(result.content).toContain(
|
|
171
|
+
'ui_show is unavailable on channel "slack"',
|
|
172
|
+
);
|
|
173
|
+
expect(sent).toHaveLength(0);
|
|
174
|
+
});
|
|
175
|
+
|
|
87
176
|
test("ui_show maps legacy top-level task_progress fields into card data", async () => {
|
|
88
177
|
const sent: ServerMessage[] = [];
|
|
89
178
|
const ctx = makeContext(sent);
|
|
@@ -249,6 +338,137 @@ describe("task_progress surface compatibility", () => {
|
|
|
249
338
|
expect(Array.isArray(templateData.steps)).toBe(true);
|
|
250
339
|
});
|
|
251
340
|
|
|
341
|
+
test("allows Slack ui_update for stored task_progress card when dynamic UI is disabled", async () => {
|
|
342
|
+
const sent: ServerMessage[] = [];
|
|
343
|
+
const ctx = makeContext(sent, {
|
|
344
|
+
channel: "slack",
|
|
345
|
+
supportsDynamicUi: false,
|
|
346
|
+
});
|
|
347
|
+
ctx.surfaceState.set("surface-1", {
|
|
348
|
+
surfaceType: "card",
|
|
349
|
+
data: {
|
|
350
|
+
title: "Working",
|
|
351
|
+
body: "",
|
|
352
|
+
template: "task_progress",
|
|
353
|
+
templateData: { status: "in_progress", steps: [] },
|
|
354
|
+
} satisfies CardSurfaceData,
|
|
355
|
+
});
|
|
356
|
+
|
|
357
|
+
const result = await surfaceProxyResolver(ctx, "ui_update", {
|
|
358
|
+
surface_id: "surface-1",
|
|
359
|
+
data: { status: "completed" },
|
|
360
|
+
});
|
|
361
|
+
|
|
362
|
+
expect(result.isError).toBe(false);
|
|
363
|
+
const updateMessage = sent.find(
|
|
364
|
+
(msg): msg is UiSurfaceUpdate => msg.type === "ui_surface_update",
|
|
365
|
+
);
|
|
366
|
+
expect(updateMessage).toBeDefined();
|
|
367
|
+
if (!updateMessage) return;
|
|
368
|
+
const templateData = (updateMessage.data as CardSurfaceData)
|
|
369
|
+
.templateData as Record<string, unknown>;
|
|
370
|
+
expect(templateData.status).toBe("completed");
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
test("blocks Slack ui_update when stored surface is not a task_progress card", async () => {
|
|
374
|
+
const sent: ServerMessage[] = [];
|
|
375
|
+
const ctx = makeContext(sent, {
|
|
376
|
+
channel: "slack",
|
|
377
|
+
supportsDynamicUi: false,
|
|
378
|
+
});
|
|
379
|
+
ctx.surfaceState.set("surface-1", {
|
|
380
|
+
surfaceType: "card",
|
|
381
|
+
data: { title: "Plain", body: "No progress" } satisfies CardSurfaceData,
|
|
382
|
+
});
|
|
383
|
+
|
|
384
|
+
const result = await surfaceProxyResolver(ctx, "ui_update", {
|
|
385
|
+
surface_id: "surface-1",
|
|
386
|
+
data: { body: "still blocked" },
|
|
387
|
+
});
|
|
388
|
+
|
|
389
|
+
expect(result.isError).toBe(true);
|
|
390
|
+
expect(result.content).toContain(
|
|
391
|
+
'ui_update is unavailable on channel "slack"',
|
|
392
|
+
);
|
|
393
|
+
expect(sent).toHaveLength(0);
|
|
394
|
+
});
|
|
395
|
+
|
|
396
|
+
test("blocks Slack ui_update that would convert a plain card to task_progress", async () => {
|
|
397
|
+
const sent: ServerMessage[] = [];
|
|
398
|
+
const ctx = makeContext(sent, {
|
|
399
|
+
channel: "slack",
|
|
400
|
+
supportsDynamicUi: false,
|
|
401
|
+
});
|
|
402
|
+
ctx.surfaceState.set("surface-1", {
|
|
403
|
+
surfaceType: "card",
|
|
404
|
+
data: { title: "Plain", body: "No progress" } satisfies CardSurfaceData,
|
|
405
|
+
});
|
|
406
|
+
|
|
407
|
+
const result = await surfaceProxyResolver(ctx, "ui_update", {
|
|
408
|
+
surface_id: "surface-1",
|
|
409
|
+
data: {
|
|
410
|
+
template: "task_progress",
|
|
411
|
+
templateData: { status: "in_progress", steps: [] },
|
|
412
|
+
},
|
|
413
|
+
});
|
|
414
|
+
|
|
415
|
+
expect(result.isError).toBe(true);
|
|
416
|
+
expect(result.content).toContain(
|
|
417
|
+
'ui_update is unavailable on channel "slack"',
|
|
418
|
+
);
|
|
419
|
+
expect(sent).toHaveLength(0);
|
|
420
|
+
});
|
|
421
|
+
|
|
422
|
+
test("blocks Slack ui_update that would change task_progress card template", async () => {
|
|
423
|
+
const sent: ServerMessage[] = [];
|
|
424
|
+
const ctx = makeContext(sent, {
|
|
425
|
+
channel: "slack",
|
|
426
|
+
supportsDynamicUi: false,
|
|
427
|
+
});
|
|
428
|
+
ctx.surfaceState.set("surface-1", {
|
|
429
|
+
surfaceType: "card",
|
|
430
|
+
data: {
|
|
431
|
+
title: "Working",
|
|
432
|
+
body: "",
|
|
433
|
+
template: "task_progress",
|
|
434
|
+
templateData: { status: "in_progress", steps: [] },
|
|
435
|
+
} satisfies CardSurfaceData,
|
|
436
|
+
});
|
|
437
|
+
|
|
438
|
+
const result = await surfaceProxyResolver(ctx, "ui_update", {
|
|
439
|
+
surface_id: "surface-1",
|
|
440
|
+
data: { template: "plain", body: "now a plain card" },
|
|
441
|
+
});
|
|
442
|
+
|
|
443
|
+
expect(result.isError).toBe(true);
|
|
444
|
+
expect(result.content).toContain(
|
|
445
|
+
'ui_update is unavailable on channel "slack"',
|
|
446
|
+
);
|
|
447
|
+
expect(sent).toHaveLength(0);
|
|
448
|
+
expect(
|
|
449
|
+
(ctx.surfaceState.get("surface-1")?.data as CardSurfaceData).template,
|
|
450
|
+
).toBe("task_progress");
|
|
451
|
+
});
|
|
452
|
+
|
|
453
|
+
test("blocks Slack ui_update when the surface is not already stored", async () => {
|
|
454
|
+
const sent: ServerMessage[] = [];
|
|
455
|
+
const ctx = makeContext(sent, {
|
|
456
|
+
channel: "slack",
|
|
457
|
+
supportsDynamicUi: false,
|
|
458
|
+
});
|
|
459
|
+
|
|
460
|
+
const result = await surfaceProxyResolver(ctx, "ui_update", {
|
|
461
|
+
surface_id: "missing-surface",
|
|
462
|
+
data: { status: "completed" },
|
|
463
|
+
});
|
|
464
|
+
|
|
465
|
+
expect(result.isError).toBe(true);
|
|
466
|
+
expect(result.content).toContain(
|
|
467
|
+
'ui_update is unavailable on channel "slack"',
|
|
468
|
+
);
|
|
469
|
+
expect(sent).toHaveLength(0);
|
|
470
|
+
});
|
|
471
|
+
|
|
252
472
|
test("ui_show rejects new interactive surface when a non-dynamic_page pending surface exists", async () => {
|
|
253
473
|
const sent: ServerMessage[] = [];
|
|
254
474
|
const ctx = makeContext(sent);
|
|
@@ -73,7 +73,16 @@ describe("conversation sync tags", () => {
|
|
|
73
73
|
resetDb();
|
|
74
74
|
});
|
|
75
75
|
|
|
76
|
-
test("rename emits
|
|
76
|
+
test("rename emits the typed title event and a metadata-only sync tag (no list umbrella)", async () => {
|
|
77
|
+
// Rename is a content-only change: the row stays in place, the list
|
|
78
|
+
// shape is unchanged, only the title field flips. Web patches the
|
|
79
|
+
// single cached row via the typed `conversation_title_updated` event
|
|
80
|
+
// (`patchConversation` in `metadata-handlers.ts`) and the per-
|
|
81
|
+
// conversation `sync_changed` metadata tag is included as a belt-and-
|
|
82
|
+
// suspenders signal for sibling-tab consumers that missed the typed
|
|
83
|
+
// event. The legacy `conversation_list_invalidated` broadcast is
|
|
84
|
+
// scoped to `targetInterfaceId: "macos"` and therefore not visible to
|
|
85
|
+
// this process-type subscriber.
|
|
77
86
|
const conversation = createConversation("Old title");
|
|
78
87
|
const route = findRoute(
|
|
79
88
|
CONVERSATION_MANAGEMENT_ROUTES,
|
|
@@ -85,23 +94,39 @@ describe("conversation sync tags", () => {
|
|
|
85
94
|
pathParams: { id: conversation.id },
|
|
86
95
|
body: { name: "New title" },
|
|
87
96
|
});
|
|
88
|
-
},
|
|
97
|
+
}, 2);
|
|
89
98
|
|
|
90
99
|
expect(received.map((event) => event.message.type)).toEqual([
|
|
91
100
|
"conversation_title_updated",
|
|
92
|
-
"conversation_list_invalidated",
|
|
93
101
|
"sync_changed",
|
|
94
102
|
]);
|
|
95
|
-
expect(received[
|
|
103
|
+
expect(received[1]!.message).toEqual({
|
|
96
104
|
type: "sync_changed",
|
|
97
|
-
tags: [
|
|
98
|
-
SYNC_TAGS.conversationsList,
|
|
99
|
-
conversationMetadataSyncTag(conversation.id),
|
|
100
|
-
],
|
|
105
|
+
tags: [conversationMetadataSyncTag(conversation.id)],
|
|
101
106
|
});
|
|
107
|
+
// Defense-in-depth: the umbrella `conversationsList` tag would force
|
|
108
|
+
// web to redrain the full paginated list — we deliberately omit it
|
|
109
|
+
// for content-only reasons.
|
|
110
|
+
expect(
|
|
111
|
+
(received[1]!.message as { tags: string[] }).tags,
|
|
112
|
+
).not.toContain(SYNC_TAGS.conversationsList);
|
|
113
|
+
// The legacy invalidation broadcast is macOS-scoped and must not
|
|
114
|
+
// reach this process-type subscriber.
|
|
115
|
+
expect(
|
|
116
|
+
received.some(
|
|
117
|
+
(event) => event.message.type === "conversation_list_invalidated",
|
|
118
|
+
),
|
|
119
|
+
).toBe(false);
|
|
102
120
|
});
|
|
103
121
|
|
|
104
|
-
test("create emits
|
|
122
|
+
test("create emits a sync_changed with the conversationsList umbrella tag", async () => {
|
|
123
|
+
// Create is shape-changing — a row is added to the paginated list,
|
|
124
|
+
// so web must redrain the list (cannot patch a row it has never
|
|
125
|
+
// fetched). The umbrella `conversationsList` tag is the signal for
|
|
126
|
+
// that redrain. Per-conversation metadata is included so any future
|
|
127
|
+
// single-row consumer can patch the freshly added row in place
|
|
128
|
+
// without an extra GET. The legacy macOS-only invalidation broadcast
|
|
129
|
+
// is not visible to process subscribers.
|
|
105
130
|
const route = findRoute(
|
|
106
131
|
CONVERSATION_MANAGEMENT_ROUTES,
|
|
107
132
|
"createConversation",
|
|
@@ -113,23 +138,33 @@ describe("conversation sync tags", () => {
|
|
|
113
138
|
body: { conversationKey: "sync-create-test" },
|
|
114
139
|
})) as { id: string };
|
|
115
140
|
conversationId = result.id;
|
|
116
|
-
},
|
|
141
|
+
}, 1);
|
|
117
142
|
|
|
118
143
|
expect(conversationId).toBeDefined();
|
|
119
144
|
expect(received.map((event) => event.message.type)).toEqual([
|
|
120
|
-
"conversation_list_invalidated",
|
|
121
145
|
"sync_changed",
|
|
122
146
|
]);
|
|
123
|
-
expect(received[
|
|
147
|
+
expect(received[0]!.message).toEqual({
|
|
124
148
|
type: "sync_changed",
|
|
125
149
|
tags: [
|
|
126
150
|
SYNC_TAGS.conversationsList,
|
|
127
151
|
conversationMetadataSyncTag(conversationId!),
|
|
128
152
|
],
|
|
129
153
|
});
|
|
154
|
+
expect(
|
|
155
|
+
received.some(
|
|
156
|
+
(event) => event.message.type === "conversation_list_invalidated",
|
|
157
|
+
),
|
|
158
|
+
).toBe(false);
|
|
130
159
|
});
|
|
131
160
|
|
|
132
|
-
test("reorder emits
|
|
161
|
+
test("reorder emits a sync_changed with the umbrella tag and per-conversation metadata tags", async () => {
|
|
162
|
+
// Reorder changes the row position in the paginated list — also
|
|
163
|
+
// shape-changing. The umbrella `conversationsList` tag forces a
|
|
164
|
+
// redrain so the new ordering shows. Per-conversation metadata tags
|
|
165
|
+
// are bundled in to give any single-row consumer a hint that the
|
|
166
|
+
// touched conversations' positions have moved (currently web
|
|
167
|
+
// consumes only the umbrella tag; metadata tags are forward-compat).
|
|
133
168
|
const first = createConversation("First");
|
|
134
169
|
const second = createConversation("Second");
|
|
135
170
|
const route = findRoute(
|
|
@@ -146,13 +181,12 @@ describe("conversation sync tags", () => {
|
|
|
146
181
|
],
|
|
147
182
|
},
|
|
148
183
|
});
|
|
149
|
-
},
|
|
184
|
+
}, 1);
|
|
150
185
|
|
|
151
186
|
expect(received.map((event) => event.message.type)).toEqual([
|
|
152
|
-
"conversation_list_invalidated",
|
|
153
187
|
"sync_changed",
|
|
154
188
|
]);
|
|
155
|
-
expect(received[
|
|
189
|
+
expect(received[0]!.message).toEqual({
|
|
156
190
|
type: "sync_changed",
|
|
157
191
|
tags: [
|
|
158
192
|
SYNC_TAGS.conversationsList,
|
|
@@ -160,9 +194,28 @@ describe("conversation sync tags", () => {
|
|
|
160
194
|
conversationMetadataSyncTag(second.id),
|
|
161
195
|
],
|
|
162
196
|
});
|
|
197
|
+
expect(
|
|
198
|
+
received.some(
|
|
199
|
+
(event) => event.message.type === "conversation_list_invalidated",
|
|
200
|
+
),
|
|
201
|
+
).toBe(false);
|
|
163
202
|
});
|
|
164
203
|
|
|
165
|
-
test("record seen emits
|
|
204
|
+
test("record seen emits only a per-conversation metadata sync tag (no list umbrella)", async () => {
|
|
205
|
+
// Seen state is per-conversation attention metadata, not list-
|
|
206
|
+
// shaped. The old behavior emitted `sync_changed` carrying the
|
|
207
|
+
// umbrella `conversationsList` tag, which forced every subscribed
|
|
208
|
+
// web client to redrain the full paginated sidebar on every
|
|
209
|
+
// conversation switch that landed on an unseen conversation (~14
|
|
210
|
+
// requests at ~300 conversations). The current behavior emits a
|
|
211
|
+
// single `sync_changed` with only the per-conversation
|
|
212
|
+
// `conversation:<id>:metadata` tag, which web consumes by GET-and-
|
|
213
|
+
// patching the single cached row via `refreshConversationRow`.
|
|
214
|
+
//
|
|
215
|
+
// The legacy `conversation_list_invalidated` broadcast is still
|
|
216
|
+
// emitted for macOS (which has no per-row patcher) but is scoped
|
|
217
|
+
// to `targetInterfaceId: "macos"` and therefore not visible to
|
|
218
|
+
// this process-type subscriber.
|
|
166
219
|
const conversation = createConversation("Attention");
|
|
167
220
|
projectAssistantMessage({
|
|
168
221
|
conversationId: conversation.id,
|
|
@@ -181,22 +234,32 @@ describe("conversation sync tags", () => {
|
|
|
181
234
|
source: "test",
|
|
182
235
|
},
|
|
183
236
|
});
|
|
184
|
-
},
|
|
237
|
+
}, 1);
|
|
185
238
|
|
|
186
239
|
expect(received.map((event) => event.message.type)).toEqual([
|
|
187
|
-
"conversation_list_invalidated",
|
|
188
240
|
"sync_changed",
|
|
189
241
|
]);
|
|
190
|
-
expect(received[
|
|
242
|
+
expect(received[0]!.message).toEqual({
|
|
191
243
|
type: "sync_changed",
|
|
192
|
-
tags: [
|
|
193
|
-
SYNC_TAGS.conversationsList,
|
|
194
|
-
conversationMetadataSyncTag(conversation.id),
|
|
195
|
-
],
|
|
244
|
+
tags: [conversationMetadataSyncTag(conversation.id)],
|
|
196
245
|
});
|
|
246
|
+
// Defense-in-depth: the umbrella `conversationsList` tag would
|
|
247
|
+
// force the very paginated-list drain this redesign exists to
|
|
248
|
+
// avoid. It must not appear here.
|
|
249
|
+
expect(
|
|
250
|
+
(received[0]!.message as { tags: string[] }).tags,
|
|
251
|
+
).not.toContain(SYNC_TAGS.conversationsList);
|
|
252
|
+
expect(
|
|
253
|
+
received.some(
|
|
254
|
+
(event) => event.message.type === "conversation_list_invalidated",
|
|
255
|
+
),
|
|
256
|
+
).toBe(false);
|
|
197
257
|
});
|
|
198
258
|
|
|
199
|
-
test("mark unread emits
|
|
259
|
+
test("mark unread emits only a per-conversation metadata sync tag (no list umbrella)", async () => {
|
|
260
|
+
// Symmetric with `record seen`: mark-unread flips the per-conversation
|
|
261
|
+
// hasUnseen flag back to true. Same per-conversation sync tag, same
|
|
262
|
+
// absence of list-level fan-out.
|
|
200
263
|
const conversation = createConversation("Attention");
|
|
201
264
|
projectAssistantMessage({
|
|
202
265
|
conversationId: conversation.id,
|
|
@@ -218,18 +281,22 @@ describe("conversation sync tags", () => {
|
|
|
218
281
|
conversationId: conversation.id,
|
|
219
282
|
},
|
|
220
283
|
});
|
|
221
|
-
},
|
|
284
|
+
}, 1);
|
|
222
285
|
|
|
223
286
|
expect(received.map((event) => event.message.type)).toEqual([
|
|
224
|
-
"conversation_list_invalidated",
|
|
225
287
|
"sync_changed",
|
|
226
288
|
]);
|
|
227
|
-
expect(received[
|
|
289
|
+
expect(received[0]!.message).toEqual({
|
|
228
290
|
type: "sync_changed",
|
|
229
|
-
tags: [
|
|
230
|
-
SYNC_TAGS.conversationsList,
|
|
231
|
-
conversationMetadataSyncTag(conversation.id),
|
|
232
|
-
],
|
|
291
|
+
tags: [conversationMetadataSyncTag(conversation.id)],
|
|
233
292
|
});
|
|
293
|
+
expect(
|
|
294
|
+
(received[0]!.message as { tags: string[] }).tags,
|
|
295
|
+
).not.toContain(SYNC_TAGS.conversationsList);
|
|
296
|
+
expect(
|
|
297
|
+
received.some(
|
|
298
|
+
(event) => event.message.type === "conversation_list_invalidated",
|
|
299
|
+
),
|
|
300
|
+
).toBe(false);
|
|
234
301
|
});
|
|
235
302
|
});
|
|
@@ -18,7 +18,7 @@ mock.module("../util/logger.js", () => ({
|
|
|
18
18
|
|
|
19
19
|
mock.module("../providers/registry.js", () => ({
|
|
20
20
|
getProvider: () => ({ name: "mock-provider" }),
|
|
21
|
-
initializeProviders: () => {},
|
|
21
|
+
initializeProviders: async () => {},
|
|
22
22
|
}));
|
|
23
23
|
|
|
24
24
|
mock.module("../config/loader.js", () => ({
|
|
@@ -87,6 +87,7 @@ mock.module("../security/secret-allowlist.js", () => ({
|
|
|
87
87
|
|
|
88
88
|
mock.module("../memory/conversation-crud.js", () => ({
|
|
89
89
|
setConversationOriginChannelIfUnset: () => {},
|
|
90
|
+
setConversationHistoryStrippedAt: () => {},
|
|
90
91
|
provenanceFromTrustContext: () => ({
|
|
91
92
|
source: "user",
|
|
92
93
|
trustContext: undefined,
|
|
@@ -27,7 +27,7 @@ mock.module("../memory/guardian-action-store.js", () => ({
|
|
|
27
27
|
|
|
28
28
|
mock.module("../providers/registry.js", () => ({
|
|
29
29
|
getProvider: () => ({ name: "mock-provider" }),
|
|
30
|
-
initializeProviders: () => {},
|
|
30
|
+
initializeProviders: async () => {},
|
|
31
31
|
}));
|
|
32
32
|
|
|
33
33
|
mock.module("../config/loader.js", () => ({
|
|
@@ -116,6 +116,7 @@ mock.module("../security/secret-allowlist.js", () => ({
|
|
|
116
116
|
|
|
117
117
|
mock.module("../memory/conversation-crud.js", () => ({
|
|
118
118
|
setConversationOriginChannelIfUnset: () => {},
|
|
119
|
+
setConversationHistoryStrippedAt: () => {},
|
|
119
120
|
provenanceFromTrustContext: () => ({
|
|
120
121
|
source: "user",
|
|
121
122
|
trustContext: undefined,
|
|
@@ -141,6 +142,9 @@ mock.module("../memory/conversation-crud.js", () => ({
|
|
|
141
142
|
deleteLastExchange: () => 0,
|
|
142
143
|
getMessageById: () => null,
|
|
143
144
|
getLastUserTimestampBefore: () => 0,
|
|
145
|
+
setLastNotifiedInferenceProfile: () => {},
|
|
146
|
+
getConversationOverrideProfileFromRow: () => undefined,
|
|
147
|
+
updateMessageMetadata: () => {},
|
|
144
148
|
}));
|
|
145
149
|
|
|
146
150
|
mock.module("../memory/conversation-queries.js", () => ({
|
|
@@ -25,7 +25,7 @@ mock.module("../memory/guardian-action-store.js", () => ({
|
|
|
25
25
|
|
|
26
26
|
mock.module("../providers/registry.js", () => ({
|
|
27
27
|
getProvider: () => ({ name: "mock-provider" }),
|
|
28
|
-
initializeProviders: () => {},
|
|
28
|
+
initializeProviders: async () => {},
|
|
29
29
|
}));
|
|
30
30
|
|
|
31
31
|
mock.module("../config/loader.js", () => ({
|
|
@@ -114,6 +114,7 @@ mock.module("../security/secret-allowlist.js", () => ({
|
|
|
114
114
|
|
|
115
115
|
mock.module("../memory/conversation-crud.js", () => ({
|
|
116
116
|
setConversationOriginChannelIfUnset: () => {},
|
|
117
|
+
setConversationHistoryStrippedAt: () => {},
|
|
117
118
|
provenanceFromTrustContext: () => ({
|
|
118
119
|
source: "user",
|
|
119
120
|
trustContext: undefined,
|
|
@@ -138,6 +139,9 @@ mock.module("../memory/conversation-crud.js", () => ({
|
|
|
138
139
|
deleteLastExchange: () => 0,
|
|
139
140
|
getMessageById: () => null,
|
|
140
141
|
getLastUserTimestampBefore: () => 0,
|
|
142
|
+
setLastNotifiedInferenceProfile: () => {},
|
|
143
|
+
getConversationOverrideProfileFromRow: () => undefined,
|
|
144
|
+
updateMessageMetadata: () => {},
|
|
141
145
|
}));
|
|
142
146
|
|
|
143
147
|
mock.module("../memory/conversation-queries.js", () => ({
|