@vellumai/assistant 0.5.16 → 0.6.0
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 +1 -1
- package/Dockerfile +0 -3
- package/knip.json +2 -1
- package/openapi.yaml +660 -80
- package/package.json +1 -1
- package/src/__tests__/actor-token-service.test.ts +68 -0
- package/src/__tests__/agent-loop.test.ts +0 -32
- package/src/__tests__/always-loaded-tools-guard.test.ts +2 -2
- package/src/__tests__/anthropic-provider.test.ts +57 -3
- package/src/__tests__/app-compiler.test.ts +120 -0
- package/src/__tests__/assistant-feature-flags-integration.test.ts +2 -2
- package/src/__tests__/call-conversation-messages.test.ts +2 -6
- package/src/__tests__/call-domain.test.ts +2 -6
- package/src/__tests__/call-pointer-messages.test.ts +2 -14
- package/src/__tests__/call-recovery.test.ts +2 -6
- package/src/__tests__/call-routes-http.test.ts +2 -6
- package/src/__tests__/call-store.test.ts +2 -6
- package/src/__tests__/cancel-resolves-conversation-key.test.ts +2 -6
- package/src/__tests__/canonical-guardian-store.test.ts +2 -6
- package/src/__tests__/channel-delivery-store.test.ts +2 -6
- package/src/__tests__/channel-retry-sweep.test.ts +2 -6
- package/src/__tests__/checker.test.ts +25 -3
- package/src/__tests__/clawhub.test.ts +54 -24
- package/src/__tests__/cli-command-risk-guard.test.ts +14 -0
- package/src/__tests__/cli-memory.test.ts +74 -69
- package/src/__tests__/config-schema.test.ts +1 -1
- package/src/__tests__/config-set-platform-guard.test.ts +302 -0
- package/src/__tests__/confirmation-request-guardian-bridge.test.ts +2 -6
- package/src/__tests__/contacts-tools.test.ts +31 -0
- package/src/__tests__/context-overflow-reducer.test.ts +86 -0
- package/src/__tests__/context-token-estimator.test.ts +175 -10
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +9 -0
- package/src/__tests__/conversation-agent-loop.test.ts +9 -0
- package/src/__tests__/conversation-attachments.test.ts +2 -6
- package/src/__tests__/conversation-attention-store.test.ts +2 -6
- package/src/__tests__/conversation-clear-safety.test.ts +2 -6
- package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +4 -10
- package/src/__tests__/conversation-disk-view-integration.test.ts +2 -6
- package/src/__tests__/conversation-disk-view.test.ts +2 -6
- package/src/__tests__/conversation-error.test.ts +33 -2
- package/src/__tests__/conversation-fork-crud.test.ts +2 -6
- package/src/__tests__/conversation-history-web-search.test.ts +5 -0
- package/src/__tests__/conversation-load-history-repair.test.ts +5 -1
- package/src/__tests__/conversation-media-retry.test.ts +91 -0
- package/src/__tests__/conversation-starter-routes.test.ts +20 -11
- package/src/__tests__/conversation-store.test.ts +2 -6
- package/src/__tests__/conversation-usage.test.ts +2 -6
- package/src/__tests__/conversation-wipe.test.ts +11 -408
- package/src/__tests__/credential-execution-feature-gates.test.ts +3 -3
- package/src/__tests__/credential-execution-shell-lockdown.test.ts +2 -2
- package/src/__tests__/credential-security-e2e.test.ts +2 -0
- package/src/__tests__/followup-tools.test.ts +2 -6
- package/src/__tests__/graph-extraction-event-date.test.ts +186 -0
- package/src/__tests__/guardian-action-conversation-turn.test.ts +2 -6
- package/src/__tests__/guardian-action-followup-executor.test.ts +2 -6
- package/src/__tests__/guardian-action-followup-store.test.ts +2 -6
- package/src/__tests__/guardian-action-grant-mint-consume.test.ts +2 -6
- package/src/__tests__/guardian-action-late-reply.test.ts +2 -6
- package/src/__tests__/guardian-action-store.test.ts +2 -6
- package/src/__tests__/guardian-binding-drift-heal.test.ts +2 -6
- package/src/__tests__/guardian-decision-primitive-canonical.test.ts +8 -8
- package/src/__tests__/guardian-dispatch.test.ts +2 -6
- package/src/__tests__/guardian-grant-minting.test.ts +2 -14
- package/src/__tests__/guardian-principal-id-roundtrip.test.ts +2 -6
- package/src/__tests__/guardian-routing-invariants.test.ts +192 -6
- package/src/__tests__/guardian-routing-state.test.ts +2 -6
- package/src/__tests__/guardian-verification-voice-binding.test.ts +2 -6
- package/src/__tests__/inbound-invite-redemption.test.ts +2 -6
- package/src/__tests__/injection-block.test.ts +154 -0
- package/src/__tests__/install-meta.test.ts +506 -0
- package/src/__tests__/install-skill-routing.test.ts +292 -0
- package/src/__tests__/invite-redemption-service.test.ts +2 -6
- package/src/__tests__/invite-routes-http.test.ts +2 -6
- package/src/__tests__/jobs-store-qdrant-breaker.test.ts +2 -14
- package/src/__tests__/list-messages-attachments.test.ts +2 -6
- package/src/__tests__/llm-context-route-provider.test.ts +2 -6
- package/src/__tests__/llm-request-log-turn-query.test.ts +2 -6
- package/src/__tests__/llm-usage-store.test.ts +2 -6
- package/src/__tests__/log-export-workspace.test.ts +2 -6
- package/src/__tests__/managed-store.test.ts +38 -11
- package/src/__tests__/memory-jobs-worker-backoff.test.ts +2 -8
- package/src/__tests__/memory-recall-log-store.test.ts +2 -6
- package/src/__tests__/memory-upsert-concurrency.test.ts +4 -112
- package/src/__tests__/non-member-access-request.test.ts +2 -6
- package/src/__tests__/notification-guardian-path.test.ts +2 -6
- package/src/__tests__/oauth-cli.test.ts +364 -2
- package/src/__tests__/oauth2-gateway-transport.test.ts +18 -3
- package/src/__tests__/outlook-attachments.test.ts +301 -0
- package/src/__tests__/outlook-automation-tools.test.ts +425 -0
- package/src/__tests__/outlook-categories.test.ts +212 -0
- package/src/__tests__/outlook-client-automation.test.ts +246 -0
- package/src/__tests__/outlook-compose-tools.test.ts +325 -0
- package/src/__tests__/outlook-declutter-tools.test.ts +585 -0
- package/src/__tests__/outlook-email-watcher.test.ts +322 -0
- package/src/__tests__/outlook-follow-up.test.ts +196 -0
- package/src/__tests__/outlook-messaging-provider.test.ts +498 -3
- package/src/__tests__/outlook-trash.test.ts +77 -0
- package/src/__tests__/outlook-unsubscribe.test.ts +250 -0
- package/src/__tests__/platform-callback-registration.test.ts +4 -4
- package/src/__tests__/playbook-execution.test.ts +76 -80
- package/src/__tests__/playbook-tools.test.ts +5 -7
- package/src/__tests__/provider-error-scenarios.test.ts +21 -0
- package/src/__tests__/rebuild-index-graph-nodes.test.ts +273 -0
- package/src/__tests__/registry.test.ts +2 -2
- package/src/__tests__/require-fresh-approval.test.ts +64 -2
- package/src/__tests__/runtime-events-sse-parity.test.ts +2 -6
- package/src/__tests__/runtime-events-sse.test.ts +2 -6
- package/src/__tests__/schedule-store.test.ts +2 -6
- package/src/__tests__/schedule-tools.test.ts +2 -6
- package/src/__tests__/scheduler-recurrence.test.ts +1 -5
- package/src/__tests__/scoped-approval-grants.test.ts +2 -6
- package/src/__tests__/scoped-grant-security-matrix.test.ts +2 -6
- package/src/__tests__/search-skills-unified.test.ts +421 -0
- package/src/__tests__/secret-onetime-send.test.ts +2 -0
- package/src/__tests__/send-endpoint-busy.test.ts +2 -6
- package/src/__tests__/sequence-store.test.ts +2 -6
- package/src/__tests__/server-history-render.test.ts +2 -6
- package/src/__tests__/skill-feature-flags-integration.test.ts +38 -31
- package/src/__tests__/skill-feature-flags.test.ts +6 -6
- package/src/__tests__/skill-load-feature-flag.test.ts +11 -11
- package/src/__tests__/skill-memory.test.ts +140 -98
- package/src/__tests__/skills-uninstall.test.ts +2 -2
- package/src/__tests__/skills.test.ts +1 -1
- package/src/__tests__/slack-inbound-verification.test.ts +2 -6
- package/src/__tests__/task-compiler.test.ts +2 -6
- package/src/__tests__/task-management-tools.test.ts +2 -6
- package/src/__tests__/task-memory-cleanup.test.ts +173 -229
- package/src/__tests__/task-runner.test.ts +2 -6
- package/src/__tests__/task-scheduler.test.ts +2 -6
- package/src/__tests__/test-preload.ts +3 -0
- package/src/__tests__/tool-approval-handler.test.ts +2 -6
- package/src/__tests__/tool-grant-request-escalation.test.ts +2 -6
- package/src/__tests__/tool-side-effects-slack-dm.test.ts +276 -0
- package/src/__tests__/trust-store.test.ts +1 -1
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +2 -6
- package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +2 -6
- package/src/__tests__/trusted-contact-multichannel.test.ts +2 -6
- package/src/__tests__/trusted-contact-verification.test.ts +2 -6
- package/src/__tests__/turn-boundary-resolution.test.ts +2 -6
- package/src/__tests__/usage-cache-backfill-migration.test.ts +1 -6
- package/src/__tests__/usage-routes.test.ts +2 -6
- package/src/__tests__/verification-control-plane-policy.test.ts +0 -2
- package/src/__tests__/voice-invite-redemption.test.ts +2 -6
- package/src/__tests__/voice-scoped-grant-consumer.test.ts +2 -6
- package/src/__tests__/voice-session-bridge.test.ts +2 -6
- package/src/__tests__/volume-security-guard.test.ts +2 -0
- package/src/__tests__/workspace-lifecycle.test.ts +29 -1
- package/src/__tests__/workspace-migration-009-backfill-conversation-disk-view.test.ts +2 -6
- package/src/__tests__/workspace-migration-013-repair-conversation-disk-view.test.ts +2 -6
- package/src/__tests__/workspace-migration-026-backfill-install-meta.test.ts +558 -0
- package/src/__tests__/workspace-policy.test.ts +1 -1
- package/src/agent/attachments.ts +7 -2
- package/src/agent/image-optimize.ts +165 -0
- package/src/agent/loop.ts +1 -15
- package/src/bundler/app-compiler.ts +179 -2
- package/src/bundler/package-resolver.ts +3 -5
- package/src/cli/__tests__/notifications.test.ts +1 -2
- package/src/cli/cli-memory.ts +67 -64
- package/src/cli/commands/avatar.ts +3 -3
- package/src/cli/commands/config.ts +26 -13
- package/src/cli/commands/doctor.ts +2 -2
- package/src/cli/commands/memory.ts +41 -55
- package/src/cli/commands/oauth/__tests__/connect.test.ts +2 -2
- package/src/cli/commands/oauth/__tests__/disconnect.test.ts +2 -2
- package/src/cli/commands/oauth/__tests__/mode.test.ts +8 -1
- package/src/cli/commands/oauth/__tests__/status.test.ts +2 -2
- package/src/cli/commands/oauth/connect.ts +11 -6
- package/src/cli/commands/oauth/mode.ts +7 -0
- package/src/cli/commands/oauth/shared.ts +39 -3
- package/src/cli/commands/platform/__tests__/connect.test.ts +1 -1
- package/src/cli/commands/platform/__tests__/disconnect.test.ts +1 -1
- package/src/cli/commands/platform/__tests__/status.test.ts +5 -5
- package/src/cli/commands/platform/index.ts +16 -16
- package/src/cli/commands/skills.ts +88 -16
- package/src/cli/commands/trust.ts +2 -2
- package/src/cli/lib/daemon-credential-client.ts +2 -3
- package/src/config/bundled-skills/acp/TOOLS.json +1 -1
- package/src/config/bundled-skills/contacts/SKILL.md +0 -1
- package/src/config/bundled-skills/contacts/TOOLS.json +0 -8
- package/src/config/bundled-skills/contacts/tools/contact-upsert.ts +0 -4
- package/src/config/bundled-skills/gmail/SKILL.md +2 -10
- package/src/config/bundled-skills/google-calendar/SKILL.md +1 -9
- package/src/config/bundled-skills/messaging/SKILL.md +10 -18
- package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +40 -33
- package/src/config/bundled-skills/outlook/SKILL.md +189 -0
- package/src/config/bundled-skills/outlook/TOOLS.json +530 -0
- package/src/config/bundled-skills/outlook/tools/outlook-attachments.ts +85 -0
- package/src/config/bundled-skills/outlook/tools/outlook-categories.ts +77 -0
- package/src/config/bundled-skills/outlook/tools/outlook-draft.ts +84 -0
- package/src/config/bundled-skills/outlook/tools/outlook-follow-up.ts +94 -0
- package/src/config/bundled-skills/outlook/tools/outlook-forward.ts +49 -0
- package/src/config/bundled-skills/outlook/tools/outlook-outreach-scan.ts +237 -0
- package/src/config/bundled-skills/outlook/tools/outlook-rules.ts +161 -0
- package/src/config/bundled-skills/outlook/tools/outlook-send-draft.ts +32 -0
- package/src/config/bundled-skills/outlook/tools/outlook-sender-digest.ts +272 -0
- package/src/config/bundled-skills/outlook/tools/outlook-trash.ts +29 -0
- package/src/config/bundled-skills/outlook/tools/outlook-unsubscribe.ts +129 -0
- package/src/config/bundled-skills/outlook/tools/outlook-vacation.ts +87 -0
- package/src/config/bundled-skills/outlook/tools/shared.ts +20 -0
- package/src/config/bundled-skills/outlook-calendar/SKILL.md +51 -0
- package/src/config/bundled-skills/outlook-calendar/TOOLS.json +221 -0
- package/src/config/bundled-skills/outlook-calendar/calendar-client.ts +252 -0
- package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-check-availability.ts +53 -0
- package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-create-event.ts +74 -0
- package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-get-event.ts +18 -0
- package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-list-events.ts +46 -0
- package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-rsvp.ts +36 -0
- package/src/config/bundled-skills/outlook-calendar/tools/shared.ts +17 -0
- package/src/config/bundled-skills/outlook-calendar/types.ts +120 -0
- package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +47 -40
- package/src/config/bundled-skills/playbooks/tools/playbook-delete.ts +16 -29
- package/src/config/bundled-skills/playbooks/tools/playbook-list.ts +16 -18
- package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +39 -47
- package/src/config/bundled-skills/slack/SKILL.md +1 -7
- package/src/config/bundled-tool-registry.ts +56 -4
- package/src/config/env-registry.ts +15 -8
- package/src/config/feature-flag-registry.json +21 -124
- package/src/config/schemas/platform.ts +8 -0
- package/src/config/schemas/timeouts.ts +1 -1
- package/src/config/skills.ts +18 -7
- package/src/context/token-estimator.ts +25 -18
- package/src/context/window-manager.ts +6 -2
- package/src/credential-execution/process-manager.ts +3 -1
- package/src/daemon/context-overflow-reducer.ts +46 -2
- package/src/daemon/conversation-agent-loop-handlers.ts +123 -82
- package/src/daemon/conversation-agent-loop.ts +96 -61
- package/src/daemon/conversation-error.ts +31 -8
- package/src/daemon/conversation-lifecycle.ts +33 -0
- package/src/daemon/conversation-media-retry.ts +85 -7
- package/src/daemon/conversation-notifiers.ts +4 -1
- package/src/daemon/conversation-runtime-assembly.ts +5 -0
- package/src/daemon/conversation.ts +41 -2
- package/src/daemon/daemon-control.ts +8 -2
- package/src/daemon/handlers/shared.ts +22 -12
- package/src/daemon/handlers/skills.ts +416 -202
- package/src/daemon/lifecycle.ts +40 -1
- package/src/daemon/main.ts +5 -1
- package/src/daemon/message-types/conversations.ts +4 -1
- package/src/daemon/message-types/messages.ts +3 -1
- package/src/daemon/message-types/skills.ts +97 -36
- package/src/daemon/providers-setup.ts +5 -0
- package/src/daemon/server.ts +11 -2
- package/src/daemon/tool-side-effects.ts +27 -5
- package/src/heartbeat/heartbeat-service.ts +1 -0
- package/src/hooks/cli.ts +2 -2
- package/src/hooks/runner.ts +15 -38
- package/src/inbound/platform-callback-registration.ts +14 -14
- package/src/memory/admin.ts +11 -45
- package/src/memory/conversation-bootstrap.ts +2 -0
- package/src/memory/conversation-crud.ts +242 -348
- package/src/memory/conversation-group-migration.ts +157 -0
- package/src/memory/conversation-queries.ts +4 -2
- package/src/memory/db-init.ts +30 -3
- package/src/memory/embed.ts +73 -0
- package/src/memory/embedding-backend.ts +8 -14
- package/src/memory/embedding-runtime-manager.ts +12 -114
- package/src/memory/fingerprint.ts +2 -2
- package/src/memory/graph/bootstrap.ts +512 -0
- package/src/memory/graph/capability-seed.ts +297 -0
- package/src/memory/graph/consolidation.ts +691 -0
- package/src/memory/graph/conversation-graph-memory.ts +630 -0
- package/src/memory/graph/decay.test.ts +208 -0
- package/src/memory/graph/decay.ts +195 -0
- package/src/memory/graph/extraction-job.ts +69 -0
- package/src/memory/graph/extraction.test.ts +936 -0
- package/src/memory/graph/extraction.ts +1254 -0
- package/src/memory/graph/graph-search.ts +266 -0
- package/src/memory/graph/image-ref-utils.ts +29 -0
- package/src/memory/graph/injection.test.ts +513 -0
- package/src/memory/graph/injection.ts +439 -0
- package/src/memory/graph/inspect.ts +534 -0
- package/src/memory/graph/narrative.ts +267 -0
- package/src/memory/graph/pattern-scan.ts +269 -0
- package/src/memory/graph/retriever.ts +1008 -0
- package/src/memory/graph/scoring.test.ts +548 -0
- package/src/memory/graph/scoring.ts +232 -0
- package/src/memory/graph/serendipity.ts +65 -0
- package/src/memory/graph/store.test.ts +1050 -0
- package/src/memory/graph/store.ts +699 -0
- package/src/memory/graph/tool-handlers.ts +426 -0
- package/src/memory/graph/tools.ts +141 -0
- package/src/memory/graph/triggers.test.ts +487 -0
- package/src/memory/graph/triggers.ts +223 -0
- package/src/memory/graph/types.ts +271 -0
- package/src/memory/group-crud.ts +191 -0
- package/src/memory/indexer.ts +37 -19
- package/src/memory/job-handlers/cleanup.ts +0 -53
- package/src/memory/job-handlers/conversation-starters.ts +91 -53
- package/src/memory/job-handlers/embedding.ts +5 -31
- package/src/memory/job-handlers/index-maintenance.ts +23 -11
- package/src/memory/job-handlers/summarization.ts +32 -17
- package/src/memory/job-utils.ts +1 -1
- package/src/memory/jobs-store.ts +50 -70
- package/src/memory/jobs-worker.ts +147 -112
- package/src/memory/message-content.ts +1 -0
- package/src/memory/migrations/202-memory-graph-tables.ts +130 -0
- package/src/memory/migrations/203-drop-memory-items-tables.ts +23 -0
- package/src/memory/migrations/204-rename-memory-graph-type-values.ts +46 -0
- package/src/memory/migrations/205-memory-graph-image-refs.ts +11 -0
- package/src/memory/migrations/index.ts +4 -0
- package/src/memory/migrations/registry.ts +8 -0
- package/src/memory/qdrant-client.ts +44 -17
- package/src/memory/schema/index.ts +1 -0
- package/src/memory/schema/memory-graph.ts +139 -0
- package/src/memory/search/semantic.ts +47 -91
- package/src/memory/task-memory-cleanup.ts +28 -50
- package/src/messaging/providers/outlook/adapter.ts +8 -1
- package/src/messaging/providers/outlook/client.ts +299 -0
- package/src/messaging/providers/outlook/types.ts +118 -0
- package/src/notifications/adapters/macos.ts +1 -0
- package/src/notifications/copy-composer.ts +9 -0
- package/src/notifications/signal.ts +16 -0
- package/src/oauth/seed-providers.ts +2 -1
- package/src/permissions/checker.ts +24 -3
- package/src/permissions/defaults.ts +4 -4
- package/src/permissions/workspace-policy.ts +1 -1
- package/src/playbooks/playbook-compiler.ts +19 -18
- package/src/playbooks/types.ts +4 -3
- package/src/prompts/system-prompt.ts +3 -29
- package/src/providers/anthropic/client.ts +47 -19
- package/src/providers/gemini/client.ts +1 -1
- package/src/providers/openai/client.ts +1 -1
- package/src/providers/registry.ts +1 -1
- package/src/providers/retry.ts +19 -3
- package/src/runtime/actor-trust-resolver.ts +5 -1
- package/src/runtime/auth/route-policy.ts +7 -0
- package/src/runtime/guardian-reply-router.ts +5 -1
- package/src/runtime/http-server.ts +23 -3
- package/src/runtime/middleware/auth.ts +20 -0
- package/src/runtime/routes/attachment-routes.test.ts +106 -0
- package/src/runtime/routes/attachment-routes.ts +106 -16
- package/src/runtime/routes/brain-graph-routes.ts +21 -22
- package/src/runtime/routes/btw-routes.ts +8 -0
- package/src/runtime/routes/conversation-management-routes.ts +2 -0
- package/src/runtime/routes/conversation-starter-routes.ts +2 -2
- package/src/runtime/routes/debug-routes.ts +1 -1
- package/src/runtime/routes/global-search-routes.ts +21 -19
- package/src/runtime/routes/group-routes.ts +207 -0
- package/src/runtime/routes/guardian-action-routes.ts +21 -10
- package/src/runtime/routes/guardian-bootstrap-routes.ts +23 -19
- package/src/runtime/routes/inbound-message-handler.ts +19 -0
- package/src/runtime/routes/inbound-stages/guardian-activation-intercept.test.ts +292 -0
- package/src/runtime/routes/inbound-stages/guardian-activation-intercept.ts +207 -0
- package/src/runtime/routes/memory-item-routes.test.ts +2 -14
- package/src/runtime/routes/memory-item-routes.ts +341 -388
- package/src/runtime/routes/schedule-routes.ts +2 -0
- package/src/runtime/routes/skills-routes.ts +103 -37
- package/src/runtime/routes/work-items-routes.test.ts +2 -6
- package/src/schedule/scheduler.ts +8 -1
- package/src/security/oauth2.ts +1 -1
- package/src/security/secure-keys.ts +4 -8
- package/src/shared/provider-env-vars.ts +19 -0
- package/src/skills/catalog-cache.ts +5 -0
- package/src/skills/catalog-install.ts +15 -14
- package/src/skills/clawhub.ts +134 -154
- package/src/skills/install-meta.ts +208 -0
- package/src/skills/managed-store.ts +27 -16
- package/src/skills/skill-memory.ts +152 -77
- package/src/skills/skillssh-registry.ts +19 -17
- package/src/tasks/task-runner.ts +3 -1
- package/src/telemetry/usage-telemetry-reporter.test.ts +3 -5
- package/src/tools/browser/runtime-check.ts +3 -1
- package/src/tools/memory/register.ts +63 -46
- package/src/tools/permission-checker.ts +7 -1
- package/src/tools/shared/filesystem/image-read.ts +22 -85
- package/src/tools/terminal/safe-env.ts +1 -0
- package/src/tools/tool-manifest.ts +3 -3
- package/src/util/browser.ts +25 -10
- package/src/util/bun-runtime.ts +172 -0
- package/src/watcher/providers/outlook-calendar.ts +343 -0
- package/src/watcher/providers/outlook.ts +198 -0
- package/src/workspace/migrations/025-remove-oauth-app-setup-skills.ts +76 -0
- package/src/workspace/migrations/026-backfill-install-meta.ts +325 -0
- package/src/workspace/migrations/027-remove-orphaned-optimized-images-cache.ts +42 -0
- package/src/workspace/migrations/registry.ts +6 -0
- package/src/__tests__/context-memory-e2e.test.ts +0 -415
- package/src/__tests__/journal-context.test.ts +0 -268
- package/src/__tests__/memory-context-benchmark.benchmark.test.ts +0 -297
- package/src/__tests__/memory-lifecycle-e2e.test.ts +0 -459
- package/src/__tests__/memory-query-builder.test.ts +0 -59
- package/src/__tests__/memory-recall-quality.test.ts +0 -1046
- package/src/__tests__/memory-regressions.experimental.test.ts +0 -629
- package/src/__tests__/memory-regressions.test.ts +0 -3696
- package/src/__tests__/memory-retrieval.benchmark.test.ts +0 -295
- package/src/daemon/conversation-memory.ts +0 -207
- package/src/memory/conversation-starters-cadence.ts +0 -74
- package/src/memory/items-extractor.ts +0 -860
- package/src/memory/job-handlers/batch-extraction.ts +0 -753
- package/src/memory/job-handlers/extraction.ts +0 -40
- package/src/memory/job-handlers/journal-carry-forward.test.ts +0 -355
- package/src/memory/job-handlers/journal-carry-forward.ts +0 -255
- package/src/memory/journal-memory.ts +0 -224
- package/src/memory/query-builder.ts +0 -47
- package/src/memory/query-expansion.ts +0 -83
- package/src/memory/retriever.test.ts +0 -1592
- package/src/memory/retriever.ts +0 -1331
- package/src/memory/search/formatting.test.ts +0 -140
- package/src/memory/search/formatting.ts +0 -262
- package/src/memory/search/mmr.ts +0 -139
- package/src/memory/search/ranking.ts +0 -15
- package/src/memory/search/staleness.ts +0 -40
- package/src/memory/search/tier-classifier.ts +0 -18
- package/src/memory/search/types.ts +0 -121
- package/src/prompts/journal-context.ts +0 -154
- package/src/tools/memory/definitions.ts +0 -69
- package/src/tools/memory/handlers.test.ts +0 -562
- package/src/tools/memory/handlers.ts +0 -434
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { beforeEach, describe, expect, mock, test } from "bun:test";
|
|
2
2
|
|
|
3
3
|
mock.module("../util/logger.js", () => ({
|
|
4
4
|
getLogger: () =>
|
|
@@ -15,22 +15,17 @@ import {
|
|
|
15
15
|
getMessages,
|
|
16
16
|
wipeConversation,
|
|
17
17
|
} from "../memory/conversation-crud.js";
|
|
18
|
-
import { getDb, initializeDb
|
|
18
|
+
import { getDb, initializeDb } from "../memory/db.js";
|
|
19
19
|
import { enqueueMemoryJob } from "../memory/jobs-store.js";
|
|
20
20
|
|
|
21
21
|
// Initialize db once before all tests
|
|
22
22
|
initializeDb();
|
|
23
23
|
|
|
24
|
-
afterAll(() => {
|
|
25
|
-
resetDb();
|
|
26
|
-
});
|
|
27
|
-
|
|
28
24
|
describe("wipeConversation", () => {
|
|
29
25
|
beforeEach(() => {
|
|
30
26
|
const db = getDb();
|
|
31
|
-
db.run(`DELETE FROM
|
|
27
|
+
db.run(`DELETE FROM memory_graph_nodes`);
|
|
32
28
|
db.run(`DELETE FROM memory_segments`);
|
|
33
|
-
db.run(`DELETE FROM memory_items`);
|
|
34
29
|
db.run(`DELETE FROM memory_summaries`);
|
|
35
30
|
db.run(`DELETE FROM memory_embeddings`);
|
|
36
31
|
db.run(`DELETE FROM memory_jobs`);
|
|
@@ -52,237 +47,6 @@ describe("wipeConversation", () => {
|
|
|
52
47
|
expect(getMessages(conv.id)).toEqual([]);
|
|
53
48
|
});
|
|
54
49
|
|
|
55
|
-
test("restores explicitly superseded memory items", async () => {
|
|
56
|
-
const convA = createConversation("conversation A");
|
|
57
|
-
const msgA = await addMessage(convA.id, "user", "I like blue");
|
|
58
|
-
|
|
59
|
-
const convB = createConversation("conversation B");
|
|
60
|
-
const msgB = await addMessage(convB.id, "user", "I like red");
|
|
61
|
-
|
|
62
|
-
const db = getDb();
|
|
63
|
-
const now = Date.now();
|
|
64
|
-
|
|
65
|
-
// Insert itemA: active preference about color
|
|
66
|
-
db.run(
|
|
67
|
-
`INSERT INTO memory_items (id, status, kind, subject, statement, confidence, fingerprint, scope_id, first_seen_at, last_seen_at)
|
|
68
|
-
VALUES ('itemA', 'active', 'preference', 'color', 'likes blue', 0.8, 'fp-a', 'default', ${now}, ${now})`,
|
|
69
|
-
);
|
|
70
|
-
|
|
71
|
-
// Insert itemB: active preference about color, supersedes itemA
|
|
72
|
-
db.run(
|
|
73
|
-
`INSERT INTO memory_items (id, status, kind, subject, statement, confidence, fingerprint, scope_id, supersedes, first_seen_at, last_seen_at)
|
|
74
|
-
VALUES ('itemB', 'active', 'preference', 'color', 'likes red', 0.9, 'fp-b', 'default', 'itemA', ${now}, ${now})`,
|
|
75
|
-
);
|
|
76
|
-
|
|
77
|
-
// Mark itemA as superseded by itemB
|
|
78
|
-
db.run(
|
|
79
|
-
`UPDATE memory_items SET status = 'superseded', superseded_by = 'itemB' WHERE id = 'itemA'`,
|
|
80
|
-
);
|
|
81
|
-
|
|
82
|
-
// Link itemA to convA's message, itemB to convB's message
|
|
83
|
-
db.run(
|
|
84
|
-
`INSERT INTO memory_item_sources (memory_item_id, message_id, created_at) VALUES ('itemA', '${msgA.id}', ${now})`,
|
|
85
|
-
);
|
|
86
|
-
db.run(
|
|
87
|
-
`INSERT INTO memory_item_sources (memory_item_id, message_id, created_at) VALUES ('itemB', '${msgB.id}', ${now})`,
|
|
88
|
-
);
|
|
89
|
-
|
|
90
|
-
const result = wipeConversation(convB.id);
|
|
91
|
-
|
|
92
|
-
// itemA should be restored to active with superseded_by cleared
|
|
93
|
-
const raw = (
|
|
94
|
-
getDb() as unknown as {
|
|
95
|
-
$client: import("bun:sqlite").Database;
|
|
96
|
-
}
|
|
97
|
-
).$client;
|
|
98
|
-
const itemARow = raw
|
|
99
|
-
.query(
|
|
100
|
-
"SELECT status, superseded_by FROM memory_items WHERE id = 'itemA'",
|
|
101
|
-
)
|
|
102
|
-
.get() as { status: string; superseded_by: string | null } | null;
|
|
103
|
-
expect(itemARow).not.toBeNull();
|
|
104
|
-
expect(itemARow!.status).toBe("active");
|
|
105
|
-
expect(itemARow!.superseded_by).toBeNull();
|
|
106
|
-
|
|
107
|
-
// itemB should no longer exist (orphaned and deleted by deleteConversation)
|
|
108
|
-
const itemBRow = (
|
|
109
|
-
getDb() as unknown as {
|
|
110
|
-
$client: import("bun:sqlite").Database;
|
|
111
|
-
}
|
|
112
|
-
).$client
|
|
113
|
-
.query("SELECT * FROM memory_items WHERE id = 'itemB'")
|
|
114
|
-
.get();
|
|
115
|
-
expect(itemBRow).toBeNull();
|
|
116
|
-
|
|
117
|
-
expect(result.unsupersededItemIds).toContain("itemA");
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
test("does not restore superseded items when superseding item has other sources", async () => {
|
|
121
|
-
const convA = createConversation("conversation A");
|
|
122
|
-
const msgA = await addMessage(convA.id, "user", "I like red in A");
|
|
123
|
-
|
|
124
|
-
const convB = createConversation("conversation B");
|
|
125
|
-
const msgB = await addMessage(convB.id, "user", "I like red in B");
|
|
126
|
-
|
|
127
|
-
const db = getDb();
|
|
128
|
-
const now = Date.now();
|
|
129
|
-
|
|
130
|
-
// Insert itemOld (will be superseded)
|
|
131
|
-
db.run(
|
|
132
|
-
`INSERT INTO memory_items (id, status, kind, subject, statement, confidence, fingerprint, scope_id, first_seen_at, last_seen_at)
|
|
133
|
-
VALUES ('itemOld', 'active', 'preference', 'color', 'likes blue', 0.8, 'fp-old', 'default', ${now}, ${now})`,
|
|
134
|
-
);
|
|
135
|
-
|
|
136
|
-
// Insert itemNew (supersedes itemOld)
|
|
137
|
-
db.run(
|
|
138
|
-
`INSERT INTO memory_items (id, status, kind, subject, statement, confidence, fingerprint, scope_id, supersedes, first_seen_at, last_seen_at)
|
|
139
|
-
VALUES ('itemNew', 'active', 'preference', 'color', 'likes red', 0.9, 'fp-new', 'default', 'itemOld', ${now}, ${now})`,
|
|
140
|
-
);
|
|
141
|
-
|
|
142
|
-
// Mark itemOld as superseded
|
|
143
|
-
db.run(
|
|
144
|
-
`UPDATE memory_items SET status = 'superseded', superseded_by = 'itemNew' WHERE id = 'itemOld'`,
|
|
145
|
-
);
|
|
146
|
-
|
|
147
|
-
// Link itemNew to BOTH conversations
|
|
148
|
-
db.run(
|
|
149
|
-
`INSERT INTO memory_item_sources (memory_item_id, message_id, created_at) VALUES ('itemNew', '${msgA.id}', ${now})`,
|
|
150
|
-
);
|
|
151
|
-
db.run(
|
|
152
|
-
`INSERT INTO memory_item_sources (memory_item_id, message_id, created_at) VALUES ('itemNew', '${msgB.id}', ${now})`,
|
|
153
|
-
);
|
|
154
|
-
|
|
155
|
-
wipeConversation(convA.id);
|
|
156
|
-
|
|
157
|
-
const raw = (
|
|
158
|
-
getDb() as unknown as {
|
|
159
|
-
$client: import("bun:sqlite").Database;
|
|
160
|
-
}
|
|
161
|
-
).$client;
|
|
162
|
-
|
|
163
|
-
// itemOld should still be superseded because itemNew has another source (convB)
|
|
164
|
-
const itemOldRow = raw
|
|
165
|
-
.query("SELECT status FROM memory_items WHERE id = 'itemOld'")
|
|
166
|
-
.get() as { status: string } | null;
|
|
167
|
-
expect(itemOldRow).not.toBeNull();
|
|
168
|
-
expect(itemOldRow!.status).toBe("superseded");
|
|
169
|
-
|
|
170
|
-
// itemNew should still exist (has source from convB)
|
|
171
|
-
const itemNewRow = raw
|
|
172
|
-
.query("SELECT * FROM memory_items WHERE id = 'itemNew'")
|
|
173
|
-
.get();
|
|
174
|
-
expect(itemNewRow).not.toBeNull();
|
|
175
|
-
});
|
|
176
|
-
|
|
177
|
-
test("restores orphaned subject-match superseded items", async () => {
|
|
178
|
-
const convB = createConversation("conversation B");
|
|
179
|
-
const msgB = await addMessage(convB.id, "user", "I use vim");
|
|
180
|
-
|
|
181
|
-
const db = getDb();
|
|
182
|
-
const now = Date.now();
|
|
183
|
-
|
|
184
|
-
// Insert itemOld: superseded with no superseded_by link
|
|
185
|
-
db.run(
|
|
186
|
-
`INSERT INTO memory_items (id, status, kind, subject, statement, confidence, fingerprint, scope_id, first_seen_at, last_seen_at)
|
|
187
|
-
VALUES ('itemOld', 'superseded', 'preference', 'editor', 'uses emacs', 0.7, 'fp-old', 'default', ${now}, ${now})`,
|
|
188
|
-
);
|
|
189
|
-
|
|
190
|
-
// Insert itemNew: active, same kind/subject/scope_id
|
|
191
|
-
db.run(
|
|
192
|
-
`INSERT INTO memory_items (id, status, kind, subject, statement, confidence, fingerprint, scope_id, first_seen_at, last_seen_at)
|
|
193
|
-
VALUES ('itemNew', 'active', 'preference', 'editor', 'uses vim', 0.9, 'fp-new', 'default', ${now}, ${now})`,
|
|
194
|
-
);
|
|
195
|
-
|
|
196
|
-
// Link itemNew to convB's message
|
|
197
|
-
db.run(
|
|
198
|
-
`INSERT INTO memory_item_sources (memory_item_id, message_id, created_at) VALUES ('itemNew', '${msgB.id}', ${now})`,
|
|
199
|
-
);
|
|
200
|
-
|
|
201
|
-
wipeConversation(convB.id);
|
|
202
|
-
|
|
203
|
-
const raw = (
|
|
204
|
-
getDb() as unknown as {
|
|
205
|
-
$client: import("bun:sqlite").Database;
|
|
206
|
-
}
|
|
207
|
-
).$client;
|
|
208
|
-
|
|
209
|
-
// itemOld should now be active (restored as orphaned subject-match superseded item)
|
|
210
|
-
const itemOldRow = raw
|
|
211
|
-
.query("SELECT status FROM memory_items WHERE id = 'itemOld'")
|
|
212
|
-
.get() as { status: string } | null;
|
|
213
|
-
expect(itemOldRow).not.toBeNull();
|
|
214
|
-
expect(itemOldRow!.status).toBe("active");
|
|
215
|
-
});
|
|
216
|
-
|
|
217
|
-
test("does not restore superseded items from unrelated conversations", async () => {
|
|
218
|
-
// convA has an item that superseded an older item — convA was previously
|
|
219
|
-
// deleted via regular deleteConversation, leaving the old item superseded
|
|
220
|
-
// with superseded_by = NULL. When we later wipe convB, Step F should NOT
|
|
221
|
-
// restore that unrelated item.
|
|
222
|
-
const convA = createConversation("conversation A");
|
|
223
|
-
const _msgA = await addMessage(convA.id, "user", "I use dark theme");
|
|
224
|
-
|
|
225
|
-
const convB = createConversation("conversation B");
|
|
226
|
-
const msgB = await addMessage(convB.id, "user", "I use vim");
|
|
227
|
-
|
|
228
|
-
const db = getDb();
|
|
229
|
-
const now = Date.now();
|
|
230
|
-
|
|
231
|
-
// unrelatedOld: superseded item from an old conversation (e.g. "uses light theme")
|
|
232
|
-
// Its superseder was deleted in a prior deleteConversation, leaving
|
|
233
|
-
// superseded_by = NULL.
|
|
234
|
-
db.run(
|
|
235
|
-
`INSERT INTO memory_items (id, status, kind, subject, statement, confidence, fingerprint, scope_id, first_seen_at, last_seen_at)
|
|
236
|
-
VALUES ('unrelatedOld', 'superseded', 'preference', 'theme', 'uses light theme', 0.7, 'fp-unrelated', 'default', ${now}, ${now})`,
|
|
237
|
-
);
|
|
238
|
-
|
|
239
|
-
// convA's active item that superseded unrelatedOld — we simulate the
|
|
240
|
-
// case where convA was already deleted, leaving unrelatedOld with
|
|
241
|
-
// superseded_by = NULL and no active replacement.
|
|
242
|
-
// (We don't actually insert the superseder — just leave unrelatedOld
|
|
243
|
-
// as a superseded item with no superseded_by and no active match.)
|
|
244
|
-
|
|
245
|
-
// convB's items — itemOld is superseded by itemNew (subject: editor)
|
|
246
|
-
db.run(
|
|
247
|
-
`INSERT INTO memory_items (id, status, kind, subject, statement, confidence, fingerprint, scope_id, first_seen_at, last_seen_at)
|
|
248
|
-
VALUES ('editorOld', 'superseded', 'preference', 'editor', 'uses emacs', 0.7, 'fp-editor-old', 'default', ${now}, ${now})`,
|
|
249
|
-
);
|
|
250
|
-
db.run(
|
|
251
|
-
`INSERT INTO memory_items (id, status, kind, subject, statement, confidence, fingerprint, scope_id, first_seen_at, last_seen_at)
|
|
252
|
-
VALUES ('editorNew', 'active', 'preference', 'editor', 'uses vim', 0.9, 'fp-editor-new', 'default', ${now}, ${now})`,
|
|
253
|
-
);
|
|
254
|
-
db.run(
|
|
255
|
-
`INSERT INTO memory_item_sources (memory_item_id, message_id, created_at) VALUES ('editorNew', '${msgB.id}', ${now})`,
|
|
256
|
-
);
|
|
257
|
-
|
|
258
|
-
const result = wipeConversation(convB.id);
|
|
259
|
-
|
|
260
|
-
const raw = (
|
|
261
|
-
getDb() as unknown as {
|
|
262
|
-
$client: import("bun:sqlite").Database;
|
|
263
|
-
}
|
|
264
|
-
).$client;
|
|
265
|
-
|
|
266
|
-
// editorOld SHOULD be restored (its kind+subject matches an orphaned item from convB)
|
|
267
|
-
const editorOldRow = raw
|
|
268
|
-
.query("SELECT status FROM memory_items WHERE id = 'editorOld'")
|
|
269
|
-
.get() as { status: string } | null;
|
|
270
|
-
expect(editorOldRow).not.toBeNull();
|
|
271
|
-
expect(editorOldRow!.status).toBe("active");
|
|
272
|
-
|
|
273
|
-
// unrelatedOld should NOT be restored — it was superseded by a different
|
|
274
|
-
// conversation's item (theme, not editor) and has nothing to do with convB
|
|
275
|
-
const unrelatedOldRow = raw
|
|
276
|
-
.query("SELECT status FROM memory_items WHERE id = 'unrelatedOld'")
|
|
277
|
-
.get() as { status: string } | null;
|
|
278
|
-
expect(unrelatedOldRow).not.toBeNull();
|
|
279
|
-
expect(unrelatedOldRow!.status).toBe("superseded");
|
|
280
|
-
|
|
281
|
-
// Only editorOld should be in the unsuperseded list, not unrelatedOld
|
|
282
|
-
expect(result.unsupersededItemIds).toContain("editorOld");
|
|
283
|
-
expect(result.unsupersededItemIds).not.toContain("unrelatedOld");
|
|
284
|
-
});
|
|
285
|
-
|
|
286
50
|
test("deletes conversation summaries", async () => {
|
|
287
51
|
const conv = createConversation("test");
|
|
288
52
|
await addMessage(conv.id, "user", "hello");
|
|
@@ -378,52 +142,14 @@ describe("wipeConversation", () => {
|
|
|
378
142
|
expect(result.deletedSummaryIds).toEqual([]);
|
|
379
143
|
expect(result.cancelledJobCount).toBe(0);
|
|
380
144
|
});
|
|
381
|
-
|
|
382
|
-
test("does not affect other conversations", async () => {
|
|
383
|
-
const convA = createConversation("conversation A");
|
|
384
|
-
await addMessage(convA.id, "user", "message in A");
|
|
385
|
-
|
|
386
|
-
const convB = createConversation("conversation B");
|
|
387
|
-
const msgB = await addMessage(convB.id, "user", "message in B");
|
|
388
|
-
|
|
389
|
-
const db = getDb();
|
|
390
|
-
const now = Date.now();
|
|
391
|
-
|
|
392
|
-
// Insert a memory item sourced from convB's message
|
|
393
|
-
db.run(
|
|
394
|
-
`INSERT INTO memory_items (id, status, kind, subject, statement, confidence, fingerprint, scope_id, first_seen_at, last_seen_at)
|
|
395
|
-
VALUES ('itemB', 'active', 'fact', 'test', 'test fact', 0.8, 'fp-b', 'default', ${now}, ${now})`,
|
|
396
|
-
);
|
|
397
|
-
db.run(
|
|
398
|
-
`INSERT INTO memory_item_sources (memory_item_id, message_id, created_at) VALUES ('itemB', '${msgB.id}', ${now})`,
|
|
399
|
-
);
|
|
400
|
-
|
|
401
|
-
wipeConversation(convA.id);
|
|
402
|
-
|
|
403
|
-
// convB should still exist
|
|
404
|
-
expect(getConversation(convB.id)).not.toBeNull();
|
|
405
|
-
expect(getMessages(convB.id)).toHaveLength(1);
|
|
406
|
-
|
|
407
|
-
// convB's memory item should still exist
|
|
408
|
-
const raw = (
|
|
409
|
-
getDb() as unknown as {
|
|
410
|
-
$client: import("bun:sqlite").Database;
|
|
411
|
-
}
|
|
412
|
-
).$client;
|
|
413
|
-
const itemBRow = raw
|
|
414
|
-
.query("SELECT * FROM memory_items WHERE id = 'itemB'")
|
|
415
|
-
.get();
|
|
416
|
-
expect(itemBRow).not.toBeNull();
|
|
417
|
-
});
|
|
418
145
|
});
|
|
419
146
|
|
|
420
147
|
describe("deleteConversation — private scope cleanup", () => {
|
|
421
148
|
beforeEach(() => {
|
|
422
149
|
const db = getDb();
|
|
423
150
|
db.run(`DELETE FROM conversation_starters`);
|
|
424
|
-
db.run(`DELETE FROM
|
|
151
|
+
db.run(`DELETE FROM memory_graph_nodes`);
|
|
425
152
|
db.run(`DELETE FROM memory_segments`);
|
|
426
|
-
db.run(`DELETE FROM memory_items`);
|
|
427
153
|
db.run(`DELETE FROM memory_summaries`);
|
|
428
154
|
db.run(`DELETE FROM memory_embeddings`);
|
|
429
155
|
db.run(`DELETE FROM memory_jobs`);
|
|
@@ -433,37 +159,6 @@ describe("deleteConversation — private scope cleanup", () => {
|
|
|
433
159
|
db.run(`DELETE FROM conversations`);
|
|
434
160
|
});
|
|
435
161
|
|
|
436
|
-
test("sourceless items cleaned up", () => {
|
|
437
|
-
const conv = createConversation({ conversationType: "private" });
|
|
438
|
-
const scopeId = conv.memoryScopeId;
|
|
439
|
-
const now = Date.now();
|
|
440
|
-
|
|
441
|
-
const raw = (
|
|
442
|
-
getDb() as unknown as {
|
|
443
|
-
$client: import("bun:sqlite").Database;
|
|
444
|
-
}
|
|
445
|
-
).$client;
|
|
446
|
-
|
|
447
|
-
// Insert a memory item with matching scopeId but no memory_item_sources
|
|
448
|
-
raw
|
|
449
|
-
.query(
|
|
450
|
-
`INSERT INTO memory_items (id, status, kind, subject, statement, confidence, fingerprint, scope_id, first_seen_at, last_seen_at)
|
|
451
|
-
VALUES ('priv-item-1', 'active', 'fact', 'test', 'test fact', 0.8, 'fp-priv-1', ?, ?, ?)`,
|
|
452
|
-
)
|
|
453
|
-
.run(scopeId, now, now);
|
|
454
|
-
|
|
455
|
-
const result = deleteConversation(conv.id);
|
|
456
|
-
|
|
457
|
-
// Item should be gone
|
|
458
|
-
const itemRow = raw
|
|
459
|
-
.query("SELECT * FROM memory_items WHERE id = 'priv-item-1'")
|
|
460
|
-
.get();
|
|
461
|
-
expect(itemRow).toBeNull();
|
|
462
|
-
|
|
463
|
-
// Its ID should be in orphanedItemIds
|
|
464
|
-
expect(result.orphanedItemIds).toContain("priv-item-1");
|
|
465
|
-
});
|
|
466
|
-
|
|
467
162
|
test("summaries cleaned up", () => {
|
|
468
163
|
const conv = createConversation({ conversationType: "private" });
|
|
469
164
|
const scopeId = conv.memoryScopeId;
|
|
@@ -496,71 +191,15 @@ describe("deleteConversation — private scope cleanup", () => {
|
|
|
496
191
|
});
|
|
497
192
|
|
|
498
193
|
test("standard conversations unaffected", async () => {
|
|
499
|
-
|
|
500
|
-
const
|
|
194
|
+
// Create a standard conversation and a private one
|
|
195
|
+
const standardConv = createConversation("standard test");
|
|
196
|
+
const privateConv = createConversation({ conversationType: "private" });
|
|
501
197
|
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
$client: import("bun:sqlite").Database;
|
|
505
|
-
}
|
|
506
|
-
).$client;
|
|
198
|
+
// Delete the private conversation
|
|
199
|
+
deleteConversation(privateConv.id);
|
|
507
200
|
|
|
508
|
-
//
|
|
509
|
-
|
|
510
|
-
.query(
|
|
511
|
-
`INSERT INTO memory_items (id, status, kind, subject, statement, confidence, fingerprint, scope_id, first_seen_at, last_seen_at)
|
|
512
|
-
VALUES ('default-item-1', 'active', 'fact', 'test', 'test fact', 0.8, 'fp-default', 'default', ?, ?)`,
|
|
513
|
-
)
|
|
514
|
-
.run(now, now);
|
|
515
|
-
|
|
516
|
-
deleteConversation(conv.id);
|
|
517
|
-
|
|
518
|
-
// Default-scope items should still exist
|
|
519
|
-
const itemRow = raw
|
|
520
|
-
.query("SELECT * FROM memory_items WHERE id = 'default-item-1'")
|
|
521
|
-
.get();
|
|
522
|
-
expect(itemRow).not.toBeNull();
|
|
523
|
-
});
|
|
524
|
-
|
|
525
|
-
test("embeddings cleaned up", () => {
|
|
526
|
-
const conv = createConversation({ conversationType: "private" });
|
|
527
|
-
const scopeId = conv.memoryScopeId;
|
|
528
|
-
const now = Date.now();
|
|
529
|
-
|
|
530
|
-
const raw = (
|
|
531
|
-
getDb() as unknown as {
|
|
532
|
-
$client: import("bun:sqlite").Database;
|
|
533
|
-
}
|
|
534
|
-
).$client;
|
|
535
|
-
|
|
536
|
-
// Insert a memory item with matching scopeId
|
|
537
|
-
raw
|
|
538
|
-
.query(
|
|
539
|
-
`INSERT INTO memory_items (id, status, kind, subject, statement, confidence, fingerprint, scope_id, first_seen_at, last_seen_at)
|
|
540
|
-
VALUES ('priv-item-emb', 'active', 'fact', 'test', 'test fact', 0.8, 'fp-priv-emb', ?, ?, ?)`,
|
|
541
|
-
)
|
|
542
|
-
.run(scopeId, now, now);
|
|
543
|
-
|
|
544
|
-
// Insert a corresponding embedding
|
|
545
|
-
raw
|
|
546
|
-
.query(
|
|
547
|
-
`INSERT INTO memory_embeddings (id, target_type, target_id, provider, model, dimensions, created_at, updated_at)
|
|
548
|
-
VALUES ('emb-priv-item', 'item', 'priv-item-emb', 'test', 'test', 384, ?, ?)`,
|
|
549
|
-
)
|
|
550
|
-
.run(now, now);
|
|
551
|
-
|
|
552
|
-
deleteConversation(conv.id);
|
|
553
|
-
|
|
554
|
-
// Both item and embedding should be deleted
|
|
555
|
-
const itemRow = raw
|
|
556
|
-
.query("SELECT * FROM memory_items WHERE id = 'priv-item-emb'")
|
|
557
|
-
.get();
|
|
558
|
-
expect(itemRow).toBeNull();
|
|
559
|
-
|
|
560
|
-
const embeddingRow = raw
|
|
561
|
-
.query("SELECT * FROM memory_embeddings WHERE id = 'emb-priv-item'")
|
|
562
|
-
.get();
|
|
563
|
-
expect(embeddingRow).toBeNull();
|
|
201
|
+
// Standard conversation should still exist
|
|
202
|
+
expect(getConversation(standardConv.id)).not.toBeNull();
|
|
564
203
|
});
|
|
565
204
|
|
|
566
205
|
test("conversationStarters cleaned up", () => {
|
|
@@ -604,40 +243,4 @@ describe("deleteConversation — private scope cleanup", () => {
|
|
|
604
243
|
.get();
|
|
605
244
|
expect(defaultStarterRow).not.toBeNull();
|
|
606
245
|
});
|
|
607
|
-
|
|
608
|
-
test("no duplicate IDs", async () => {
|
|
609
|
-
const conv = createConversation({ conversationType: "private" });
|
|
610
|
-
const scopeId = conv.memoryScopeId;
|
|
611
|
-
const msg = await addMessage(conv.id, "user", "hello");
|
|
612
|
-
const now = Date.now();
|
|
613
|
-
|
|
614
|
-
const raw = (
|
|
615
|
-
getDb() as unknown as {
|
|
616
|
-
$client: import("bun:sqlite").Database;
|
|
617
|
-
}
|
|
618
|
-
).$client;
|
|
619
|
-
|
|
620
|
-
// Insert a memory item with the private scopeId AND a source linking to the message
|
|
621
|
-
raw
|
|
622
|
-
.query(
|
|
623
|
-
`INSERT INTO memory_items (id, status, kind, subject, statement, confidence, fingerprint, scope_id, first_seen_at, last_seen_at)
|
|
624
|
-
VALUES ('priv-item-dup', 'active', 'fact', 'test', 'test fact', 0.8, 'fp-priv-dup', ?, ?, ?)`,
|
|
625
|
-
)
|
|
626
|
-
.run(scopeId, now, now);
|
|
627
|
-
|
|
628
|
-
raw
|
|
629
|
-
.query(
|
|
630
|
-
`INSERT INTO memory_item_sources (memory_item_id, message_id, created_at) VALUES ('priv-item-dup', ?, ?)`,
|
|
631
|
-
)
|
|
632
|
-
.run(msg.id, now);
|
|
633
|
-
|
|
634
|
-
const result = deleteConversation(conv.id);
|
|
635
|
-
|
|
636
|
-
// The item ID should appear exactly once in orphanedItemIds (caught by
|
|
637
|
-
// source-based cleanup, not double-counted by scope sweep).
|
|
638
|
-
const count = result.orphanedItemIds.filter(
|
|
639
|
-
(id) => id === "priv-item-dup",
|
|
640
|
-
).length;
|
|
641
|
-
expect(count).toBe(1);
|
|
642
|
-
});
|
|
643
246
|
});
|
|
@@ -180,7 +180,7 @@ describe("CES flags do not affect unrelated flags", () => {
|
|
|
180
180
|
expect(isAssistantFeatureFlagEnabled("browser", config)).toBe(true);
|
|
181
181
|
});
|
|
182
182
|
|
|
183
|
-
test("enabling all CES flags does not change
|
|
183
|
+
test("enabling all CES flags does not change sounds flag (defaultEnabled: true)", () => {
|
|
184
184
|
const overrides: Record<string, boolean> = {};
|
|
185
185
|
for (const key of ALL_CES_FLAG_KEYS) {
|
|
186
186
|
overrides[key] = true;
|
|
@@ -188,7 +188,7 @@ describe("CES flags do not affect unrelated flags", () => {
|
|
|
188
188
|
_setOverridesForTesting(overrides);
|
|
189
189
|
const config = makeConfig();
|
|
190
190
|
|
|
191
|
-
//
|
|
192
|
-
expect(isAssistantFeatureFlagEnabled("
|
|
191
|
+
// sounds defaults to true in the registry and should stay true
|
|
192
|
+
expect(isAssistantFeatureFlagEnabled("sounds", config)).toBe(true);
|
|
193
193
|
});
|
|
194
194
|
});
|
|
@@ -33,8 +33,8 @@ describe("trust class categorization for CES lockdown", () => {
|
|
|
33
33
|
expect(isUntrustedTrustClass("unknown")).toBe(true);
|
|
34
34
|
});
|
|
35
35
|
|
|
36
|
-
test("undefined is
|
|
37
|
-
expect(isUntrustedTrustClass(undefined)).toBe(
|
|
36
|
+
test("undefined is untrusted", () => {
|
|
37
|
+
expect(isUntrustedTrustClass(undefined)).toBe(true);
|
|
38
38
|
});
|
|
39
39
|
});
|
|
40
40
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { beforeEach, describe, expect, mock, test } from "bun:test";
|
|
2
2
|
|
|
3
3
|
mock.module("../util/logger.js", () => ({
|
|
4
4
|
getLogger: () =>
|
|
@@ -16,7 +16,7 @@ mock.module("../config/loader.js", () => ({
|
|
|
16
16
|
|
|
17
17
|
import type { Database } from "bun:sqlite";
|
|
18
18
|
|
|
19
|
-
import { getDb, initializeDb
|
|
19
|
+
import { getDb, initializeDb } from "../memory/db.js";
|
|
20
20
|
import { executeFollowupCreate } from "../tools/followups/followup_create.js";
|
|
21
21
|
import { executeFollowupList } from "../tools/followups/followup_list.js";
|
|
22
22
|
import { executeFollowupResolve } from "../tools/followups/followup_resolve.js";
|
|
@@ -24,10 +24,6 @@ import type { ToolContext } from "../tools/types.js";
|
|
|
24
24
|
|
|
25
25
|
initializeDb();
|
|
26
26
|
|
|
27
|
-
afterAll(() => {
|
|
28
|
-
resetDb();
|
|
29
|
-
});
|
|
30
|
-
|
|
31
27
|
function getRawDb(): Database {
|
|
32
28
|
return (getDb() as unknown as { $client: Database }).$client;
|
|
33
29
|
}
|