@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
|
@@ -12,8 +12,8 @@ const TEST_DIR = process.env.VELLUM_WORKSPACE_DIR!;
|
|
|
12
12
|
|
|
13
13
|
let currentConfig: Record<string, unknown> = {};
|
|
14
14
|
|
|
15
|
-
const DECLARED_SKILL_ID = "
|
|
16
|
-
const DECLARED_FLAG_KEY = "
|
|
15
|
+
const DECLARED_SKILL_ID = "sounds";
|
|
16
|
+
const DECLARED_FLAG_KEY = "sounds";
|
|
17
17
|
|
|
18
18
|
const noopLogger = new Proxy({} as Record<string, unknown>, {
|
|
19
19
|
get: (_target, prop) => (prop === "child" ? () => noopLogger : () => {}),
|
|
@@ -86,8 +86,8 @@ describe("skill_load feature flag enforcement", () => {
|
|
|
86
86
|
test("returns deterministic error for flag OFF skill", async () => {
|
|
87
87
|
writeSkill(
|
|
88
88
|
DECLARED_SKILL_ID,
|
|
89
|
-
"
|
|
90
|
-
"Toggle
|
|
89
|
+
"Sounds",
|
|
90
|
+
"Toggle sounds behavior",
|
|
91
91
|
"Use the feature.",
|
|
92
92
|
);
|
|
93
93
|
writeFileSync(
|
|
@@ -107,8 +107,8 @@ describe("skill_load feature flag enforcement", () => {
|
|
|
107
107
|
test("loads skill normally when flag is ON", async () => {
|
|
108
108
|
writeSkill(
|
|
109
109
|
DECLARED_SKILL_ID,
|
|
110
|
-
"
|
|
111
|
-
"Toggle
|
|
110
|
+
"Sounds",
|
|
111
|
+
"Toggle sounds behavior",
|
|
112
112
|
"Use the feature.",
|
|
113
113
|
);
|
|
114
114
|
writeFileSync(
|
|
@@ -121,14 +121,14 @@ describe("skill_load feature flag enforcement", () => {
|
|
|
121
121
|
const result = await executeSkillLoad({ skill: DECLARED_SKILL_ID });
|
|
122
122
|
|
|
123
123
|
expect(result.isError).toBe(false);
|
|
124
|
-
expect(result.content).toContain("Skill:
|
|
124
|
+
expect(result.content).toContain("Skill: Sounds");
|
|
125
125
|
});
|
|
126
126
|
|
|
127
127
|
test("loads skill when flag key is absent (registry defaults to enabled)", async () => {
|
|
128
128
|
writeSkill(
|
|
129
129
|
DECLARED_SKILL_ID,
|
|
130
|
-
"
|
|
131
|
-
"Toggle
|
|
130
|
+
"Sounds",
|
|
131
|
+
"Toggle sounds behavior",
|
|
132
132
|
"Use the feature.",
|
|
133
133
|
);
|
|
134
134
|
writeFileSync(
|
|
@@ -140,8 +140,8 @@ describe("skill_load feature flag enforcement", () => {
|
|
|
140
140
|
|
|
141
141
|
const result = await executeSkillLoad({ skill: DECLARED_SKILL_ID });
|
|
142
142
|
|
|
143
|
-
//
|
|
143
|
+
// sounds is declared in the registry with defaultEnabled: true
|
|
144
144
|
expect(result.isError).toBe(false);
|
|
145
|
-
expect(result.content).toContain("Skill:
|
|
145
|
+
expect(result.content).toContain("Skill: Sounds");
|
|
146
146
|
});
|
|
147
147
|
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { rmSync } from "node:fs";
|
|
2
2
|
import { afterAll, beforeEach, describe, expect, mock, test } from "bun:test";
|
|
3
3
|
|
|
4
|
-
import { eq } from "drizzle-orm";
|
|
4
|
+
import { eq, like } from "drizzle-orm";
|
|
5
5
|
|
|
6
6
|
mock.module("../util/logger.js", () => ({
|
|
7
7
|
getLogger: () =>
|
|
@@ -28,6 +28,16 @@ mock.module("../config/skills.js", () => ({
|
|
|
28
28
|
loadSkillCatalog: (..._args: unknown[]) => mockLoadSkillCatalog(),
|
|
29
29
|
}));
|
|
30
30
|
|
|
31
|
+
// Controllable mock for getCachedCatalogSync used by seedCatalogSkillMemories
|
|
32
|
+
let mockGetCachedCatalogSync: () => import("../skills/catalog-install.js").CatalogSkill[] =
|
|
33
|
+
() => [];
|
|
34
|
+
|
|
35
|
+
mock.module("../skills/catalog-cache.js", () => ({
|
|
36
|
+
getCachedCatalogSync: (..._args: unknown[]) => mockGetCachedCatalogSync(),
|
|
37
|
+
getCatalog: async () => mockGetCachedCatalogSync(),
|
|
38
|
+
invalidateCatalogCache: () => {},
|
|
39
|
+
}));
|
|
40
|
+
|
|
31
41
|
// Controllable mock for isAssistantFeatureFlagEnabled used by resolveSkillStates
|
|
32
42
|
let mockIsFeatureFlagEnabled: (key: string) => boolean = () => true;
|
|
33
43
|
|
|
@@ -61,7 +71,7 @@ mock.module("../config/loader.js", () => ({
|
|
|
61
71
|
|
|
62
72
|
import type { SkillSummary } from "../config/skills.js";
|
|
63
73
|
import { getDb, initializeDb, resetDb } from "../memory/db.js";
|
|
64
|
-
import {
|
|
74
|
+
import { memoryGraphNodes, memoryJobs } from "../memory/schema.js";
|
|
65
75
|
import {
|
|
66
76
|
buildCapabilityStatement,
|
|
67
77
|
deleteSkillCapabilityMemory,
|
|
@@ -81,9 +91,8 @@ afterAll(() => {
|
|
|
81
91
|
|
|
82
92
|
function resetTables() {
|
|
83
93
|
const db = getDb();
|
|
84
|
-
db.run("DELETE FROM memory_item_sources");
|
|
85
94
|
db.run("DELETE FROM memory_embeddings");
|
|
86
|
-
db.run("DELETE FROM
|
|
95
|
+
db.run("DELETE FROM memory_graph_nodes");
|
|
87
96
|
db.run("DELETE FROM memory_jobs");
|
|
88
97
|
}
|
|
89
98
|
|
|
@@ -231,59 +240,59 @@ describe("fromSkillSummary", () => {
|
|
|
231
240
|
describe("upsertSkillCapabilityMemory", () => {
|
|
232
241
|
beforeEach(resetTables);
|
|
233
242
|
|
|
234
|
-
test("inserts with correct
|
|
243
|
+
test("inserts with correct type, content, confidence, significance", () => {
|
|
235
244
|
const input = fromSkillSummary(makeSkillSummary());
|
|
236
245
|
upsertSkillCapabilityMemory("test-skill", input);
|
|
237
246
|
|
|
238
247
|
const db = getDb();
|
|
239
|
-
const items = db.select().from(
|
|
248
|
+
const items = db.select().from(memoryGraphNodes).all();
|
|
240
249
|
expect(items).toHaveLength(1);
|
|
241
|
-
expect(items[0].
|
|
242
|
-
expect(items[0].
|
|
250
|
+
expect(items[0].type).toBe("procedural");
|
|
251
|
+
expect(items[0].content).toMatch(/^skill:test-skill\n/);
|
|
243
252
|
expect(items[0].confidence).toBe(1.0);
|
|
244
|
-
expect(items[0].
|
|
245
|
-
expect(items[0].
|
|
253
|
+
expect(items[0].significance).toBe(0.7);
|
|
254
|
+
expect(items[0].fidelity).toBe("vivid");
|
|
246
255
|
expect(items[0].scopeId).toBe("default");
|
|
247
256
|
|
|
248
|
-
// Should also enqueue an
|
|
257
|
+
// Should also enqueue an embed_graph_node job
|
|
249
258
|
const jobs = db.select().from(memoryJobs).all();
|
|
250
259
|
expect(jobs).toHaveLength(1);
|
|
251
|
-
expect(jobs[0].type).toBe("
|
|
260
|
+
expect(jobs[0].type).toBe("embed_graph_node");
|
|
252
261
|
});
|
|
253
262
|
|
|
254
|
-
test("is idempotent (same entry only touches
|
|
263
|
+
test("is idempotent (same entry only touches lastAccessed)", () => {
|
|
255
264
|
const input = fromSkillSummary(makeSkillSummary());
|
|
256
265
|
upsertSkillCapabilityMemory("test-skill", input);
|
|
257
266
|
|
|
258
267
|
const db = getDb();
|
|
259
|
-
const before = db.select().from(
|
|
268
|
+
const before = db.select().from(memoryGraphNodes).all();
|
|
260
269
|
expect(before).toHaveLength(1);
|
|
261
|
-
const
|
|
270
|
+
const originalLastAccessed = before[0].lastAccessed;
|
|
262
271
|
|
|
263
272
|
// Upsert again
|
|
264
273
|
upsertSkillCapabilityMemory("test-skill", input);
|
|
265
274
|
|
|
266
|
-
const after = db.select().from(
|
|
275
|
+
const after = db.select().from(memoryGraphNodes).all();
|
|
267
276
|
expect(after).toHaveLength(1);
|
|
268
|
-
//
|
|
269
|
-
expect(after[0].
|
|
270
|
-
expect(after[0].
|
|
277
|
+
// Same content, so only lastAccessed changes
|
|
278
|
+
expect(after[0].content).toBe(before[0].content);
|
|
279
|
+
expect(after[0].lastAccessed).toBeGreaterThanOrEqual(originalLastAccessed);
|
|
271
280
|
|
|
272
281
|
// Should NOT enqueue a second embed job (only 1 from initial insert)
|
|
273
282
|
const jobs = db.select().from(memoryJobs).all();
|
|
274
283
|
expect(jobs).toHaveLength(1);
|
|
275
284
|
});
|
|
276
285
|
|
|
277
|
-
test("updates
|
|
286
|
+
test("updates content when description changes", () => {
|
|
278
287
|
const input = fromSkillSummary(
|
|
279
288
|
makeSkillSummary({ description: "Original description" }),
|
|
280
289
|
);
|
|
281
290
|
upsertSkillCapabilityMemory("test-skill", input);
|
|
282
291
|
|
|
283
292
|
const db = getDb();
|
|
284
|
-
const before = db.select().from(
|
|
293
|
+
const before = db.select().from(memoryGraphNodes).all();
|
|
285
294
|
expect(before).toHaveLength(1);
|
|
286
|
-
expect(before[0].
|
|
295
|
+
expect(before[0].content).toContain("Original description");
|
|
287
296
|
|
|
288
297
|
// Change description
|
|
289
298
|
const updatedInput = fromSkillSummary(
|
|
@@ -291,10 +300,10 @@ describe("upsertSkillCapabilityMemory", () => {
|
|
|
291
300
|
);
|
|
292
301
|
upsertSkillCapabilityMemory("test-skill", updatedInput);
|
|
293
302
|
|
|
294
|
-
const after = db.select().from(
|
|
303
|
+
const after = db.select().from(memoryGraphNodes).all();
|
|
295
304
|
expect(after).toHaveLength(1);
|
|
296
|
-
expect(after[0].
|
|
297
|
-
expect(after[0].
|
|
305
|
+
expect(after[0].content).toContain("Updated description");
|
|
306
|
+
expect(after[0].content).not.toBe(before[0].content);
|
|
298
307
|
|
|
299
308
|
// Should enqueue a second embed job
|
|
300
309
|
const jobs = db.select().from(memoryJobs).all();
|
|
@@ -307,13 +316,13 @@ describe("upsertSkillCapabilityMemory", () => {
|
|
|
307
316
|
|
|
308
317
|
const db = getDb();
|
|
309
318
|
// Soft-delete the item
|
|
310
|
-
db.update(
|
|
311
|
-
.set({
|
|
312
|
-
.where(
|
|
319
|
+
db.update(memoryGraphNodes)
|
|
320
|
+
.set({ fidelity: "gone" })
|
|
321
|
+
.where(like(memoryGraphNodes.content, "skill:test-skill\n%"))
|
|
313
322
|
.run();
|
|
314
323
|
|
|
315
|
-
const deleted = db.select().from(
|
|
316
|
-
expect(deleted[0].
|
|
324
|
+
const deleted = db.select().from(memoryGraphNodes).all();
|
|
325
|
+
expect(deleted[0].fidelity).toBe("gone");
|
|
317
326
|
|
|
318
327
|
// Clear jobs from initial insert
|
|
319
328
|
db.run("DELETE FROM memory_jobs");
|
|
@@ -321,14 +330,14 @@ describe("upsertSkillCapabilityMemory", () => {
|
|
|
321
330
|
// Upsert again — should reactivate
|
|
322
331
|
upsertSkillCapabilityMemory("test-skill", input);
|
|
323
332
|
|
|
324
|
-
const reactivated = db.select().from(
|
|
333
|
+
const reactivated = db.select().from(memoryGraphNodes).all();
|
|
325
334
|
expect(reactivated).toHaveLength(1);
|
|
326
|
-
expect(reactivated[0].
|
|
335
|
+
expect(reactivated[0].fidelity).toBe("vivid");
|
|
327
336
|
|
|
328
337
|
// Should enqueue embed job for reactivated item
|
|
329
338
|
const jobs = db.select().from(memoryJobs).all();
|
|
330
339
|
expect(jobs).toHaveLength(1);
|
|
331
|
-
expect(jobs[0].type).toBe("
|
|
340
|
+
expect(jobs[0].type).toBe("embed_graph_node");
|
|
332
341
|
});
|
|
333
342
|
|
|
334
343
|
test("does not throw on DB error", () => {
|
|
@@ -338,9 +347,9 @@ describe("upsertSkillCapabilityMemory", () => {
|
|
|
338
347
|
// dropping the table it reads from. Use a fresh DB without initialization.
|
|
339
348
|
// Instead, verify the try/catch by closing and reopening:
|
|
340
349
|
// resetDb closes the connection; getDb lazily reconnects.
|
|
341
|
-
// We drop the
|
|
350
|
+
// We drop the memory_graph_nodes table to force an error on the next query.
|
|
342
351
|
const db = getDb();
|
|
343
|
-
db.run("DROP TABLE IF EXISTS
|
|
352
|
+
db.run("DROP TABLE IF EXISTS memory_graph_nodes");
|
|
344
353
|
|
|
345
354
|
expect(() => {
|
|
346
355
|
upsertSkillCapabilityMemory(
|
|
@@ -372,15 +381,15 @@ describe("deleteSkillCapabilityMemory", () => {
|
|
|
372
381
|
upsertSkillCapabilityMemory("test-skill", input);
|
|
373
382
|
|
|
374
383
|
const db = getDb();
|
|
375
|
-
const before = db.select().from(
|
|
384
|
+
const before = db.select().from(memoryGraphNodes).all();
|
|
376
385
|
expect(before).toHaveLength(1);
|
|
377
|
-
expect(before[0].
|
|
386
|
+
expect(before[0].fidelity).toBe("vivid");
|
|
378
387
|
|
|
379
388
|
deleteSkillCapabilityMemory("test-skill");
|
|
380
389
|
|
|
381
|
-
const after = db.select().from(
|
|
390
|
+
const after = db.select().from(memoryGraphNodes).all();
|
|
382
391
|
expect(after).toHaveLength(1);
|
|
383
|
-
expect(after[0].
|
|
392
|
+
expect(after[0].fidelity).toBe("gone");
|
|
384
393
|
});
|
|
385
394
|
|
|
386
395
|
test("is no-op for missing item", () => {
|
|
@@ -390,7 +399,7 @@ describe("deleteSkillCapabilityMemory", () => {
|
|
|
390
399
|
}).not.toThrow();
|
|
391
400
|
|
|
392
401
|
const db = getDb();
|
|
393
|
-
const items = db.select().from(
|
|
402
|
+
const items = db.select().from(memoryGraphNodes).all();
|
|
394
403
|
expect(items).toHaveLength(0);
|
|
395
404
|
});
|
|
396
405
|
|
|
@@ -398,7 +407,7 @@ describe("deleteSkillCapabilityMemory", () => {
|
|
|
398
407
|
// Close and reopen DB, then drop the table to force a query error
|
|
399
408
|
resetDb();
|
|
400
409
|
const db = getDb();
|
|
401
|
-
db.run("DROP TABLE IF EXISTS
|
|
410
|
+
db.run("DROP TABLE IF EXISTS memory_graph_nodes");
|
|
402
411
|
|
|
403
412
|
expect(() => {
|
|
404
413
|
deleteSkillCapabilityMemory("test-skill");
|
|
@@ -423,6 +432,10 @@ describe("seedCatalogSkillMemories", () => {
|
|
|
423
432
|
// Reset mocks to defaults
|
|
424
433
|
mockLoadSkillCatalog = () => [];
|
|
425
434
|
mockIsFeatureFlagEnabled = () => true;
|
|
435
|
+
// Default: non-empty cache so pruning is allowed
|
|
436
|
+
mockGetCachedCatalogSync = () => [
|
|
437
|
+
{ id: "_sentinel", name: "_sentinel", description: "" },
|
|
438
|
+
];
|
|
426
439
|
});
|
|
427
440
|
|
|
428
441
|
test("upserts capability memories for all enabled skills", () => {
|
|
@@ -450,21 +463,21 @@ describe("seedCatalogSkillMemories", () => {
|
|
|
450
463
|
const db = getDb();
|
|
451
464
|
const items = db
|
|
452
465
|
.select()
|
|
453
|
-
.from(
|
|
454
|
-
.where(eq(
|
|
466
|
+
.from(memoryGraphNodes)
|
|
467
|
+
.where(eq(memoryGraphNodes.type, "procedural"))
|
|
455
468
|
.all();
|
|
456
469
|
expect(items).toHaveLength(3);
|
|
457
470
|
|
|
458
|
-
const
|
|
459
|
-
expect(
|
|
471
|
+
const contentPrefixes = items.map((i) => i.content.split("\n")[0]).sort();
|
|
472
|
+
expect(contentPrefixes).toEqual([
|
|
460
473
|
"skill:skill-a",
|
|
461
474
|
"skill:skill-b",
|
|
462
475
|
"skill:skill-c",
|
|
463
476
|
]);
|
|
464
477
|
|
|
465
|
-
// All should be
|
|
478
|
+
// All should be vivid
|
|
466
479
|
for (const item of items) {
|
|
467
|
-
expect(item.
|
|
480
|
+
expect(item.fidelity).toBe("vivid");
|
|
468
481
|
}
|
|
469
482
|
});
|
|
470
483
|
|
|
@@ -491,16 +504,16 @@ describe("seedCatalogSkillMemories", () => {
|
|
|
491
504
|
const db = getDb();
|
|
492
505
|
const items = db
|
|
493
506
|
.select()
|
|
494
|
-
.from(
|
|
495
|
-
.where(eq(
|
|
507
|
+
.from(memoryGraphNodes)
|
|
508
|
+
.where(eq(memoryGraphNodes.type, "procedural"))
|
|
496
509
|
.all();
|
|
497
510
|
expect(items).toHaveLength(2);
|
|
498
511
|
|
|
499
|
-
const
|
|
500
|
-
expect(
|
|
512
|
+
const contentPrefixes = items.map((i) => i.content.split("\n")[0]).sort();
|
|
513
|
+
expect(contentPrefixes).toEqual(["skill:bundled-skill", "skill:managed-skill"]);
|
|
501
514
|
|
|
502
515
|
for (const item of items) {
|
|
503
|
-
expect(item.
|
|
516
|
+
expect(item.fidelity).toBe("vivid");
|
|
504
517
|
}
|
|
505
518
|
});
|
|
506
519
|
|
|
@@ -550,14 +563,14 @@ describe("seedCatalogSkillMemories", () => {
|
|
|
550
563
|
const db = getDb();
|
|
551
564
|
const items = db
|
|
552
565
|
.select()
|
|
553
|
-
.from(
|
|
554
|
-
.where(eq(
|
|
566
|
+
.from(memoryGraphNodes)
|
|
567
|
+
.where(eq(memoryGraphNodes.type, "procedural"))
|
|
555
568
|
.all();
|
|
556
569
|
|
|
557
570
|
// Only allowed-bundled and managed-skill should be seeded
|
|
558
571
|
expect(items).toHaveLength(2);
|
|
559
|
-
const
|
|
560
|
-
expect(
|
|
572
|
+
const contentPrefixes = items.map((i) => i.content.split("\n")[0]).sort();
|
|
573
|
+
expect(contentPrefixes).toEqual(["skill:allowed-bundled", "skill:managed-skill"]);
|
|
561
574
|
|
|
562
575
|
// Restore default config mock
|
|
563
576
|
mock.module("../config/loader.js", () => ({
|
|
@@ -594,11 +607,11 @@ describe("seedCatalogSkillMemories", () => {
|
|
|
594
607
|
const db = getDb();
|
|
595
608
|
const beforeItems = db
|
|
596
609
|
.select()
|
|
597
|
-
.from(
|
|
598
|
-
.where(eq(
|
|
610
|
+
.from(memoryGraphNodes)
|
|
611
|
+
.where(eq(memoryGraphNodes.type, "procedural"))
|
|
599
612
|
.all();
|
|
600
613
|
expect(beforeItems).toHaveLength(3);
|
|
601
|
-
expect(beforeItems.every((i) => i.
|
|
614
|
+
expect(beforeItems.every((i) => i.fidelity === "vivid")).toBe(true);
|
|
602
615
|
|
|
603
616
|
// Now seed with only skill-a — skill-b and skill-c should be pruned
|
|
604
617
|
mockLoadSkillCatalog = () => [
|
|
@@ -612,20 +625,20 @@ describe("seedCatalogSkillMemories", () => {
|
|
|
612
625
|
|
|
613
626
|
const afterItems = db
|
|
614
627
|
.select()
|
|
615
|
-
.from(
|
|
616
|
-
.where(eq(
|
|
628
|
+
.from(memoryGraphNodes)
|
|
629
|
+
.where(eq(memoryGraphNodes.type, "procedural"))
|
|
617
630
|
.all();
|
|
618
631
|
expect(afterItems).toHaveLength(3); // still 3 rows, but 2 are soft-deleted
|
|
619
632
|
|
|
620
|
-
const active = afterItems.filter((i) => i.
|
|
621
|
-
const deleted = afterItems.filter((i) => i.
|
|
633
|
+
const active = afterItems.filter((i) => i.fidelity === "vivid");
|
|
634
|
+
const deleted = afterItems.filter((i) => i.fidelity === "gone");
|
|
622
635
|
|
|
623
636
|
expect(active).toHaveLength(1);
|
|
624
|
-
expect(active[0].
|
|
637
|
+
expect(active[0].content).toMatch(/^skill:skill-a\n/);
|
|
625
638
|
|
|
626
639
|
expect(deleted).toHaveLength(2);
|
|
627
|
-
const
|
|
628
|
-
expect(
|
|
640
|
+
const deletedPrefixes = deleted.map((i) => i.content.split("\n")[0]).sort();
|
|
641
|
+
expect(deletedPrefixes).toEqual(["skill:skill-b", "skill:skill-c"]);
|
|
629
642
|
});
|
|
630
643
|
|
|
631
644
|
test("handles empty catalog without errors", () => {
|
|
@@ -636,38 +649,67 @@ describe("seedCatalogSkillMemories", () => {
|
|
|
636
649
|
);
|
|
637
650
|
|
|
638
651
|
const db = getDb();
|
|
639
|
-
const beforeItems = db.select().from(
|
|
652
|
+
const beforeItems = db.select().from(memoryGraphNodes).all();
|
|
640
653
|
expect(beforeItems).toHaveLength(1);
|
|
641
|
-
expect(beforeItems[0].
|
|
654
|
+
expect(beforeItems[0].fidelity).toBe("vivid");
|
|
642
655
|
|
|
643
656
|
// Seed with empty catalog
|
|
644
657
|
mockLoadSkillCatalog = () => [];
|
|
645
658
|
seedCatalogSkillMemories();
|
|
646
659
|
|
|
647
660
|
// The existing skill should be pruned (soft-deleted)
|
|
648
|
-
const afterItems = db.select().from(
|
|
661
|
+
const afterItems = db.select().from(memoryGraphNodes).all();
|
|
662
|
+
expect(afterItems).toHaveLength(1);
|
|
663
|
+
expect(afterItems[0].fidelity).toBe("gone");
|
|
664
|
+
});
|
|
665
|
+
|
|
666
|
+
test("does not prune when catalog cache is empty", () => {
|
|
667
|
+
// Pre-populate a skill
|
|
668
|
+
upsertSkillCapabilityMemory(
|
|
669
|
+
"existing-skill",
|
|
670
|
+
fromSkillSummary(makeSkillSummary({ id: "existing-skill" })),
|
|
671
|
+
);
|
|
672
|
+
|
|
673
|
+
const db = getDb();
|
|
674
|
+
const beforeItems = db.select().from(memoryGraphNodes).all();
|
|
675
|
+
expect(beforeItems).toHaveLength(1);
|
|
676
|
+
expect(beforeItems[0].fidelity).toBe("vivid");
|
|
677
|
+
|
|
678
|
+
// Seed with empty catalog AND empty cache — pruning guard should skip
|
|
679
|
+
mockLoadSkillCatalog = () => [];
|
|
680
|
+
mockGetCachedCatalogSync = () => [];
|
|
681
|
+
seedCatalogSkillMemories();
|
|
682
|
+
|
|
683
|
+
// The existing skill should NOT be pruned because the cache is empty
|
|
684
|
+
const afterItems = db.select().from(memoryGraphNodes).all();
|
|
649
685
|
expect(afterItems).toHaveLength(1);
|
|
650
|
-
expect(afterItems[0].
|
|
686
|
+
expect(afterItems[0].fidelity).toBe("vivid");
|
|
651
687
|
});
|
|
652
688
|
|
|
653
689
|
test("does not prune non-skill capability memories", () => {
|
|
654
690
|
// Pre-insert a non-skill capability memory directly into the DB
|
|
655
691
|
const db = getDb();
|
|
656
692
|
const now = Date.now();
|
|
657
|
-
db.insert(
|
|
693
|
+
db.insert(memoryGraphNodes)
|
|
658
694
|
.values({
|
|
659
695
|
id: "cli-doctor-item",
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
status: "active",
|
|
696
|
+
type: "procedural",
|
|
697
|
+
content: "cli:doctor\nThe doctor command diagnoses issues.",
|
|
698
|
+
fidelity: "vivid",
|
|
664
699
|
confidence: 1.0,
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
sourceType: "extraction",
|
|
700
|
+
significance: 0.7,
|
|
701
|
+
sourceType: "inferred",
|
|
668
702
|
scopeId: "default",
|
|
669
|
-
|
|
670
|
-
|
|
703
|
+
created: now,
|
|
704
|
+
lastAccessed: now,
|
|
705
|
+
lastConsolidated: now,
|
|
706
|
+
emotionalCharge: '{"valence":0,"intensity":0.1,"decayCurve":"linear","decayRate":0.05,"originalIntensity":0.1}',
|
|
707
|
+
stability: 14,
|
|
708
|
+
reinforcementCount: 0,
|
|
709
|
+
lastReinforced: now,
|
|
710
|
+
sourceConversations: "[]",
|
|
711
|
+
narrativeRole: null,
|
|
712
|
+
partOfStory: null,
|
|
671
713
|
})
|
|
672
714
|
.run();
|
|
673
715
|
|
|
@@ -677,11 +719,11 @@ describe("seedCatalogSkillMemories", () => {
|
|
|
677
719
|
|
|
678
720
|
const item = db
|
|
679
721
|
.select()
|
|
680
|
-
.from(
|
|
681
|
-
.where(
|
|
722
|
+
.from(memoryGraphNodes)
|
|
723
|
+
.where(like(memoryGraphNodes.content, "cli:doctor\n%"))
|
|
682
724
|
.get();
|
|
683
725
|
expect(item).toBeDefined();
|
|
684
|
-
expect(item!.
|
|
726
|
+
expect(item!.fidelity).toBe("vivid");
|
|
685
727
|
});
|
|
686
728
|
|
|
687
729
|
test("does not throw when loadSkillCatalog throws", () => {
|
|
@@ -717,14 +759,14 @@ describe("seedCatalogSkillMemories", () => {
|
|
|
717
759
|
const db = getDb();
|
|
718
760
|
const items = db
|
|
719
761
|
.select()
|
|
720
|
-
.from(
|
|
721
|
-
.where(eq(
|
|
762
|
+
.from(memoryGraphNodes)
|
|
763
|
+
.where(eq(memoryGraphNodes.type, "procedural"))
|
|
722
764
|
.all();
|
|
723
765
|
|
|
724
766
|
// Only the unflagged skill should have a capability row
|
|
725
767
|
expect(items).toHaveLength(1);
|
|
726
|
-
expect(items[0].
|
|
727
|
-
expect(items[0].
|
|
768
|
+
expect(items[0].content).toMatch(/^skill:unflagged-skill\n/);
|
|
769
|
+
expect(items[0].fidelity).toBe("vivid");
|
|
728
770
|
});
|
|
729
771
|
|
|
730
772
|
test("prunes pre-existing capability for a skill whose flag becomes disabled", () => {
|
|
@@ -749,11 +791,11 @@ describe("seedCatalogSkillMemories", () => {
|
|
|
749
791
|
const db = getDb();
|
|
750
792
|
const beforeItems = db
|
|
751
793
|
.select()
|
|
752
|
-
.from(
|
|
753
|
-
.where(eq(
|
|
794
|
+
.from(memoryGraphNodes)
|
|
795
|
+
.where(eq(memoryGraphNodes.type, "procedural"))
|
|
754
796
|
.all();
|
|
755
797
|
expect(beforeItems).toHaveLength(2);
|
|
756
|
-
expect(beforeItems.every((i) => i.
|
|
798
|
+
expect(beforeItems.every((i) => i.fidelity === "vivid")).toBe(true);
|
|
757
799
|
|
|
758
800
|
// Now disable the flag — the flagged skill should be pruned
|
|
759
801
|
mockIsFeatureFlagEnabled = (key: string) => key !== "my_gated_feature";
|
|
@@ -761,19 +803,19 @@ describe("seedCatalogSkillMemories", () => {
|
|
|
761
803
|
|
|
762
804
|
const afterItems = db
|
|
763
805
|
.select()
|
|
764
|
-
.from(
|
|
765
|
-
.where(eq(
|
|
806
|
+
.from(memoryGraphNodes)
|
|
807
|
+
.where(eq(memoryGraphNodes.type, "procedural"))
|
|
766
808
|
.all();
|
|
767
809
|
expect(afterItems).toHaveLength(2); // still 2 rows, but one soft-deleted
|
|
768
810
|
|
|
769
|
-
const active = afterItems.filter((i) => i.
|
|
770
|
-
const deleted = afterItems.filter((i) => i.
|
|
811
|
+
const active = afterItems.filter((i) => i.fidelity === "vivid");
|
|
812
|
+
const deleted = afterItems.filter((i) => i.fidelity === "gone");
|
|
771
813
|
|
|
772
814
|
expect(active).toHaveLength(1);
|
|
773
|
-
expect(active[0].
|
|
815
|
+
expect(active[0].content).toMatch(/^skill:unflagged-skill\n/);
|
|
774
816
|
|
|
775
817
|
expect(deleted).toHaveLength(1);
|
|
776
|
-
expect(deleted[0].
|
|
818
|
+
expect(deleted[0].content).toMatch(/^skill:flagged-skill\n/);
|
|
777
819
|
});
|
|
778
820
|
|
|
779
821
|
test("does not throw on DB error during pruning", () => {
|
|
@@ -785,10 +827,10 @@ describe("seedCatalogSkillMemories", () => {
|
|
|
785
827
|
}),
|
|
786
828
|
];
|
|
787
829
|
|
|
788
|
-
// Drop
|
|
830
|
+
// Drop memory_graph_nodes to force a DB error during the prune phase
|
|
789
831
|
resetDb();
|
|
790
832
|
const db = getDb();
|
|
791
|
-
db.run("DROP TABLE IF EXISTS
|
|
833
|
+
db.run("DROP TABLE IF EXISTS memory_graph_nodes");
|
|
792
834
|
|
|
793
835
|
expect(() => seedCatalogSkillMemories()).not.toThrow();
|
|
794
836
|
|
|
@@ -60,7 +60,7 @@ describe("assistant skills uninstall", () => {
|
|
|
60
60
|
|
|
61
61
|
// GIVEN a skill is installed locally
|
|
62
62
|
installFakeSkill("weather");
|
|
63
|
-
writeSkillsIndex("- weather\n-
|
|
63
|
+
writeSkillsIndex("- weather\n- vellum-self-knowledge\n");
|
|
64
64
|
|
|
65
65
|
// WHEN we uninstall the skill
|
|
66
66
|
uninstallSkillLocally("weather");
|
|
@@ -73,7 +73,7 @@ describe("assistant skills uninstall", () => {
|
|
|
73
73
|
expect(index).not.toContain("weather");
|
|
74
74
|
|
|
75
75
|
// AND other skills should remain in the index
|
|
76
|
-
expect(index).toContain("
|
|
76
|
+
expect(index).toContain("vellum-self-knowledge");
|
|
77
77
|
});
|
|
78
78
|
|
|
79
79
|
test("errors when skill is not installed", () => {
|
|
@@ -642,7 +642,7 @@ describe("ingress-dependent setup skills declare public-ingress intentionally",
|
|
|
642
642
|
"utf-8",
|
|
643
643
|
);
|
|
644
644
|
expect(content).toContain("avoid-when:");
|
|
645
|
-
expect(content.toLowerCase()).toContain("managed
|
|
645
|
+
expect(content.toLowerCase()).toContain("platform-managed");
|
|
646
646
|
});
|
|
647
647
|
});
|
|
648
648
|
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* 4. Notify the guardian of the access attempt
|
|
9
9
|
* 5. When the user replies with the code in the DM, verify and activate
|
|
10
10
|
*/
|
|
11
|
-
import {
|
|
11
|
+
import { beforeEach, describe, expect, mock, test } from "bun:test";
|
|
12
12
|
|
|
13
13
|
// ---------------------------------------------------------------------------
|
|
14
14
|
// Test isolation: in-memory SQLite via temp directory
|
|
@@ -56,16 +56,12 @@ mock.module("../runtime/gateway-client.js", () => ({
|
|
|
56
56
|
}));
|
|
57
57
|
|
|
58
58
|
import { createGuardianBinding } from "../contacts/contacts-write.js";
|
|
59
|
-
import { getDb, initializeDb
|
|
59
|
+
import { getDb, initializeDb } from "../memory/db.js";
|
|
60
60
|
import { findActiveSession } from "../runtime/channel-verification-service.js";
|
|
61
61
|
import { handleChannelInbound } from "../runtime/routes/channel-routes.js";
|
|
62
62
|
|
|
63
63
|
initializeDb();
|
|
64
64
|
|
|
65
|
-
afterAll(() => {
|
|
66
|
-
resetDb();
|
|
67
|
-
});
|
|
68
|
-
|
|
69
65
|
// ---------------------------------------------------------------------------
|
|
70
66
|
// Helpers
|
|
71
67
|
// ---------------------------------------------------------------------------
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { beforeEach, describe, expect, test } from "bun:test";
|
|
2
2
|
import { mock } from "bun:test";
|
|
3
3
|
|
|
4
4
|
mock.module("../util/logger.js", () => ({
|
|
@@ -21,7 +21,7 @@ mock.module("./indexer.js", () => ({
|
|
|
21
21
|
|
|
22
22
|
import type { Database } from "bun:sqlite";
|
|
23
23
|
|
|
24
|
-
import { getDb, initializeDb
|
|
24
|
+
import { getDb, initializeDb } from "../memory/db.js";
|
|
25
25
|
import {
|
|
26
26
|
compileTaskFromConversation,
|
|
27
27
|
saveCompiledTask,
|
|
@@ -31,10 +31,6 @@ import { getTask } from "../tasks/task-store.js";
|
|
|
31
31
|
|
|
32
32
|
initializeDb();
|
|
33
33
|
|
|
34
|
-
afterAll(() => {
|
|
35
|
-
resetDb();
|
|
36
|
-
});
|
|
37
|
-
|
|
38
34
|
// ── Helpers ──────────────────────────────────────────────────────────
|
|
39
35
|
|
|
40
36
|
function getRawDb(): Database {
|