@vellumai/assistant 0.10.9 → 0.10.10-dev.202607162206.d08e98e
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 +8 -0
- package/docs/activation-funnel-telemetry.md +13 -7
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/package.json +1 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/__tests__/redacted-credential.test.ts +200 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/redacted-credential.ts +226 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/package.json +1 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/__tests__/redacted-credential.test.ts +200 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/redacted-credential.ts +226 -0
- package/node_modules/@vellumai/service-contracts/package.json +1 -0
- package/node_modules/@vellumai/service-contracts/src/__tests__/redacted-credential.test.ts +200 -0
- package/node_modules/@vellumai/service-contracts/src/redacted-credential.ts +226 -0
- package/openapi.yaml +530 -107
- package/package.json +1 -1
- package/scripts/generate-openapi.ts +8 -0
- package/src/__tests__/activation-early-marking.test.ts +6 -5
- package/src/__tests__/agent-loop-override-profile.test.ts +22 -25
- package/src/__tests__/agent-wake-override-profile.test.ts +21 -48
- package/src/__tests__/app-builder-tool-scripts.test.ts +0 -1
- package/src/__tests__/app-bundler.test.ts +4 -12
- package/src/__tests__/app-executors.test.ts +2 -49
- package/src/__tests__/app-routes-csp.test.ts +114 -146
- package/src/__tests__/auth-fallback-events-store.test.ts +8 -1
- package/src/__tests__/build-persisted-content.test.ts +96 -0
- package/src/__tests__/bundle-scanner.test.ts +27 -1
- package/src/__tests__/call-controller.test.ts +291 -0
- package/src/__tests__/call-site-routing-connection-auto-resolve.test.ts +165 -0
- package/src/__tests__/chat-credential-redaction.test.ts +1395 -0
- package/src/__tests__/chat-reveal-guard-priming.test.ts +791 -0
- package/src/__tests__/compaction.benchmark.test.ts +2 -1
- package/src/__tests__/compactor-image-manifest-trust.test.ts +50 -0
- package/src/__tests__/config-loader-backfill.test.ts +9 -4
- package/src/__tests__/config-schema-cmd.test.ts +10 -11
- package/src/__tests__/config-schema.test.ts +190 -257
- package/src/__tests__/conversation-agent-loop-fatal-cleanup.test.ts +208 -0
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +5 -19
- package/src/__tests__/conversation-agent-loop.test.ts +22 -9
- package/src/__tests__/conversation-error.test.ts +31 -0
- package/src/__tests__/conversation-load-history-repair.test.ts +110 -0
- package/src/__tests__/conversation-process-callsite.test.ts +12 -19
- package/src/__tests__/conversation-routes-slash-commands.test.ts +7 -21
- package/src/__tests__/conversation-summarize-route.test.ts +36 -44
- package/src/__tests__/conversation-surfaces-action-delivery.test.ts +1 -0
- package/src/__tests__/conversation-surfaces-activation-emit.test.ts +7 -7
- package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +0 -1
- package/src/__tests__/conversation-tool-setup-attribution.test.ts +0 -1
- package/src/__tests__/conversation-usage.test.ts +4 -12
- package/src/__tests__/credential-routes.test.ts +250 -0
- package/src/__tests__/credential-security-invariants.test.ts +3 -0
- package/src/__tests__/db-migration-rollback.test.ts +22 -0
- package/src/__tests__/empty-response-hook.test.ts +186 -1
- package/src/__tests__/external-plugin-loader.test.ts +11 -5
- package/src/__tests__/heartbeat-service.test.ts +0 -28
- package/src/__tests__/host-shell-tool.test.ts +2 -0
- package/src/__tests__/inactive-tool-error-messages.test.ts +2 -2
- package/src/__tests__/inference-no-mode-boot-e2e.test.ts +52 -8
- package/src/__tests__/internal-telemetry-routes.test.ts +23 -4
- package/src/__tests__/invite-routes-http.test.ts +12 -16
- package/src/__tests__/list-all-apps.test.ts +0 -4
- package/src/__tests__/llm-context-resolution.test.ts +32 -56
- package/src/__tests__/llm-request-log-turn-query.test.ts +109 -0
- package/src/__tests__/llm-resolver-override-or-default.test.ts +3 -52
- package/src/__tests__/llm-resolver.test.ts +342 -602
- package/src/__tests__/llm-schema.test.ts +79 -37
- package/src/__tests__/max-tokens-continue-hook.test.ts +19 -0
- package/src/__tests__/media-stream-output.test.ts +259 -3
- package/src/__tests__/media-stream-server-integration.test.ts +22 -1
- package/src/__tests__/media-stream-stt-session.test.ts +47 -0
- package/src/__tests__/memory-jobs-worker-cleanup-cadence.test.ts +33 -0
- package/src/__tests__/memory-recall-log-store.test.ts +47 -13
- package/src/__tests__/mock-gateway-ipc.ts +46 -1
- package/src/__tests__/mtime-cache.test.ts +61 -0
- package/src/__tests__/navigate-settings-tab.test.ts +2 -0
- package/src/__tests__/normalize-onboarding.test.ts +33 -0
- package/src/__tests__/onboarding-persona-write.test.ts +26 -0
- package/src/__tests__/plugin-api-resolve-credential.test.ts +140 -0
- package/src/__tests__/plugin-app-serve-routes.test.ts +166 -14
- package/src/__tests__/plugin-import-boundary-reverse-guard.test.ts +2 -0
- package/src/__tests__/post-turn-tool-result-truncation.test.ts +38 -0
- package/src/__tests__/provider-commit-message-generator.test.ts +27 -20
- package/src/__tests__/provider-connections-backfill.test.ts +138 -0
- package/src/__tests__/provider-platform-proxy-integration.test.ts +10 -31
- package/src/__tests__/provider-registry-ollama.test.ts +8 -18
- package/src/__tests__/provider-send-message-override-profile.test.ts +23 -23
- package/src/__tests__/provider-usage-tracking.test.ts +9 -19
- package/src/__tests__/prune-old-conversations-job.test.ts +12 -0
- package/src/__tests__/published-app-updater.test.ts +22 -16
- package/src/__tests__/registry.test.ts +5 -16
- package/src/__tests__/retry-openrouter-only-normalization.test.ts +22 -23
- package/src/__tests__/retry-thinking-adaptive-only.test.ts +43 -48
- package/src/__tests__/retry-thinking-tool-choice.test.ts +57 -66
- package/src/__tests__/retry-verbosity-normalization.test.ts +24 -23
- package/src/__tests__/reveal-success-registry.test.ts +123 -0
- package/src/__tests__/run-conversation-turn-persistence.test.ts +130 -0
- package/src/__tests__/secret-fixtures.ts +9 -0
- package/src/__tests__/server-history-render.test.ts +28 -0
- package/src/__tests__/skills.test.ts +9 -4
- package/src/__tests__/slack-share-routes.test.ts +0 -1
- package/src/__tests__/stt-stream-session.test.ts +6 -5
- package/src/__tests__/subagent-call-site-routing.test.ts +69 -95
- package/src/__tests__/subagent-disposal.test.ts +2 -0
- package/src/__tests__/subagent-fork-notifications.test.ts +2 -0
- package/src/__tests__/subagent-fork-spawn.test.ts +2 -0
- package/src/__tests__/subagent-manager-notify.test.ts +2 -0
- package/src/__tests__/subagent-role-registry.test.ts +37 -0
- package/src/__tests__/subagent-spawn-and-await.test.ts +1 -0
- package/src/__tests__/subagent-terminal-message.test.ts +50 -0
- package/src/__tests__/subagent-tool-gate-mode.test.ts +78 -5
- package/src/__tests__/surface-completion-nudge-hook.test.ts +19 -0
- package/src/__tests__/telemetry-routes.test.ts +99 -19
- package/src/__tests__/tool-audit.test.ts +34 -4
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +1 -1
- package/src/__tests__/tool-profiler.test.ts +72 -1
- package/src/__tests__/tool-result-spool.test.ts +49 -4
- package/src/__tests__/tool-side-effects-slack-dm.test.ts +0 -1
- package/src/__tests__/ui-channel-variants.test.ts +108 -0
- package/src/__tests__/ui-shape-teaching.test.ts +255 -0
- package/src/__tests__/usage-attribution.test.ts +18 -41
- package/src/__tests__/user-plugin-loader.test.ts +4 -4
- package/src/__tests__/voice-config-update.test.ts +46 -0
- package/src/__tests__/voice-session-bridge.test.ts +216 -84
- package/src/__tests__/workspace-migration-131-drop-web-fetch-mode.test.ts +120 -0
- package/src/agent/loop.ts +4 -3
- package/src/api/events/open-conversation.test.ts +64 -0
- package/src/api/events/open-conversation.ts +33 -0
- package/src/api/index.ts +6 -0
- package/src/api/responses/conversation-message.ts +5 -0
- package/src/apps/app-store.ts +25 -35
- package/src/bundler/app-bundler.ts +34 -48
- package/src/bundler/app-compiler.ts +39 -4
- package/src/bundler/bundle-scanner.ts +13 -0
- package/src/bundler/manifest.ts +1 -1
- package/src/calls/__tests__/voice-session-bridge.test.ts +47 -0
- package/src/calls/call-constants.ts +5 -0
- package/src/calls/call-controller.ts +100 -32
- package/src/calls/call-transport.ts +9 -0
- package/src/calls/media-stream-output.ts +107 -4
- package/src/calls/media-stream-server.ts +29 -9
- package/src/calls/media-stream-stt-session.ts +7 -1
- package/src/calls/media-turn-detector.ts +11 -1
- package/src/calls/voice-session-bridge.ts +84 -63
- package/src/cli/commands/__tests__/inference-providers.test.ts +270 -33
- package/src/cli/commands/__tests__/notifications.test.ts +24 -3
- package/src/cli/commands/config.help.ts +6 -6
- package/src/cli/commands/credentials.help.ts +13 -0
- package/src/cli/commands/credentials.ts +6 -1
- package/src/cli/commands/email.help.ts +7 -0
- package/src/cli/commands/email.ts +35 -1
- package/src/cli/commands/inference-providers.ts +168 -107
- package/src/cli/commands/inference.help.ts +118 -46
- package/src/cli/commands/memory/index.help.ts +23 -0
- package/src/cli/commands/memory/nodes.ts +146 -0
- package/src/cli/commands/notifications.help.ts +10 -10
- package/src/cli/commands/oauth/connect-surface-guidance.test.ts +40 -0
- package/src/cli/commands/oauth/connect-surface-guidance.ts +54 -0
- package/src/cli/commands/oauth/connect.test.ts +126 -0
- package/src/cli/commands/oauth/connect.ts +29 -6
- package/src/cli/commands/oauth/index.help.ts +7 -1
- package/src/cli/commands/oauth/status.test.ts +69 -3
- package/src/cli/commands/oauth/status.ts +50 -12
- package/src/cli/commands/plugins.help.ts +13 -2
- package/src/cli/commands/plugins.ts +61 -7
- package/src/cli/commands/telemetry.help.ts +13 -0
- package/src/cli/commands/telemetry.ts +45 -5
- package/src/cli/lib/__tests__/plugin-catalog-local.test.ts +8 -2
- package/src/cli/lib/__tests__/upgrade-plugin.test.ts +213 -9
- package/src/cli/lib/bundled-marketplace.json +93 -36
- package/src/cli/lib/inspect-plugin.ts +5 -1
- package/src/cli/lib/install-from-github.ts +68 -4
- package/src/cli/lib/plugin-catalog-local.ts +6 -2
- package/src/cli/lib/plugin-fingerprint.ts +3 -3
- package/src/cli/lib/upgrade-plugin.ts +236 -35
- package/src/config/__tests__/default-profile-catalog.test.ts +8 -12
- package/src/config/__tests__/plugin-resident-skill-discovery.test.ts +137 -0
- package/src/config/__tests__/profile-materialization.test.ts +1 -88
- package/src/config/bundled-skills/AGENTS.md +3 -30
- package/src/config/bundled-skills/app-builder/SKILL.md +5 -3
- package/src/config/bundled-skills/app-builder/TOOLS.json +23 -0
- package/src/config/bundled-skills/app-builder/tools/app-open.ts +32 -0
- package/src/config/bundled-skills/messaging/tools/messaging-send.ts +1 -1
- package/src/config/bundled-skills/phone-calls/references/CONFIG.md +7 -7
- package/src/config/bundled-skills/schedule/SKILL.md +1 -1
- package/src/config/bundled-skills/schedule/TOOLS.json +1 -1
- package/src/config/bundled-skills/settings/TOOLS.json +3 -1
- package/src/config/bundled-skills/settings/tools/navigate-settings-tab.ts +2 -0
- package/src/config/bundled-skills/settings/tools/voice-config-update.ts +18 -10
- package/src/config/bundled-skills/subagent/SKILL.md +2 -0
- package/src/config/bundled-skills/subagent/TOOLS.json +1 -1
- package/src/config/call-site-defaults.ts +3 -3
- package/src/config/feature-flag-registry.json +24 -39
- package/src/config/llm-resolver.ts +88 -475
- package/src/config/profile-materialization.ts +11 -11
- package/src/config/schema.ts +93 -127
- package/src/config/schemas/__tests__/live-voice.test.ts +24 -6
- package/src/config/schemas/__tests__/stt.test.ts +31 -3
- package/src/config/schemas/live-voice.ts +10 -4
- package/src/config/schemas/llm.ts +52 -15
- package/src/config/schemas/memory-lifecycle.ts +1 -1
- package/src/config/schemas/memory-retrospective.ts +8 -0
- package/src/config/schemas/memory-v2.ts +2 -2
- package/src/config/schemas/memory-v3.ts +1 -1
- package/src/config/schemas/services.ts +6 -3
- package/src/config/schemas/stt.ts +38 -21
- package/src/config/schemas/tts.ts +13 -18
- package/src/config/skills.ts +31 -21
- package/src/context/compactor.ts +44 -7
- package/src/context/post-turn-tool-result-truncation.ts +4 -2
- package/src/context/tool-result-spool.ts +26 -5
- package/src/conversations/__tests__/message-consolidation.test.ts +48 -0
- package/src/conversations/message-consolidation.ts +22 -2
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +5 -12
- package/src/daemon/app-source-watcher.ts +17 -23
- package/src/daemon/chat-credential-redaction.ts +1365 -0
- package/src/daemon/conversation-agent-loop-handlers.ts +627 -34
- package/src/daemon/conversation-agent-loop.ts +71 -31
- package/src/daemon/conversation-error.ts +36 -14
- package/src/daemon/conversation-process.ts +22 -0
- package/src/daemon/conversation-store.ts +35 -0
- package/src/daemon/conversation-surfaces.ts +25 -25
- package/src/daemon/conversation-tool-setup.ts +33 -7
- package/src/daemon/conversation.ts +55 -5
- package/src/daemon/handlers/shared.ts +33 -2
- package/src/daemon/lifecycle.ts +4 -4
- package/src/daemon/message-types/conversations.ts +6 -17
- package/src/daemon/providers-setup.ts +8 -0
- package/src/daemon/tool-setup-types.ts +7 -1
- package/src/daemon/wake-conversation-ops.ts +10 -1
- package/src/hooks/types.ts +9 -0
- package/src/ipc/__tests__/email-ipc.test.ts +90 -0
- package/src/ipc/gateway-client.test.ts +59 -0
- package/src/ipc/gateway-client.ts +70 -27
- package/src/live-voice/__tests__/live-voice-events.test.ts +14 -2
- package/src/live-voice/__tests__/live-voice-integration.test.ts +116 -2
- package/src/live-voice/__tests__/live-voice-vad.test.ts +804 -13
- package/src/live-voice/__tests__/protocol.test.ts +122 -0
- package/src/live-voice/live-voice-session.ts +443 -40
- package/src/live-voice/protocol.ts +143 -1
- package/src/monitoring/__tests__/plugin-source-watch.test.ts +3 -1
- package/src/monitoring/plugin-source-watch.ts +3 -62
- package/src/notifications/README.md +1 -1
- package/src/permissions/checker.ts +8 -4
- package/src/persistence/__tests__/db-init-migrations-ok.test.ts +26 -0
- package/src/persistence/conversation-crud.ts +104 -2
- package/src/persistence/db-init.ts +14 -3
- package/src/persistence/job-handlers/cleanup.ts +15 -7
- package/src/persistence/llm-request-log-store.ts +88 -52
- package/src/persistence/migrations/298-move-memory-jobs-to-memory-db.ts +7 -31
- package/src/persistence/migrations/305-drop-contact-acl-columns.ts +3 -2
- package/src/persistence/migrations/326-move-injection-events-to-memory-db.ts +8 -34
- package/src/persistence/migrations/336-move-memory-v2-activation-logs-to-memory-db.ts +90 -0
- package/src/persistence/migrations/337-move-memory-recall-logs-to-memory-db.ts +114 -0
- package/src/persistence/migrations/338-move-memory-v3-selections-to-memory-db.ts +84 -0
- package/src/persistence/migrations/339-move-activation-sessions-to-memory-db.ts +52 -0
- package/src/persistence/migrations/__tests__/run-migrations.test.ts +155 -0
- package/src/persistence/migrations/helpers/relocation.ts +44 -1
- package/src/persistence/migrations/run-migrations.ts +25 -1
- package/src/persistence/schema/infrastructure.ts +9 -0
- package/src/persistence/schema/memory-core.ts +3 -0
- package/src/persistence/schema/memory-injection.ts +2 -0
- package/src/persistence/steps.ts +36 -0
- package/src/platform/client.test.ts +1 -44
- package/src/platform/client.ts +10 -20
- package/src/platform/consent-cache.test.ts +89 -23
- package/src/platform/consent-cache.ts +71 -33
- package/src/plugin-api/constants.ts +12 -0
- package/src/plugin-api/conversation-turn.ts +37 -14
- package/src/plugin-api/index.ts +11 -1
- package/src/plugin-api/resolve-credential.ts +75 -0
- package/src/plugin-api/vision-support.test.ts +8 -19
- package/src/plugin-api/vision-support.ts +26 -17
- package/src/plugins/collect-source-versions.ts +77 -0
- package/src/plugins/defaults/compaction/compact.ts +6 -0
- package/src/plugins/defaults/compaction/window-manager.ts +9 -0
- package/src/plugins/defaults/empty-response/hooks/post-model-call.ts +18 -24
- package/src/plugins/defaults/empty-response/hooks/user-prompt-submit.ts +38 -0
- package/src/plugins/defaults/empty-response/refusal-quarantine.ts +99 -0
- package/src/plugins/defaults/image-fallback/__tests__/caption-cache-persistence.test.ts +7 -3
- package/src/plugins/defaults/index.ts +8 -1
- package/src/plugins/defaults/max-tokens-continue/hooks/post-model-call.ts +4 -1
- package/src/plugins/defaults/memory/__tests__/activation-session-store.test.ts +48 -6
- package/src/plugins/defaults/memory/__tests__/db-memory-attach.test.ts +28 -22
- package/src/plugins/defaults/memory/__tests__/memory-log-stores-degraded.test.ts +148 -0
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-job.test.ts +80 -8
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-prompt.test.ts +202 -0
- package/src/plugins/defaults/memory/__tests__/memory-v2-activation-log-store.test.ts +64 -25
- package/src/plugins/defaults/memory/__tests__/memory-v2-concept-frequency.test.ts +24 -11
- package/src/plugins/defaults/memory/__tests__/prompt-override.test.ts +70 -6
- package/src/plugins/defaults/memory/__tests__/table-relocation.test.ts +278 -0
- package/src/plugins/defaults/memory/activation-session-store.ts +27 -20
- package/src/plugins/defaults/memory/context-search/sources/memory-v2.ts +2 -9
- package/src/plugins/defaults/memory/context-search/sources/workspace.ts +1 -8
- package/src/plugins/defaults/memory/graph/retriever.test.ts +6 -6
- package/src/plugins/defaults/memory/graph/store.ts +114 -0
- package/src/plugins/defaults/memory/graph/tool-handlers.ts +36 -1
- package/src/plugins/defaults/memory/graph/tools.ts +47 -13
- package/src/plugins/defaults/memory/graph-topology/build-memory-graph.ts +16 -35
- package/src/plugins/defaults/memory/jobs-worker.ts +10 -1
- package/src/plugins/defaults/memory/memory-db.ts +3 -2
- package/src/plugins/defaults/memory/memory-recall-log-store.ts +129 -66
- package/src/plugins/defaults/memory/memory-retrospective-constants.ts +8 -0
- package/src/plugins/defaults/memory/memory-retrospective-job.ts +11 -122
- package/src/plugins/defaults/memory/memory-retrospective-prompt.ts +216 -0
- package/src/plugins/defaults/memory/memory-v2-activation-log-store.ts +84 -46
- package/src/plugins/defaults/memory/memory-v2-concept-frequency.ts +42 -32
- package/src/plugins/defaults/memory/path-containment.ts +21 -0
- package/src/plugins/defaults/memory/prompt-override.ts +51 -13
- package/src/plugins/defaults/memory/tools.test.ts +34 -0
- package/src/plugins/defaults/memory/tools.ts +12 -2
- package/src/plugins/defaults/memory/v2/__tests__/harness-compare.test.ts +19 -15
- package/src/plugins/defaults/memory/v2/__tests__/harness-oracle.test.ts +24 -19
- package/src/plugins/defaults/memory/v2/__tests__/harness-replay-input.test.ts +19 -15
- package/src/plugins/defaults/memory/v2/__tests__/injection.test.ts +22 -2
- package/src/plugins/defaults/memory/v2/__tests__/prompts-consolidation.test.ts +5 -3
- package/src/plugins/defaults/memory/v2/harness/oracle.ts +59 -41
- package/src/plugins/defaults/memory/v2/harness/replay-input.ts +29 -25
- package/src/plugins/defaults/memory/v2/migration.ts +46 -16
- package/src/plugins/defaults/memory/v2/prompts/consolidation.ts +4 -0
- package/src/plugins/defaults/memory/v3/__tests__/carry-integration.test.ts +17 -15
- package/src/plugins/defaults/memory/v3/__tests__/gate.test.ts +24 -22
- package/src/plugins/defaults/memory/v3/__tests__/injection.test.ts +9 -5
- package/src/plugins/defaults/memory/v3/__tests__/orchestrate.test.ts +277 -10
- package/src/plugins/defaults/memory/v3/__tests__/selection-log-store.test.ts +57 -5
- package/src/plugins/defaults/memory/v3/__tests__/shadow-integration.test.ts +9 -7
- package/src/plugins/defaults/memory/v3/__tests__/shadow-plugin.test.ts +38 -7
- package/src/plugins/defaults/memory/v3/hot-set.test.ts +36 -18
- package/src/plugins/defaults/memory/v3/hot-set.ts +12 -14
- package/src/plugins/defaults/memory/v3/learned-edges.test.ts +47 -27
- package/src/plugins/defaults/memory/v3/learned-edges.ts +12 -14
- package/src/plugins/defaults/memory/v3/orchestrate.ts +139 -22
- package/src/plugins/defaults/memory/v3/prune.test.ts +10 -3
- package/src/plugins/defaults/memory/v3/prune.ts +17 -11
- package/src/plugins/defaults/memory/v3/selection-log-store.ts +23 -11
- package/src/plugins/defaults/memory/v3/shadow-plugin.ts +70 -53
- package/src/plugins/defaults/surface-completion-nudge/hooks/post-model-call.ts +9 -6
- package/src/plugins/external-plugin-loader.ts +15 -15
- package/src/plugins/mtime-cache.ts +47 -0
- package/src/plugins/pipeline.ts +9 -1
- package/src/plugins/plugin-execution-context.ts +44 -0
- package/src/plugins/plugin-tree-walk.ts +31 -24
- package/src/plugins/source-fingerprint.ts +3 -4
- package/src/prompts/normalize-onboarding.ts +12 -0
- package/src/prompts/persona-resolver.ts +8 -0
- package/src/prompts/templates/BOOTSTRAP-ACTIVATION-RAIL.md +1 -1
- package/src/providers/__tests__/dispatch-connection-routing.test.ts +6 -9
- package/src/providers/__tests__/registry-native-web-search.test.ts +4 -10
- package/src/providers/__tests__/retry-callsite.test.ts +235 -215
- package/src/providers/__tests__/satellite-connection-routing.test.ts +8 -16
- package/src/providers/atlascloud/client.ts +10 -49
- package/src/providers/baseten/client.ts +43 -0
- package/src/providers/call-site-routing.ts +26 -13
- package/src/providers/connection-resolution.ts +9 -11
- package/src/providers/fetch-provider-catalog.ts +4 -2
- package/src/providers/inference/__tests__/adapter-factory-openai-compatible.test.ts +29 -4
- package/src/providers/inference/__tests__/connection-availability-keyless.test.ts +78 -0
- package/src/providers/inference/adapter-factory.ts +27 -6
- package/src/providers/inference/auth.ts +29 -1
- package/src/providers/inference/backfill.ts +61 -10
- package/src/providers/inference/connection-availability.ts +3 -2
- package/src/providers/inference/resolve-auth.ts +9 -1
- package/src/providers/model-catalog.ts +37 -0
- package/src/providers/openai/__tests__/api-error-normalization.test.ts +24 -2
- package/src/providers/openai/api-key-validation.ts +70 -0
- package/src/providers/retry.ts +2 -0
- package/src/providers/types.ts +11 -4
- package/src/providers/vellum-model-routing.test.ts +26 -0
- package/src/providers/vellum-model-routing.ts +30 -0
- package/src/providers/voice-error-copy.ts +47 -0
- package/src/runtime/agent-wake.ts +40 -24
- package/src/runtime/for-chat-mint-registry.ts +118 -0
- package/src/runtime/reveal-nonce.ts +49 -0
- package/src/runtime/reveal-success-registry.ts +306 -0
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +88 -3
- package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +161 -30
- package/src/runtime/routes/__tests__/migration-vellum-metadata-reconcile.test.ts +7 -0
- package/src/runtime/routes/__tests__/schedule-worker-routes.test.ts +15 -0
- package/src/runtime/routes/app-management-routes.ts +152 -45
- package/src/runtime/routes/app-routes.ts +16 -77
- package/src/runtime/routes/canned-message-complete.ts +16 -16
- package/src/runtime/routes/conversation-management-routes.ts +17 -14
- package/src/runtime/routes/conversation-query-routes.ts +54 -6
- package/src/runtime/routes/conversation-routes.ts +48 -2
- package/src/runtime/routes/credential-routes.ts +116 -3
- package/src/runtime/routes/email-routes.ts +17 -1
- package/src/runtime/routes/inbound-stages/transcribe-audio.test.ts +33 -5
- package/src/runtime/routes/inbound-stages/transcribe-audio.ts +6 -5
- package/src/runtime/routes/inference-provider-connection-routes.ts +77 -28
- package/src/runtime/routes/inference-send-routes.ts +1 -1
- package/src/runtime/routes/internal-telemetry-routes.ts +7 -6
- package/src/runtime/routes/plugins-routes.ts +37 -6
- package/src/runtime/routes/publish-routes.ts +15 -18
- package/src/runtime/routes/schedule-worker-routes.ts +9 -0
- package/src/runtime/routes/secret-routes.ts +10 -0
- package/src/runtime/routes/telemetry-routes.ts +149 -45
- package/src/schedule/__tests__/schedule-timezone.test.ts +101 -0
- package/src/schedule/__tests__/worker-watchdog.test.ts +209 -0
- package/src/schedule/schedule-store.ts +12 -1
- package/src/schedule/schedule-timezone.ts +63 -0
- package/src/schedule/scheduler.ts +100 -6
- package/src/schedule/worker-control.ts +19 -0
- package/src/security/auth-fallback-events-store.ts +7 -6
- package/src/security/secret-scanner.ts +26 -1
- package/src/services/published-app-updater.ts +6 -11
- package/src/stt/stt-stream-session.ts +36 -16
- package/src/subagent/manager.ts +34 -8
- package/src/telemetry/AGENTS.md +30 -1
- package/src/telemetry/__tests__/config-setting-snapshot.test.ts +18 -0
- package/src/telemetry/__tests__/outbox-test-harness.ts +5 -3
- package/src/telemetry/config-setting-snapshot.ts +44 -10
- package/src/telemetry/telemetry-event-sources.test.ts +124 -30
- package/src/telemetry/telemetry-event-sources.ts +137 -83
- package/src/telemetry/telemetry-events-outbox.test.ts +46 -1
- package/src/telemetry/telemetry-events-outbox.ts +60 -9
- package/src/telemetry/telemetry-wire-source.json +1 -1
- package/src/telemetry/telemetry-wire-validation.ts +39 -2
- package/src/telemetry/telemetry-wire.generated.ts +8 -0
- package/src/telemetry/tool-audit.ts +15 -9
- package/src/telemetry/tool-executed-events-store.test.ts +1 -1
- package/src/telemetry/turn-events-store.ts +20 -0
- package/src/telemetry/types.ts +45 -12
- package/src/telemetry/usage-telemetry-reporter.test.ts +294 -25
- package/src/telemetry/usage-telemetry-reporter.ts +117 -18
- package/src/telemetry/watchdog-direct-emit.test.ts +11 -3
- package/src/telemetry/watchdog-direct-emit.ts +11 -6
- package/src/tools/apps/executors.ts +11 -36
- package/src/tools/executor.ts +14 -1
- package/src/tools/host-terminal/host-shell.ts +6 -2
- package/src/tools/network/__tests__/web-fetch-firecrawl.test.ts +1 -1
- package/src/tools/network/__tests__/web-fetch-metadata.test.ts +25 -0
- package/src/tools/network/web-fetch.ts +6 -2
- package/src/tools/skills/sandbox-runner.ts +5 -2
- package/src/tools/subagent/spawn.ts +7 -11
- package/src/tools/terminal/shell.ts +5 -2
- package/src/tools/tool-manifest.ts +0 -2
- package/src/tools/tool-profiler.ts +37 -6
- package/src/tools/ui-surface/channel-variants.ts +101 -0
- package/src/tools/ui-surface/definitions.ts +23 -67
- package/src/tools/ui-surface/surface-shape-docs.ts +229 -0
- package/src/tts/__tests__/provider-adapters.test.ts +18 -0
- package/src/tts/provider-catalog.ts +2 -4
- package/src/tts/providers/deepgram-provider.ts +10 -1
- package/src/types/onboarding-context.ts +8 -0
- package/src/usage/attribution.ts +18 -112
- package/src/{config/bundled-skills/messaging/tools/gmail-mime-helpers.ts → util/mime-type.ts} +4 -1
- package/src/util/provider-error-patterns.ts +7 -1
- package/src/util/worker-process.ts +105 -0
- package/src/watcher/__tests__/telemetry.test.ts +17 -4
- package/src/watcher/telemetry.ts +5 -5
- package/src/workspace/migrations/131-drop-web-fetch-mode.ts +61 -0
- package/src/workspace/migrations/registry.ts +2 -0
- package/src/workspace/provider-commit-message-generator.ts +6 -4
- package/src/__tests__/app-open-proxy.test.ts +0 -67
- package/src/onboarding/onboarding-research-events-store.test.ts +0 -230
- package/src/onboarding/onboarding-research-events-store.ts +0 -104
- package/src/runtime/routes/assets/vellum-design-system.css +0 -2236
- package/src/tools/apps/definitions.ts +0 -73
- package/src/tools/apps/open-proxy.ts +0 -43
|
@@ -883,3 +883,117 @@ export function getNodeEditHistory(
|
|
|
883
883
|
.limit(limit)
|
|
884
884
|
.all();
|
|
885
885
|
}
|
|
886
|
+
|
|
887
|
+
// ---------------------------------------------------------------------------
|
|
888
|
+
// Graph stats
|
|
889
|
+
// ---------------------------------------------------------------------------
|
|
890
|
+
|
|
891
|
+
/** Fidelity counts for active (non-gone) nodes. */
|
|
892
|
+
export interface FidelityBreakdown {
|
|
893
|
+
vivid: number;
|
|
894
|
+
clear: number;
|
|
895
|
+
faded: number;
|
|
896
|
+
gist: number;
|
|
897
|
+
}
|
|
898
|
+
|
|
899
|
+
/** Aggregate health snapshot of the memory v2 graph. */
|
|
900
|
+
export interface GraphStats {
|
|
901
|
+
/** Total active (non-gone) node count. */
|
|
902
|
+
total: number;
|
|
903
|
+
/** Node count by MemoryType. */
|
|
904
|
+
byType: Partial<Record<MemoryType, number>>;
|
|
905
|
+
/** Node count by fidelity, excluding gone. */
|
|
906
|
+
byFidelity: FidelityBreakdown;
|
|
907
|
+
/** Nodes with significance < 0.15 (at risk of decaying away). */
|
|
908
|
+
atRisk: number;
|
|
909
|
+
/** Live edge count — both endpoints are non-gone. */
|
|
910
|
+
edgeCount: number;
|
|
911
|
+
/** Epoch ms of the oldest active node, or null if the graph is empty. */
|
|
912
|
+
oldestCreated: number | null;
|
|
913
|
+
/** Epoch ms of the newest active node, or null if the graph is empty. */
|
|
914
|
+
newestCreated: number | null;
|
|
915
|
+
/** Epoch ms of the most recent reinforcement event, or null if none. */
|
|
916
|
+
lastReinforced: number | null;
|
|
917
|
+
/** Mean significance across all active nodes (0–1). */
|
|
918
|
+
avgSignificance: number;
|
|
919
|
+
/** Up to 5 highest-significance nodes (content, significance, fidelity, type). */
|
|
920
|
+
topNodes: Array<{
|
|
921
|
+
content: string;
|
|
922
|
+
significance: number;
|
|
923
|
+
fidelity: string;
|
|
924
|
+
type: string;
|
|
925
|
+
}>;
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
/**
|
|
929
|
+
* Compute a health snapshot of the memory v2 graph in two queries:
|
|
930
|
+
* 1. A full scan of active nodes (significance DESC) to derive all
|
|
931
|
+
* per-node aggregates in one JS pass.
|
|
932
|
+
* 2. A SQL COUNT of live edges (both endpoints non-gone).
|
|
933
|
+
*
|
|
934
|
+
* Callers that only need the summary number can use `countNodes()` instead.
|
|
935
|
+
*/
|
|
936
|
+
export function computeGraphStats(): GraphStats {
|
|
937
|
+
// Full scan — significance DESC so topNodes is just the first slice.
|
|
938
|
+
const nodes = queryNodes({ fidelityNot: ["gone"] });
|
|
939
|
+
|
|
940
|
+
const byType: Partial<Record<MemoryType, number>> = {};
|
|
941
|
+
const byFidelity: FidelityBreakdown = {
|
|
942
|
+
vivid: 0,
|
|
943
|
+
clear: 0,
|
|
944
|
+
faded: 0,
|
|
945
|
+
gist: 0,
|
|
946
|
+
};
|
|
947
|
+
let atRisk = 0;
|
|
948
|
+
let sigSum = 0;
|
|
949
|
+
let oldestCreated: number | null = null;
|
|
950
|
+
let newestCreated: number | null = null;
|
|
951
|
+
let lastReinforced: number | null = null;
|
|
952
|
+
|
|
953
|
+
for (const n of nodes) {
|
|
954
|
+
byType[n.type] = (byType[n.type] ?? 0) + 1;
|
|
955
|
+
if (n.fidelity !== "gone") {
|
|
956
|
+
byFidelity[n.fidelity as keyof FidelityBreakdown] += 1;
|
|
957
|
+
}
|
|
958
|
+
if (n.significance < 0.15) atRisk++;
|
|
959
|
+
sigSum += n.significance;
|
|
960
|
+
if (oldestCreated === null || n.created < oldestCreated)
|
|
961
|
+
oldestCreated = n.created;
|
|
962
|
+
if (newestCreated === null || n.created > newestCreated)
|
|
963
|
+
newestCreated = n.created;
|
|
964
|
+
if (lastReinforced === null || n.lastReinforced > lastReinforced)
|
|
965
|
+
lastReinforced = n.lastReinforced;
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
// Live edge count: both endpoints must be non-gone.
|
|
969
|
+
const db = getDb();
|
|
970
|
+
const edgeResult = db
|
|
971
|
+
.select({ count: sql<number>`count(*)` })
|
|
972
|
+
.from(memoryGraphEdges)
|
|
973
|
+
.where(
|
|
974
|
+
and(
|
|
975
|
+
sql`NOT EXISTS (SELECT 1 FROM ${memoryGraphNodes} WHERE ${memoryGraphNodes.id} = ${memoryGraphEdges.sourceNodeId} AND ${memoryGraphNodes.fidelity} = 'gone')`,
|
|
976
|
+
sql`NOT EXISTS (SELECT 1 FROM ${memoryGraphNodes} WHERE ${memoryGraphNodes.id} = ${memoryGraphEdges.targetNodeId} AND ${memoryGraphNodes.fidelity} = 'gone')`,
|
|
977
|
+
),
|
|
978
|
+
)
|
|
979
|
+
.get();
|
|
980
|
+
|
|
981
|
+
return {
|
|
982
|
+
total: nodes.length,
|
|
983
|
+
byType,
|
|
984
|
+
byFidelity,
|
|
985
|
+
atRisk,
|
|
986
|
+
edgeCount: edgeResult?.count ?? 0,
|
|
987
|
+
oldestCreated,
|
|
988
|
+
newestCreated,
|
|
989
|
+
lastReinforced,
|
|
990
|
+
avgSignificance: nodes.length > 0 ? sigSum / nodes.length : 0,
|
|
991
|
+
// nodes is already sorted significance DESC — slice gives the top N.
|
|
992
|
+
topNodes: nodes.slice(0, 5).map((n) => ({
|
|
993
|
+
content: n.content,
|
|
994
|
+
significance: n.significance,
|
|
995
|
+
fidelity: n.fidelity,
|
|
996
|
+
type: n.type,
|
|
997
|
+
})),
|
|
998
|
+
};
|
|
999
|
+
}
|
|
@@ -14,7 +14,14 @@ import { enqueueMemoryJob } from "../../../../persistence/jobs-store.js";
|
|
|
14
14
|
import { enqueuePkbIndexJob } from "../jobs/embed-pkb-file.js";
|
|
15
15
|
import { getLogger } from "../logging.js";
|
|
16
16
|
import { getWorkspaceDir } from "../paths.js";
|
|
17
|
-
import {
|
|
17
|
+
import type { GraphStats } from "./store.js";
|
|
18
|
+
import {
|
|
19
|
+
computeGraphStats,
|
|
20
|
+
deleteNode,
|
|
21
|
+
queryNodes,
|
|
22
|
+
recordNodeEdit,
|
|
23
|
+
updateNode,
|
|
24
|
+
} from "./store.js";
|
|
18
25
|
|
|
19
26
|
const log = getLogger("graph-tool-handlers");
|
|
20
27
|
|
|
@@ -429,3 +436,31 @@ export function handleListMemory(
|
|
|
429
436
|
total: filtered.length,
|
|
430
437
|
};
|
|
431
438
|
}
|
|
439
|
+
|
|
440
|
+
// ---------------------------------------------------------------------------
|
|
441
|
+
// handleStatsMemory
|
|
442
|
+
// ---------------------------------------------------------------------------
|
|
443
|
+
|
|
444
|
+
export interface StatsMemoryResult {
|
|
445
|
+
success: boolean;
|
|
446
|
+
message: string;
|
|
447
|
+
stats: GraphStats | null;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
export function handleStatsMemory(config: AssistantConfig): StatsMemoryResult {
|
|
451
|
+
if (!config.memory.v2.enabled) {
|
|
452
|
+
return {
|
|
453
|
+
success: false,
|
|
454
|
+
message: "stats requires memory v2.",
|
|
455
|
+
stats: null,
|
|
456
|
+
};
|
|
457
|
+
}
|
|
458
|
+
const stats = computeGraphStats();
|
|
459
|
+
const n = stats.total;
|
|
460
|
+
const e = stats.edgeCount;
|
|
461
|
+
return {
|
|
462
|
+
success: true,
|
|
463
|
+
message: `${n} active node${n === 1 ? "" : "s"}, ${e} edge${e === 1 ? "" : "s"}.`,
|
|
464
|
+
stats,
|
|
465
|
+
};
|
|
466
|
+
}
|
|
@@ -62,18 +62,33 @@ export const graphRecallDefinition = {
|
|
|
62
62
|
const REMEMBER_DESCRIPTION =
|
|
63
63
|
"Remember anything concrete shared in conversation: corrections, plans, decisions, felt moments, names, dates, commitments, preferences. Corrections are the highest priority — call `remember` the same turn the correction lands. You don't have to call this on every turn; a retrospective pass reviews the conversation after each message-count / time interval and saves what you didn't capture. Use judgment: pause and remember when something feels worth marking, not because the volume is required.";
|
|
64
64
|
|
|
65
|
+
const REMEMBER_CONTENT_DESCRIPTION =
|
|
66
|
+
"The fact(s) to remember. Pass a single string for one fact, or an array of strings to record several independent facts in one call. When a turn surfaces multiple unrelated facts, pass them all as an array in one call rather than calling `remember` once per fact. Write naturally — a preference, a detail, a commitment, a plan. No need to categorize.";
|
|
67
|
+
|
|
65
68
|
/**
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
69
|
+
* Appended to the `content` description only under the wiki memory model
|
|
70
|
+
* (memory v2/v3), where the v2/v3 consolidation prompts treat `[[slug]]`
|
|
71
|
+
* hints as read-first candidates when filing buffer entries. v1/PKB
|
|
72
|
+
* workspaces have no wiki pages for the hints to reference, and the pkb
|
|
73
|
+
* filing job has no instruction to interpret or strip the markup, so it
|
|
74
|
+
* would persist as literal buffer text there.
|
|
72
75
|
*/
|
|
73
|
-
export const
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
76
|
+
export const REMEMBER_PAGE_HINT_GUIDANCE =
|
|
77
|
+
"When a fact relates to memory pages already in your context, reference the most specific ones inline as [[slug]] wikilinks — consolidation reads hinted pages first when filing the fact, which matters most for corrections (the hint names the page carrying the outdated fact). Hint only pages you have actually seen, and prefer specific pages over broad hubs.";
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Build the `remember` input schema. `pageHints` reflects the wiki-memory
|
|
81
|
+
* (`memory.v2.enabled`) state and appends
|
|
82
|
+
* {@link REMEMBER_PAGE_HINT_GUIDANCE} to the `content` description. It is a
|
|
83
|
+
* thunk re-resolved on every read of that description: the registry's
|
|
84
|
+
* finalized tool shares the returned schema object by reference, so a
|
|
85
|
+
* runtime config edit is reflected on the next schema serialization without
|
|
86
|
+
* re-registering the tool.
|
|
87
|
+
*/
|
|
88
|
+
export function buildRememberInputSchema(options: {
|
|
89
|
+
pageHints: () => boolean;
|
|
90
|
+
}) {
|
|
91
|
+
return {
|
|
77
92
|
type: "object",
|
|
78
93
|
properties: {
|
|
79
94
|
content: {
|
|
@@ -81,8 +96,11 @@ export const graphRememberDefinition = {
|
|
|
81
96
|
{ type: "string" },
|
|
82
97
|
{ type: "array", items: { type: "string" }, minItems: 1 },
|
|
83
98
|
],
|
|
84
|
-
description:
|
|
85
|
-
|
|
99
|
+
get description(): string {
|
|
100
|
+
return options.pageHints()
|
|
101
|
+
? `${REMEMBER_CONTENT_DESCRIPTION} ${REMEMBER_PAGE_HINT_GUIDANCE}`
|
|
102
|
+
: REMEMBER_CONTENT_DESCRIPTION;
|
|
103
|
+
},
|
|
86
104
|
},
|
|
87
105
|
finish_turn: {
|
|
88
106
|
type: "boolean",
|
|
@@ -91,5 +109,21 @@ export const graphRememberDefinition = {
|
|
|
91
109
|
},
|
|
92
110
|
},
|
|
93
111
|
required: ["content"],
|
|
94
|
-
}
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Save a fact to the assistant's knowledge base. The fact is appended to
|
|
117
|
+
* `buffer.md` (immediately available in the next conversation) and the daily
|
|
118
|
+
* archive (permanent date-indexed record). When `memory.v2.enabled` is true,
|
|
119
|
+
* writes go under `memory/`; otherwise they go under `pkb/`. Consolidation
|
|
120
|
+
* of the buffer into longer-form storage runs as a separate periodic job in
|
|
121
|
+
* both modes. This base definition carries the mode-neutral schema; the
|
|
122
|
+
* registered tool appends the page-hint guidance on wiki-memory installs via
|
|
123
|
+
* {@link buildRememberInputSchema}.
|
|
124
|
+
*/
|
|
125
|
+
export const graphRememberDefinition = {
|
|
126
|
+
name: "remember",
|
|
127
|
+
description: REMEMBER_DESCRIPTION,
|
|
128
|
+
input_schema: buildRememberInputSchema({ pageHints: () => false }),
|
|
95
129
|
} satisfies ToolDefinition;
|
|
@@ -17,7 +17,6 @@
|
|
|
17
17
|
|
|
18
18
|
import { isMemoryV3Live } from "../../../../config/memory-v3-gate.js";
|
|
19
19
|
import type { AssistantConfig } from "../../../../config/types.js";
|
|
20
|
-
import { getDb } from "../../../../persistence/db-connection.js";
|
|
21
20
|
import { getWorkspaceDir } from "../paths.js";
|
|
22
21
|
import { getPageIndex, type PageIndexEntry } from "../v2/page-index.js";
|
|
23
22
|
import { readPage, renderPageContent } from "../v2/page-store.js";
|
|
@@ -251,28 +250,17 @@ export async function getMemoryGraph(
|
|
|
251
250
|
|
|
252
251
|
const workspaceDir = getWorkspaceDir();
|
|
253
252
|
const pageIndex = await getPageIndex(workspaceDir);
|
|
254
|
-
//
|
|
255
|
-
//
|
|
256
|
-
//
|
|
257
|
-
//
|
|
258
|
-
//
|
|
259
|
-
const entries = pageIndex.entries;
|
|
260
|
-
|
|
261
|
-
// Synthetic rows (skills / CLI commands) carry `modifiedAt: 0` and have no
|
|
262
|
-
// on-disk page. Keyed by slug (not prefix) so a real user page that happens
|
|
263
|
-
// to live under a reserved prefix is NOT mistaken for a synthetic one.
|
|
264
|
-
const syntheticSlugs = new Set(
|
|
265
|
-
entries.filter((e) => e.modifiedAt <= 0).map((e) => e.slug),
|
|
266
|
-
);
|
|
253
|
+
// The Memory graph is the assistant's learned mind: concept pages and the
|
|
254
|
+
// links between them. Skills and plugins have their own dedicated pages, so
|
|
255
|
+
// synthetic capability rows (skills / CLI commands, which carry `modifiedAt: 0`)
|
|
256
|
+
// are excluded here — the map is about what the assistant knows, not what it
|
|
257
|
+
// can do.
|
|
258
|
+
const entries = pageIndex.entries.filter((e) => e.modifiedAt > 0);
|
|
267
259
|
|
|
268
260
|
// Raw (frontmatter + body) page reader, matching the v3 lane build. A read
|
|
269
261
|
// that rejects drops that article's authored/wikilink edges but keeps its
|
|
270
|
-
// numeric fallbacks.
|
|
271
|
-
// their guaranteed-miss read; a real page is read so its links are captured.
|
|
262
|
+
// numeric fallbacks.
|
|
272
263
|
const pageRaw = async (slug: Slug): Promise<string> => {
|
|
273
|
-
if (syntheticSlugs.has(slug)) {
|
|
274
|
-
return "";
|
|
275
|
-
}
|
|
276
264
|
const page = await readPage(workspaceDir, slug);
|
|
277
265
|
if (!page) {
|
|
278
266
|
throw new Error(`page not found: ${slug}`);
|
|
@@ -289,27 +277,20 @@ export async function getMemoryGraph(
|
|
|
289
277
|
// little extra edge noise) is a fair trade. Floors keep the thresholds sane
|
|
290
278
|
// even when the retrieval config is aggressive or disables the lane.
|
|
291
279
|
const learned = config.memory.v3.learnedEdges;
|
|
292
|
-
const learnedGraph = computeLearnedEdgeGraph(
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
maxPerPage: Math.max(learned.maxPerPage, GRAPH_LEARNED_MIN_MAX_PER_PAGE),
|
|
302
|
-
now: Date.now(),
|
|
303
|
-
windowMs: LEARNED_EDGES_WINDOW_DAYS * DAY_MS,
|
|
304
|
-
knownSlugs: new Set(entries.map((e) => e.slug)),
|
|
305
|
-
},
|
|
306
|
-
);
|
|
280
|
+
const learnedGraph = computeLearnedEdgeGraph({
|
|
281
|
+
halfLifeMs: learned.halfLifeDays * DAY_MS,
|
|
282
|
+
minCount: Math.max(1, learned.minCount * GRAPH_LEARNED_MIN_COUNT_FACTOR),
|
|
283
|
+
npmiFloor: Math.max(0, learned.npmiFloor * GRAPH_LEARNED_NPMI_FLOOR_FACTOR),
|
|
284
|
+
maxPerPage: Math.max(learned.maxPerPage, GRAPH_LEARNED_MIN_MAX_PER_PAGE),
|
|
285
|
+
now: Date.now(),
|
|
286
|
+
windowMs: LEARNED_EDGES_WINDOW_DAYS * DAY_MS,
|
|
287
|
+
knownSlugs: new Set(entries.map((e) => e.slug)),
|
|
288
|
+
});
|
|
307
289
|
|
|
308
290
|
const assembled = assembleMemoryGraph({
|
|
309
291
|
entries,
|
|
310
292
|
staticAdjacency: staticGraph.adjacency,
|
|
311
293
|
learnedAdjacency: learnedGraph.adjacency,
|
|
312
|
-
pruneDisconnectedNonConcepts: true,
|
|
313
294
|
});
|
|
314
295
|
|
|
315
296
|
return { backend: BACKEND_MEMORY_V3, supported: true, ...assembled };
|
|
@@ -665,7 +665,10 @@ function recordCleanupEnqueued(kind: CleanupJobKind, nowMs: number): void {
|
|
|
665
665
|
* Enqueue periodic cleanup jobs, each on a cadence equal to its own retention
|
|
666
666
|
* window. A job that keeps data for N is re-enqueued at most once per N:
|
|
667
667
|
* pruning that retains LLM logs for 1h runs hourly, pruning that retains
|
|
668
|
-
* conversations for 30d runs every 30d.
|
|
668
|
+
* conversations for 30d runs every 30d. A non-positive window disables its job
|
|
669
|
+
* (`conversationRetentionDays`/`auditLog.retentionDays` of 0, or
|
|
670
|
+
* `llmRequestLogRetentionMs` of `null`/0) — a 0 window would otherwise make the
|
|
671
|
+
* cadence 0 and busy-loop the enqueue. Each job's throttle is tracked
|
|
669
672
|
* independently in cleanup-schedule-state (and persisted via checkpoints so the
|
|
670
673
|
* cadence survives restarts), and enqueue is deduped in jobs-store, so repeated
|
|
671
674
|
* calls remain safe.
|
|
@@ -708,8 +711,14 @@ export function maybeEnqueueScheduledCleanupJobs(
|
|
|
708
711
|
);
|
|
709
712
|
}
|
|
710
713
|
|
|
714
|
+
// A retention of `null` or `0` disables LLM-request-log pruning (keep
|
|
715
|
+
// forever). `0` must be excluded here, not just `null`: the cadence interval
|
|
716
|
+
// equals the retention window, so `isDue("llm_request_logs", 0)` reduces to
|
|
717
|
+
// `nowMs - lastEnqueue >= 0` — always true — which would re-enqueue the prune
|
|
718
|
+
// on every idle/drain tick and spin a sqlite3 subprocess many times a second.
|
|
711
719
|
if (
|
|
712
720
|
cleanup.llmRequestLogRetentionMs !== null &&
|
|
721
|
+
cleanup.llmRequestLogRetentionMs > 0 &&
|
|
713
722
|
isDue("llm_request_logs", cleanup.llmRequestLogRetentionMs)
|
|
714
723
|
) {
|
|
715
724
|
const jobId = enqueuePruneOldLlmRequestLogsJob(
|
|
@@ -5,8 +5,9 @@ const log = getLogger("memory-db");
|
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* The plugin's accessor for the dedicated memory database
|
|
8
|
-
* (`assistant-memory.db`), where the memory plugin's relocated tables live
|
|
9
|
-
*
|
|
8
|
+
* (`assistant-memory.db`), where the memory plugin's relocated tables live.
|
|
9
|
+
* The `move-*-to-memory-db` migrations in `persistence/migrations/` define
|
|
10
|
+
* the current set of relocated tables.
|
|
10
11
|
*
|
|
11
12
|
* Fail-soft: returns `null` when the file cannot be opened, logging a warn
|
|
12
13
|
* tagged with the calling context. Callers degrade rather than throw — the
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { and, eq, inArray, isNull } from "drizzle-orm";
|
|
2
1
|
import { v4 as uuid } from "uuid";
|
|
3
2
|
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
3
|
+
import { getLogger } from "./logging.js";
|
|
4
|
+
import { memorySqliteOrNull } from "./memory-db.js";
|
|
5
|
+
|
|
6
|
+
const log = getLogger("memory-recall-log-store");
|
|
6
7
|
|
|
7
8
|
export interface RecordMemoryRecallLogParams {
|
|
8
9
|
conversationId: string;
|
|
@@ -29,51 +30,74 @@ export interface RecordMemoryRecallLogParams {
|
|
|
29
30
|
export function recordMemoryRecallLog(
|
|
30
31
|
params: RecordMemoryRecallLogParams,
|
|
31
32
|
): void {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
33
|
+
// Best-effort — telemetry writes must never abort the agent turn, so a
|
|
34
|
+
// degraded memory connection or a failed insert only logs a warning.
|
|
35
|
+
try {
|
|
36
|
+
const raw = memorySqliteOrNull("recordMemoryRecallLog");
|
|
37
|
+
if (!raw) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
raw
|
|
41
|
+
.prepare(
|
|
42
|
+
`INSERT INTO memory_recall_logs (
|
|
43
|
+
id, conversation_id, message_id, enabled, degraded, provider,
|
|
44
|
+
model, degradation_json, semantic_hits, merged_count,
|
|
45
|
+
selected_count, tier1_count, tier2_count,
|
|
46
|
+
hybrid_search_latency_ms, sparse_vector_used, injected_tokens,
|
|
47
|
+
latency_ms, top_candidates_json, injected_text, reason,
|
|
48
|
+
query_context, created_at
|
|
49
|
+
) VALUES (?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
50
|
+
)
|
|
51
|
+
.run(
|
|
52
|
+
uuid(),
|
|
53
|
+
params.conversationId,
|
|
54
|
+
params.enabled ? 1 : 0,
|
|
55
|
+
params.degraded ? 1 : 0,
|
|
56
|
+
params.provider ?? null,
|
|
57
|
+
params.model ?? null,
|
|
58
|
+
params.degradationJson ? JSON.stringify(params.degradationJson) : null,
|
|
59
|
+
params.semanticHits,
|
|
60
|
+
params.mergedCount,
|
|
61
|
+
params.selectedCount,
|
|
62
|
+
params.tier1Count,
|
|
63
|
+
params.tier2Count,
|
|
64
|
+
params.hybridSearchLatencyMs,
|
|
65
|
+
params.sparseVectorUsed ? 1 : 0,
|
|
66
|
+
params.injectedTokens,
|
|
67
|
+
params.latencyMs,
|
|
68
|
+
JSON.stringify(params.topCandidatesJson),
|
|
69
|
+
params.injectedText ?? null,
|
|
70
|
+
params.reason ?? null,
|
|
71
|
+
params.queryContext ?? null,
|
|
72
|
+
Date.now(),
|
|
73
|
+
);
|
|
74
|
+
} catch (err) {
|
|
75
|
+
log.warn({ err }, "failed to record memory recall log; continuing");
|
|
76
|
+
}
|
|
61
77
|
}
|
|
62
78
|
|
|
63
79
|
export function backfillMemoryRecallLogMessageId(
|
|
64
80
|
conversationId: string,
|
|
65
81
|
messageId: string,
|
|
66
82
|
): void {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
83
|
+
try {
|
|
84
|
+
const raw = memorySqliteOrNull("backfillMemoryRecallLogMessageId");
|
|
85
|
+
if (!raw) {
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
raw
|
|
89
|
+
.prepare(
|
|
90
|
+
`UPDATE memory_recall_logs
|
|
91
|
+
SET message_id = ?
|
|
92
|
+
WHERE conversation_id = ? AND message_id IS NULL`,
|
|
93
|
+
)
|
|
94
|
+
.run(messageId, conversationId);
|
|
95
|
+
} catch (err) {
|
|
96
|
+
log.warn(
|
|
97
|
+
{ err },
|
|
98
|
+
"failed to backfill memory recall log messageId; continuing",
|
|
99
|
+
);
|
|
100
|
+
}
|
|
77
101
|
}
|
|
78
102
|
|
|
79
103
|
export interface MemoryRecallLog {
|
|
@@ -104,9 +128,13 @@ export interface MemoryRecallLog {
|
|
|
104
128
|
* Entries already in inspector format pass through unchanged.
|
|
105
129
|
*/
|
|
106
130
|
export function normalizeTopCandidates(raw: unknown): unknown {
|
|
107
|
-
if (!Array.isArray(raw))
|
|
131
|
+
if (!Array.isArray(raw)) {
|
|
132
|
+
return raw;
|
|
133
|
+
}
|
|
108
134
|
return raw.flatMap((entry: Record<string, unknown>) => {
|
|
109
|
-
if (!entry || typeof entry !== "object")
|
|
135
|
+
if (!entry || typeof entry !== "object") {
|
|
136
|
+
return [];
|
|
137
|
+
}
|
|
110
138
|
|
|
111
139
|
// Start with a shallow copy, then apply field renames
|
|
112
140
|
const { key, finalScore, semantic, recency, kind: _kind, ...rest } = entry;
|
|
@@ -137,36 +165,71 @@ export function normalizeTopCandidates(raw: unknown): unknown {
|
|
|
137
165
|
});
|
|
138
166
|
}
|
|
139
167
|
|
|
168
|
+
interface MemoryRecallLogRow {
|
|
169
|
+
enabled: number;
|
|
170
|
+
degraded: number;
|
|
171
|
+
provider: string | null;
|
|
172
|
+
model: string | null;
|
|
173
|
+
degradation_json: string | null;
|
|
174
|
+
semantic_hits: number;
|
|
175
|
+
merged_count: number;
|
|
176
|
+
selected_count: number;
|
|
177
|
+
tier1_count: number;
|
|
178
|
+
tier2_count: number;
|
|
179
|
+
hybrid_search_latency_ms: number;
|
|
180
|
+
sparse_vector_used: number;
|
|
181
|
+
injected_tokens: number;
|
|
182
|
+
latency_ms: number;
|
|
183
|
+
top_candidates_json: string;
|
|
184
|
+
injected_text: string | null;
|
|
185
|
+
reason: string | null;
|
|
186
|
+
query_context: string | null;
|
|
187
|
+
}
|
|
188
|
+
|
|
140
189
|
export function getMemoryRecallLogByMessageIds(
|
|
141
190
|
messageIds: string[],
|
|
142
191
|
): MemoryRecallLog | null {
|
|
143
|
-
if (messageIds.length === 0)
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
const row =
|
|
192
|
+
if (messageIds.length === 0) {
|
|
193
|
+
return null;
|
|
194
|
+
}
|
|
195
|
+
const raw = memorySqliteOrNull("getMemoryRecallLogByMessageIds");
|
|
196
|
+
if (!raw) {
|
|
197
|
+
return null;
|
|
198
|
+
}
|
|
199
|
+
const placeholders = messageIds.map(() => "?").join(",");
|
|
200
|
+
const row = raw
|
|
201
|
+
.query(
|
|
202
|
+
`SELECT enabled, degraded, provider, model, degradation_json,
|
|
203
|
+
semantic_hits, merged_count, selected_count, tier1_count,
|
|
204
|
+
tier2_count, hybrid_search_latency_ms, sparse_vector_used,
|
|
205
|
+
injected_tokens, latency_ms, top_candidates_json,
|
|
206
|
+
injected_text, reason, query_context
|
|
207
|
+
FROM memory_recall_logs
|
|
208
|
+
WHERE message_id IN (${placeholders})
|
|
209
|
+
LIMIT 1`,
|
|
210
|
+
)
|
|
211
|
+
.get(...messageIds) as MemoryRecallLogRow | null;
|
|
212
|
+
if (!row) {
|
|
213
|
+
return null;
|
|
214
|
+
}
|
|
152
215
|
return {
|
|
153
216
|
enabled: !!row.enabled,
|
|
154
217
|
degraded: !!row.degraded,
|
|
155
218
|
provider: row.provider,
|
|
156
219
|
model: row.model,
|
|
157
|
-
degradation: row.
|
|
158
|
-
semanticHits: row.
|
|
159
|
-
mergedCount: row.
|
|
160
|
-
selectedCount: row.
|
|
161
|
-
tier1Count: row.
|
|
162
|
-
tier2Count: row.
|
|
163
|
-
hybridSearchLatencyMs: row.
|
|
164
|
-
sparseVectorUsed: !!row.
|
|
165
|
-
injectedTokens: row.
|
|
166
|
-
latencyMs: row.
|
|
167
|
-
topCandidates: normalizeTopCandidates(JSON.parse(row.
|
|
168
|
-
injectedText: row.
|
|
220
|
+
degradation: row.degradation_json ? JSON.parse(row.degradation_json) : null,
|
|
221
|
+
semanticHits: row.semantic_hits,
|
|
222
|
+
mergedCount: row.merged_count,
|
|
223
|
+
selectedCount: row.selected_count,
|
|
224
|
+
tier1Count: row.tier1_count,
|
|
225
|
+
tier2Count: row.tier2_count,
|
|
226
|
+
hybridSearchLatencyMs: row.hybrid_search_latency_ms,
|
|
227
|
+
sparseVectorUsed: !!row.sparse_vector_used,
|
|
228
|
+
injectedTokens: row.injected_tokens,
|
|
229
|
+
latencyMs: row.latency_ms,
|
|
230
|
+
topCandidates: normalizeTopCandidates(JSON.parse(row.top_candidates_json)),
|
|
231
|
+
injectedText: row.injected_text,
|
|
169
232
|
reason: row.reason,
|
|
170
|
-
queryContext: row.
|
|
233
|
+
queryContext: row.query_context,
|
|
171
234
|
};
|
|
172
235
|
}
|
|
@@ -70,3 +70,11 @@ export const SKILL_CARD_MESSAGE_KIND = "skill-authored-card";
|
|
|
70
70
|
* the `"memory_retrospective"` member of `TitleOrigin`.
|
|
71
71
|
*/
|
|
72
72
|
export const MEMORY_RETROSPECTIVE_ORIGIN = "memory_retrospective";
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Bundled skill that provides the retrospective's authoring tools
|
|
76
|
+
* (`find_similar_skills`, `scaffold_managed_skill`, and the `skill_load`
|
|
77
|
+
* target). Preactivated for the fork wake so those tools join the turn's active
|
|
78
|
+
* set from turn 1, and matched by the permission checker's origin-scoped grant.
|
|
79
|
+
*/
|
|
80
|
+
export const SKILL_MANAGEMENT_SKILL_ID = "skill-management";
|