@vellumai/assistant 0.5.5 → 0.5.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +16 -2
- package/ARCHITECTURE.md +6 -75
- package/Dockerfile +4 -5
- package/README.md +0 -2
- package/bun.lock +0 -414
- package/docs/architecture/keychain-broker.md +45 -240
- package/docs/architecture/security.md +0 -17
- package/docs/credential-execution-service.md +2 -2
- package/node_modules/@vellumai/ces-contracts/package.json +1 -0
- package/node_modules/@vellumai/ces-contracts/src/rpc.ts +119 -0
- package/node_modules/@vellumai/credential-storage/package.json +1 -0
- package/node_modules/@vellumai/egress-proxy/package.json +1 -0
- package/package.json +2 -3
- package/src/__tests__/actor-token-service.test.ts +1 -2
- package/src/__tests__/assistant-feature-flags-integration.test.ts +30 -29
- package/src/__tests__/browser-skill-endstate.test.ts +6 -5
- package/src/__tests__/btw-routes.test.ts +0 -39
- package/src/__tests__/call-domain.test.ts +0 -128
- package/src/__tests__/ces-rpc-credential-backend.test.ts +199 -0
- package/src/__tests__/channel-approval-routes.test.ts +0 -5
- package/src/__tests__/channel-readiness-service.test.ts +1 -60
- package/src/__tests__/checker.test.ts +4 -2
- package/src/__tests__/cli-command-risk-guard.test.ts +112 -0
- package/src/__tests__/config-schema-cmd.test.ts +0 -1
- package/src/__tests__/config-schema.test.ts +3 -3
- package/src/__tests__/context-window-manager.test.ts +78 -0
- package/src/__tests__/conversation-attention-telegram.test.ts +0 -5
- package/src/__tests__/conversation-init.benchmark.test.ts +0 -2
- package/src/__tests__/conversation-skill-tools.test.ts +0 -54
- package/src/__tests__/conversation-title-service.test.ts +117 -1
- package/src/__tests__/credential-execution-feature-gates.test.ts +28 -14
- package/src/__tests__/credential-execution-managed-contract.test.ts +33 -18
- package/src/__tests__/credential-security-e2e.test.ts +0 -66
- package/src/__tests__/credential-security-invariants.test.ts +4 -45
- package/src/__tests__/credentials-cli.test.ts +78 -0
- package/src/__tests__/db-migration-rollback.test.ts +2015 -1
- package/src/__tests__/docker-signing-key-bootstrap.test.ts +98 -0
- package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +6 -4
- package/src/__tests__/guardian-routing-state.test.ts +0 -5
- package/src/__tests__/host-shell-tool.test.ts +6 -7
- package/src/__tests__/http-user-message-parity.test.ts +3 -103
- package/src/__tests__/inbound-invite-redemption.test.ts +0 -4
- package/src/__tests__/inline-skill-load-permissions.test.ts +6 -8
- package/src/__tests__/intent-routing.test.ts +0 -13
- package/src/__tests__/jobs-store-qdrant-breaker.test.ts +178 -0
- package/src/__tests__/keychain-broker-client.test.ts +161 -22
- package/src/__tests__/memory-jobs-worker-backoff.test.ts +150 -0
- package/src/__tests__/memory-regressions.test.ts +8 -30
- package/src/__tests__/migration-export-http.test.ts +2 -2
- package/src/__tests__/migration-import-commit-http.test.ts +2 -2
- package/src/__tests__/migration-import-preflight-http.test.ts +2 -2
- package/src/__tests__/migration-validate-http.test.ts +2 -2
- package/src/__tests__/non-member-access-request.test.ts +0 -5
- package/src/__tests__/notification-decision-fallback.test.ts +4 -0
- package/src/__tests__/notification-decision-identity.test.ts +4 -0
- package/src/__tests__/permission-types.test.ts +1 -0
- package/src/__tests__/provider-managed-proxy-integration.test.ts +5 -6
- package/src/__tests__/qdrant-manager.test.ts +28 -2
- package/src/__tests__/registry.test.ts +0 -6
- package/src/__tests__/require-fresh-approval.test.ts +4 -0
- package/src/__tests__/runtime-attachment-metadata.test.ts +0 -4
- package/src/__tests__/secret-routes-managed-proxy.test.ts +0 -4
- package/src/__tests__/secure-keys.test.ts +83 -263
- package/src/__tests__/shell-identity.test.ts +96 -6
- package/src/__tests__/skill-feature-flags-integration.test.ts +22 -14
- package/src/__tests__/skill-feature-flags.test.ts +46 -45
- package/src/__tests__/skill-load-feature-flag.test.ts +7 -10
- package/src/__tests__/skill-load-inline-command.test.ts +8 -12
- package/src/__tests__/skill-load-inline-includes.test.ts +6 -10
- package/src/__tests__/skill-load-tool.test.ts +0 -2
- package/src/__tests__/skill-projection-feature-flag.test.ts +33 -29
- package/src/__tests__/skills.test.ts +0 -2
- package/src/__tests__/slack-inbound-verification.test.ts +0 -4
- package/src/__tests__/suggestion-routes.test.ts +1 -32
- package/src/__tests__/system-prompt.test.ts +0 -1
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +4 -0
- package/src/__tests__/tool-executor-shell-integration.test.ts +5 -3
- package/src/__tests__/tool-executor.test.ts +4 -0
- package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +0 -5
- package/src/__tests__/trusted-contact-multichannel.test.ts +0 -4
- package/src/__tests__/update-bulletin.test.ts +0 -2
- package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +6 -9
- package/src/__tests__/voice-scoped-grant-consumer.test.ts +0 -6
- package/src/__tests__/workspace-migration-015-migrate-credentials-to-keychain.test.ts +252 -0
- package/src/__tests__/workspace-migration-016-migrate-credentials-from-keychain.test.ts +218 -0
- package/src/__tests__/workspace-migration-down-functions.test.ts +1009 -0
- package/src/__tests__/workspace-migrations-runner.test.ts +114 -0
- package/src/calls/audio-store.test.ts +97 -0
- package/src/calls/audio-store.ts +205 -0
- package/src/calls/call-controller.ts +85 -7
- package/src/calls/call-domain.ts +3 -0
- package/src/calls/call-store.ts +10 -3
- package/src/calls/fish-audio-client.ts +117 -0
- package/src/calls/relay-server.ts +27 -0
- package/src/calls/twilio-routes.ts +2 -1
- package/src/calls/types.ts +1 -0
- package/src/calls/voice-ingress-preflight.ts +0 -42
- package/src/calls/voice-quality.ts +26 -5
- package/src/calls/voice-session-bridge.ts +6 -12
- package/src/cli/commands/config.ts +1 -4
- package/src/cli/commands/conversations.ts +0 -18
- package/src/cli/commands/credentials.ts +34 -4
- package/src/cli/commands/oauth/index.ts +7 -0
- package/src/cli/commands/oauth/platform.ts +179 -0
- package/src/cli/commands/platform.ts +3 -3
- package/src/config/assistant-feature-flags.ts +186 -5
- package/src/config/bundled-skills/messaging/SKILL.md +5 -5
- package/src/config/bundled-skills/phone-calls/TOOLS.json +4 -0
- package/src/config/bundled-skills/settings/TOOLS.json +2 -2
- package/src/config/bundled-skills/settings/tools/voice-config-update.ts +42 -0
- package/src/config/bundled-tool-registry.ts +1 -11
- package/src/config/env-registry.ts +1 -1
- package/src/config/env.ts +16 -16
- package/src/config/feature-flag-registry.json +48 -16
- package/src/config/loader.ts +98 -31
- package/src/config/schema.ts +4 -25
- package/src/config/schemas/calls.ts +13 -0
- package/src/config/schemas/fish-audio.ts +39 -0
- package/src/config/schemas/memory.ts +0 -4
- package/src/config/schemas/platform.ts +1 -1
- package/src/config/schemas/security.ts +4 -4
- package/src/config/types.ts +0 -1
- package/src/contacts/contact-store.ts +39 -0
- package/src/contacts/types.ts +2 -0
- package/src/context/window-manager.ts +53 -2
- package/src/credential-execution/approval-bridge.ts +1 -0
- package/src/credential-execution/executable-discovery.ts +28 -4
- package/src/credential-execution/feature-gates.ts +16 -0
- package/src/credential-execution/process-manager.ts +38 -0
- package/src/daemon/assistant-attachments.ts +9 -0
- package/src/daemon/config-watcher.ts +6 -4
- package/src/daemon/conversation-agent-loop.ts +0 -60
- package/src/daemon/conversation-memory.ts +0 -117
- package/src/daemon/conversation-runtime-assembly.ts +0 -2
- package/src/daemon/conversation-tool-setup.ts +0 -105
- package/src/daemon/conversation.ts +10 -1
- package/src/daemon/handlers/config-vercel.ts +92 -0
- package/src/daemon/handlers/conversations.ts +0 -11
- package/src/daemon/handlers/skills.ts +2 -15
- package/src/daemon/install-symlink.ts +195 -0
- package/src/daemon/lifecycle.ts +229 -96
- package/src/daemon/message-types/conversations.ts +3 -4
- package/src/daemon/message-types/diagnostics.ts +3 -22
- package/src/daemon/message-types/messages.ts +0 -2
- package/src/daemon/message-types/upgrades.ts +8 -0
- package/src/daemon/server.ts +30 -92
- package/src/events/domain-events.ts +2 -1
- package/src/followups/followup-store.ts +5 -2
- package/src/inbound/platform-callback-registration.ts +3 -3
- package/src/instrument.ts +8 -5
- package/src/memory/conversation-crud.ts +0 -236
- package/src/memory/conversation-title-service.ts +76 -11
- package/src/memory/db-init.ts +15 -11
- package/src/memory/indexer.ts +15 -106
- package/src/memory/items-extractor.ts +15 -1
- package/src/memory/job-handlers/conversation-starters.ts +4 -1
- package/src/memory/job-handlers/embedding.ts +0 -79
- package/src/memory/job-utils.ts +1 -1
- package/src/memory/jobs-store.ts +30 -13
- package/src/memory/jobs-worker.ts +31 -27
- package/src/memory/migrations/001-job-deferrals.ts +19 -0
- package/src/memory/migrations/004-entity-relation-dedup.ts +10 -0
- package/src/memory/migrations/005-fingerprint-scope-unique.ts +76 -0
- package/src/memory/migrations/006-scope-salted-fingerprints.ts +50 -0
- package/src/memory/migrations/007-assistant-id-to-self.ts +10 -0
- package/src/memory/migrations/008-remove-assistant-id-columns.ts +34 -0
- package/src/memory/migrations/009-llm-usage-events-drop-assistant-id.ts +26 -0
- package/src/memory/migrations/014-backfill-inbox-thread-state.ts +10 -0
- package/src/memory/migrations/015-drop-active-search-index.ts +17 -0
- package/src/memory/migrations/019-notification-tables-schema-migration.ts +12 -0
- package/src/memory/migrations/020-rename-macos-ios-channel-to-vellum.ts +121 -0
- package/src/memory/migrations/024-embedding-vector-blob.ts +74 -0
- package/src/memory/migrations/026a-embeddings-nullable-vector-json.ts +82 -0
- package/src/memory/migrations/036-normalize-phone-identities.ts +11 -0
- package/src/memory/migrations/116-messages-fts.ts +106 -1
- package/src/memory/migrations/126-backfill-guardian-principal-id.ts +52 -0
- package/src/memory/migrations/127-guardian-principal-id-not-null.ts +77 -0
- package/src/memory/migrations/134-contacts-notes-column.ts +13 -0
- package/src/memory/migrations/135-backfill-contact-interaction-stats.ts +20 -0
- package/src/memory/migrations/136-drop-assistant-id-columns.ts +52 -0
- package/src/memory/migrations/140-backfill-usage-cache-accounting.ts +13 -0
- package/src/memory/migrations/141-rename-verification-table.ts +54 -0
- package/src/memory/migrations/142-rename-verification-session-id-column.ts +25 -0
- package/src/memory/migrations/143-rename-guardian-verification-values.ts +35 -0
- package/src/memory/migrations/144-rename-voice-to-phone.ts +136 -0
- package/src/memory/migrations/145-drop-accounts-table.ts +32 -0
- package/src/memory/migrations/147-migrate-reminders-to-schedules.ts +14 -1
- package/src/memory/migrations/148-drop-reminders-table.ts +35 -1
- package/src/memory/migrations/150-oauth-apps-client-secret-path.ts +69 -1
- package/src/memory/migrations/162-guardian-timestamps-epoch-ms.ts +290 -0
- package/src/memory/migrations/169-rename-gmail-provider-key-to-google.ts +51 -1
- package/src/memory/migrations/174-rename-thread-starters-table.ts +47 -1
- package/src/memory/migrations/176-drop-capability-card-state.ts +13 -0
- package/src/memory/migrations/180-backfill-inline-attachments-to-disk.ts +16 -0
- package/src/memory/migrations/181-rename-thread-starters-checkpoints.ts +28 -1
- package/src/memory/migrations/189-drop-simplified-memory.ts +42 -0
- package/src/memory/migrations/190-call-session-skip-disclosure.ts +15 -0
- package/src/memory/migrations/191-backfill-audio-attachment-mime-types.ts +64 -0
- package/src/memory/migrations/192-contacts-user-file-column.ts +15 -0
- package/src/memory/migrations/index.ts +5 -3
- package/src/memory/migrations/registry.ts +90 -0
- package/src/memory/migrations/validate-migration-state.ts +137 -11
- package/src/memory/qdrant-circuit-breaker.ts +9 -0
- package/src/memory/qdrant-client.ts +4 -6
- package/src/memory/qdrant-manager.ts +64 -7
- package/src/memory/schema/calls.ts +1 -0
- package/src/memory/schema/contacts.ts +1 -0
- package/src/memory/schema/conversations.ts +0 -3
- package/src/memory/schema/index.ts +0 -2
- package/src/messaging/draft-store.ts +2 -2
- package/src/notifications/decision-engine.ts +4 -1
- package/src/oauth/connection-resolver.ts +6 -4
- package/src/permissions/checker.ts +0 -38
- package/src/permissions/defaults.ts +3 -3
- package/src/permissions/shell-identity.ts +76 -22
- package/src/permissions/trust-client.ts +2 -13
- package/src/permissions/trust-store.ts +8 -3
- package/src/permissions/types.ts +4 -2
- package/src/platform/client.ts +35 -7
- package/src/prompts/persona-resolver.ts +138 -0
- package/src/prompts/system-prompt.ts +36 -4
- package/src/prompts/templates/users/default.md +1 -0
- package/src/providers/registry.ts +27 -40
- package/src/runtime/auth/__tests__/credential-service.test.ts +0 -1
- package/src/runtime/auth/__tests__/external-assistant-id.test.ts +13 -68
- package/src/runtime/auth/external-assistant-id.ts +13 -59
- package/src/runtime/auth/route-policy.ts +29 -1
- package/src/runtime/auth/token-service.ts +53 -15
- package/src/runtime/channel-readiness-service.ts +1 -16
- package/src/runtime/http-server.ts +29 -2
- package/src/runtime/middleware/error-handler.ts +1 -9
- package/src/runtime/routes/audio-routes.ts +40 -0
- package/src/runtime/routes/btw-routes.ts +0 -17
- package/src/runtime/routes/conversation-management-routes.ts +0 -36
- package/src/runtime/routes/conversation-query-routes.ts +106 -2
- package/src/runtime/routes/conversation-routes.ts +4 -43
- package/src/runtime/routes/diagnostics-routes.ts +1 -477
- package/src/runtime/routes/identity-routes.ts +18 -29
- package/src/runtime/routes/inbound-stages/secret-ingress-check.ts +4 -33
- package/src/runtime/routes/inbound-stages/transcribe-audio.test.ts +1 -1
- package/src/runtime/routes/integrations/vercel.ts +89 -0
- package/src/runtime/routes/log-export-routes.ts +5 -0
- package/src/runtime/routes/memory-item-routes.test.ts +221 -3
- package/src/runtime/routes/memory-item-routes.ts +144 -4
- package/src/runtime/routes/migration-rollback-routes.ts +209 -0
- package/src/runtime/routes/migration-routes.ts +17 -1
- package/src/runtime/routes/notification-routes.ts +58 -0
- package/src/runtime/routes/schedule-routes.ts +65 -0
- package/src/runtime/routes/settings-routes.ts +41 -1
- package/src/runtime/routes/tts-routes.ts +86 -0
- package/src/runtime/routes/upgrade-broadcast-routes.ts +175 -0
- package/src/runtime/routes/workspace-commit-routes.ts +62 -0
- package/src/runtime/routes/workspace-routes.test.ts +22 -1
- package/src/runtime/routes/workspace-routes.ts +1 -1
- package/src/runtime/routes/workspace-utils.ts +86 -2
- package/src/schedule/schedule-store.ts +0 -21
- package/src/security/ces-credential-client.ts +59 -22
- package/src/security/ces-rpc-credential-backend.ts +85 -0
- package/src/security/credential-backend.ts +12 -88
- package/src/security/keychain-broker-client.ts +10 -2
- package/src/security/secure-keys.ts +94 -113
- package/src/skills/catalog-install.ts +13 -7
- package/src/skills/inline-command-render.ts +5 -1
- package/src/skills/inline-command-runner.ts +30 -2
- package/src/telemetry/usage-telemetry-reporter.ts +4 -2
- package/src/tools/calls/call-start.ts +1 -0
- package/src/tools/executor.ts +0 -4
- package/src/tools/memory/handlers.ts +1 -129
- package/src/tools/network/script-proxy/session-manager.ts +19 -4
- package/src/tools/network/web-fetch.ts +3 -1
- package/src/tools/permission-checker.ts +18 -0
- package/src/tools/skills/execute.ts +1 -1
- package/src/tools/skills/load.ts +9 -2
- package/src/tools/types.ts +0 -8
- package/src/util/errors.ts +0 -12
- package/src/util/platform.ts +8 -55
- package/src/util/xml.ts +8 -0
- package/src/workspace/git-service.ts +5 -2
- package/src/workspace/heartbeat-service.ts +5 -24
- package/src/workspace/migrations/001-avatar-rename.ts +15 -0
- package/src/workspace/migrations/003-seed-device-id.ts +17 -1
- package/src/workspace/migrations/004-extract-collect-usage-data.ts +33 -0
- package/src/workspace/migrations/005-add-send-diagnostics.ts +3 -0
- package/src/workspace/migrations/006-services-config.ts +49 -0
- package/src/workspace/migrations/007-web-search-provider-rename.ts +27 -0
- package/src/workspace/migrations/008-voice-timeout-and-max-steps.ts +3 -0
- package/src/workspace/migrations/009-backfill-conversation-disk-view.ts +4 -0
- package/src/workspace/migrations/010-app-dir-rename.ts +78 -0
- package/src/workspace/migrations/011-backfill-installation-id.ts +11 -0
- package/src/workspace/migrations/012-rename-conversation-disk-view-dirs.ts +44 -0
- package/src/workspace/migrations/013-repair-conversation-disk-view.ts +5 -0
- package/src/workspace/migrations/015-migrate-credentials-to-keychain.ts +153 -0
- package/src/workspace/migrations/016-extract-feature-flags-to-protected.ts +156 -0
- package/src/workspace/migrations/016-migrate-credentials-from-keychain.ts +150 -0
- package/src/workspace/migrations/017-seed-persona-dirs.ts +95 -0
- package/src/workspace/migrations/migrate-to-workspace-volume.ts +23 -1
- package/src/workspace/migrations/registry.ts +8 -0
- package/src/workspace/migrations/runner.ts +106 -2
- package/src/workspace/migrations/types.ts +4 -0
- package/src/__tests__/archive-recall.test.ts +0 -560
- package/src/__tests__/claude-code-skill-regression.test.ts +0 -206
- package/src/__tests__/claude-code-tool-profiles.test.ts +0 -99
- package/src/__tests__/conversation-memory-dirty-tail.test.ts +0 -150
- package/src/__tests__/conversation-switch-memory-reduction.test.ts +0 -474
- package/src/__tests__/db-memory-archive-migration.test.ts +0 -372
- package/src/__tests__/db-memory-brief-state-migration.test.ts +0 -213
- package/src/__tests__/db-memory-reducer-checkpoints.test.ts +0 -273
- package/src/__tests__/diagnostics-export.test.ts +0 -288
- package/src/__tests__/local-gateway-health.test.ts +0 -209
- package/src/__tests__/memory-brief-open-loops.test.ts +0 -530
- package/src/__tests__/memory-brief-time.test.ts +0 -285
- package/src/__tests__/memory-brief-wrapper.test.ts +0 -311
- package/src/__tests__/memory-chunk-archive.test.ts +0 -400
- package/src/__tests__/memory-chunk-dual-write.test.ts +0 -453
- package/src/__tests__/memory-episode-archive.test.ts +0 -370
- package/src/__tests__/memory-episode-dual-write.test.ts +0 -626
- package/src/__tests__/memory-observation-archive.test.ts +0 -375
- package/src/__tests__/memory-observation-dual-write.test.ts +0 -318
- package/src/__tests__/memory-reducer-job.test.ts +0 -538
- package/src/__tests__/memory-reducer-scheduling.test.ts +0 -473
- package/src/__tests__/memory-reducer-store.test.ts +0 -728
- package/src/__tests__/memory-reducer-types.test.ts +0 -707
- package/src/__tests__/memory-reducer.test.ts +0 -704
- package/src/__tests__/memory-simplified-config.test.ts +0 -281
- package/src/__tests__/secret-ingress-handler.test.ts +0 -120
- package/src/__tests__/simplified-memory-e2e.test.ts +0 -666
- package/src/__tests__/simplified-memory-runtime.test.ts +0 -616
- package/src/__tests__/swarm-conversation-integration.test.ts +0 -358
- package/src/__tests__/swarm-dag-pathological.test.ts +0 -547
- package/src/__tests__/swarm-orchestrator.test.ts +0 -463
- package/src/__tests__/swarm-plan-validator.test.ts +0 -384
- package/src/__tests__/swarm-recursion.test.ts +0 -197
- package/src/__tests__/swarm-router-planner.test.ts +0 -234
- package/src/__tests__/swarm-tool.test.ts +0 -185
- package/src/__tests__/swarm-worker-backend.test.ts +0 -144
- package/src/__tests__/swarm-worker-runner.test.ts +0 -288
- package/src/commands/__tests__/cc-command-registry.test.ts +0 -396
- package/src/commands/cc-command-registry.ts +0 -248
- package/src/config/bundled-skills/claude-code/SKILL.md +0 -53
- package/src/config/bundled-skills/claude-code/TOOLS.json +0 -47
- package/src/config/bundled-skills/claude-code/tools/claude-code.ts +0 -12
- package/src/config/bundled-skills/orchestration/SKILL.md +0 -33
- package/src/config/bundled-skills/orchestration/TOOLS.json +0 -35
- package/src/config/bundled-skills/orchestration/tools/swarm-delegate.ts +0 -12
- package/src/config/schemas/memory-simplified.ts +0 -101
- package/src/config/schemas/swarm.ts +0 -82
- package/src/logfire.ts +0 -135
- package/src/memory/archive-recall.ts +0 -516
- package/src/memory/archive-store.ts +0 -400
- package/src/memory/brief-formatting.ts +0 -33
- package/src/memory/brief-open-loops.ts +0 -266
- package/src/memory/brief-time.ts +0 -162
- package/src/memory/brief.ts +0 -75
- package/src/memory/job-handlers/backfill-simplified-memory.ts +0 -462
- package/src/memory/job-handlers/reduce-conversation-memory.ts +0 -229
- package/src/memory/migrations/185-memory-brief-state.ts +0 -52
- package/src/memory/migrations/186-memory-archive.ts +0 -109
- package/src/memory/migrations/187-memory-reducer-checkpoints.ts +0 -19
- package/src/memory/reducer-scheduler.ts +0 -242
- package/src/memory/reducer-store.ts +0 -271
- package/src/memory/reducer-types.ts +0 -106
- package/src/memory/reducer.ts +0 -467
- package/src/memory/schema/memory-archive.ts +0 -121
- package/src/memory/schema/memory-brief.ts +0 -55
- package/src/runtime/local-gateway-health.ts +0 -275
- package/src/security/secret-ingress.ts +0 -68
- package/src/swarm/backend-claude-code.ts +0 -225
- package/src/swarm/checkpoint.ts +0 -137
- package/src/swarm/graph-utils.ts +0 -53
- package/src/swarm/index.ts +0 -55
- package/src/swarm/limits.ts +0 -66
- package/src/swarm/orchestrator.ts +0 -424
- package/src/swarm/plan-validator.ts +0 -117
- package/src/swarm/router-planner.ts +0 -162
- package/src/swarm/router-prompts.ts +0 -39
- package/src/swarm/synthesizer.ts +0 -81
- package/src/swarm/types.ts +0 -72
- package/src/swarm/worker-backend.ts +0 -131
- package/src/swarm/worker-prompts.ts +0 -80
- package/src/swarm/worker-runner.ts +0 -170
- package/src/tools/claude-code/claude-code.ts +0 -610
- package/src/tools/swarm/delegate.ts +0 -205
|
@@ -1,616 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tests for the simplified memory runtime injection path in
|
|
3
|
-
* conversation-memory.ts.
|
|
4
|
-
*
|
|
5
|
-
* Covers:
|
|
6
|
-
* - Brief-only turns (no archive recall trigger)
|
|
7
|
-
* - Brief-plus-recall turns (archive recall fires)
|
|
8
|
-
* - Disabled-flag fallback (legacy path used when flag is off)
|
|
9
|
-
*/
|
|
10
|
-
import { mkdtempSync, rmSync } from "node:fs";
|
|
11
|
-
import { tmpdir } from "node:os";
|
|
12
|
-
import { join } from "node:path";
|
|
13
|
-
import {
|
|
14
|
-
afterAll,
|
|
15
|
-
beforeAll,
|
|
16
|
-
beforeEach,
|
|
17
|
-
describe,
|
|
18
|
-
expect,
|
|
19
|
-
mock,
|
|
20
|
-
test,
|
|
21
|
-
} from "bun:test";
|
|
22
|
-
|
|
23
|
-
const testDir = mkdtempSync(join(tmpdir(), "simplified-memory-runtime-test-"));
|
|
24
|
-
const dbPath = join(testDir, "test.db");
|
|
25
|
-
|
|
26
|
-
// ── Platform mock (must come before any module imports) ──────────────
|
|
27
|
-
|
|
28
|
-
mock.module("../util/platform.js", () => ({
|
|
29
|
-
getDataDir: () => testDir,
|
|
30
|
-
getRootDir: () => testDir,
|
|
31
|
-
isMacOS: () => process.platform === "darwin",
|
|
32
|
-
isLinux: () => process.platform === "linux",
|
|
33
|
-
isWindows: () => process.platform === "win32",
|
|
34
|
-
getPidPath: () => join(testDir, "test.pid"),
|
|
35
|
-
getDbPath: () => dbPath,
|
|
36
|
-
getLogPath: () => join(testDir, "test.log"),
|
|
37
|
-
ensureDataDir: () => {},
|
|
38
|
-
}));
|
|
39
|
-
|
|
40
|
-
mock.module("../util/logger.js", () => ({
|
|
41
|
-
getLogger: () =>
|
|
42
|
-
new Proxy({} as Record<string, unknown>, {
|
|
43
|
-
get: () => () => {},
|
|
44
|
-
}),
|
|
45
|
-
truncateForLog: (value: string) => value,
|
|
46
|
-
}));
|
|
47
|
-
|
|
48
|
-
// ── Configurable config mock ────────────────────────────────────────
|
|
49
|
-
|
|
50
|
-
import { DEFAULT_CONFIG } from "../config/defaults.js";
|
|
51
|
-
import type { AssistantConfig } from "../config/types.js";
|
|
52
|
-
|
|
53
|
-
let testConfig: AssistantConfig = {
|
|
54
|
-
...DEFAULT_CONFIG,
|
|
55
|
-
memory: {
|
|
56
|
-
...DEFAULT_CONFIG.memory,
|
|
57
|
-
enabled: true,
|
|
58
|
-
simplified: {
|
|
59
|
-
...DEFAULT_CONFIG.memory.simplified,
|
|
60
|
-
enabled: true,
|
|
61
|
-
},
|
|
62
|
-
},
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
mock.module("../config/loader.js", () => ({
|
|
66
|
-
loadConfig: () => testConfig,
|
|
67
|
-
getConfig: () => testConfig,
|
|
68
|
-
loadRawConfig: () => ({}),
|
|
69
|
-
saveRawConfig: () => {},
|
|
70
|
-
invalidateConfigCache: () => {},
|
|
71
|
-
}));
|
|
72
|
-
|
|
73
|
-
// Stub out the legacy retriever to ensure the simplified path does not
|
|
74
|
-
// call into the heavy V2 hybrid pipeline. If the legacy path is used
|
|
75
|
-
// unexpectedly, the test will fail with a clear error.
|
|
76
|
-
//
|
|
77
|
-
// We provide the real `injectMemoryRecallAsUserBlock` inline since
|
|
78
|
-
// it's a pure function used by both the legacy and simplified paths.
|
|
79
|
-
mock.module("../memory/retriever.js", () => ({
|
|
80
|
-
buildMemoryRecall: () => {
|
|
81
|
-
throw new Error(
|
|
82
|
-
"buildMemoryRecall should not be called in simplified mode",
|
|
83
|
-
);
|
|
84
|
-
},
|
|
85
|
-
injectMemoryRecallAsUserBlock: (
|
|
86
|
-
msgs: import("../providers/types.js").Message[],
|
|
87
|
-
memoryRecallText: string,
|
|
88
|
-
): import("../providers/types.js").Message[] => {
|
|
89
|
-
if (memoryRecallText.trim().length === 0) return msgs;
|
|
90
|
-
if (msgs.length === 0) return msgs;
|
|
91
|
-
const userTail = msgs[msgs.length - 1];
|
|
92
|
-
if (!userTail || userTail.role !== "user") return msgs;
|
|
93
|
-
return [
|
|
94
|
-
...msgs.slice(0, -1),
|
|
95
|
-
{
|
|
96
|
-
...userTail,
|
|
97
|
-
content: [
|
|
98
|
-
{ type: "text" as const, text: memoryRecallText },
|
|
99
|
-
...userTail.content,
|
|
100
|
-
],
|
|
101
|
-
},
|
|
102
|
-
];
|
|
103
|
-
},
|
|
104
|
-
}));
|
|
105
|
-
|
|
106
|
-
// Stub out modules used only by the legacy pipeline (budget, token
|
|
107
|
-
// estimator, query builder) so they never execute in simplified mode.
|
|
108
|
-
mock.module("../memory/query-builder.js", () => ({
|
|
109
|
-
buildMemoryQuery: () => {
|
|
110
|
-
throw new Error("buildMemoryQuery should not be called in simplified mode");
|
|
111
|
-
},
|
|
112
|
-
}));
|
|
113
|
-
mock.module("../memory/retrieval-budget.js", () => ({
|
|
114
|
-
computeRecallBudget: () => {
|
|
115
|
-
throw new Error(
|
|
116
|
-
"computeRecallBudget should not be called in simplified mode",
|
|
117
|
-
);
|
|
118
|
-
},
|
|
119
|
-
}));
|
|
120
|
-
mock.module("../context/token-estimator.js", () => ({
|
|
121
|
-
estimatePromptTokens: () => 0,
|
|
122
|
-
}));
|
|
123
|
-
|
|
124
|
-
// ── Now import the module under test ────────────────────────────────
|
|
125
|
-
|
|
126
|
-
import { v4 as uuid } from "uuid";
|
|
127
|
-
|
|
128
|
-
import {
|
|
129
|
-
type MemoryPrepareContext,
|
|
130
|
-
prepareMemoryContext,
|
|
131
|
-
} from "../daemon/conversation-memory.js";
|
|
132
|
-
import type { ServerMessage } from "../daemon/message-protocol.js";
|
|
133
|
-
import {
|
|
134
|
-
insertCompactionEpisode,
|
|
135
|
-
insertObservation,
|
|
136
|
-
} from "../memory/archive-store.js";
|
|
137
|
-
import { getDb, initializeDb, resetDb } from "../memory/db.js";
|
|
138
|
-
import { getSqlite } from "../memory/db-connection.js";
|
|
139
|
-
import { conversations, messages } from "../memory/schema.js";
|
|
140
|
-
import type { Message } from "../providers/types.js";
|
|
141
|
-
|
|
142
|
-
// ── Helpers ─────────────────────────────────────────────────────────
|
|
143
|
-
|
|
144
|
-
function removeTestDbFiles(): void {
|
|
145
|
-
rmSync(dbPath, { force: true });
|
|
146
|
-
rmSync(`${dbPath}-shm`, { force: true });
|
|
147
|
-
rmSync(`${dbPath}-wal`, { force: true });
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
function getRawDb(): import("bun:sqlite").Database {
|
|
151
|
-
return getSqlite();
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
function insertTimeContext(opts: {
|
|
155
|
-
id: string;
|
|
156
|
-
summary: string;
|
|
157
|
-
activeFrom: number;
|
|
158
|
-
activeUntil: number;
|
|
159
|
-
scopeId?: string;
|
|
160
|
-
}): void {
|
|
161
|
-
const now = Date.now();
|
|
162
|
-
getRawDb().run(
|
|
163
|
-
`INSERT INTO time_contexts (id, scope_id, summary, source, active_from, active_until, created_at, updated_at)
|
|
164
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
165
|
-
[
|
|
166
|
-
opts.id,
|
|
167
|
-
opts.scopeId ?? "default",
|
|
168
|
-
opts.summary,
|
|
169
|
-
"conversation",
|
|
170
|
-
opts.activeFrom,
|
|
171
|
-
opts.activeUntil,
|
|
172
|
-
now,
|
|
173
|
-
now,
|
|
174
|
-
],
|
|
175
|
-
);
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
function insertOpenLoop(opts: {
|
|
179
|
-
id: string;
|
|
180
|
-
summary: string;
|
|
181
|
-
dueAt?: number | null;
|
|
182
|
-
updatedAt?: number;
|
|
183
|
-
}): void {
|
|
184
|
-
const now = Date.now();
|
|
185
|
-
getRawDb().run(
|
|
186
|
-
`INSERT INTO open_loops (id, scope_id, summary, status, source, due_at, surfaced_at, created_at, updated_at)
|
|
187
|
-
VALUES (?, ?, ?, ?, 'conversation', ?, ?, ?, ?)`,
|
|
188
|
-
[
|
|
189
|
-
opts.id,
|
|
190
|
-
"default",
|
|
191
|
-
opts.summary,
|
|
192
|
-
"open",
|
|
193
|
-
opts.dueAt ?? null,
|
|
194
|
-
null,
|
|
195
|
-
now,
|
|
196
|
-
opts.updatedAt ?? now,
|
|
197
|
-
],
|
|
198
|
-
);
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
function createConversation(id: string, title: string | null = null): void {
|
|
202
|
-
const db = getDb();
|
|
203
|
-
const now = Date.now();
|
|
204
|
-
db.insert(conversations)
|
|
205
|
-
.values({
|
|
206
|
-
id,
|
|
207
|
-
title,
|
|
208
|
-
createdAt: now,
|
|
209
|
-
updatedAt: now,
|
|
210
|
-
})
|
|
211
|
-
.run();
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
function createMessage(
|
|
215
|
-
id: string,
|
|
216
|
-
conversationId: string,
|
|
217
|
-
role: string = "user",
|
|
218
|
-
content: string = "test message",
|
|
219
|
-
): void {
|
|
220
|
-
const db = getDb();
|
|
221
|
-
db.insert(messages)
|
|
222
|
-
.values({
|
|
223
|
-
id,
|
|
224
|
-
conversationId,
|
|
225
|
-
role,
|
|
226
|
-
content,
|
|
227
|
-
createdAt: Date.now(),
|
|
228
|
-
})
|
|
229
|
-
.run();
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
function makeUserMessage(text: string): Message {
|
|
233
|
-
return {
|
|
234
|
-
role: "user",
|
|
235
|
-
content: [{ type: "text", text }],
|
|
236
|
-
};
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
function buildCtx(
|
|
240
|
-
overrides: Partial<MemoryPrepareContext> = {},
|
|
241
|
-
): MemoryPrepareContext {
|
|
242
|
-
return {
|
|
243
|
-
conversationId: uuid(),
|
|
244
|
-
messages: [makeUserMessage("Hello")],
|
|
245
|
-
systemPrompt: "",
|
|
246
|
-
provider: { name: "anthropic" } as MemoryPrepareContext["provider"],
|
|
247
|
-
scopeId: "default",
|
|
248
|
-
includeDefaultFallback: true,
|
|
249
|
-
trustClass: "guardian",
|
|
250
|
-
...overrides,
|
|
251
|
-
};
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
const HOUR = 60 * 60 * 1000;
|
|
255
|
-
const DAY = 24 * HOUR;
|
|
256
|
-
|
|
257
|
-
// ── Setup / Teardown ────────────────────────────────────────────────
|
|
258
|
-
|
|
259
|
-
describe("Simplified Memory Runtime", () => {
|
|
260
|
-
const events: ServerMessage[] = [];
|
|
261
|
-
const onEvent = (msg: ServerMessage) => events.push(msg);
|
|
262
|
-
const abortController = new AbortController();
|
|
263
|
-
|
|
264
|
-
beforeAll(() => {
|
|
265
|
-
initializeDb();
|
|
266
|
-
});
|
|
267
|
-
|
|
268
|
-
beforeEach(() => {
|
|
269
|
-
events.length = 0;
|
|
270
|
-
resetDb();
|
|
271
|
-
removeTestDbFiles();
|
|
272
|
-
initializeDb();
|
|
273
|
-
// Reset config to simplified-enabled for each test
|
|
274
|
-
testConfig = {
|
|
275
|
-
...DEFAULT_CONFIG,
|
|
276
|
-
memory: {
|
|
277
|
-
...DEFAULT_CONFIG.memory,
|
|
278
|
-
enabled: true,
|
|
279
|
-
simplified: {
|
|
280
|
-
...DEFAULT_CONFIG.memory.simplified,
|
|
281
|
-
enabled: true,
|
|
282
|
-
},
|
|
283
|
-
},
|
|
284
|
-
};
|
|
285
|
-
});
|
|
286
|
-
|
|
287
|
-
afterAll(() => {
|
|
288
|
-
resetDb();
|
|
289
|
-
rmSync(testDir, { recursive: true, force: true });
|
|
290
|
-
});
|
|
291
|
-
|
|
292
|
-
// ── Brief-only turns ────────────────────────────────────────────
|
|
293
|
-
|
|
294
|
-
describe("brief-only turns", () => {
|
|
295
|
-
test("injects <memory_brief> when time context exists", async () => {
|
|
296
|
-
const now = Date.now();
|
|
297
|
-
insertTimeContext({
|
|
298
|
-
id: "tc-1",
|
|
299
|
-
summary: "Deploy to staging at 3pm",
|
|
300
|
-
activeFrom: now - HOUR,
|
|
301
|
-
activeUntil: now + 2 * HOUR,
|
|
302
|
-
});
|
|
303
|
-
|
|
304
|
-
const ctx = buildCtx({
|
|
305
|
-
messages: [makeUserMessage("What should I be working on?")],
|
|
306
|
-
});
|
|
307
|
-
const msgId = uuid();
|
|
308
|
-
|
|
309
|
-
const result = await prepareMemoryContext(
|
|
310
|
-
ctx,
|
|
311
|
-
"What should I be working on?",
|
|
312
|
-
msgId,
|
|
313
|
-
abortController.signal,
|
|
314
|
-
onEvent,
|
|
315
|
-
);
|
|
316
|
-
|
|
317
|
-
// Should have injected memory_brief into the last user message
|
|
318
|
-
const lastMsg = result.runMessages[result.runMessages.length - 1];
|
|
319
|
-
expect(lastMsg.role).toBe("user");
|
|
320
|
-
const textBlocks = lastMsg.content.filter((b) => b.type === "text");
|
|
321
|
-
const injectedText = textBlocks
|
|
322
|
-
.map((b) => ("text" in b ? b.text : ""))
|
|
323
|
-
.join("\n");
|
|
324
|
-
|
|
325
|
-
expect(injectedText).toContain("<memory_brief>");
|
|
326
|
-
expect(injectedText).toContain("Deploy to staging at 3pm");
|
|
327
|
-
expect(injectedText).toContain("</memory_brief>");
|
|
328
|
-
|
|
329
|
-
// Should NOT contain <supporting_recall> (no archive data or trigger)
|
|
330
|
-
expect(injectedText).not.toContain("<supporting_recall>");
|
|
331
|
-
|
|
332
|
-
// Should have emitted memory_status
|
|
333
|
-
expect(events.some((e) => e.type === "memory_status")).toBe(true);
|
|
334
|
-
});
|
|
335
|
-
|
|
336
|
-
test("injects <memory_brief> with open loops", async () => {
|
|
337
|
-
const now = Date.now();
|
|
338
|
-
insertOpenLoop({
|
|
339
|
-
id: "ol-1",
|
|
340
|
-
summary: "Review the PR for the auth refactor",
|
|
341
|
-
dueAt: now + 6 * HOUR,
|
|
342
|
-
updatedAt: now - DAY * 10,
|
|
343
|
-
});
|
|
344
|
-
|
|
345
|
-
const ctx = buildCtx({
|
|
346
|
-
messages: [makeUserMessage("What are my pending tasks?")],
|
|
347
|
-
});
|
|
348
|
-
const msgId = uuid();
|
|
349
|
-
|
|
350
|
-
const result = await prepareMemoryContext(
|
|
351
|
-
ctx,
|
|
352
|
-
"What are my pending tasks?",
|
|
353
|
-
msgId,
|
|
354
|
-
abortController.signal,
|
|
355
|
-
onEvent,
|
|
356
|
-
);
|
|
357
|
-
|
|
358
|
-
const lastMsg = result.runMessages[result.runMessages.length - 1];
|
|
359
|
-
const textBlocks = lastMsg.content.filter((b) => b.type === "text");
|
|
360
|
-
const injectedText = textBlocks
|
|
361
|
-
.map((b) => ("text" in b ? b.text : ""))
|
|
362
|
-
.join("\n");
|
|
363
|
-
|
|
364
|
-
expect(injectedText).toContain("<memory_brief>");
|
|
365
|
-
expect(injectedText).toContain("Review the PR for the auth refactor");
|
|
366
|
-
expect(injectedText).toContain("</memory_brief>");
|
|
367
|
-
});
|
|
368
|
-
|
|
369
|
-
test("returns unmodified messages when brief is empty and no recall", async () => {
|
|
370
|
-
// No time contexts or open loops — brief will be empty
|
|
371
|
-
const ctx = buildCtx({
|
|
372
|
-
messages: [makeUserMessage("Write a function to sort an array")],
|
|
373
|
-
});
|
|
374
|
-
const msgId = uuid();
|
|
375
|
-
|
|
376
|
-
const result = await prepareMemoryContext(
|
|
377
|
-
ctx,
|
|
378
|
-
"Write a function to sort an array",
|
|
379
|
-
msgId,
|
|
380
|
-
abortController.signal,
|
|
381
|
-
onEvent,
|
|
382
|
-
);
|
|
383
|
-
|
|
384
|
-
// Messages should be unmodified
|
|
385
|
-
expect(result.runMessages).toEqual(ctx.messages);
|
|
386
|
-
expect(result.recall.injectedText).toBe("");
|
|
387
|
-
});
|
|
388
|
-
});
|
|
389
|
-
|
|
390
|
-
// ── Brief-plus-recall turns ─────────────────────────────────────
|
|
391
|
-
|
|
392
|
-
describe("brief-plus-recall turns", () => {
|
|
393
|
-
test("injects both <memory_brief> and <supporting_recall>", async () => {
|
|
394
|
-
const now = Date.now();
|
|
395
|
-
|
|
396
|
-
// Seed time context for the brief
|
|
397
|
-
insertTimeContext({
|
|
398
|
-
id: "tc-1",
|
|
399
|
-
summary: "Code review session at 4pm",
|
|
400
|
-
activeFrom: now - HOUR,
|
|
401
|
-
activeUntil: now + 3 * HOUR,
|
|
402
|
-
});
|
|
403
|
-
|
|
404
|
-
// Seed archive data that will trigger recall
|
|
405
|
-
const convId = uuid();
|
|
406
|
-
const msgId = uuid();
|
|
407
|
-
createConversation(convId, "Authentication Discussion");
|
|
408
|
-
createMessage(msgId, convId);
|
|
409
|
-
|
|
410
|
-
insertObservation({
|
|
411
|
-
conversationId: convId,
|
|
412
|
-
messageId: msgId,
|
|
413
|
-
role: "user",
|
|
414
|
-
content:
|
|
415
|
-
"User wants to migrate authentication from JWT to session tokens",
|
|
416
|
-
scopeId: "default",
|
|
417
|
-
});
|
|
418
|
-
|
|
419
|
-
const ctx = buildCtx({
|
|
420
|
-
messages: [
|
|
421
|
-
makeUserMessage(
|
|
422
|
-
"Do you remember what we discussed about authentication?",
|
|
423
|
-
),
|
|
424
|
-
],
|
|
425
|
-
});
|
|
426
|
-
const userMsgId = uuid();
|
|
427
|
-
|
|
428
|
-
const result = await prepareMemoryContext(
|
|
429
|
-
ctx,
|
|
430
|
-
"Do you remember what we discussed about authentication?",
|
|
431
|
-
userMsgId,
|
|
432
|
-
abortController.signal,
|
|
433
|
-
onEvent,
|
|
434
|
-
);
|
|
435
|
-
|
|
436
|
-
const lastMsg = result.runMessages[result.runMessages.length - 1];
|
|
437
|
-
const textBlocks = lastMsg.content.filter((b) => b.type === "text");
|
|
438
|
-
const injectedText = textBlocks
|
|
439
|
-
.map((b) => ("text" in b ? b.text : ""))
|
|
440
|
-
.join("\n");
|
|
441
|
-
|
|
442
|
-
// Both blocks should be present
|
|
443
|
-
expect(injectedText).toContain("<memory_brief>");
|
|
444
|
-
expect(injectedText).toContain("Code review session at 4pm");
|
|
445
|
-
expect(injectedText).toContain("</memory_brief>");
|
|
446
|
-
expect(injectedText).toContain("<supporting_recall>");
|
|
447
|
-
expect(injectedText).toContain("authentication");
|
|
448
|
-
expect(injectedText).toContain("</supporting_recall>");
|
|
449
|
-
});
|
|
450
|
-
|
|
451
|
-
test("injects only <supporting_recall> when brief is empty but recall triggers", async () => {
|
|
452
|
-
// No time contexts or open loops, so brief is empty
|
|
453
|
-
const convId = uuid();
|
|
454
|
-
const msgId = uuid();
|
|
455
|
-
createConversation(convId, "Database Planning");
|
|
456
|
-
createMessage(msgId, convId);
|
|
457
|
-
|
|
458
|
-
insertCompactionEpisode({
|
|
459
|
-
scopeId: "default",
|
|
460
|
-
conversationId: convId,
|
|
461
|
-
title: "PostgreSQL Migration",
|
|
462
|
-
summary:
|
|
463
|
-
"Discussed migrating from MySQL to PostgreSQL with a phased approach",
|
|
464
|
-
tokenEstimate: 25,
|
|
465
|
-
startAt: Date.now() - DAY,
|
|
466
|
-
endAt: Date.now() - 12 * HOUR,
|
|
467
|
-
});
|
|
468
|
-
|
|
469
|
-
const ctx = buildCtx({
|
|
470
|
-
messages: [
|
|
471
|
-
makeUserMessage("Do you remember the PostgreSQL migration plan?"),
|
|
472
|
-
],
|
|
473
|
-
});
|
|
474
|
-
const userMsgId = uuid();
|
|
475
|
-
|
|
476
|
-
const result = await prepareMemoryContext(
|
|
477
|
-
ctx,
|
|
478
|
-
"Do you remember the PostgreSQL migration plan?",
|
|
479
|
-
userMsgId,
|
|
480
|
-
abortController.signal,
|
|
481
|
-
onEvent,
|
|
482
|
-
);
|
|
483
|
-
|
|
484
|
-
const lastMsg = result.runMessages[result.runMessages.length - 1];
|
|
485
|
-
const textBlocks = lastMsg.content.filter((b) => b.type === "text");
|
|
486
|
-
const injectedText = textBlocks
|
|
487
|
-
.map((b) => ("text" in b ? b.text : ""))
|
|
488
|
-
.join("\n");
|
|
489
|
-
|
|
490
|
-
// Brief should not be present (empty)
|
|
491
|
-
expect(injectedText).not.toContain("<memory_brief>");
|
|
492
|
-
// Recall should be present
|
|
493
|
-
expect(injectedText).toContain("<supporting_recall>");
|
|
494
|
-
expect(injectedText).toContain("PostgreSQL");
|
|
495
|
-
expect(injectedText).toContain("</supporting_recall>");
|
|
496
|
-
});
|
|
497
|
-
});
|
|
498
|
-
|
|
499
|
-
// ── Disabled-flag fallback ──────────────────────────────────────
|
|
500
|
-
|
|
501
|
-
describe("disabled-flag fallback", () => {
|
|
502
|
-
test("falls back to legacy path when memory.simplified.enabled is false", async () => {
|
|
503
|
-
// Disable the simplified flag
|
|
504
|
-
testConfig = {
|
|
505
|
-
...DEFAULT_CONFIG,
|
|
506
|
-
memory: {
|
|
507
|
-
...DEFAULT_CONFIG.memory,
|
|
508
|
-
enabled: true,
|
|
509
|
-
simplified: {
|
|
510
|
-
...DEFAULT_CONFIG.memory.simplified,
|
|
511
|
-
enabled: false,
|
|
512
|
-
},
|
|
513
|
-
},
|
|
514
|
-
};
|
|
515
|
-
|
|
516
|
-
// The legacy retriever mock throws, so we need to unmock it for
|
|
517
|
-
// this test. Instead, we verify the flag gating by checking the
|
|
518
|
-
// code path via the mock that throws — if the simplified path is
|
|
519
|
-
// correctly bypassed, the legacy path will be invoked.
|
|
520
|
-
const ctx = buildCtx({
|
|
521
|
-
messages: [makeUserMessage("Hello there")],
|
|
522
|
-
});
|
|
523
|
-
const msgId = uuid();
|
|
524
|
-
|
|
525
|
-
// The legacy path calls buildMemoryRecall which we mocked to throw.
|
|
526
|
-
// This confirms the code took the legacy path, not the simplified one.
|
|
527
|
-
let hitLegacyPath = false;
|
|
528
|
-
try {
|
|
529
|
-
await prepareMemoryContext(
|
|
530
|
-
ctx,
|
|
531
|
-
"Hello there",
|
|
532
|
-
msgId,
|
|
533
|
-
abortController.signal,
|
|
534
|
-
onEvent,
|
|
535
|
-
);
|
|
536
|
-
} catch (err) {
|
|
537
|
-
if (
|
|
538
|
-
err instanceof Error &&
|
|
539
|
-
err.message.includes("should not be called in simplified mode")
|
|
540
|
-
) {
|
|
541
|
-
hitLegacyPath = true;
|
|
542
|
-
} else {
|
|
543
|
-
throw err;
|
|
544
|
-
}
|
|
545
|
-
}
|
|
546
|
-
|
|
547
|
-
expect(hitLegacyPath).toBe(true);
|
|
548
|
-
});
|
|
549
|
-
});
|
|
550
|
-
|
|
551
|
-
// ── Gate checks ─────────────────────────────────────────────────
|
|
552
|
-
|
|
553
|
-
describe("gate checks", () => {
|
|
554
|
-
test("skips memory for untrusted actors in simplified mode", async () => {
|
|
555
|
-
const now = Date.now();
|
|
556
|
-
insertTimeContext({
|
|
557
|
-
id: "tc-1",
|
|
558
|
-
summary: "Meeting in 1 hour",
|
|
559
|
-
activeFrom: now - HOUR,
|
|
560
|
-
activeUntil: now + HOUR,
|
|
561
|
-
});
|
|
562
|
-
|
|
563
|
-
const ctx = buildCtx({
|
|
564
|
-
trustClass: "unknown",
|
|
565
|
-
messages: [makeUserMessage("What are my meetings?")],
|
|
566
|
-
});
|
|
567
|
-
const msgId = uuid();
|
|
568
|
-
|
|
569
|
-
const result = await prepareMemoryContext(
|
|
570
|
-
ctx,
|
|
571
|
-
"What are my meetings?",
|
|
572
|
-
msgId,
|
|
573
|
-
abortController.signal,
|
|
574
|
-
onEvent,
|
|
575
|
-
);
|
|
576
|
-
|
|
577
|
-
// Should return unmodified messages (no memory injection)
|
|
578
|
-
expect(result.runMessages).toEqual(ctx.messages);
|
|
579
|
-
expect(result.recall.enabled).toBe(false);
|
|
580
|
-
});
|
|
581
|
-
|
|
582
|
-
test("skips memory for tool-result-only turns in simplified mode", async () => {
|
|
583
|
-
const now = Date.now();
|
|
584
|
-
insertTimeContext({
|
|
585
|
-
id: "tc-1",
|
|
586
|
-
summary: "Important deadline",
|
|
587
|
-
activeFrom: now - HOUR,
|
|
588
|
-
activeUntil: now + HOUR,
|
|
589
|
-
});
|
|
590
|
-
|
|
591
|
-
const toolResultMsg: Message = {
|
|
592
|
-
role: "user",
|
|
593
|
-
content: [
|
|
594
|
-
{
|
|
595
|
-
type: "tool_result",
|
|
596
|
-
tool_use_id: "tool-1",
|
|
597
|
-
content: "tool output",
|
|
598
|
-
},
|
|
599
|
-
],
|
|
600
|
-
};
|
|
601
|
-
const ctx = buildCtx({ messages: [toolResultMsg] });
|
|
602
|
-
const msgId = uuid();
|
|
603
|
-
|
|
604
|
-
const result = await prepareMemoryContext(
|
|
605
|
-
ctx,
|
|
606
|
-
"",
|
|
607
|
-
msgId,
|
|
608
|
-
abortController.signal,
|
|
609
|
-
onEvent,
|
|
610
|
-
);
|
|
611
|
-
|
|
612
|
-
// Should return unmodified messages
|
|
613
|
-
expect(result.runMessages).toEqual(ctx.messages);
|
|
614
|
-
});
|
|
615
|
-
});
|
|
616
|
-
});
|