@vellumai/assistant 0.4.48 → 0.4.50
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 +26 -35
- package/README.md +5 -26
- package/docs/architecture/integrations.md +45 -41
- package/docs/architecture/keychain-broker.md +3 -3
- package/docs/architecture/memory.md +180 -119
- package/docs/runbook-trusted-contacts.md +3 -8
- package/hook-templates/debug-prompt-logger/hook.json +1 -1
- package/hook-templates/debug-prompt-logger/run.sh +1 -3
- package/package.json +2 -2
- package/src/__tests__/actor-token-service.test.ts +0 -1
- package/src/__tests__/agent-loop.test.ts +3 -1
- package/src/__tests__/anthropic-provider.test.ts +249 -2
- package/src/__tests__/approval-cascade.test.ts +796 -0
- package/src/__tests__/approval-primitive.test.ts +0 -1
- package/src/__tests__/approval-routes-http.test.ts +4 -0
- package/src/__tests__/assistant-attachments.test.ts +12 -34
- package/src/__tests__/assistant-feature-flag-guard.test.ts +0 -23
- package/src/__tests__/assistant-feature-flag-guardrails.test.ts +76 -0
- package/src/__tests__/assistant-feature-flags-integration.test.ts +0 -1
- package/src/__tests__/browser-skill-baseline-tool-payload.test.ts +2 -2
- package/src/__tests__/canonical-guardian-store.test.ts +95 -0
- package/src/__tests__/channel-guardian.test.ts +0 -2
- package/src/__tests__/channel-readiness-routes.test.ts +15 -6
- package/src/__tests__/channel-readiness-service.test.ts +10 -9
- package/src/__tests__/checker.test.ts +13 -20
- package/src/__tests__/computer-use-skill-manifest-regression.test.ts +1 -1
- package/src/__tests__/computer-use-tools.test.ts +2 -19
- package/src/__tests__/config-schema.test.ts +1 -68
- package/src/__tests__/config-watcher.test.ts +0 -1
- package/src/__tests__/confirmation-request-guardian-bridge.test.ts +0 -1
- package/src/__tests__/context-image-dimensions.test.ts +332 -0
- package/src/__tests__/context-memory-e2e.test.ts +11 -100
- package/src/__tests__/context-token-estimator.test.ts +196 -13
- package/src/__tests__/conversation-attention-store.test.ts +0 -1
- package/src/__tests__/conversation-attention-telegram.test.ts +0 -1
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +152 -0
- package/src/__tests__/conversation-routes-slash-commands.test.ts +2 -0
- package/src/__tests__/credential-metadata-store.test.ts +64 -73
- package/src/__tests__/credential-security-e2e.test.ts +1 -0
- package/src/__tests__/credential-security-invariants.test.ts +13 -7
- package/src/__tests__/credential-vault-unit.test.ts +284 -49
- package/src/__tests__/credential-vault.test.ts +150 -16
- package/src/__tests__/credentials-cli.test.ts +71 -0
- package/src/__tests__/cu-unified-flow.test.ts +532 -0
- package/src/__tests__/date-context.test.ts +93 -77
- package/src/__tests__/deterministic-verification-control-plane.test.ts +64 -0
- package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +0 -1
- package/src/__tests__/ephemeral-permissions.test.ts +3 -3
- package/src/__tests__/gateway-only-guard.test.ts +0 -1
- package/src/__tests__/guardian-action-grant-mint-consume.test.ts +0 -1
- package/src/__tests__/guardian-decision-primitive-canonical.test.ts +0 -1
- package/src/__tests__/guardian-routing-invariants.test.ts +93 -1
- package/src/__tests__/guardian-verification-voice-binding.test.ts +0 -1
- package/src/__tests__/handlers-user-message-approval-consumption.test.ts +0 -39
- package/src/__tests__/heartbeat-service.test.ts +0 -1
- package/src/__tests__/history-repair.test.ts +245 -0
- package/src/__tests__/host-cu-proxy.test.ts +791 -0
- package/src/__tests__/host-shell-tool.test.ts +27 -15
- package/src/__tests__/http-user-message-parity.test.ts +2 -0
- package/src/__tests__/ingress-url-consistency.test.ts +14 -21
- package/src/__tests__/integration-status.test.ts +32 -51
- package/src/__tests__/intent-routing.test.ts +0 -1
- package/src/__tests__/invite-redemption-service.test.ts +65 -1
- package/src/__tests__/invite-routes-http.test.ts +10 -9
- package/src/__tests__/keychain-broker-client.test.ts +14 -46
- package/src/__tests__/memory-context-benchmark.benchmark.test.ts +56 -18
- package/src/__tests__/memory-lifecycle-e2e.test.ts +244 -387
- package/src/__tests__/memory-recall-quality.test.ts +244 -407
- package/src/__tests__/memory-regressions.experimental.test.ts +126 -101
- package/src/__tests__/memory-regressions.test.ts +477 -2841
- package/src/__tests__/memory-retrieval.benchmark.test.ts +33 -150
- package/src/__tests__/memory-upsert-concurrency.test.ts +5 -244
- package/src/__tests__/mime-builder.test.ts +28 -0
- package/src/__tests__/native-web-search.test.ts +1 -0
- package/src/__tests__/notification-routing-intent.test.ts +0 -1
- package/src/__tests__/oauth-cli.test.ts +941 -15
- package/src/__tests__/oauth-provider-profiles.test.ts +9 -9
- package/src/__tests__/oauth-scope-policy.test.ts +4 -6
- package/src/__tests__/oauth-store.test.ts +870 -0
- package/src/__tests__/onboarding-starter-tasks.test.ts +0 -1
- package/src/__tests__/provider-error-scenarios.test.ts +0 -1
- package/src/__tests__/provider-streaming.benchmark.test.ts +0 -1
- package/src/__tests__/public-ingress-urls.test.ts +15 -21
- package/src/__tests__/qdrant-collection-migration.test.ts +53 -8
- package/src/__tests__/recording-handler.test.ts +3 -4
- package/src/__tests__/registry.test.ts +2 -3
- package/src/__tests__/relay-server.test.ts +46 -1
- package/src/__tests__/runtime-events-sse.test.ts +55 -7
- package/src/__tests__/schedule-store.test.ts +0 -1
- package/src/__tests__/schedule-tools.test.ts +32 -0
- package/src/__tests__/scheduler-recurrence.test.ts +0 -1
- package/src/__tests__/scoped-approval-grants.test.ts +0 -1
- package/src/__tests__/scoped-grant-security-matrix.test.ts +0 -1
- package/src/__tests__/script-proxy-certs.test.ts +1 -1
- package/src/__tests__/secret-ingress-handler.test.ts +0 -1
- package/src/__tests__/secret-onetime-send.test.ts +1 -0
- package/src/__tests__/secure-keys.test.ts +7 -2
- package/src/__tests__/send-endpoint-busy.test.ts +24 -6
- package/src/__tests__/sequence-store.test.ts +0 -1
- package/src/__tests__/session-abort-tool-results.test.ts +1 -14
- package/src/__tests__/session-agent-loop-overflow.test.ts +1583 -0
- package/src/__tests__/session-agent-loop.test.ts +19 -15
- package/src/__tests__/session-confirmation-signals.test.ts +1 -15
- package/src/__tests__/session-error.test.ts +124 -2
- package/src/__tests__/session-history-web-search.test.ts +918 -0
- package/src/__tests__/session-init.benchmark.test.ts +4 -5
- package/src/__tests__/session-pre-run-repair.test.ts +1 -14
- package/src/__tests__/session-provider-retry-repair.test.ts +25 -28
- package/src/__tests__/session-queue.test.ts +37 -27
- package/src/__tests__/session-runtime-assembly.test.ts +54 -0
- package/src/__tests__/session-slash-known.test.ts +1 -15
- package/src/__tests__/session-slash-queue.test.ts +1 -15
- package/src/__tests__/session-slash-unknown.test.ts +1 -15
- package/src/__tests__/session-workspace-cache-state.test.ts +3 -33
- package/src/__tests__/session-workspace-injection.test.ts +3 -37
- package/src/__tests__/session-workspace-tool-tracking.test.ts +3 -37
- package/src/__tests__/skill-include-graph.test.ts +66 -0
- package/src/__tests__/skill-load-feature-flag.test.ts +0 -1
- package/src/__tests__/skill-load-tool.test.ts +149 -1
- package/src/__tests__/skill-projection-feature-flag.test.ts +0 -1
- package/src/__tests__/skills-install-extract.test.ts +93 -0
- package/src/__tests__/skills-uninstall.test.ts +1 -1
- package/src/__tests__/skills.test.ts +3 -3
- package/src/__tests__/skillssh-registry.test.ts +451 -0
- package/src/__tests__/slack-channel-config.test.ts +67 -3
- package/src/__tests__/slack-share-routes.test.ts +17 -19
- package/src/__tests__/system-prompt.test.ts +0 -1
- package/src/__tests__/telegram-invite-adapter.test.ts +18 -22
- package/src/__tests__/terminal-tools.test.ts +4 -3
- package/src/__tests__/test-support/computer-use-skill-harness.ts +3 -2
- package/src/__tests__/tool-approval-handler.test.ts +0 -1
- package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +0 -1
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +0 -1
- package/src/__tests__/tool-executor-shell-integration.test.ts +0 -1
- package/src/__tests__/tool-executor.test.ts +0 -1
- package/src/__tests__/tool-grant-request-escalation.test.ts +0 -1
- package/src/__tests__/trust-store-pattern-matches.test.ts +29 -0
- package/src/__tests__/trust-store.test.ts +7 -13
- package/src/__tests__/trusted-contact-approval-notifier.test.ts +0 -1
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +0 -1
- package/src/__tests__/twilio-routes.test.ts +0 -16
- package/src/__tests__/verification-control-plane-policy.test.ts +0 -1
- package/src/__tests__/voice-invite-redemption.test.ts +32 -1
- package/src/__tests__/voice-scoped-grant-consumer.test.ts +0 -1
- package/src/agent/ax-tree-compaction.test.ts +286 -0
- package/src/agent/loop.ts +104 -131
- package/src/approvals/AGENTS.md +1 -1
- package/src/approvals/guardian-request-resolvers.ts +14 -2
- package/src/bundler/compiler-tools.ts +66 -2
- package/src/calls/call-domain.ts +133 -6
- package/src/calls/call-store.ts +6 -0
- package/src/calls/relay-server.ts +52 -18
- package/src/calls/relay-setup-router.ts +17 -1
- package/src/calls/twilio-config.ts +3 -8
- package/src/calls/twilio-routes.ts +1 -2
- package/src/calls/types.ts +3 -1
- package/src/calls/voice-ingress-preflight.ts +1 -1
- package/src/cli/commands/browser-relay.ts +18 -12
- package/src/cli/commands/completions.ts +0 -3
- package/src/cli/commands/credentials.ts +101 -15
- package/src/cli/commands/doctor.ts +4 -3
- package/src/cli/commands/mcp.ts +46 -59
- package/src/cli/commands/memory.ts +16 -165
- package/src/cli/commands/oauth/apps.ts +284 -0
- package/src/cli/commands/oauth/connections.ts +633 -0
- package/src/cli/commands/oauth/index.ts +52 -0
- package/src/cli/commands/oauth/providers.ts +256 -0
- package/src/cli/commands/sessions.ts +5 -2
- package/src/cli/commands/skills.ts +177 -339
- package/src/cli/http-client.ts +0 -20
- package/src/cli/main-screen.tsx +2 -2
- package/src/cli/program.ts +6 -11
- package/src/cli/reference.ts +1 -3
- package/src/cli.ts +4 -10
- package/src/config/assistant-feature-flags.ts +0 -3
- package/src/config/bundled-skills/_shared/CLI_RETRIEVAL_PATTERN.md +1 -1
- package/src/config/bundled-skills/computer-use/SKILL.md +3 -6
- package/src/config/bundled-skills/computer-use/TOOLS.json +23 -5
- package/src/config/bundled-skills/computer-use/tools/{computer-use-request-control.ts → computer-use-observe.ts} +1 -5
- package/src/config/bundled-skills/google-calendar/calendar-client.ts +21 -16
- package/src/config/bundled-skills/messaging/tools/shared.ts +1 -4
- package/src/config/bundled-skills/settings/SKILL.md +1 -1
- package/src/config/bundled-skills/settings/TOOLS.json +2 -8
- package/src/config/bundled-skills/settings/tools/voice-config-update.ts +5 -33
- package/src/config/bundled-tool-registry.ts +2 -5
- package/src/config/env-registry.ts +14 -83
- package/src/config/env.ts +11 -50
- package/src/config/feature-flag-registry.json +16 -16
- package/src/config/loader.ts +0 -6
- package/src/config/schema.ts +4 -13
- package/src/config/schemas/memory-lifecycle.ts +0 -9
- package/src/config/schemas/memory-processing.ts +0 -180
- package/src/config/schemas/memory-retrieval.ts +32 -104
- package/src/config/schemas/memory.ts +0 -10
- package/src/config/skills.ts +21 -2
- package/src/config/types.ts +0 -4
- package/src/context/image-dimensions.ts +229 -0
- package/src/context/token-estimator.ts +75 -12
- package/src/context/window-manager.ts +53 -11
- package/src/daemon/assistant-attachments.ts +1 -13
- package/src/daemon/config-watcher.ts +61 -3
- package/src/daemon/daemon-control.ts +1 -1
- package/src/daemon/date-context.ts +114 -31
- package/src/daemon/handlers/config-ingress.ts +8 -33
- package/src/daemon/handlers/config-slack-channel.ts +49 -46
- package/src/daemon/handlers/config-telegram.ts +32 -16
- package/src/daemon/handlers/sessions.ts +27 -36
- package/src/daemon/handlers/shared.ts +0 -130
- package/src/daemon/handlers/skills.ts +20 -1
- package/src/daemon/history-repair.ts +72 -8
- package/src/daemon/host-cu-proxy.ts +430 -0
- package/src/daemon/lifecycle.ts +67 -71
- package/src/daemon/mcp-reload-service.ts +2 -2
- package/src/daemon/message-protocol.ts +3 -0
- package/src/daemon/message-types/computer-use.ts +1 -129
- package/src/daemon/message-types/host-cu.ts +19 -0
- package/src/daemon/message-types/memory.ts +4 -16
- package/src/daemon/message-types/messages.ts +4 -0
- package/src/daemon/message-types/sessions.ts +4 -0
- package/src/daemon/server.ts +25 -21
- package/src/daemon/session-agent-loop-handlers.ts +40 -0
- package/src/daemon/session-agent-loop.ts +334 -48
- package/src/daemon/session-attachments.ts +1 -2
- package/src/daemon/session-error.ts +89 -6
- package/src/daemon/session-history.ts +17 -7
- package/src/daemon/session-media-retry.ts +6 -2
- package/src/daemon/session-memory.ts +69 -149
- package/src/daemon/session-process.ts +10 -1
- package/src/daemon/session-runtime-assembly.ts +49 -19
- package/src/daemon/session-slash.ts +1 -1
- package/src/daemon/session-surfaces.ts +43 -28
- package/src/daemon/session-tool-setup.ts +9 -10
- package/src/daemon/session.ts +150 -17
- package/src/daemon/tool-side-effects.ts +2 -8
- package/src/daemon/watch-handler.ts +2 -2
- package/src/events/tool-metrics-listener.ts +2 -2
- package/src/hooks/manager.ts +1 -4
- package/src/inbound/public-ingress-urls.ts +7 -7
- package/src/instrument.ts +61 -1
- package/src/logfire.ts +16 -5
- package/src/memory/admin.ts +2 -191
- package/src/memory/canonical-guardian-store.ts +38 -2
- package/src/memory/conversation-crud.ts +0 -33
- package/src/memory/conversation-key-store.ts +21 -0
- package/src/memory/conversation-queries.ts +22 -3
- package/src/memory/db-init.ts +32 -0
- package/src/memory/embedding-backend.ts +84 -8
- package/src/memory/embedding-types.ts +9 -1
- package/src/memory/indexer.ts +7 -46
- package/src/memory/items-extractor.ts +274 -76
- package/src/memory/job-handlers/backfill.ts +2 -127
- package/src/memory/job-handlers/cleanup.ts +2 -16
- package/src/memory/job-handlers/extraction.ts +2 -138
- package/src/memory/job-handlers/index-maintenance.ts +1 -6
- package/src/memory/job-handlers/summarization.ts +3 -148
- package/src/memory/job-utils.ts +21 -59
- package/src/memory/jobs-store.ts +1 -159
- package/src/memory/jobs-worker.ts +9 -52
- package/src/memory/migrations/104-core-indexes.ts +3 -3
- package/src/memory/migrations/149-oauth-tables.ts +62 -0
- package/src/memory/migrations/150-oauth-apps-client-secret-path.ts +98 -0
- package/src/memory/migrations/151-oauth-providers-ping-url.ts +11 -0
- package/src/memory/migrations/152-memory-item-supersession.ts +44 -0
- package/src/memory/migrations/153-drop-entity-tables.ts +15 -0
- package/src/memory/migrations/154-drop-fts.ts +20 -0
- package/src/memory/migrations/155-drop-conflicts.ts +7 -0
- package/src/memory/migrations/156-call-session-invite-metadata.ts +24 -0
- package/src/memory/migrations/index.ts +8 -0
- package/src/memory/qdrant-client.ts +148 -51
- package/src/memory/raw-query.ts +1 -1
- package/src/memory/retriever.test.ts +294 -273
- package/src/memory/retriever.ts +421 -645
- package/src/memory/schema/calls.ts +2 -0
- package/src/memory/schema/index.ts +1 -0
- package/src/memory/schema/memory-core.ts +3 -48
- package/src/memory/schema/oauth.ts +67 -0
- package/src/memory/search/formatting.ts +263 -176
- package/src/memory/search/lexical.ts +1 -254
- package/src/memory/search/ranking.ts +0 -455
- package/src/memory/search/semantic.ts +100 -14
- package/src/memory/search/staleness.ts +47 -0
- package/src/memory/search/tier-classifier.ts +21 -0
- package/src/memory/search/types.ts +15 -77
- package/src/memory/task-memory-cleanup.ts +4 -6
- package/src/messaging/provider.ts +4 -4
- package/src/messaging/providers/gmail/client.ts +82 -2
- package/src/messaging/providers/gmail/mime-builder.ts +17 -7
- package/src/messaging/providers/gmail/people-client.ts +10 -10
- package/src/messaging/providers/telegram-bot/adapter.ts +17 -17
- package/src/messaging/providers/whatsapp/adapter.ts +11 -8
- package/src/messaging/registry.ts +2 -32
- package/src/notifications/copy-composer.ts +0 -5
- package/src/notifications/signal.ts +4 -5
- package/src/oauth/byo-connection.test.ts +133 -25
- package/src/oauth/byo-connection.ts +22 -6
- package/src/oauth/connect-orchestrator.ts +113 -57
- package/src/oauth/connect-types.ts +17 -23
- package/src/oauth/connection-resolver.ts +35 -11
- package/src/oauth/connection.ts +1 -1
- package/src/oauth/manual-token-connection.ts +104 -0
- package/src/oauth/oauth-store.ts +582 -0
- package/src/oauth/platform-connection.test.ts +29 -0
- package/src/oauth/platform-connection.ts +6 -5
- package/src/oauth/provider-behaviors.ts +124 -0
- package/src/oauth/scope-policy.ts +9 -2
- package/src/oauth/seed-providers.ts +167 -0
- package/src/oauth/token-persistence.ts +81 -77
- package/src/permissions/checker.ts +3 -3
- package/src/permissions/defaults.ts +1 -1
- package/src/permissions/prompter.ts +10 -1
- package/src/permissions/trust-store.ts +36 -1
- package/src/playbooks/playbook-compiler.ts +1 -1
- package/src/prompts/__tests__/build-cli-reference-section.test.ts +3 -1
- package/src/prompts/system-prompt.ts +46 -42
- package/src/providers/anthropic/client.ts +59 -20
- package/src/providers/retry.ts +1 -27
- package/src/providers/types.ts +7 -1
- package/src/runtime/AGENTS.md +9 -0
- package/src/runtime/auth/route-policy.ts +6 -6
- package/src/runtime/channel-reply-delivery.ts +0 -40
- package/src/runtime/gateway-client.ts +0 -7
- package/src/runtime/guardian-reply-router.ts +24 -22
- package/src/runtime/http-server.ts +10 -8
- package/src/runtime/http-types.ts +2 -2
- package/src/runtime/invite-redemption-service.ts +19 -1
- package/src/runtime/invite-service.ts +25 -0
- package/src/runtime/middleware/twilio-validation.ts +1 -11
- package/src/runtime/pending-interactions.ts +14 -12
- package/src/runtime/routes/brain-graph-routes.ts +10 -90
- package/src/runtime/routes/channel-delivery-routes.ts +0 -1
- package/src/runtime/routes/conversation-routes.ts +81 -19
- package/src/runtime/routes/events-routes.ts +21 -11
- package/src/runtime/routes/host-cu-routes.ts +97 -0
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +21 -12
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +12 -111
- package/src/runtime/routes/integrations/slack/share.ts +6 -7
- package/src/runtime/routes/log-export-routes.ts +126 -8
- package/src/runtime/routes/memory-item-routes.test.ts +754 -0
- package/src/runtime/routes/memory-item-routes.ts +503 -0
- package/src/runtime/routes/session-management-routes.ts +3 -3
- package/src/runtime/routes/settings-routes.ts +55 -48
- package/src/runtime/routes/surface-action-routes.ts +1 -1
- package/src/runtime/routes/trust-rules-routes.ts +14 -0
- package/src/runtime/routes/watch-routes.ts +128 -0
- package/src/runtime/routes/workspace-routes.ts +2 -1
- package/src/schedule/integration-status.ts +10 -9
- package/src/security/credential-key.ts +0 -156
- package/src/security/keychain-broker-client.ts +22 -10
- package/src/security/oauth2.ts +1 -1
- package/src/security/secure-keys.ts +25 -3
- package/src/security/token-manager.ts +137 -64
- package/src/skills/catalog-install.ts +414 -0
- package/src/skills/include-graph.ts +32 -0
- package/src/skills/skillssh-registry.ts +503 -0
- package/src/telegram/bot-username.ts +2 -3
- package/src/tools/assets/search.ts +5 -1
- package/src/tools/browser/network-recorder.ts +1 -1
- package/src/tools/browser/network-recording-types.ts +1 -1
- package/src/tools/computer-use/definitions.ts +36 -11
- package/src/tools/computer-use/registry.ts +5 -6
- package/src/tools/credentials/broker.ts +1 -2
- package/src/tools/credentials/metadata-store.ts +17 -121
- package/src/tools/credentials/vault.ts +92 -167
- package/src/tools/memory/definitions.ts +4 -13
- package/src/tools/memory/handlers.test.ts +83 -103
- package/src/tools/memory/handlers.ts +50 -85
- package/src/tools/registry.ts +2 -7
- package/src/tools/schedule/create.ts +8 -1
- package/src/tools/schedule/update.ts +8 -1
- package/src/tools/skills/load.ts +85 -3
- package/src/tools/watch/watch-state.ts +0 -12
- package/src/util/logger.ts +7 -41
- package/src/util/platform.ts +9 -28
- package/src/watcher/providers/google-calendar.ts +2 -1
- package/src/__tests__/clarification-resolver.test.ts +0 -193
- package/src/__tests__/computer-use-session-compaction.test.ts +0 -143
- package/src/__tests__/computer-use-session-lifecycle.test.ts +0 -322
- package/src/__tests__/computer-use-session-working-dir.test.ts +0 -166
- package/src/__tests__/computer-use-skill-baseline.test.ts +0 -78
- package/src/__tests__/computer-use-skill-endstate.test.ts +0 -105
- package/src/__tests__/computer-use-skill-lifecycle-cleanup.test.ts +0 -249
- package/src/__tests__/conflict-intent-tokenization.test.ts +0 -160
- package/src/__tests__/conflict-policy.test.ts +0 -269
- package/src/__tests__/conflict-store.test.ts +0 -372
- package/src/__tests__/contradiction-checker.test.ts +0 -361
- package/src/__tests__/entity-extractor.test.ts +0 -211
- package/src/__tests__/entity-search.test.ts +0 -1117
- package/src/__tests__/profile-compiler.test.ts +0 -392
- package/src/__tests__/ride-shotgun-handler.test.ts +0 -452
- package/src/__tests__/session-conflict-gate.test.ts +0 -1228
- package/src/__tests__/session-profile-injection.test.ts +0 -557
- package/src/cli/commands/dev.ts +0 -129
- package/src/cli/commands/map.ts +0 -391
- package/src/cli/commands/oauth.ts +0 -77
- package/src/config/bundled-skills/knowledge-graph/SKILL.md +0 -25
- package/src/config/bundled-skills/knowledge-graph/TOOLS.json +0 -66
- package/src/config/bundled-skills/knowledge-graph/tools/graph-query.ts +0 -211
- package/src/daemon/computer-use-session.ts +0 -1026
- package/src/daemon/ride-shotgun-handler.ts +0 -569
- package/src/daemon/session-conflict-gate.ts +0 -167
- package/src/daemon/session-dynamic-profile.ts +0 -77
- package/src/memory/clarification-resolver.ts +0 -417
- package/src/memory/conflict-intent.ts +0 -205
- package/src/memory/conflict-policy.ts +0 -127
- package/src/memory/conflict-store.ts +0 -410
- package/src/memory/contradiction-checker.ts +0 -508
- package/src/memory/entity-extractor.ts +0 -535
- package/src/memory/format-recall.ts +0 -47
- package/src/memory/fts-reconciler.ts +0 -165
- package/src/memory/job-handlers/conflict.ts +0 -200
- package/src/memory/profile-compiler.ts +0 -195
- package/src/memory/recall-cache.ts +0 -117
- package/src/memory/search/entity.ts +0 -535
- package/src/memory/search/query-expansion.test.ts +0 -70
- package/src/memory/search/query-expansion.ts +0 -118
- package/src/oauth/provider-base-urls.ts +0 -21
- package/src/oauth/provider-profiles.ts +0 -192
- package/src/prompts/computer-use-prompt.ts +0 -98
- package/src/runtime/routes/computer-use-routes.ts +0 -641
- package/src/runtime/routes/mcp-routes.ts +0 -20
- package/src/runtime/telegram-streaming-delivery.test.ts +0 -729
- package/src/runtime/telegram-streaming-delivery.ts +0 -393
- package/src/tools/computer-use/request-computer-control.ts +0 -56
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import type { Command } from "commander";
|
|
2
2
|
|
|
3
|
+
import {
|
|
4
|
+
disconnectOAuthProvider,
|
|
5
|
+
getConnectionByProvider,
|
|
6
|
+
listConnections,
|
|
7
|
+
type OAuthConnectionRow,
|
|
8
|
+
} from "../../oauth/oauth-store.js";
|
|
3
9
|
import { credentialKey } from "../../security/credential-key.js";
|
|
4
10
|
import {
|
|
5
11
|
deleteSecureKeyAsync,
|
|
@@ -48,15 +54,45 @@ function scrubSecret(secret: string | undefined): string {
|
|
|
48
54
|
return "****" + secret.slice(-4);
|
|
49
55
|
}
|
|
50
56
|
|
|
57
|
+
/**
|
|
58
|
+
* Safely look up an OAuth connection for a credential service.
|
|
59
|
+
* Returns undefined when the oauth-store has no data or the tables
|
|
60
|
+
* haven't been created yet (pre-migration).
|
|
61
|
+
*/
|
|
62
|
+
function safeGetConnectionByProvider(
|
|
63
|
+
service: string,
|
|
64
|
+
): OAuthConnectionRow | undefined {
|
|
65
|
+
try {
|
|
66
|
+
return getConnectionByProvider(service);
|
|
67
|
+
} catch {
|
|
68
|
+
return undefined;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Safely list all OAuth connections. Returns an empty array when the
|
|
74
|
+
* oauth-store has no data or the tables haven't been created yet.
|
|
75
|
+
*/
|
|
76
|
+
function safeListConnections(): OAuthConnectionRow[] {
|
|
77
|
+
try {
|
|
78
|
+
return listConnections();
|
|
79
|
+
} catch {
|
|
80
|
+
return [];
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
51
84
|
/**
|
|
52
85
|
* Build a structured credential output object suitable for both `inspect`
|
|
53
86
|
* and `list` responses. Produces an identical shape for every credential.
|
|
87
|
+
* Optionally enriches with data from the oauth-store when a matching
|
|
88
|
+
* connection exists.
|
|
54
89
|
*/
|
|
55
90
|
function buildCredentialOutput(
|
|
56
91
|
metadata: CredentialMetadata,
|
|
57
92
|
secret: string | undefined,
|
|
93
|
+
connection?: OAuthConnectionRow,
|
|
58
94
|
): Record<string, unknown> {
|
|
59
|
-
|
|
95
|
+
const output: Record<string, unknown> = {
|
|
60
96
|
ok: true,
|
|
61
97
|
service: metadata.service,
|
|
62
98
|
field: metadata.field,
|
|
@@ -67,14 +103,24 @@ function buildCredentialOutput(
|
|
|
67
103
|
usageDescription: metadata.usageDescription ?? null,
|
|
68
104
|
allowedTools: metadata.allowedTools,
|
|
69
105
|
allowedDomains: metadata.allowedDomains,
|
|
70
|
-
grantedScopes: metadata.grantedScopes ?? null,
|
|
71
|
-
expiresAt: metadata.expiresAt
|
|
72
|
-
? new Date(metadata.expiresAt).toISOString()
|
|
73
|
-
: null,
|
|
74
106
|
createdAt: new Date(metadata.createdAt).toISOString(),
|
|
75
107
|
updatedAt: new Date(metadata.updatedAt).toISOString(),
|
|
76
108
|
injectionTemplateCount: metadata.injectionTemplates?.length ?? 0,
|
|
109
|
+
grantedScopes: connection ? JSON.parse(connection.grantedScopes) : null,
|
|
110
|
+
expiresAt: connection?.expiresAt
|
|
111
|
+
? new Date(connection.expiresAt).toISOString()
|
|
112
|
+
: null,
|
|
77
113
|
};
|
|
114
|
+
|
|
115
|
+
if (connection) {
|
|
116
|
+
output.oauthConnectionId = connection.id;
|
|
117
|
+
output.oauthAccountInfo = connection.accountInfo ?? null;
|
|
118
|
+
output.oauthStatus = connection.status;
|
|
119
|
+
output.oauthHasRefreshToken = connection.hasRefreshToken === 1;
|
|
120
|
+
output.oauthLabel = connection.label ?? null;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return output;
|
|
78
124
|
}
|
|
79
125
|
|
|
80
126
|
/**
|
|
@@ -101,15 +147,19 @@ function printCredentialHuman(output: Record<string, unknown>): void {
|
|
|
101
147
|
log.info(
|
|
102
148
|
` Domains: ${(output.allowedDomains as string[]).join(", ")}`,
|
|
103
149
|
);
|
|
104
|
-
if (output.grantedScopes)
|
|
105
|
-
log.info(
|
|
106
|
-
` Scopes: ${(output.grantedScopes as string[]).join(", ")}`,
|
|
107
|
-
);
|
|
108
|
-
if (output.expiresAt) log.info(` Expires: ${output.expiresAt}`);
|
|
109
150
|
log.info(` Created: ${output.createdAt}`);
|
|
110
151
|
log.info(` Updated: ${output.updatedAt}`);
|
|
111
152
|
if ((output.injectionTemplateCount as number) > 0)
|
|
112
153
|
log.info(` Templates: ${output.injectionTemplateCount}`);
|
|
154
|
+
|
|
155
|
+
// OAuth connection enrichment
|
|
156
|
+
if (output.oauthStatus) {
|
|
157
|
+
log.info(` OAuth: ${output.oauthStatus}`);
|
|
158
|
+
if (output.oauthAccountInfo)
|
|
159
|
+
log.info(` Account: ${output.oauthAccountInfo}`);
|
|
160
|
+
if (output.oauthLabel) log.info(` OAuth Label: ${output.oauthLabel}`);
|
|
161
|
+
log.info(` Refresh: ${output.oauthHasRefreshToken ? "yes" : "no"}`);
|
|
162
|
+
}
|
|
113
163
|
}
|
|
114
164
|
|
|
115
165
|
// ---------------------------------------------------------------------------
|
|
@@ -198,9 +248,24 @@ Examples:
|
|
|
198
248
|
});
|
|
199
249
|
}
|
|
200
250
|
|
|
251
|
+
// Build a lookup of oauth connections keyed by providerKey for enrichment.
|
|
252
|
+
// listConnections() returns rows in no guaranteed order, so we compare
|
|
253
|
+
// createdAt to keep the most recent active connection per provider —
|
|
254
|
+
// matching the behaviour of getConnectionByProvider() used by inspect.
|
|
255
|
+
const allConnections = safeListConnections();
|
|
256
|
+
const connectionsByProvider = new Map<string, OAuthConnectionRow>();
|
|
257
|
+
for (const conn of allConnections) {
|
|
258
|
+
if (conn.status !== "active") continue;
|
|
259
|
+
const existing = connectionsByProvider.get(conn.providerKey);
|
|
260
|
+
if (!existing || conn.createdAt > existing.createdAt) {
|
|
261
|
+
connectionsByProvider.set(conn.providerKey, conn);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
201
265
|
const credentials = allMetadata.map((m) => {
|
|
202
266
|
const secret = getSecureKey(credentialKey(m.service, m.field));
|
|
203
|
-
|
|
267
|
+
const connection = connectionsByProvider.get(m.service);
|
|
268
|
+
return buildCredentialOutput(m, secret, connection);
|
|
204
269
|
});
|
|
205
270
|
|
|
206
271
|
writeOutput(cmd, { ok: true, credentials });
|
|
@@ -367,7 +432,29 @@ Examples:
|
|
|
367
432
|
|
|
368
433
|
const metadataDeleted = deleteCredentialMetadata(service, field);
|
|
369
434
|
|
|
370
|
-
|
|
435
|
+
// Also clean up the OAuth connection and new-format secure keys.
|
|
436
|
+
// disconnectOAuthProvider is a no-op when no connection exists.
|
|
437
|
+
let oauthResult: "disconnected" | "not-found" | "error" = "not-found";
|
|
438
|
+
try {
|
|
439
|
+
oauthResult = await disconnectOAuthProvider(service);
|
|
440
|
+
} catch {
|
|
441
|
+
// Best-effort — OAuth tables may not exist yet
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
if (oauthResult === "error") {
|
|
445
|
+
writeOutput(cmd, {
|
|
446
|
+
ok: false,
|
|
447
|
+
error: "Failed to disconnect OAuth provider — please try again",
|
|
448
|
+
});
|
|
449
|
+
process.exitCode = 1;
|
|
450
|
+
return;
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
if (
|
|
454
|
+
secretResult !== "deleted" &&
|
|
455
|
+
!metadataDeleted &&
|
|
456
|
+
oauthResult !== "disconnected"
|
|
457
|
+
) {
|
|
371
458
|
writeOutput(cmd, { ok: false, error: "Credential not found" });
|
|
372
459
|
process.exitCode = 1;
|
|
373
460
|
return;
|
|
@@ -464,8 +551,6 @@ Examples:
|
|
|
464
551
|
usageDescription: null,
|
|
465
552
|
allowedTools: [],
|
|
466
553
|
allowedDomains: [],
|
|
467
|
-
grantedScopes: null,
|
|
468
|
-
expiresAt: null,
|
|
469
554
|
createdAt: null,
|
|
470
555
|
updatedAt: null,
|
|
471
556
|
injectionTemplateCount: 0,
|
|
@@ -479,7 +564,8 @@ Examples:
|
|
|
479
564
|
return;
|
|
480
565
|
}
|
|
481
566
|
|
|
482
|
-
const
|
|
567
|
+
const connection = safeGetConnectionByProvider(metadata.service);
|
|
568
|
+
const output = buildCredentialOutput(metadata, secret, connection);
|
|
483
569
|
writeOutput(cmd, output);
|
|
484
570
|
|
|
485
571
|
if (!shouldOutputJson(cmd)) {
|
|
@@ -3,8 +3,10 @@ import { existsSync, readFileSync, statSync } from "node:fs";
|
|
|
3
3
|
|
|
4
4
|
import type { Command } from "commander";
|
|
5
5
|
|
|
6
|
+
import { getRuntimeHttpPort } from "../../config/env.js";
|
|
6
7
|
import { loadRawConfig } from "../../config/loader.js";
|
|
7
8
|
import { shouldAutoStartDaemon } from "../../daemon/connection-policy.js";
|
|
9
|
+
import { isHttpHealthy } from "../../daemon/daemon-control.js";
|
|
8
10
|
import {
|
|
9
11
|
getDbPath,
|
|
10
12
|
getLogPath,
|
|
@@ -13,7 +15,6 @@ import {
|
|
|
13
15
|
getWorkspaceHooksDir,
|
|
14
16
|
getWorkspaceSkillsDir,
|
|
15
17
|
} from "../../util/platform.js";
|
|
16
|
-
import { getHttpBaseUrl, httpHealthCheck } from "../http-client.js";
|
|
17
18
|
import { log } from "../logger.js";
|
|
18
19
|
|
|
19
20
|
export function registerDoctorCommand(program: Command): void {
|
|
@@ -57,7 +58,7 @@ Examples:
|
|
|
57
58
|
log.info("Vellum Doctor\n");
|
|
58
59
|
|
|
59
60
|
// 0. Connection policy info
|
|
60
|
-
const httpUrl =
|
|
61
|
+
const httpUrl = `http://127.0.0.1:${getRuntimeHttpPort()}`;
|
|
61
62
|
const autostart = shouldAutoStartDaemon();
|
|
62
63
|
log.info(` HTTP: ${httpUrl}`);
|
|
63
64
|
log.info(` Autostart: ${autostart ? "enabled" : "disabled"}\n`);
|
|
@@ -103,7 +104,7 @@ Examples:
|
|
|
103
104
|
|
|
104
105
|
// 3. Daemon reachable (HTTP health check)
|
|
105
106
|
try {
|
|
106
|
-
const healthy = await
|
|
107
|
+
const healthy = await isHttpHealthy();
|
|
107
108
|
if (healthy) {
|
|
108
109
|
pass("Assistant reachable");
|
|
109
110
|
} else {
|
package/src/cli/commands/mcp.ts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { mkdirSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
|
|
1
4
|
import { UnauthorizedError } from "@modelcontextprotocol/sdk/client/auth.js";
|
|
2
5
|
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
3
6
|
import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";
|
|
@@ -11,7 +14,7 @@ import {
|
|
|
11
14
|
deleteMcpOAuthCredentials,
|
|
12
15
|
McpOAuthProvider,
|
|
13
16
|
} from "../../mcp/mcp-oauth-provider.js";
|
|
14
|
-
import {
|
|
17
|
+
import { getWorkspaceDir } from "../../util/platform.js";
|
|
15
18
|
import { log } from "../logger.js";
|
|
16
19
|
|
|
17
20
|
export const HEALTH_CHECK_TIMEOUT_MS = 10_000;
|
|
@@ -51,6 +54,21 @@ export async function checkServerHealth(
|
|
|
51
54
|
}
|
|
52
55
|
}
|
|
53
56
|
|
|
57
|
+
/**
|
|
58
|
+
* Write a signal file so the daemon's ConfigWatcher triggers an MCP reload.
|
|
59
|
+
* Used by `mcp reload`, `mcp auth`, and any operation that needs the daemon
|
|
60
|
+
* to reconnect MCP servers.
|
|
61
|
+
*/
|
|
62
|
+
function signalMcpReload(): void {
|
|
63
|
+
try {
|
|
64
|
+
const signalsDir = join(getWorkspaceDir(), "signals");
|
|
65
|
+
mkdirSync(signalsDir, { recursive: true });
|
|
66
|
+
writeFileSync(join(signalsDir, "mcp-reload"), "");
|
|
67
|
+
} catch {
|
|
68
|
+
// Best-effort — the daemon may not be running or the directory may not exist.
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
54
72
|
export function registerMcpCommand(program: Command): void {
|
|
55
73
|
const mcp = program
|
|
56
74
|
.command("mcp")
|
|
@@ -67,8 +85,8 @@ server uses one of three transport types:
|
|
|
67
85
|
sse Remote server using Server-Sent Events
|
|
68
86
|
streamable-http Remote server using Streamable HTTP transport
|
|
69
87
|
|
|
70
|
-
|
|
71
|
-
|
|
88
|
+
MCP server configuration changes are detected automatically by the running
|
|
89
|
+
assistant. You can also run 'vellum mcp reload' to trigger a manual reload.
|
|
72
90
|
|
|
73
91
|
Examples:
|
|
74
92
|
$ assistant mcp list
|
|
@@ -251,61 +269,20 @@ Examples:
|
|
|
251
269
|
.addHelpText(
|
|
252
270
|
"after",
|
|
253
271
|
`
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
272
|
+
Signals the running assistant to disconnect and reconnect all MCP servers
|
|
273
|
+
using the current configuration from disk. Active sessions pick up new tools
|
|
274
|
+
on their next turn automatically. The assistant must be running.
|
|
257
275
|
|
|
258
276
|
Examples:
|
|
259
277
|
$ vellum mcp reload
|
|
260
278
|
$ vellum mcp reload # after editing config.json to add a new server
|
|
261
279
|
$ vellum mcp reload # after running "vellum mcp auth <server>"`,
|
|
262
280
|
)
|
|
263
|
-
.action(
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
success: boolean;
|
|
269
|
-
serverCount?: number;
|
|
270
|
-
toolCount?: number;
|
|
271
|
-
servers?: {
|
|
272
|
-
id: string;
|
|
273
|
-
connected: boolean;
|
|
274
|
-
disabled?: boolean;
|
|
275
|
-
toolCount: number;
|
|
276
|
-
tools: string[];
|
|
277
|
-
}[];
|
|
278
|
-
error?: string;
|
|
279
|
-
};
|
|
280
|
-
if (response.success) {
|
|
281
|
-
log.info(
|
|
282
|
-
`MCP servers reloaded: ${response.serverCount} server(s), ${response.toolCount} tool(s)\n`,
|
|
283
|
-
);
|
|
284
|
-
if (response.servers && response.servers.length > 0) {
|
|
285
|
-
for (const server of response.servers) {
|
|
286
|
-
const status = server.disabled
|
|
287
|
-
? "⊘ Disabled"
|
|
288
|
-
: server.connected
|
|
289
|
-
? "\u2713 Connected"
|
|
290
|
-
: "\u2717 Not connected";
|
|
291
|
-
log.info(` ${server.id}`);
|
|
292
|
-
log.info(` Status: ${status}`);
|
|
293
|
-
log.info(
|
|
294
|
-
` Tools: ${server.toolCount > 0 ? server.tools.join(", ") : "(none)"}`,
|
|
295
|
-
);
|
|
296
|
-
log.info("");
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
} else {
|
|
300
|
-
log.error(`Failed to reload: ${response.error}`);
|
|
301
|
-
process.exitCode = 1;
|
|
302
|
-
}
|
|
303
|
-
} catch (err) {
|
|
304
|
-
log.error(
|
|
305
|
-
`Failed to send reload request: ${err instanceof Error ? err.message : err}`,
|
|
306
|
-
);
|
|
307
|
-
process.exitCode = 1;
|
|
308
|
-
}
|
|
281
|
+
.action(() => {
|
|
282
|
+
signalMcpReload();
|
|
283
|
+
log.info(
|
|
284
|
+
"MCP reload signal sent. The running assistant will reconnect servers shortly.",
|
|
285
|
+
);
|
|
309
286
|
});
|
|
310
287
|
|
|
311
288
|
mcp
|
|
@@ -422,7 +399,10 @@ Examples:
|
|
|
422
399
|
|
|
423
400
|
saveRawConfig(raw);
|
|
424
401
|
log.info(`Added MCP server "${name}" (${opts.transportType})`);
|
|
425
|
-
log.info(
|
|
402
|
+
log.info(
|
|
403
|
+
"The running assistant will pick up this change automatically. " +
|
|
404
|
+
"Or run 'vellum mcp reload' to apply now.",
|
|
405
|
+
);
|
|
426
406
|
},
|
|
427
407
|
);
|
|
428
408
|
|
|
@@ -444,8 +424,8 @@ OAuth flow. If the server already has valid cached tokens, the command succeeds
|
|
|
444
424
|
immediately without opening a browser. Tokens are cached locally for future use
|
|
445
425
|
by the assistant.
|
|
446
426
|
|
|
447
|
-
After successful authentication,
|
|
448
|
-
|
|
427
|
+
After successful authentication, the running assistant detects the change
|
|
428
|
+
automatically. You can also run 'vellum mcp reload' to apply immediately.
|
|
449
429
|
|
|
450
430
|
Examples:
|
|
451
431
|
$ assistant mcp auth my-server
|
|
@@ -603,7 +583,11 @@ Examples:
|
|
|
603
583
|
provider.stopCallbackServer();
|
|
604
584
|
|
|
605
585
|
log.info(`Authentication successful for "${name}".`);
|
|
606
|
-
log.info(
|
|
586
|
+
log.info(
|
|
587
|
+
"The running assistant will pick up this change automatically. " +
|
|
588
|
+
"Or run 'vellum mcp reload' to apply now.",
|
|
589
|
+
);
|
|
590
|
+
signalMcpReload();
|
|
607
591
|
process.exit(0);
|
|
608
592
|
});
|
|
609
593
|
|
|
@@ -621,8 +605,8 @@ any stored OAuth credentials (tokens, client info, discovery metadata) for
|
|
|
621
605
|
sse/streamable-http servers. If no OAuth credentials exist, the cleanup is
|
|
622
606
|
silently skipped.
|
|
623
607
|
|
|
624
|
-
After removal,
|
|
625
|
-
|
|
608
|
+
After removal, the running assistant detects the change automatically. You
|
|
609
|
+
can also run 'vellum mcp reload' to apply immediately.
|
|
626
610
|
|
|
627
611
|
Examples:
|
|
628
612
|
$ assistant mcp remove my-server
|
|
@@ -655,6 +639,9 @@ Examples:
|
|
|
655
639
|
delete servers[name];
|
|
656
640
|
saveRawConfig(raw);
|
|
657
641
|
log.info(`Removed MCP server "${name}".`);
|
|
658
|
-
log.info(
|
|
642
|
+
log.info(
|
|
643
|
+
"The running assistant will pick up this change automatically. " +
|
|
644
|
+
"Or run 'vellum mcp reload' to apply now.",
|
|
645
|
+
);
|
|
659
646
|
});
|
|
660
647
|
}
|
|
@@ -1,21 +1,16 @@
|
|
|
1
1
|
import type { Command } from "commander";
|
|
2
2
|
|
|
3
3
|
import {
|
|
4
|
-
dismissPendingConflicts,
|
|
5
4
|
getMemorySystemStatus,
|
|
6
5
|
queryMemory,
|
|
7
6
|
requestMemoryBackfill,
|
|
8
7
|
requestMemoryCleanup,
|
|
9
8
|
requestMemoryRebuildIndex,
|
|
10
9
|
} from "../../memory/admin.js";
|
|
11
|
-
import { listPendingConflictDetails } from "../../memory/conflict-store.js";
|
|
12
10
|
import { listConversations } from "../../memory/conversation-queries.js";
|
|
13
|
-
import { rawGet } from "../../memory/db.js";
|
|
14
11
|
import { initializeDb } from "../db.js";
|
|
15
12
|
import { log } from "../logger.js";
|
|
16
13
|
|
|
17
|
-
const SHORT_HASH_LENGTH = 8;
|
|
18
|
-
|
|
19
14
|
export function registerMemoryCommand(program: Command): void {
|
|
20
15
|
const memory = program
|
|
21
16
|
.command("memory")
|
|
@@ -24,23 +19,20 @@ export function registerMemoryCommand(program: Command): void {
|
|
|
24
19
|
memory.addHelpText(
|
|
25
20
|
"after",
|
|
26
21
|
`
|
|
27
|
-
The memory subsystem indexes conversation segments
|
|
28
|
-
and vector embeddings for semantic recall
|
|
29
|
-
|
|
30
|
-
"pending_clarification" status until explicitly dismissed or resolved.
|
|
22
|
+
The memory subsystem indexes conversation segments using hybrid search (dense
|
|
23
|
+
and sparse vector embeddings) for semantic recall, with tier classification
|
|
24
|
+
to prioritize high-value memories.
|
|
31
25
|
|
|
32
26
|
Key concepts:
|
|
33
27
|
segments Chunks of conversation text extracted for indexing
|
|
34
28
|
items Distilled facts/statements derived from segments
|
|
35
29
|
summaries Compressed representations of conversation history
|
|
36
30
|
embeddings Vector representations used for semantic similarity search
|
|
37
|
-
conflicts Pairs of contradictory statements awaiting resolution
|
|
38
31
|
|
|
39
32
|
Examples:
|
|
40
33
|
$ assistant memory status
|
|
41
34
|
$ assistant memory query "What is the project deadline?"
|
|
42
|
-
$ assistant memory backfill
|
|
43
|
-
$ assistant memory dismiss-conflicts --all`,
|
|
35
|
+
$ assistant memory backfill`,
|
|
44
36
|
);
|
|
45
37
|
|
|
46
38
|
memory
|
|
@@ -59,10 +51,7 @@ Fields shown:
|
|
|
59
51
|
items Total distilled fact items stored
|
|
60
52
|
summaries Total compressed conversation summaries
|
|
61
53
|
embeddings Total vector embeddings computed
|
|
62
|
-
|
|
63
|
-
resolved conflicts Conflicts that have been dismissed or resolved
|
|
64
|
-
oldest pending age How long the oldest unresolved conflict has been waiting
|
|
65
|
-
cleanup backlogs Number of resolved conflicts and superseded items pending cleanup
|
|
54
|
+
cleanup backlogs Number of superseded items pending cleanup
|
|
66
55
|
cleanup throughput Number of cleanup operations completed in the last 24 hours
|
|
67
56
|
jobs Status of background jobs (backfill, cleanup, rebuild-index)
|
|
68
57
|
|
|
@@ -84,29 +73,9 @@ Examples:
|
|
|
84
73
|
log.info(`Items: ${status.counts.items.toLocaleString()}`);
|
|
85
74
|
log.info(`Summaries: ${status.counts.summaries.toLocaleString()}`);
|
|
86
75
|
log.info(`Embeddings: ${status.counts.embeddings.toLocaleString()}`);
|
|
87
|
-
log.info(
|
|
88
|
-
`Pending conflicts: ${status.conflicts.pending.toLocaleString()}`,
|
|
89
|
-
);
|
|
90
|
-
log.info(
|
|
91
|
-
`Resolved conflicts: ${status.conflicts.resolved.toLocaleString()}`,
|
|
92
|
-
);
|
|
93
|
-
if (status.conflicts.oldestPendingAgeMs != null) {
|
|
94
|
-
const oldestMinutes = Math.floor(
|
|
95
|
-
status.conflicts.oldestPendingAgeMs / 60_000,
|
|
96
|
-
);
|
|
97
|
-
log.info(`Oldest pending conflict age: ${oldestMinutes} min`);
|
|
98
|
-
} else {
|
|
99
|
-
log.info("Oldest pending conflict age: n/a");
|
|
100
|
-
}
|
|
101
|
-
log.info(
|
|
102
|
-
`Cleanup backlog (resolved conflicts): ${status.cleanup.resolvedBacklog.toLocaleString()}`,
|
|
103
|
-
);
|
|
104
76
|
log.info(
|
|
105
77
|
`Cleanup backlog (superseded items): ${status.cleanup.supersededBacklog.toLocaleString()}`,
|
|
106
78
|
);
|
|
107
|
-
log.info(
|
|
108
|
-
`Cleanup throughput 24h (resolved conflicts): ${status.cleanup.resolvedCompleted24h.toLocaleString()}`,
|
|
109
|
-
);
|
|
110
79
|
log.info(
|
|
111
80
|
`Cleanup throughput 24h (superseded items): ${status.cleanup.supersededCompleted24h.toLocaleString()}`,
|
|
112
81
|
);
|
|
@@ -123,8 +92,8 @@ Examples:
|
|
|
123
92
|
.addHelpText(
|
|
124
93
|
"after",
|
|
125
94
|
`
|
|
126
|
-
Queues a background job to index unprocessed conversation segments into
|
|
127
|
-
|
|
95
|
+
Queues a background job to index unprocessed conversation segments into
|
|
96
|
+
vector embeddings. The job resumes from where the last backfill left off,
|
|
128
97
|
processing only new or unindexed segments.
|
|
129
98
|
|
|
130
99
|
The --force flag restarts the backfill from the very beginning, reprocessing
|
|
@@ -144,7 +113,7 @@ Examples:
|
|
|
144
113
|
memory
|
|
145
114
|
.command("cleanup")
|
|
146
115
|
.description(
|
|
147
|
-
"Queue cleanup jobs for
|
|
116
|
+
"Queue cleanup jobs for stale superseded items",
|
|
148
117
|
)
|
|
149
118
|
.option(
|
|
150
119
|
"--retention-ms <ms>",
|
|
@@ -153,11 +122,8 @@ Examples:
|
|
|
153
122
|
.addHelpText(
|
|
154
123
|
"after",
|
|
155
124
|
`
|
|
156
|
-
Queues
|
|
157
|
-
|
|
158
|
-
dismissed or resolved past the retention threshold.
|
|
159
|
-
2. Stale superseded items cleanup — removes memory items that have been
|
|
160
|
-
superseded by newer, corrected facts past the retention threshold.
|
|
125
|
+
Queues a background cleanup job to remove memory items that have been
|
|
126
|
+
superseded by newer, corrected facts past the retention threshold.
|
|
161
127
|
|
|
162
128
|
The optional --retention-ms flag sets the minimum age (in milliseconds) a
|
|
163
129
|
record must have before it is eligible for cleanup. If omitted, the system
|
|
@@ -175,9 +141,6 @@ Examples:
|
|
|
175
141
|
const jobs = requestMemoryCleanup(
|
|
176
142
|
Number.isFinite(retentionMs) ? retentionMs : undefined,
|
|
177
143
|
);
|
|
178
|
-
log.info(
|
|
179
|
-
`Queued cleanup_resolved_conflicts job: ${jobs.resolvedConflictsJobId}`,
|
|
180
|
-
);
|
|
181
144
|
log.info(
|
|
182
145
|
`Queued cleanup_stale_superseded_items job: ${jobs.staleSupersededItemsJobId}`,
|
|
183
146
|
);
|
|
@@ -195,8 +158,8 @@ Examples:
|
|
|
195
158
|
Arguments:
|
|
196
159
|
text The recall query string used to search memory (e.g. "What is the
|
|
197
160
|
project deadline?"). Matched against indexed segments using the full
|
|
198
|
-
recall pipeline:
|
|
199
|
-
(time-weighted)
|
|
161
|
+
recall pipeline: semantic (dense + sparse vector similarity) and recency
|
|
162
|
+
(time-weighted).
|
|
200
163
|
|
|
201
164
|
Runs the complete memory recall pipeline and displays hit counts for each
|
|
202
165
|
retrieval strategy, the total injected token count, query latency, and the
|
|
@@ -221,10 +184,8 @@ Examples:
|
|
|
221
184
|
if (result.degraded) {
|
|
222
185
|
log.info(`Memory degraded: ${result.reason ?? "unknown reason"}`);
|
|
223
186
|
}
|
|
224
|
-
log.info(`Lexical hits: ${result.lexicalHits}`);
|
|
225
187
|
log.info(`Semantic hits: ${result.semanticHits}`);
|
|
226
188
|
log.info(`Recency hits: ${result.recencyHits}`);
|
|
227
|
-
log.info(`Entity hits: ${result.entityHits}`);
|
|
228
189
|
log.info(`Injected tokens: ${result.injectedTokens}`);
|
|
229
190
|
log.info(`Latency: ${result.latencyMs}ms`);
|
|
230
191
|
if (result.injectedText.length > 0) {
|
|
@@ -237,13 +198,13 @@ Examples:
|
|
|
237
198
|
|
|
238
199
|
memory
|
|
239
200
|
.command("rebuild-index")
|
|
240
|
-
.description("Queue a memory
|
|
201
|
+
.description("Queue a memory embedding index rebuild job")
|
|
241
202
|
.addHelpText(
|
|
242
203
|
"after",
|
|
243
204
|
`
|
|
244
|
-
Queues a background job that performs a full rebuild of
|
|
245
|
-
|
|
246
|
-
|
|
205
|
+
Queues a background job that performs a full rebuild of the vector embedding
|
|
206
|
+
index. All existing index data is dropped and reconstructed from the source
|
|
207
|
+
memory items.
|
|
247
208
|
|
|
248
209
|
This is useful after schema changes, embedding model upgrades, or if index
|
|
249
210
|
corruption is suspected. The rebuild runs asynchronously; use "assistant memory
|
|
@@ -258,114 +219,4 @@ Examples:
|
|
|
258
219
|
const jobId = requestMemoryRebuildIndex();
|
|
259
220
|
log.info(`Queued rebuild-index job: ${jobId}`);
|
|
260
221
|
});
|
|
261
|
-
|
|
262
|
-
memory
|
|
263
|
-
.command("dismiss-conflicts")
|
|
264
|
-
.description("Dismiss pending memory conflicts (all or matching a pattern)")
|
|
265
|
-
.option("-a, --all", "Dismiss all pending conflicts")
|
|
266
|
-
.option(
|
|
267
|
-
"-p, --pattern <regex>",
|
|
268
|
-
"Dismiss conflicts where either statement matches this regex",
|
|
269
|
-
)
|
|
270
|
-
.option("-s, --scope <id>", 'Memory scope (default: "default")')
|
|
271
|
-
.option("--dry-run", "Show what would be dismissed without making changes")
|
|
272
|
-
.addHelpText(
|
|
273
|
-
"after",
|
|
274
|
-
`
|
|
275
|
-
Two modes of operation:
|
|
276
|
-
--all Dismiss every pending conflict in the scope
|
|
277
|
-
--pattern <regex> Dismiss only conflicts where either the existing or
|
|
278
|
-
candidate statement matches the given regex (case-insensitive)
|
|
279
|
-
|
|
280
|
-
At least one of --all or --pattern must be provided. If both are given,
|
|
281
|
-
--all takes priority and all pending conflicts are dismissed.
|
|
282
|
-
|
|
283
|
-
The --scope flag targets a specific memory scope. Defaults to "default" if
|
|
284
|
-
omitted. The --dry-run flag previews which conflicts would be dismissed
|
|
285
|
-
without actually modifying any records.
|
|
286
|
-
|
|
287
|
-
Examples:
|
|
288
|
-
$ assistant memory dismiss-conflicts --all
|
|
289
|
-
$ assistant memory dismiss-conflicts --pattern "project deadline" --dry-run
|
|
290
|
-
$ assistant memory dismiss-conflicts --pattern "^preferred\\b" --scope work`,
|
|
291
|
-
)
|
|
292
|
-
.action(
|
|
293
|
-
(opts: {
|
|
294
|
-
all?: boolean;
|
|
295
|
-
pattern?: string;
|
|
296
|
-
scope?: string;
|
|
297
|
-
dryRun?: boolean;
|
|
298
|
-
}) => {
|
|
299
|
-
if (!opts.all && !opts.pattern) {
|
|
300
|
-
log.info("At least one of --all or --pattern must be provided.");
|
|
301
|
-
log.info("Use --dry-run to preview without making changes.");
|
|
302
|
-
return;
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
initializeDb();
|
|
306
|
-
|
|
307
|
-
const pattern = opts.pattern
|
|
308
|
-
? new RegExp(opts.pattern, "i")
|
|
309
|
-
: undefined;
|
|
310
|
-
|
|
311
|
-
if (opts.dryRun) {
|
|
312
|
-
const scopeId = opts.scope ?? "default";
|
|
313
|
-
const totalPending =
|
|
314
|
-
rawGet<{ c: number }>(
|
|
315
|
-
`SELECT COUNT(*) AS c FROM memory_item_conflicts WHERE scope_id = ? AND status = 'pending_clarification'`,
|
|
316
|
-
scopeId,
|
|
317
|
-
)?.c ?? 0;
|
|
318
|
-
|
|
319
|
-
// Show a sample of conflicts (can't paginate without dismissing)
|
|
320
|
-
const sample = listPendingConflictDetails(scopeId, 1000);
|
|
321
|
-
let matchCount = 0;
|
|
322
|
-
for (const conflict of sample) {
|
|
323
|
-
const matches =
|
|
324
|
-
opts.all ||
|
|
325
|
-
(pattern &&
|
|
326
|
-
(pattern.test(conflict.existingStatement) ||
|
|
327
|
-
pattern.test(conflict.candidateStatement)));
|
|
328
|
-
if (!matches) continue;
|
|
329
|
-
matchCount++;
|
|
330
|
-
log.info(
|
|
331
|
-
` [${conflict.id.slice(0, SHORT_HASH_LENGTH)}] "${
|
|
332
|
-
conflict.existingStatement
|
|
333
|
-
}" vs "${conflict.candidateStatement}"`,
|
|
334
|
-
);
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
if (opts.all) {
|
|
338
|
-
// --all matches everything, so matchCount is just the sample size
|
|
339
|
-
log.info(
|
|
340
|
-
`\nDry run: ${totalPending} of ${totalPending} pending conflicts would be dismissed.`,
|
|
341
|
-
);
|
|
342
|
-
} else {
|
|
343
|
-
const moreNote =
|
|
344
|
-
totalPending > sample.length
|
|
345
|
-
? ` (showing first ${sample.length} of ${totalPending})`
|
|
346
|
-
: "";
|
|
347
|
-
log.info(
|
|
348
|
-
`\nDry run: ${matchCount} of ${totalPending} pending conflicts would be dismissed.${moreNote}`,
|
|
349
|
-
);
|
|
350
|
-
}
|
|
351
|
-
return;
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
const result = dismissPendingConflicts({
|
|
355
|
-
all: opts.all,
|
|
356
|
-
pattern,
|
|
357
|
-
scopeId: opts.scope,
|
|
358
|
-
});
|
|
359
|
-
for (const detail of result.details) {
|
|
360
|
-
log.info(
|
|
361
|
-
` Dismissed [${detail.id.slice(0, SHORT_HASH_LENGTH)}]: "${
|
|
362
|
-
detail.existingStatement
|
|
363
|
-
}" vs "${detail.candidateStatement}"`,
|
|
364
|
-
);
|
|
365
|
-
}
|
|
366
|
-
log.info(
|
|
367
|
-
`\nDismissed ${result.dismissed} conflicts. ${result.remaining} pending conflicts remain.`,
|
|
368
|
-
);
|
|
369
|
-
},
|
|
370
|
-
);
|
|
371
222
|
}
|