@vellumai/assistant 0.10.2-dev.202606250318.5e7cfb0 → 0.10.2
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/bun.lock +0 -20
- package/docs/workspace-tools.md +33 -42
- package/eslint-rules/cli-no-daemon-internals.js +0 -6
- package/node_modules/@vellumai/gateway-client/src/__tests__/trust-verdict-contract.test.ts +0 -31
- package/node_modules/@vellumai/gateway-client/src/gateway-ipc-contracts.ts +0 -44
- package/node_modules/@vellumai/gateway-client/src/index.ts +0 -14
- package/node_modules/@vellumai/gateway-client/src/trust-verdict-contract.ts +0 -17
- package/node_modules/@vellumai/service-contracts/package.json +0 -1
- package/node_modules/@vellumai/service-contracts/src/index.ts +0 -1
- package/openapi.yaml +0 -155
- package/package.json +1 -4
- package/scripts/test.sh +15 -36
- package/src/__tests__/actor-token-service.test.ts +14 -36
- package/src/__tests__/agent-loop-override-profile.test.ts +0 -1
- package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +0 -2
- package/src/__tests__/agent-wake-override-profile.test.ts +0 -2
- package/src/__tests__/annotate-activity-metadata.test.ts +0 -2
- package/src/__tests__/annotate-risk-options.test.ts +0 -2
- package/src/__tests__/approval-cascade.test.ts +0 -2
- package/src/__tests__/assistant-attachments.test.ts +0 -42
- package/src/__tests__/background-workers-disk-pressure.test.ts +0 -2
- package/src/__tests__/btw-routes.test.ts +0 -2
- package/src/__tests__/build-persisted-content.test.ts +0 -2
- package/src/__tests__/call-controller.test.ts +0 -19
- package/src/__tests__/channel-guardian.test.ts +58 -94
- package/src/__tests__/channel-reply-delivery.test.ts +0 -2
- package/src/__tests__/compaction-events.test.ts +0 -2
- package/src/__tests__/compaction.benchmark.test.ts +0 -2
- package/src/__tests__/compactor-call-site-logging.test.ts +0 -2
- package/src/__tests__/compactor-low-watermark-cut.test.ts +0 -2
- package/src/__tests__/compactor-preserved-tail-count.test.ts +0 -2
- package/src/__tests__/compactor-summary-call-truncation.test.ts +0 -2
- package/src/__tests__/compactor-web-search-strip.test.ts +0 -2
- package/src/__tests__/config-loader-backfill.test.ts +10 -123
- package/src/__tests__/config-schema.test.ts +0 -1
- package/src/__tests__/confirmation-request-guardian-bridge.test.ts +29 -31
- package/src/__tests__/contacts-relay-reads.test.ts +15 -13
- package/src/__tests__/conversation-abort-tool-results.test.ts +0 -2
- package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +0 -2
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +0 -2
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +0 -2
- package/src/__tests__/conversation-agent-loop.test.ts +0 -134
- package/src/__tests__/conversation-analysis-routes.test.ts +0 -2
- package/src/__tests__/conversation-app-control-lifecycle.test.ts +0 -2
- package/src/__tests__/conversation-confirmation-signals.test.ts +0 -2
- package/src/__tests__/conversation-history-web-search.test.ts +0 -2
- package/src/__tests__/conversation-load-history-repair.test.ts +0 -2
- package/src/__tests__/conversation-load-history-stripped.test.ts +0 -2
- package/src/__tests__/conversation-pairing.test.ts +0 -2
- package/src/__tests__/conversation-process-app-control-preactivation.test.ts +0 -2
- package/src/__tests__/conversation-process-callsite.test.ts +0 -2
- package/src/__tests__/conversation-provider-retry-repair.test.ts +0 -2
- package/src/__tests__/conversation-queue.test.ts +0 -91
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +0 -14
- package/src/__tests__/conversation-routes-slash-commands.test.ts +0 -14
- package/src/__tests__/conversation-slash-queue.test.ts +0 -2
- package/src/__tests__/conversation-slash-unknown.test.ts +0 -2
- package/src/__tests__/conversation-speed-override.test.ts +0 -2
- package/src/__tests__/conversation-surfaces-task-progress.test.ts +0 -29
- package/src/__tests__/conversation-title-service.test.ts +0 -2
- package/src/__tests__/conversation-tool-setup-attribution.test.ts +0 -47
- package/src/__tests__/conversation-usage.test.ts +0 -2
- package/src/__tests__/conversation-workspace-cache-state.test.ts +0 -2
- package/src/__tests__/conversation-workspace-injection.test.ts +0 -2
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +0 -2
- package/src/__tests__/credential-security-invariants.test.ts +1 -1
- package/src/__tests__/db-migration-rollback.test.ts +171 -205
- package/src/__tests__/db-test-helpers.ts +4 -5
- package/src/__tests__/deterministic-verification-control-plane.test.ts +2 -4
- package/src/__tests__/disk-pressure-guard.test.ts +0 -41
- package/src/__tests__/dm-persistence.test.ts +0 -2
- package/src/__tests__/emit-signal-routing-intent.test.ts +5 -10
- package/src/__tests__/events-dev-bypass-actor.test.ts +1 -7
- package/src/__tests__/exploration-drift-hook.test.ts +2 -3
- package/src/__tests__/filing-service.test.ts +0 -2
- package/src/__tests__/guardian-binding-drift-heal.test.ts +10 -75
- package/src/__tests__/guardian-dispatch.test.ts +1 -95
- package/src/__tests__/guardian-outbound-http.test.ts +0 -13
- package/src/__tests__/heartbeat-disk-pressure.test.ts +0 -2
- package/src/__tests__/heartbeat-service.test.ts +0 -2
- package/src/__tests__/helpers/channel-test-adapter.ts +7 -1
- package/src/__tests__/host-app-control-routes.test.ts +30 -24
- package/src/__tests__/host-bash-routes.test.ts +41 -31
- package/src/__tests__/host-browser-routes.test.ts +32 -26
- package/src/__tests__/host-cu-routes-targeted.test.ts +33 -25
- package/src/__tests__/host-file-routes-targeted.test.ts +52 -40
- package/src/__tests__/host-transfer-routes-targeted.test.ts +43 -31
- package/src/__tests__/http-user-message-parity.test.ts +8 -290
- package/src/__tests__/inbound-invite-redemption.test.ts +0 -28
- package/src/__tests__/inbound-slack-persistence.test.ts +0 -2
- package/src/__tests__/invite-redemption-service.test.ts +0 -198
- package/src/__tests__/llm-context-normalization.test.ts +0 -105
- package/src/__tests__/llm-request-log-error-payload.test.ts +9 -71
- package/src/__tests__/llm-usage-store.test.ts +0 -25
- package/src/__tests__/mcp-health-check.test.ts +1 -2
- package/src/__tests__/media-stream-server-integration.test.ts +0 -127
- package/src/__tests__/memory-retrieval-hook.test.ts +0 -2
- package/src/__tests__/messaging-send-tool.test.ts +0 -2
- package/src/__tests__/migration-import-from-url.test.ts +2 -2
- package/src/__tests__/mtime-cache.test.ts +5 -146
- package/src/__tests__/native-web-search.test.ts +0 -2
- package/src/__tests__/non-member-access-request.test.ts +17 -189
- package/src/__tests__/notification-broadcaster.test.ts +0 -4
- package/src/__tests__/notification-decision-recipient-context.test.ts +32 -33
- package/src/__tests__/notification-deep-link.test.ts +0 -6
- package/src/__tests__/notification-guardian-path.test.ts +0 -19
- package/src/__tests__/openai-provider.test.ts +12 -22
- package/src/__tests__/openai-responses-provider.test.ts +2 -12
- package/src/__tests__/outbound-slack-persistence.test.ts +0 -2
- package/src/__tests__/pending-interactions-resolved-event.test.ts +4 -7
- package/src/__tests__/persistence-secret-redaction.test.ts +0 -2
- package/src/__tests__/plugin-bootstrap.test.ts +73 -3
- package/src/__tests__/plugin-route-contribution.test.ts +17 -4
- package/src/__tests__/plugin-tool-contribution.test.ts +18 -3
- package/src/__tests__/plugin-types.test.ts +2 -0
- package/src/__tests__/process-message-background-slack.test.ts +0 -2
- package/src/__tests__/process-message-display-content.test.ts +0 -2
- package/src/__tests__/provider-error-scenarios.test.ts +4 -5
- package/src/__tests__/provider-usage-tracking.test.ts +0 -39
- package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +0 -2
- package/src/__tests__/registry.test.ts +1 -4
- package/src/__tests__/relay-server.test.ts +25 -694
- package/src/__tests__/runtime-attachment-metadata.test.ts +1 -0
- package/src/__tests__/secret-ingress-http.test.ts +0 -14
- package/src/__tests__/send-endpoint-busy.test.ts +8 -30
- package/src/__tests__/skills.test.ts +0 -44
- package/src/__tests__/slack-inbound-verification.test.ts +2 -47
- package/src/__tests__/stt-hints.test.ts +13 -44
- package/src/__tests__/subagent-detail.test.ts +0 -27
- package/src/__tests__/subagent-disposal.test.ts +0 -65
- package/src/__tests__/subagent-notify-parent.test.ts +0 -2
- package/src/__tests__/subagent-role-registry.test.ts +2 -7
- package/src/__tests__/subagent-spawn-tool-fork.test.ts +0 -2
- package/src/__tests__/subagent-tools.test.ts +0 -2
- package/src/__tests__/suggestion-routes.test.ts +0 -2
- package/src/__tests__/title-generate-hook.test.ts +0 -2
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +0 -2
- package/src/__tests__/tool-executor.test.ts +11 -16
- package/src/__tests__/tool-preview-lifecycle.test.ts +0 -2
- package/src/__tests__/tool-result-metadata-plumbing.test.ts +0 -2
- package/src/__tests__/tool-start-timestamp.test.ts +0 -2
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +10 -10
- package/src/__tests__/twilio-routes.test.ts +0 -96
- package/src/__tests__/ui-file-upload-surface.test.ts +0 -86
- package/src/__tests__/verification-control-plane-policy.test.ts +0 -2
- package/src/__tests__/voice-invite-redemption.test.ts +0 -33
- package/src/__tests__/web-search-backend-failure.test.ts +0 -2
- package/src/__tests__/workspace-migration-remove-hooks.test.ts +35 -14
- package/src/__tests__/workspace-tool-loader.test.ts +2 -195
- package/src/__tests__/workspace-tools-watcher-flag.test.ts +70 -0
- package/src/agent/loop.ts +0 -56
- package/src/api/index.ts +1 -19
- package/src/api/responses/llm-request-log-entry.ts +0 -29
- package/src/api/responses/subagent-detail.ts +0 -17
- package/src/api/surfaces.ts +3 -39
- package/src/approvals/guardian-request-resolvers.ts +11 -1
- package/src/calls/__tests__/relay-setup-router.test.ts +4 -262
- package/src/calls/call-domain.ts +3 -3
- package/src/calls/guardian-dispatch.ts +8 -10
- package/src/calls/inbound-trust-reader.ts +1 -17
- package/src/calls/media-stream-server.ts +0 -21
- package/src/calls/relay-server.ts +50 -167
- package/src/calls/relay-setup-router.ts +7 -37
- package/src/calls/relay-verification.ts +4 -4
- package/src/calls/stt-hints.ts +12 -9
- package/src/calls/twilio-routes.ts +4 -14
- package/src/channels/types.ts +20 -10
- package/src/cli/commands/__tests__/cache.test.ts +1 -8
- package/src/cli/commands/cache.ts +181 -194
- package/src/cli/commands/db/__tests__/repair.test.ts +5 -6
- package/src/cli/commands/db/status.ts +1 -37
- package/src/cli/commands/mcp.ts +218 -252
- package/src/cli/commands/memory/index.ts +0 -2
- package/src/cli/commands/plugins.ts +3 -75
- package/src/cli/lib/__tests__/install-from-github.test.ts +0 -102
- package/src/cli/lib/__tests__/list-installed-plugins.test.ts +1 -160
- package/src/cli/lib/list-installed-plugins.ts +1 -179
- package/src/config/__tests__/sync-gated-profiles.test.ts +3 -11
- package/src/config/bundled-skills/contacts/tools/contact-merge.ts +17 -27
- package/src/config/bundled-skills/contacts/tools/contact-search.ts +3 -13
- package/src/config/bundled-skills/subagent/SKILL.md +1 -1
- package/src/config/bundled-skills/subagent/TOOLS.json +1 -1
- package/src/config/feature-flag-registry.json +13 -5
- package/src/config/loader.ts +5 -38
- package/src/config/schemas/__tests__/memory-v3.test.ts +0 -1
- package/src/config/schemas/memory-lifecycle.ts +0 -12
- package/src/config/schemas/memory-v3.ts +0 -7
- package/src/config/schemas/memory.ts +0 -4
- package/src/config/schemas/timeouts.ts +0 -8
- package/src/config/seed-inference-profiles.ts +11 -21
- package/src/config/skills.ts +5 -27
- package/src/config/sync-gated-profiles.ts +13 -12
- package/src/contacts/contacts-write.ts +0 -3
- package/src/daemon/assistant-attachments.ts +4 -27
- package/src/daemon/conversation-agent-loop.ts +0 -28
- package/src/daemon/conversation-process.ts +16 -35
- package/src/daemon/conversation-surfaces.ts +38 -111
- package/src/daemon/conversation-tool-setup.ts +16 -50
- package/src/daemon/conversation.ts +1 -13
- package/src/daemon/disk-pressure-guard.ts +2 -12
- package/src/daemon/event-loop-watchdog.ts +1 -28
- package/src/daemon/external-plugins-bootstrap.ts +34 -4
- package/src/daemon/handlers/__tests__/config-a2a-redeem.test.ts +0 -25
- package/src/daemon/handlers/config-a2a.ts +14 -6
- package/src/daemon/handlers/config-channels.ts +22 -78
- package/src/daemon/handlers/conversations.ts +0 -77
- package/src/daemon/lifecycle.ts +0 -4
- package/src/daemon/mcp-reload-service.ts +0 -10
- package/src/daemon/memory-v2-startup.test.ts +0 -72
- package/src/daemon/memory-v2-startup.ts +19 -87
- package/src/daemon/message-types/conversations.ts +0 -2
- package/src/daemon/message-types/surfaces.ts +12 -12
- package/src/daemon/server.ts +4 -0
- package/src/daemon/shutdown-handlers.ts +0 -20
- package/src/daemon/tool-setup-types.ts +0 -9
- package/src/daemon/workspace-tools-watcher.ts +328 -0
- package/src/ipc/__tests__/clients-list-ipc.test.ts +1 -1
- package/src/ipc/assistant-server.ts +2 -2
- package/src/mcp/__tests__/mcp-auth-orchestrator.test.ts +0 -1
- package/src/mcp/client.ts +1 -15
- package/src/mcp/mcp-auth-orchestrator.ts +1 -6
- package/src/mcp/mcp-oauth-provider.ts +8 -19
- package/src/memory/__tests__/memory-retrospective-job.test.ts +0 -8
- package/src/memory/conversation-crud.ts +0 -38
- package/src/memory/db-connection.ts +3 -22
- package/src/memory/db-init.ts +502 -36
- package/src/memory/db-singleton.ts +4 -6
- package/src/memory/jobs-worker.ts +0 -58
- package/src/memory/llm-request-log-store.ts +1 -26
- package/src/memory/llm-usage-store.ts +20 -48
- package/src/memory/memory-retrospective-job.ts +8 -9
- package/src/memory/migrations/209-strip-thinking-from-consolidated.ts +56 -130
- package/src/memory/migrations/__tests__/run-migrations.test.ts +2 -2
- package/src/memory/migrations/registry.ts +573 -0
- package/src/memory/migrations/run-migrations.ts +6 -90
- package/src/memory/migrations/validate-migration-state.ts +66 -101
- package/src/memory/schema/conversations.ts +0 -9
- package/src/memory/schema/infrastructure.ts +0 -20
- package/src/memory/v2/__tests__/cli-command-store.test.ts +0 -25
- package/src/memory/v2/__tests__/skill-store.test.ts +0 -80
- package/src/memory/v2/cli-command-store.ts +38 -75
- package/src/memory/v2/prompts/consolidation.ts +82 -13
- package/src/memory/v2/prompts/router.ts +93 -21
- package/src/memory/v2/skill-store.ts +31 -68
- package/src/notifications/__tests__/broadcaster.test.ts +8 -16
- package/src/notifications/__tests__/decision-engine.test.ts +9 -78
- package/src/notifications/broadcaster.ts +1 -8
- package/src/notifications/decision-engine.ts +7 -15
- package/src/notifications/destination-resolver.ts +24 -68
- package/src/notifications/emit-signal.ts +14 -39
- package/src/permissions/question-prompter.test.ts +1 -1
- package/src/permissions/question-prompter.ts +4 -7
- package/src/plugin-api/index.ts +6 -6
- package/src/plugin-api/types.ts +5 -3
- package/src/plugin-api/vision-support.test.ts +4 -28
- package/src/plugin-api/vision-support.ts +31 -66
- package/src/plugins/defaults/advisor/__tests__/consult.test.ts +0 -161
- package/src/plugins/defaults/advisor/consult.ts +6 -110
- package/src/plugins/defaults/advisor/steering.ts +2 -14
- package/src/plugins/defaults/advisor/tools/advisor.ts +5 -32
- package/src/plugins/defaults/exploration-drift/hooks/post-tool-use.ts +1 -2
- package/src/plugins/defaults/image-fallback/__tests__/image-fallback.test.ts +7 -47
- package/src/plugins/defaults/image-fallback/hooks/post-tool-use.ts +11 -10
- package/src/plugins/defaults/image-fallback/hooks/user-prompt-submit.ts +20 -12
- package/src/plugins/defaults/image-fallback/src/caption-blocks.ts +11 -42
- package/src/plugins/defaults/memory-v3-shadow/__tests__/injection.test.ts +3 -33
- package/src/plugins/defaults/memory-v3-shadow/__tests__/pool-select.test.ts +4 -48
- package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-plugin.test.ts +8 -4
- package/src/plugins/defaults/memory-v3-shadow/injector.ts +15 -43
- package/src/plugins/defaults/memory-v3-shadow/orchestrate.ts +2 -11
- package/src/plugins/defaults/memory-v3-shadow/pool-select.ts +13 -77
- package/src/plugins/defaults/memory-v3-shadow/shadow-plugin.ts +11 -12
- package/src/plugins/mtime-cache.ts +291 -76
- package/src/plugins/pipeline.ts +13 -111
- package/src/plugins/types.ts +2 -0
- package/src/providers/anthropic/client.ts +0 -5
- package/src/providers/call-site-routing.ts +0 -4
- package/src/providers/model-catalog.ts +0 -16
- package/src/providers/openai/__tests__/api-error-detail.test.ts +120 -0
- package/src/providers/openai/chat-completions-provider.ts +83 -37
- package/src/providers/openai/responses-provider.ts +46 -50
- package/src/providers/openrouter/client.ts +0 -5
- package/src/providers/provider-send-message.ts +0 -4
- package/src/providers/ratelimit.ts +0 -4
- package/src/providers/retry.ts +0 -4
- package/src/providers/types.ts +0 -9
- package/src/providers/usage-tracking.ts +0 -4
- package/src/runtime/__tests__/trust-verdict-consumer.test.ts +3 -335
- package/src/runtime/access-request-helper.ts +39 -19
- package/src/runtime/actor-trust-resolver.ts +2 -2
- package/src/runtime/assistant-event-hub.ts +1 -1
- package/src/runtime/assistant-stream-state.ts +2 -9
- package/src/runtime/auth/require-bound-guardian.ts +11 -21
- package/src/runtime/channel-verification-service.ts +31 -56
- package/src/runtime/confirmation-request-guardian-bridge.ts +3 -3
- package/src/runtime/guardian-vellum-migration.ts +7 -66
- package/src/runtime/invite-redemption-service.ts +187 -198
- package/src/runtime/local-actor-identity.ts +11 -76
- package/src/runtime/pending-interactions.ts +1 -11
- package/src/runtime/routes/__tests__/channel-verification-revoke.test.ts +5 -56
- package/src/runtime/routes/__tests__/channel-verification-routes.test.ts +1 -1
- package/src/runtime/routes/__tests__/surface-action-routes.test.ts +0 -187
- package/src/runtime/routes/browser-routes.ts +1 -1
- package/src/runtime/routes/canonical-guardian-expiry-sweep.ts +5 -13
- package/src/runtime/routes/channel-verification-routes.ts +3 -3
- package/src/runtime/routes/contact-routes.ts +32 -8
- package/src/runtime/routes/conversation-cli-routes.ts +5 -4
- package/src/runtime/routes/conversation-list-routes.ts +7 -4
- package/src/runtime/routes/conversation-query-routes.ts +0 -72
- package/src/runtime/routes/conversation-routes.ts +85 -84
- package/src/runtime/routes/events-routes.ts +2 -2
- package/src/runtime/routes/global-search-routes.ts +1 -3
- package/src/runtime/routes/guardian-action-routes.ts +5 -4
- package/src/runtime/routes/host-app-control-routes.ts +4 -5
- package/src/runtime/routes/host-bash-routes.ts +4 -5
- package/src/runtime/routes/host-browser-routes.ts +11 -9
- package/src/runtime/routes/host-cu-routes.ts +4 -5
- package/src/runtime/routes/host-file-routes.ts +4 -5
- package/src/runtime/routes/host-transfer-routes.ts +6 -6
- package/src/runtime/routes/http-adapter.ts +1 -1
- package/src/runtime/routes/identity-routes.ts +2 -3
- package/src/runtime/routes/inbound-message-handler.ts +5 -5
- package/src/runtime/routes/inbound-stages/acl-enforcement.test.ts +5 -97
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +49 -61
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +4 -16
- package/src/runtime/routes/inbound-stages/escalation-intercept.ts +7 -7
- package/src/runtime/routes/inbound-stages/guardian-activation-intercept.test.ts +8 -21
- package/src/runtime/routes/inbound-stages/guardian-activation-intercept.ts +3 -14
- package/src/runtime/routes/index.ts +0 -2
- package/src/runtime/routes/llm-context-normalization.ts +0 -83
- package/src/runtime/routes/mcp-auth-routes.ts +19 -171
- package/src/runtime/routes/migration-rollback-routes.ts +3 -4
- package/src/runtime/routes/migration-routes.ts +1 -4
- package/src/runtime/routes/subagents-routes.ts +0 -5
- package/src/runtime/routes/surface-action-routes.ts +56 -42
- package/src/runtime/services/__tests__/conversation-serializer.test.ts +0 -1
- package/src/runtime/services/conversation-serializer.ts +9 -7
- package/src/runtime/tool-grant-request-helper.ts +3 -3
- package/src/runtime/trust-verdict-consumer.ts +9 -85
- package/src/runtime/verification-outbound-actions.ts +18 -18
- package/src/signals/user-message.ts +0 -16
- package/src/subagent/manager.ts +0 -9
- package/src/subagent/types.ts +3 -3
- package/src/telemetry/types.ts +1 -34
- package/src/telemetry/usage-telemetry-reporter.test.ts +2 -3
- package/src/telemetry/usage-telemetry-reporter.ts +3 -87
- package/src/tools/ask-question/ask-question-tool.test.ts +0 -29
- package/src/tools/ask-question/ask-question-tool.ts +0 -13
- package/src/tools/executor.ts +4 -4
- package/src/tools/registry.ts +0 -18
- package/src/tools/shared/filesystem/path-policy.ts +5 -12
- package/src/tools/tool-approval-handler.ts +1 -1
- package/src/tools/tool-defaults.ts +2 -9
- package/src/tools/tool-manifest.ts +0 -3
- package/src/tools/types.ts +2 -17
- package/src/tools/workspace-tools/loader.ts +244 -348
- package/src/util/errors.ts +1 -26
- package/src/util/platform.ts +0 -5
- package/src/workflows/library.test.ts +0 -140
- package/src/workflows/library.ts +28 -82
- package/src/workspace/migrations/017-seed-persona-dirs.ts +34 -3
- package/src/workspace/migrations/019-scope-journal-to-guardian.ts +24 -3
- package/src/workspace/migrations/048-remove-workspace-hooks.ts +66 -14
- package/src/workspace/migrations/registry.ts +0 -2
- package/node_modules/@vellumai/gateway-client/src/__tests__/guardian-delivery-contract.test.ts +0 -91
- package/node_modules/@vellumai/gateway-client/src/guardian-delivery-contract.ts +0 -48
- package/node_modules/@vellumai/service-contracts/src/__tests__/channels.test.ts +0 -28
- package/node_modules/@vellumai/service-contracts/src/channels.ts +0 -41
- package/src/__tests__/code-search-tool.test.ts +0 -585
- package/src/__tests__/guardian-expiry-notifier.test.ts +0 -282
- package/src/__tests__/mcp-config-secret-boundary.test.ts +0 -390
- package/src/__tests__/plugin-pipeline.test.ts +0 -96
- package/src/__tests__/sse-actor-principal-guardian-source.test.ts +0 -102
- package/src/__tests__/steer-on-enqueue-question.test.ts +0 -181
- package/src/__tests__/workspace-migration-111-prune-seeded-callsite-defaults.test.ts +0 -208
- package/src/agent/loop-exclusive-tool.test.ts +0 -150
- package/src/api/constants/sse-replay.ts +0 -41
- package/src/api/events/conversation-notice.ts +0 -26
- package/src/approvals/guardian-channel-delivery.ts +0 -30
- package/src/approvals/guardian-expiry-notifier.ts +0 -148
- package/src/cli/commands/memory/__tests__/worker.test.ts +0 -302
- package/src/cli/commands/memory/worker.ts +0 -175
- package/src/config/__tests__/loader-callsite-strip-fallback.test.ts +0 -143
- package/src/config/prune-seeded-callsite-defaults.ts +0 -110
- package/src/contacts/__tests__/contacts-write-revoke-relay.test.ts +0 -129
- package/src/contacts/__tests__/guardian-delivery-reader.test.ts +0 -312
- package/src/contacts/__tests__/member-write-relay.test.ts +0 -202
- package/src/contacts/guardian-delivery-reader.ts +0 -223
- package/src/contacts/member-write-relay.ts +0 -189
- package/src/daemon/conversation-notices.ts +0 -60
- package/src/daemon/handlers/__tests__/config-channels.test.ts +0 -225
- package/src/hooks/hook-loader.ts +0 -341
- package/src/mcp/mcp-header-store.ts +0 -134
- package/src/memory/__tests__/301-create-watchdog-events.test.ts +0 -110
- package/src/memory/__tests__/prompt-override.test.ts +0 -192
- package/src/memory/__tests__/watchdog-events-store.test.ts +0 -161
- package/src/memory/migrations/300-add-processing-started-at.ts +0 -30
- package/src/memory/migrations/301-create-watchdog-events.ts +0 -45
- package/src/memory/migrations/__tests__/209-strip-thinking-from-consolidated.test.ts +0 -224
- package/src/memory/prompt-override.ts +0 -129
- package/src/memory/steps.ts +0 -573
- package/src/memory/watchdog-events-store.ts +0 -87
- package/src/memory/worker-control.ts +0 -118
- package/src/memory/worker-process.ts +0 -72
- package/src/notifications/__tests__/connected-channels.test.ts +0 -114
- package/src/notifications/__tests__/destination-resolver.test.ts +0 -256
- package/src/onboarding/checkin-event.test.ts +0 -222
- package/src/onboarding/checkin-event.ts +0 -321
- package/src/onboarding/schedule-checkin.ts +0 -190
- package/src/plugins/defaults/advisor/__tests__/context-pack-gating.test.ts +0 -106
- package/src/plugins/defaults/advisor/__tests__/context-pack.test.ts +0 -60
- package/src/plugins/defaults/advisor/context-pack.ts +0 -288
- package/src/plugins/defaults/memory-v3-shadow/pool-select.test.ts +0 -146
- package/src/plugins/surface-import.ts +0 -121
- package/src/providers/openai/__tests__/api-error-normalization.test.ts +0 -321
- package/src/providers/openai/api-error-normalization.ts +0 -270
- package/src/runtime/__tests__/channel-verification-service.test.ts +0 -133
- package/src/runtime/__tests__/guardian-vellum-migration.test.ts +0 -181
- package/src/runtime/__tests__/is-guardian-bound-for-channel.test.ts +0 -66
- package/src/runtime/__tests__/local-principal-trust.test.ts +0 -164
- package/src/runtime/anchored-guardian.test.ts +0 -156
- package/src/runtime/anchored-guardian.ts +0 -135
- package/src/runtime/auth/__tests__/require-bound-guardian.test.ts +0 -99
- package/src/runtime/local-principal-trust.ts +0 -52
- package/src/runtime/routes/__tests__/contact-routes.test.ts +0 -212
- package/src/runtime/routes/__tests__/global-search-routes.test.ts +0 -93
- package/src/runtime/routes/onboarding-checkin-routes.ts +0 -86
- package/src/tools/filesystem/search.ts +0 -543
- package/src/util/telemetry-db-path.ts +0 -24
- package/src/workspace/migrations/111-prune-seeded-callsite-defaults.ts +0 -134
|
@@ -61,36 +61,6 @@ mock.module("../runtime/gateway-client.js", () => ({
|
|
|
61
61
|
},
|
|
62
62
|
}));
|
|
63
63
|
|
|
64
|
-
// Guardian identity for the access request resolves via the gateway delivery
|
|
65
|
-
// reader, not the local contacts DB. Seed it per-test via seedGatewayGuardian.
|
|
66
|
-
interface GatewayGuardian {
|
|
67
|
-
channelType: string;
|
|
68
|
-
contactId: string;
|
|
69
|
-
principalId?: string | null;
|
|
70
|
-
displayName?: string | null;
|
|
71
|
-
address: string;
|
|
72
|
-
externalChatId?: string | null;
|
|
73
|
-
status: string;
|
|
74
|
-
verifiedAt?: number | null;
|
|
75
|
-
}
|
|
76
|
-
let gatewayGuardians: GatewayGuardian[] = [];
|
|
77
|
-
mock.module("../contacts/guardian-delivery-reader.js", () => ({
|
|
78
|
-
getGuardianDelivery: async () => gatewayGuardians,
|
|
79
|
-
guardianForChannel: (list: GatewayGuardian[], channelType: string) =>
|
|
80
|
-
list.find((g) => g.channelType === channelType && g.status === "active"),
|
|
81
|
-
}));
|
|
82
|
-
|
|
83
|
-
function seedGatewayGuardian(g: Partial<GatewayGuardian> & {
|
|
84
|
-
channelType: string;
|
|
85
|
-
address: string;
|
|
86
|
-
}): void {
|
|
87
|
-
gatewayGuardians.push({
|
|
88
|
-
contactId: `c-${g.channelType}`,
|
|
89
|
-
status: "active",
|
|
90
|
-
...g,
|
|
91
|
-
});
|
|
92
|
-
}
|
|
93
|
-
|
|
94
64
|
import {
|
|
95
65
|
listCanonicalGuardianDeliveries,
|
|
96
66
|
listCanonicalGuardianRequests,
|
|
@@ -125,7 +95,6 @@ function resetState(): string {
|
|
|
125
95
|
db.run("DELETE FROM contacts");
|
|
126
96
|
emitSignalCalls.length = 0;
|
|
127
97
|
deliverReplyCalls.length = 0;
|
|
128
|
-
gatewayGuardians = [];
|
|
129
98
|
mockEmitResult = {
|
|
130
99
|
signalId: "mock-signal-id",
|
|
131
100
|
deduplicated: false,
|
|
@@ -133,15 +102,8 @@ function resetState(): string {
|
|
|
133
102
|
reason: "mock",
|
|
134
103
|
deliveryResults: [],
|
|
135
104
|
};
|
|
136
|
-
// Seed the vellum anchor binding
|
|
137
|
-
// startup in production). The DB write mirrors it for any local INFO reads.
|
|
105
|
+
// Seed the vellum anchor binding (gateway does this at startup in production)
|
|
138
106
|
const principalId = `vellum-principal-${crypto.randomUUID()}`;
|
|
139
|
-
seedGatewayGuardian({
|
|
140
|
-
channelType: "vellum",
|
|
141
|
-
address: principalId,
|
|
142
|
-
principalId,
|
|
143
|
-
displayName: principalId,
|
|
144
|
-
});
|
|
145
107
|
createGuardianBinding({
|
|
146
108
|
channel: "vellum",
|
|
147
109
|
guardianExternalUserId: principalId,
|
|
@@ -210,12 +172,6 @@ describe("non-member access request notification", () => {
|
|
|
210
172
|
|
|
211
173
|
test("guardian is notified when a non-member messages and a guardian binding exists", async () => {
|
|
212
174
|
// Set up a guardian binding for this channel using the anchor principal
|
|
213
|
-
seedGatewayGuardian({
|
|
214
|
-
channelType: "telegram",
|
|
215
|
-
address: "guardian-user-789",
|
|
216
|
-
externalChatId: "guardian-chat-789",
|
|
217
|
-
principalId: anchorPrincipalId,
|
|
218
|
-
});
|
|
219
175
|
createGuardianBinding({
|
|
220
176
|
channel: "telegram",
|
|
221
177
|
guardianExternalUserId: "guardian-user-789",
|
|
@@ -261,12 +217,6 @@ describe("non-member access request notification", () => {
|
|
|
261
217
|
});
|
|
262
218
|
|
|
263
219
|
test("no duplicate approval requests for repeated messages from same non-member", async () => {
|
|
264
|
-
seedGatewayGuardian({
|
|
265
|
-
channelType: "telegram",
|
|
266
|
-
address: "guardian-user-789",
|
|
267
|
-
externalChatId: "guardian-chat-789",
|
|
268
|
-
principalId: anchorPrincipalId,
|
|
269
|
-
});
|
|
270
220
|
createGuardianBinding({
|
|
271
221
|
channel: "telegram",
|
|
272
222
|
guardianExternalUserId: "guardian-user-789",
|
|
@@ -339,12 +289,6 @@ describe("non-member access request notification", () => {
|
|
|
339
289
|
// Only a voice guardian binding exists — no Telegram binding.
|
|
340
290
|
// Since cross-channel fallback was removed, the access request resolves
|
|
341
291
|
// to the assistant's vellum anchor identity instead.
|
|
342
|
-
seedGatewayGuardian({
|
|
343
|
-
channelType: "phone",
|
|
344
|
-
address: "guardian-voice-user",
|
|
345
|
-
externalChatId: "guardian-voice-chat",
|
|
346
|
-
principalId: anchorPrincipalId,
|
|
347
|
-
});
|
|
348
292
|
createGuardianBinding({
|
|
349
293
|
channel: "phone",
|
|
350
294
|
guardianExternalUserId: "guardian-voice-user",
|
|
@@ -407,8 +351,8 @@ describe("access-request-helper unit tests", () => {
|
|
|
407
351
|
anchorPrincipalId = resetState();
|
|
408
352
|
});
|
|
409
353
|
|
|
410
|
-
test("notifyGuardianOfAccessRequest returns no_sender_id when actorExternalId is absent",
|
|
411
|
-
const result =
|
|
354
|
+
test("notifyGuardianOfAccessRequest returns no_sender_id when actorExternalId is absent", () => {
|
|
355
|
+
const result = notifyGuardianOfAccessRequest({
|
|
412
356
|
canonicalAssistantId: "self",
|
|
413
357
|
sourceChannel: "telegram",
|
|
414
358
|
conversationExternalId: "chat-123",
|
|
@@ -428,8 +372,8 @@ describe("access-request-helper unit tests", () => {
|
|
|
428
372
|
expect(pending.length).toBe(0);
|
|
429
373
|
});
|
|
430
374
|
|
|
431
|
-
test("notifyGuardianOfAccessRequest creates request with self-healed principal when no binding exists",
|
|
432
|
-
const result =
|
|
375
|
+
test("notifyGuardianOfAccessRequest creates request with self-healed principal when no binding exists", () => {
|
|
376
|
+
const result = notifyGuardianOfAccessRequest({
|
|
433
377
|
canonicalAssistantId: "self",
|
|
434
378
|
sourceChannel: "telegram",
|
|
435
379
|
conversationExternalId: "chat-123",
|
|
@@ -456,14 +400,8 @@ describe("access-request-helper unit tests", () => {
|
|
|
456
400
|
expect(emitSignalCalls.length).toBe(1);
|
|
457
401
|
});
|
|
458
402
|
|
|
459
|
-
test("notifyGuardianOfAccessRequest falls back to assistant-anchored vellum identity when source-channel binding is missing",
|
|
403
|
+
test("notifyGuardianOfAccessRequest falls back to assistant-anchored vellum identity when source-channel binding is missing", () => {
|
|
460
404
|
// Only voice binding exists
|
|
461
|
-
seedGatewayGuardian({
|
|
462
|
-
channelType: "phone",
|
|
463
|
-
address: "guardian-voice",
|
|
464
|
-
externalChatId: "voice-chat",
|
|
465
|
-
principalId: "test-principal-id",
|
|
466
|
-
});
|
|
467
405
|
createGuardianBinding({
|
|
468
406
|
channel: "phone",
|
|
469
407
|
guardianExternalUserId: "guardian-voice",
|
|
@@ -472,7 +410,7 @@ describe("access-request-helper unit tests", () => {
|
|
|
472
410
|
verifiedVia: "test",
|
|
473
411
|
});
|
|
474
412
|
|
|
475
|
-
const result =
|
|
413
|
+
const result = notifyGuardianOfAccessRequest({
|
|
476
414
|
canonicalAssistantId: "self",
|
|
477
415
|
sourceChannel: "telegram",
|
|
478
416
|
conversationExternalId: "tg-chat",
|
|
@@ -497,20 +435,8 @@ describe("access-request-helper unit tests", () => {
|
|
|
497
435
|
expect(payload.guardianBindingChannel).toBe("vellum");
|
|
498
436
|
});
|
|
499
437
|
|
|
500
|
-
test("notifyGuardianOfAccessRequest prefers source-channel binding over vellum anchor",
|
|
438
|
+
test("notifyGuardianOfAccessRequest prefers source-channel binding over vellum anchor", () => {
|
|
501
439
|
// Both Telegram and voice bindings exist with the anchor principal
|
|
502
|
-
seedGatewayGuardian({
|
|
503
|
-
channelType: "telegram",
|
|
504
|
-
address: "guardian-tg",
|
|
505
|
-
externalChatId: "tg-chat",
|
|
506
|
-
principalId: anchorPrincipalId,
|
|
507
|
-
});
|
|
508
|
-
seedGatewayGuardian({
|
|
509
|
-
channelType: "phone",
|
|
510
|
-
address: "guardian-voice",
|
|
511
|
-
externalChatId: "voice-chat",
|
|
512
|
-
principalId: anchorPrincipalId,
|
|
513
|
-
});
|
|
514
440
|
createGuardianBinding({
|
|
515
441
|
channel: "telegram",
|
|
516
442
|
guardianExternalUserId: "guardian-tg",
|
|
@@ -526,7 +452,7 @@ describe("access-request-helper unit tests", () => {
|
|
|
526
452
|
verifiedVia: "test",
|
|
527
453
|
});
|
|
528
454
|
|
|
529
|
-
const result =
|
|
455
|
+
const result = notifyGuardianOfAccessRequest({
|
|
530
456
|
canonicalAssistantId: "self",
|
|
531
457
|
sourceChannel: "telegram",
|
|
532
458
|
conversationExternalId: "chat-123",
|
|
@@ -551,100 +477,8 @@ describe("access-request-helper unit tests", () => {
|
|
|
551
477
|
expect(payload.guardianBindingChannel).toBe("telegram");
|
|
552
478
|
});
|
|
553
479
|
|
|
554
|
-
test("notifyGuardianOfAccessRequest
|
|
555
|
-
|
|
556
|
-
gatewayGuardians = [];
|
|
557
|
-
// Local dual-written mirror still has the vellum anchor + telegram binding.
|
|
558
|
-
createGuardianBinding({
|
|
559
|
-
channel: "telegram",
|
|
560
|
-
guardianExternalUserId: "guardian-tg",
|
|
561
|
-
guardianDeliveryChatId: "tg-chat",
|
|
562
|
-
guardianPrincipalId: anchorPrincipalId,
|
|
563
|
-
verifiedVia: "test",
|
|
564
|
-
});
|
|
565
|
-
|
|
566
|
-
const result = await notifyGuardianOfAccessRequest({
|
|
567
|
-
canonicalAssistantId: "self",
|
|
568
|
-
sourceChannel: "telegram",
|
|
569
|
-
conversationExternalId: "chat-123",
|
|
570
|
-
actorExternalId: "unknown-user",
|
|
571
|
-
});
|
|
572
|
-
|
|
573
|
-
expect(result.notified).toBe(true);
|
|
574
|
-
|
|
575
|
-
const pending = listCanonicalGuardianRequests({
|
|
576
|
-
status: "pending",
|
|
577
|
-
requesterExternalUserId: "unknown-user",
|
|
578
|
-
kind: "access_request",
|
|
579
|
-
});
|
|
580
|
-
expect(pending.length).toBe(1);
|
|
581
|
-
// Request is decidable: local read supplied the principal + source binding.
|
|
582
|
-
expect(pending[0].guardianPrincipalId).toBe(anchorPrincipalId);
|
|
583
|
-
expect(pending[0].guardianExternalUserId).toBe("guardian-tg");
|
|
584
|
-
|
|
585
|
-
const payload = emitSignalCalls[0].contextPayload as Record<
|
|
586
|
-
string,
|
|
587
|
-
unknown
|
|
588
|
-
>;
|
|
589
|
-
expect(payload.guardianBindingChannel).toBe("telegram");
|
|
590
|
-
});
|
|
591
|
-
|
|
592
|
-
test("notifyGuardianOfAccessRequest falls back to local vellum anchor when gateway delivery is empty", async () => {
|
|
593
|
-
// Gateway empty; only the local vellum anchor from resetState remains.
|
|
594
|
-
gatewayGuardians = [];
|
|
595
|
-
|
|
596
|
-
const result = await notifyGuardianOfAccessRequest({
|
|
597
|
-
canonicalAssistantId: "self",
|
|
598
|
-
sourceChannel: "telegram",
|
|
599
|
-
conversationExternalId: "chat-123",
|
|
600
|
-
actorExternalId: "unknown-user",
|
|
601
|
-
});
|
|
602
|
-
|
|
603
|
-
expect(result.notified).toBe(true);
|
|
604
|
-
|
|
605
|
-
const pending = listCanonicalGuardianRequests({
|
|
606
|
-
status: "pending",
|
|
607
|
-
requesterExternalUserId: "unknown-user",
|
|
608
|
-
kind: "access_request",
|
|
609
|
-
});
|
|
610
|
-
expect(pending.length).toBe(1);
|
|
611
|
-
// Decidable via the local vellum anchor principal.
|
|
612
|
-
expect(pending[0].guardianPrincipalId).toBe(anchorPrincipalId);
|
|
613
|
-
|
|
614
|
-
const payload = emitSignalCalls[0].contextPayload as Record<
|
|
615
|
-
string,
|
|
616
|
-
unknown
|
|
617
|
-
>;
|
|
618
|
-
expect(payload.guardianBindingChannel).toBe("vellum");
|
|
619
|
-
});
|
|
620
|
-
|
|
621
|
-
test("notifyGuardianOfAccessRequest does not create a decisionable request when both gateway and local reads are empty", async () => {
|
|
622
|
-
// Genuinely unbound assistant: gateway empty AND no local binding. Prior
|
|
623
|
-
// behavior rejects creation of a decisionable request without a principal.
|
|
624
|
-
gatewayGuardians = [];
|
|
625
|
-
const db = getDb();
|
|
626
|
-
db.run("DELETE FROM contact_channels");
|
|
627
|
-
db.run("DELETE FROM contacts");
|
|
628
|
-
|
|
629
|
-
await expect(
|
|
630
|
-
notifyGuardianOfAccessRequest({
|
|
631
|
-
canonicalAssistantId: "self",
|
|
632
|
-
sourceChannel: "telegram",
|
|
633
|
-
conversationExternalId: "chat-123",
|
|
634
|
-
actorExternalId: "unknown-user",
|
|
635
|
-
}),
|
|
636
|
-
).rejects.toThrow();
|
|
637
|
-
|
|
638
|
-
const pending = listCanonicalGuardianRequests({
|
|
639
|
-
status: "pending",
|
|
640
|
-
requesterExternalUserId: "unknown-user",
|
|
641
|
-
kind: "access_request",
|
|
642
|
-
});
|
|
643
|
-
expect(pending.length).toBe(0);
|
|
644
|
-
});
|
|
645
|
-
|
|
646
|
-
test("notifyGuardianOfAccessRequest for voice channel includes actorDisplayName in contextPayload", async () => {
|
|
647
|
-
const result = await notifyGuardianOfAccessRequest({
|
|
480
|
+
test("notifyGuardianOfAccessRequest for voice channel includes actorDisplayName in contextPayload", () => {
|
|
481
|
+
const result = notifyGuardianOfAccessRequest({
|
|
648
482
|
canonicalAssistantId: "self",
|
|
649
483
|
sourceChannel: "phone",
|
|
650
484
|
conversationExternalId: "+15559998888",
|
|
@@ -674,8 +508,8 @@ describe("access-request-helper unit tests", () => {
|
|
|
674
508
|
expect(pending.length).toBe(1);
|
|
675
509
|
});
|
|
676
510
|
|
|
677
|
-
test("notifyGuardianOfAccessRequest includes requestCode in contextPayload",
|
|
678
|
-
const result =
|
|
511
|
+
test("notifyGuardianOfAccessRequest includes requestCode in contextPayload", () => {
|
|
512
|
+
const result = notifyGuardianOfAccessRequest({
|
|
679
513
|
canonicalAssistantId: "self",
|
|
680
514
|
sourceChannel: "telegram",
|
|
681
515
|
conversationExternalId: "chat-123",
|
|
@@ -695,8 +529,8 @@ describe("access-request-helper unit tests", () => {
|
|
|
695
529
|
expect((payload.requestCode as string).length).toBe(6);
|
|
696
530
|
});
|
|
697
531
|
|
|
698
|
-
test("notifyGuardianOfAccessRequest includes previousMemberStatus in contextPayload",
|
|
699
|
-
const result =
|
|
532
|
+
test("notifyGuardianOfAccessRequest includes previousMemberStatus in contextPayload", () => {
|
|
533
|
+
const result = notifyGuardianOfAccessRequest({
|
|
700
534
|
canonicalAssistantId: "self",
|
|
701
535
|
sourceChannel: "telegram",
|
|
702
536
|
conversationExternalId: "chat-123",
|
|
@@ -736,7 +570,7 @@ describe("access-request-helper unit tests", () => {
|
|
|
736
570
|
],
|
|
737
571
|
};
|
|
738
572
|
|
|
739
|
-
const result =
|
|
573
|
+
const result = notifyGuardianOfAccessRequest({
|
|
740
574
|
canonicalAssistantId: "self",
|
|
741
575
|
sourceChannel: "phone",
|
|
742
576
|
conversationExternalId: "+15556667777",
|
|
@@ -769,12 +603,6 @@ describe("access-request-helper unit tests", () => {
|
|
|
769
603
|
// Set up a telegram guardian binding with the anchor principal so
|
|
770
604
|
// guardianResolutionSource resolves to "source-channel-contact" and
|
|
771
605
|
// sameChannelOnly is true.
|
|
772
|
-
seedGatewayGuardian({
|
|
773
|
-
channelType: "telegram",
|
|
774
|
-
address: "guardian-user-456",
|
|
775
|
-
externalChatId: "guardian-chat-456",
|
|
776
|
-
principalId: anchorPrincipalId,
|
|
777
|
-
});
|
|
778
606
|
createGuardianBinding({
|
|
779
607
|
channel: "telegram",
|
|
780
608
|
guardianExternalUserId: "guardian-user-456",
|
|
@@ -797,7 +625,7 @@ describe("access-request-helper unit tests", () => {
|
|
|
797
625
|
],
|
|
798
626
|
};
|
|
799
627
|
|
|
800
|
-
const result =
|
|
628
|
+
const result = notifyGuardianOfAccessRequest({
|
|
801
629
|
canonicalAssistantId: "self",
|
|
802
630
|
sourceChannel: "telegram",
|
|
803
631
|
conversationExternalId: "chat-123",
|
|
@@ -24,10 +24,6 @@ mock.module("../util/logger.js", () => ({
|
|
|
24
24
|
}),
|
|
25
25
|
}));
|
|
26
26
|
|
|
27
|
-
mock.module("../contacts/guardian-delivery-reader.js", () => ({
|
|
28
|
-
getGuardianDelivery: async () => null,
|
|
29
|
-
}));
|
|
30
|
-
|
|
31
27
|
// Mock destination-resolver to return a destination for every requested channel.
|
|
32
28
|
// External channels (telegram, slack) include bindingContext.
|
|
33
29
|
mock.module("../notifications/destination-resolver.js", () => ({
|
|
@@ -36,36 +36,17 @@ mock.module("../prompts/system-prompt.js", () => ({
|
|
|
36
36
|
buildCoreIdentityContext: () => null,
|
|
37
37
|
}));
|
|
38
38
|
|
|
39
|
-
// ── Guardian
|
|
39
|
+
// ── Guardian contact mock ────────────────────────────────────────────
|
|
40
40
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
mock.module("../contacts/guardian-delivery-reader.js", () => ({
|
|
47
|
-
getGuardianDelivery: async () => guardianDeliveryFixture,
|
|
48
|
-
anyGuardian: (list: Array<{ contactId: string }>) => list[0],
|
|
49
|
-
}));
|
|
41
|
+
let mockGuardianResult: {
|
|
42
|
+
contact: { notes: string | null };
|
|
43
|
+
channels: Record<string, unknown>[];
|
|
44
|
+
} | null = null;
|
|
50
45
|
|
|
51
46
|
mock.module("../contacts/contact-store.js", () => ({
|
|
52
|
-
|
|
53
|
-
contactInfoFixture[contactId] ?? null,
|
|
47
|
+
listGuardianChannels: () => mockGuardianResult,
|
|
54
48
|
}));
|
|
55
49
|
|
|
56
|
-
const GUARDIAN_CONTACT_ID = "guardian-contact-1";
|
|
57
|
-
|
|
58
|
-
/** Bind a guardian with the given notes (or no guardian when notes is null). */
|
|
59
|
-
function setGuardian(notes: string | null | undefined): void {
|
|
60
|
-
if (notes === undefined) {
|
|
61
|
-
guardianDeliveryFixture = [];
|
|
62
|
-
contactInfoFixture = {};
|
|
63
|
-
return;
|
|
64
|
-
}
|
|
65
|
-
guardianDeliveryFixture = [{ contactId: GUARDIAN_CONTACT_ID }];
|
|
66
|
-
contactInfoFixture = { [GUARDIAN_CONTACT_ID]: { notes } };
|
|
67
|
-
}
|
|
68
|
-
|
|
69
50
|
// ── Provider mock with system prompt capture ──────────────────────────
|
|
70
51
|
|
|
71
52
|
let configuredProvider: {
|
|
@@ -153,12 +134,15 @@ describe("recipient context in notification decision engine", () => {
|
|
|
153
134
|
beforeEach(() => {
|
|
154
135
|
configuredProvider = null;
|
|
155
136
|
extractedToolUse = null;
|
|
156
|
-
|
|
137
|
+
mockGuardianResult = null;
|
|
157
138
|
capturedSystemPrompt = undefined;
|
|
158
139
|
});
|
|
159
140
|
|
|
160
141
|
test("guardian contact notes appear in system prompt as <recipient-context>", async () => {
|
|
161
|
-
|
|
142
|
+
mockGuardianResult = {
|
|
143
|
+
contact: { notes: "Prefers formal tone. Address as Dr. Smith." },
|
|
144
|
+
channels: [{ type: "vellum" }],
|
|
145
|
+
};
|
|
162
146
|
setupLLMProvider();
|
|
163
147
|
|
|
164
148
|
const signal = makeSignal();
|
|
@@ -173,7 +157,7 @@ describe("recipient context in notification decision engine", () => {
|
|
|
173
157
|
});
|
|
174
158
|
|
|
175
159
|
test("recipient-context is omitted when no guardian exists", async () => {
|
|
176
|
-
|
|
160
|
+
mockGuardianResult = null;
|
|
177
161
|
setupLLMProvider();
|
|
178
162
|
|
|
179
163
|
const signal = makeSignal();
|
|
@@ -185,7 +169,10 @@ describe("recipient context in notification decision engine", () => {
|
|
|
185
169
|
});
|
|
186
170
|
|
|
187
171
|
test("recipient-context is omitted when guardian notes are null", async () => {
|
|
188
|
-
|
|
172
|
+
mockGuardianResult = {
|
|
173
|
+
contact: { notes: null },
|
|
174
|
+
channels: [{ type: "vellum" }],
|
|
175
|
+
};
|
|
189
176
|
setupLLMProvider();
|
|
190
177
|
|
|
191
178
|
const signal = makeSignal();
|
|
@@ -197,7 +184,10 @@ describe("recipient context in notification decision engine", () => {
|
|
|
197
184
|
});
|
|
198
185
|
|
|
199
186
|
test("recipient-context is omitted when guardian notes are empty string", async () => {
|
|
200
|
-
|
|
187
|
+
mockGuardianResult = {
|
|
188
|
+
contact: { notes: "" },
|
|
189
|
+
channels: [{ type: "vellum" }],
|
|
190
|
+
};
|
|
201
191
|
setupLLMProvider();
|
|
202
192
|
|
|
203
193
|
const signal = makeSignal();
|
|
@@ -209,7 +199,10 @@ describe("recipient context in notification decision engine", () => {
|
|
|
209
199
|
});
|
|
210
200
|
|
|
211
201
|
test("large guardian notes are truncated to prevent oversized prompts", async () => {
|
|
212
|
-
|
|
202
|
+
mockGuardianResult = {
|
|
203
|
+
contact: { notes: "N".repeat(3000) },
|
|
204
|
+
channels: [{ type: "vellum" }],
|
|
205
|
+
};
|
|
213
206
|
setupLLMProvider();
|
|
214
207
|
|
|
215
208
|
const signal = makeSignal();
|
|
@@ -233,7 +226,10 @@ describe("recipient context in notification decision engine", () => {
|
|
|
233
226
|
});
|
|
234
227
|
|
|
235
228
|
test("fallback path works correctly without recipient context", async () => {
|
|
236
|
-
|
|
229
|
+
mockGuardianResult = {
|
|
230
|
+
contact: { notes: "Prefers formal tone." },
|
|
231
|
+
channels: [{ type: "vellum" }],
|
|
232
|
+
};
|
|
237
233
|
// null provider forces fallback path
|
|
238
234
|
configuredProvider = null;
|
|
239
235
|
|
|
@@ -251,7 +247,10 @@ describe("recipient context in notification decision engine", () => {
|
|
|
251
247
|
});
|
|
252
248
|
|
|
253
249
|
test("recipient-context appears after user-preferences in prompt", async () => {
|
|
254
|
-
|
|
250
|
+
mockGuardianResult = {
|
|
251
|
+
contact: { notes: "Prefers brief updates." },
|
|
252
|
+
channels: [{ type: "vellum" }],
|
|
253
|
+
};
|
|
255
254
|
setupLLMProvider();
|
|
256
255
|
|
|
257
256
|
const signal = makeSignal();
|
|
@@ -20,10 +20,6 @@ mock.module("../util/logger.js", () => ({
|
|
|
20
20
|
}),
|
|
21
21
|
}));
|
|
22
22
|
|
|
23
|
-
mock.module("../contacts/guardian-delivery-reader.js", () => ({
|
|
24
|
-
getGuardianDelivery: async () => null,
|
|
25
|
-
}));
|
|
26
|
-
|
|
27
23
|
// Mock destination-resolver for broadcaster tests
|
|
28
24
|
mock.module("../notifications/destination-resolver.js", () => ({
|
|
29
25
|
resolveDestinations: (channels: string[]) => {
|
|
@@ -46,8 +42,6 @@ mock.module("../notifications/deliveries-store.js", () => ({
|
|
|
46
42
|
// can be driven from tests without DB access.
|
|
47
43
|
let mockExistingConversations: Record<string, { id: string }> = {};
|
|
48
44
|
mock.module("../memory/conversation-crud.js", () => ({
|
|
49
|
-
setConversationProcessingStartedAt: () => {},
|
|
50
|
-
isConversationProcessing: () => false,
|
|
51
45
|
getConversation: (id: string) => mockExistingConversations[id] ?? null,
|
|
52
46
|
}));
|
|
53
47
|
|
|
@@ -68,25 +68,6 @@ mock.module("../notifications/emit-signal.js", () => ({
|
|
|
68
68
|
},
|
|
69
69
|
}));
|
|
70
70
|
|
|
71
|
-
// Guardian principalId is resolved from the gateway binding reader. Mirror the
|
|
72
|
-
// seeded vellum binding so dispatch can resolve the principal.
|
|
73
|
-
mock.module("../contacts/guardian-delivery-reader.js", () => ({
|
|
74
|
-
getGuardianDelivery: async () => [
|
|
75
|
-
{
|
|
76
|
-
channelType: "vellum",
|
|
77
|
-
contactId: "guardian-vellum",
|
|
78
|
-
principalId: "test-principal-id",
|
|
79
|
-
address: "local",
|
|
80
|
-
status: "active",
|
|
81
|
-
},
|
|
82
|
-
],
|
|
83
|
-
guardianForChannel: (
|
|
84
|
-
list: Array<{ channelType: string; status: string }>,
|
|
85
|
-
channelType: string,
|
|
86
|
-
) => list.find((g) => g.channelType === channelType && g.status === "active"),
|
|
87
|
-
anyGuardian: (list: unknown[]) => list[0],
|
|
88
|
-
}));
|
|
89
|
-
|
|
90
71
|
import {
|
|
91
72
|
createCallSession,
|
|
92
73
|
createPendingQuestion,
|
|
@@ -58,16 +58,6 @@ let lastConstructorOptions: Record<string, unknown> | null = null;
|
|
|
58
58
|
let shouldThrow: Error | null = null;
|
|
59
59
|
const DEFAULT_SDK_TIMEOUT_MS = 1_860_000;
|
|
60
60
|
|
|
61
|
-
// Each provider installs a `fetch` wrapper to capture raw error bodies, so the
|
|
62
|
-
// constructor options carry a `fetch` function; assert the meaningful options
|
|
63
|
-
// via objectContaining and confirm `fetch` is wired.
|
|
64
|
-
function expectOpenAIConstructorOptions(
|
|
65
|
-
expected: Record<string, unknown>,
|
|
66
|
-
): void {
|
|
67
|
-
expect(lastConstructorOptions).toEqual(expect.objectContaining(expected));
|
|
68
|
-
expect(typeof lastConstructorOptions?.fetch).toBe("function");
|
|
69
|
-
}
|
|
70
|
-
|
|
71
61
|
function userMsg(text: string): Message {
|
|
72
62
|
return { role: "user", content: [{ type: "text", text }] };
|
|
73
63
|
}
|
|
@@ -319,7 +309,7 @@ describe("OpenAIProvider", () => {
|
|
|
319
309
|
});
|
|
320
310
|
|
|
321
311
|
expect(compatible.name).toBe("ollama");
|
|
322
|
-
|
|
312
|
+
expect(lastConstructorOptions).toEqual({
|
|
323
313
|
apiKey: "sk-local",
|
|
324
314
|
baseURL: "http://127.0.0.1:11434/v1",
|
|
325
315
|
timeout: DEFAULT_SDK_TIMEOUT_MS,
|
|
@@ -332,7 +322,7 @@ describe("OpenAIProvider", () => {
|
|
|
332
322
|
delete process.env.OLLAMA_BASE_URL;
|
|
333
323
|
const ollama = new OllamaProvider("llama3.2");
|
|
334
324
|
expect(ollama.name).toBe("ollama");
|
|
335
|
-
|
|
325
|
+
expect(lastConstructorOptions).toEqual({
|
|
336
326
|
apiKey: "ollama",
|
|
337
327
|
baseURL: "http://127.0.0.1:11434/v1",
|
|
338
328
|
timeout: DEFAULT_SDK_TIMEOUT_MS,
|
|
@@ -352,7 +342,7 @@ describe("OpenAIProvider", () => {
|
|
|
352
342
|
process.env.OLLAMA_BASE_URL = " ";
|
|
353
343
|
const ollama = new OllamaProvider("llama3.2");
|
|
354
344
|
expect(ollama.name).toBe("ollama");
|
|
355
|
-
|
|
345
|
+
expect(lastConstructorOptions).toEqual({
|
|
356
346
|
apiKey: "ollama",
|
|
357
347
|
baseURL: "http://127.0.0.1:11434/v1",
|
|
358
348
|
timeout: DEFAULT_SDK_TIMEOUT_MS,
|
|
@@ -1270,7 +1260,7 @@ describe("custom baseURL initialization", () => {
|
|
|
1270
1260
|
});
|
|
1271
1261
|
|
|
1272
1262
|
expect(managed.name).toBe("openai");
|
|
1273
|
-
|
|
1263
|
+
expect(lastConstructorOptions).toEqual({
|
|
1274
1264
|
apiKey: "ast-key-123",
|
|
1275
1265
|
baseURL: "https://platform.example.com/v1/runtime-proxy/openai",
|
|
1276
1266
|
timeout: DEFAULT_SDK_TIMEOUT_MS,
|
|
@@ -1280,7 +1270,7 @@ describe("custom baseURL initialization", () => {
|
|
|
1280
1270
|
test("OpenAIProvider without baseURL calls provider directly", () => {
|
|
1281
1271
|
new OpenAIProvider("sk-user-key", "gpt-4o");
|
|
1282
1272
|
|
|
1283
|
-
|
|
1273
|
+
expect(lastConstructorOptions).toEqual({
|
|
1284
1274
|
apiKey: "sk-user-key",
|
|
1285
1275
|
baseURL: undefined,
|
|
1286
1276
|
timeout: DEFAULT_SDK_TIMEOUT_MS,
|
|
@@ -1292,7 +1282,7 @@ describe("custom baseURL initialization", () => {
|
|
|
1292
1282
|
streamTimeoutMs: 300_000,
|
|
1293
1283
|
});
|
|
1294
1284
|
|
|
1295
|
-
|
|
1285
|
+
expect(lastConstructorOptions).toEqual({
|
|
1296
1286
|
apiKey: "sk-user-key",
|
|
1297
1287
|
baseURL: undefined,
|
|
1298
1288
|
timeout: 360_000,
|
|
@@ -1309,7 +1299,7 @@ describe("custom baseURL initialization", () => {
|
|
|
1309
1299
|
);
|
|
1310
1300
|
|
|
1311
1301
|
expect(managed.name).toBe("fireworks");
|
|
1312
|
-
|
|
1302
|
+
expect(lastConstructorOptions).toEqual({
|
|
1313
1303
|
apiKey: "ast-key-123",
|
|
1314
1304
|
baseURL: "https://platform.example.com/v1/runtime-proxy/fireworks",
|
|
1315
1305
|
timeout: DEFAULT_SDK_TIMEOUT_MS,
|
|
@@ -1322,7 +1312,7 @@ describe("custom baseURL initialization", () => {
|
|
|
1322
1312
|
"accounts/fireworks/models/llama-v3p1-70b-instruct",
|
|
1323
1313
|
);
|
|
1324
1314
|
|
|
1325
|
-
|
|
1315
|
+
expect(lastConstructorOptions).toEqual({
|
|
1326
1316
|
apiKey: "fw-user-key",
|
|
1327
1317
|
baseURL: "https://api.fireworks.ai/inference/v1",
|
|
1328
1318
|
timeout: DEFAULT_SDK_TIMEOUT_MS,
|
|
@@ -1335,7 +1325,7 @@ describe("custom baseURL initialization", () => {
|
|
|
1335
1325
|
});
|
|
1336
1326
|
|
|
1337
1327
|
expect(managed.name).toBe("openrouter");
|
|
1338
|
-
|
|
1328
|
+
expect(lastConstructorOptions).toEqual({
|
|
1339
1329
|
apiKey: "ast-key-123",
|
|
1340
1330
|
baseURL: "https://platform.example.com/v1/runtime-proxy/openrouter",
|
|
1341
1331
|
timeout: DEFAULT_SDK_TIMEOUT_MS,
|
|
@@ -1345,7 +1335,7 @@ describe("custom baseURL initialization", () => {
|
|
|
1345
1335
|
test("OpenRouterProvider without custom baseURL uses default OpenRouter URL", () => {
|
|
1346
1336
|
new OpenRouterProvider("or-user-key", "openai/gpt-4o");
|
|
1347
1337
|
|
|
1348
|
-
|
|
1338
|
+
expect(lastConstructorOptions).toEqual({
|
|
1349
1339
|
apiKey: "or-user-key",
|
|
1350
1340
|
baseURL: "https://openrouter.ai/api/v1",
|
|
1351
1341
|
timeout: DEFAULT_SDK_TIMEOUT_MS,
|
|
@@ -1358,7 +1348,7 @@ describe("custom baseURL initialization", () => {
|
|
|
1358
1348
|
});
|
|
1359
1349
|
|
|
1360
1350
|
expect(managed.name).toBe("minimax");
|
|
1361
|
-
|
|
1351
|
+
expect(lastConstructorOptions).toEqual({
|
|
1362
1352
|
apiKey: "ast-key-123",
|
|
1363
1353
|
baseURL: "https://platform.example.com/v1/runtime-proxy/minimax",
|
|
1364
1354
|
timeout: DEFAULT_SDK_TIMEOUT_MS,
|
|
@@ -1368,7 +1358,7 @@ describe("custom baseURL initialization", () => {
|
|
|
1368
1358
|
test("MinimaxProvider without custom baseURL uses default MiniMax URL", () => {
|
|
1369
1359
|
new MinimaxProvider("mm-user-key", "MiniMax-M2.7");
|
|
1370
1360
|
|
|
1371
|
-
|
|
1361
|
+
expect(lastConstructorOptions).toEqual({
|
|
1372
1362
|
apiKey: "mm-user-key",
|
|
1373
1363
|
baseURL: "https://api.minimax.io/v1",
|
|
1374
1364
|
timeout: DEFAULT_SDK_TIMEOUT_MS,
|
|
@@ -24,16 +24,6 @@ let lastConstructorOptions: Record<string, unknown> | null = null;
|
|
|
24
24
|
let shouldThrow: Error | null = null;
|
|
25
25
|
const DEFAULT_SDK_TIMEOUT_MS = 1_860_000;
|
|
26
26
|
|
|
27
|
-
// Each provider installs a `fetch` wrapper to capture raw error bodies, so the
|
|
28
|
-
// constructor options carry a `fetch` function; assert the meaningful options
|
|
29
|
-
// via objectContaining and confirm `fetch` is wired.
|
|
30
|
-
function expectOpenAIConstructorOptions(
|
|
31
|
-
expected: Record<string, unknown>,
|
|
32
|
-
): void {
|
|
33
|
-
expect(lastConstructorOptions).toEqual(expect.objectContaining(expected));
|
|
34
|
-
expect(typeof lastConstructorOptions?.fetch).toBe("function");
|
|
35
|
-
}
|
|
36
|
-
|
|
37
27
|
// Simulate OpenAI.APIError
|
|
38
28
|
class FakeAPIError extends Error {
|
|
39
29
|
status: number;
|
|
@@ -228,7 +218,7 @@ describe("OpenAIResponsesProvider", () => {
|
|
|
228
218
|
providerLabel: "Managed OpenAI",
|
|
229
219
|
});
|
|
230
220
|
|
|
231
|
-
|
|
221
|
+
expect(lastConstructorOptions).toEqual({
|
|
232
222
|
apiKey: "sk-custom",
|
|
233
223
|
baseURL: "https://proxy.example.com/v1",
|
|
234
224
|
timeout: DEFAULT_SDK_TIMEOUT_MS,
|
|
@@ -240,7 +230,7 @@ describe("OpenAIResponsesProvider", () => {
|
|
|
240
230
|
streamTimeoutMs: 300_000,
|
|
241
231
|
});
|
|
242
232
|
|
|
243
|
-
|
|
233
|
+
expect(lastConstructorOptions).toEqual({
|
|
244
234
|
apiKey: "sk-custom",
|
|
245
235
|
baseURL: undefined,
|
|
246
236
|
timeout: 360_000,
|
|
@@ -72,8 +72,6 @@ const persistedRows: Array<{
|
|
|
72
72
|
metadata: string | null;
|
|
73
73
|
}> = [];
|
|
74
74
|
mock.module("../memory/conversation-crud.js", () => ({
|
|
75
|
-
setConversationProcessingStartedAt: () => {},
|
|
76
|
-
isConversationProcessing: () => false,
|
|
77
75
|
addMessage: (
|
|
78
76
|
conversationId: string,
|
|
79
77
|
role: string,
|