@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
|
@@ -38,7 +38,6 @@ mock.module("../runtime/assistant-event-hub.js", () => ({
|
|
|
38
38
|
|
|
39
39
|
const {
|
|
40
40
|
DISK_PRESSURE_CLEAR_THRESHOLD_PERCENT,
|
|
41
|
-
DISK_PRESSURE_MIN_FREE_FLOOR_MB,
|
|
42
41
|
DISK_PRESSURE_OVERRIDE_CONFIRMATION,
|
|
43
42
|
DISK_PRESSURE_THRESHOLD_PERCENT,
|
|
44
43
|
DISK_PRESSURE_WARNING_CLEAR_THRESHOLD_PERCENT,
|
|
@@ -343,44 +342,4 @@ describe("disk pressure guard", () => {
|
|
|
343
342
|
setDiskUsage(DISK_PRESSURE_WARNING_CLEAR_THRESHOLD_PERCENT - 1);
|
|
344
343
|
expect(evaluateDiskPressureNow().state).toBe("ok");
|
|
345
344
|
});
|
|
346
|
-
|
|
347
|
-
test("stays ok at a critical usage percentage while ample free space remains", () => {
|
|
348
|
-
// 99% used of a large volume still leaves gigabytes free — above the floor.
|
|
349
|
-
const totalMb = 1_000_000;
|
|
350
|
-
const usedMb = Math.round(totalMb * 0.99); // freeMb ~= 10_000 MiB
|
|
351
|
-
setDiskUsage(usedMb, totalMb);
|
|
352
|
-
expect(diskSample!.freeMb).toBeGreaterThanOrEqual(
|
|
353
|
-
DISK_PRESSURE_MIN_FREE_FLOOR_MB,
|
|
354
|
-
);
|
|
355
|
-
|
|
356
|
-
const status = evaluateDiskPressureNow();
|
|
357
|
-
|
|
358
|
-
expect(status.state).toBe("ok");
|
|
359
|
-
expect(status.locked).toBe(false);
|
|
360
|
-
expect(status.effectivelyLocked).toBe(false);
|
|
361
|
-
});
|
|
362
|
-
|
|
363
|
-
test("stays ok at a warning usage percentage while ample free space remains", () => {
|
|
364
|
-
const totalMb = 1_000_000;
|
|
365
|
-
const usedMb = Math.round(totalMb * 0.85); // 85% used, freeMb ~= 150_000 MiB
|
|
366
|
-
setDiskUsage(usedMb, totalMb);
|
|
367
|
-
|
|
368
|
-
const status = evaluateDiskPressureNow();
|
|
369
|
-
|
|
370
|
-
expect(status.state).toBe("ok");
|
|
371
|
-
});
|
|
372
|
-
|
|
373
|
-
test("locks at a critical usage percentage once free space drops below the floor", () => {
|
|
374
|
-
// High percentage AND little absolute headroom: floor does not apply.
|
|
375
|
-
const totalMb = 100_000;
|
|
376
|
-
const freeMb = DISK_PRESSURE_MIN_FREE_FLOOR_MB - 1;
|
|
377
|
-
setDiskUsage(totalMb - freeMb, totalMb);
|
|
378
|
-
expect(diskSample!.freeMb).toBeLessThan(DISK_PRESSURE_MIN_FREE_FLOOR_MB);
|
|
379
|
-
|
|
380
|
-
const status = evaluateDiskPressureNow();
|
|
381
|
-
|
|
382
|
-
expect(status.state).toBe("critical");
|
|
383
|
-
expect(status.locked).toBe(true);
|
|
384
|
-
expect(status.effectivelyLocked).toBe(true);
|
|
385
|
-
});
|
|
386
345
|
});
|
|
@@ -30,8 +30,6 @@ const addMessageCalls: Array<{
|
|
|
30
30
|
}> = [];
|
|
31
31
|
|
|
32
32
|
mock.module("../memory/conversation-crud.js", () => ({
|
|
33
|
-
setConversationProcessingStartedAt: () => {},
|
|
34
|
-
isConversationProcessing: () => false,
|
|
35
33
|
addMessage: async (
|
|
36
34
|
conversationId: string,
|
|
37
35
|
role: string,
|
|
@@ -19,19 +19,14 @@ mock.module("../channels/config.js", () => ({
|
|
|
19
19
|
getDeliverableChannels: () => ["vellum", "telegram"],
|
|
20
20
|
}));
|
|
21
21
|
|
|
22
|
-
// Guardian connectivity is resolved from the gateway pull. No active guardian
|
|
23
|
-
// binding ⇒ binding-based channels (telegram) are not reported connected.
|
|
24
|
-
mock.module("../contacts/guardian-delivery-reader.js", () => ({
|
|
25
|
-
getGuardianDelivery: async () => [],
|
|
26
|
-
guardianForChannel: () => undefined,
|
|
27
|
-
}));
|
|
28
|
-
|
|
29
|
-
// connectivity falls back to the local contacts read on a per-channel gateway
|
|
30
|
-
// no-match; no local binding ⇒ telegram stays disconnected.
|
|
31
22
|
mock.module("../contacts/contact-store.js", () => ({
|
|
32
|
-
findGuardianForChannel: () => null,
|
|
23
|
+
findGuardianForChannel: (_channelType: string, _assistantId: string) => null,
|
|
33
24
|
}));
|
|
34
25
|
|
|
26
|
+
// Note: stale mock for channel-guardian-store.js removed — the barrel was
|
|
27
|
+
// deleted and none of the functions it mocked (getActiveBinding) existed in
|
|
28
|
+
// the barrel.
|
|
29
|
+
|
|
35
30
|
mock.module("../notifications/adapters/macos.js", () => ({
|
|
36
31
|
VellumAdapter: class {
|
|
37
32
|
constructor(_broadcastFn: unknown) {}
|
|
@@ -29,13 +29,7 @@ mock.module("../config/env.js", () => ({
|
|
|
29
29
|
}));
|
|
30
30
|
|
|
31
31
|
mock.module("../runtime/local-actor-identity.js", () => ({
|
|
32
|
-
|
|
33
|
-
resolveActorPrincipalIdForLocalGuardianSync: (
|
|
34
|
-
rawHeader: string | undefined,
|
|
35
|
-
) => {
|
|
36
|
-
if (rawHeader !== "dev-bypass" || !fakeHttpAuthDisabled) return rawHeader;
|
|
37
|
-
return fakeGuardianPrincipalId;
|
|
38
|
-
},
|
|
32
|
+
findLocalGuardianPrincipalId: () => fakeGuardianPrincipalId,
|
|
39
33
|
}));
|
|
40
34
|
|
|
41
35
|
mock.module("../util/logger.js", () => ({
|
|
@@ -225,11 +225,10 @@ describe("exploration-drift post-tool-use hook — long-dig trigger", () => {
|
|
|
225
225
|
expect(ctx.toolResponse.content).toBe(BASE_CONTENT);
|
|
226
226
|
});
|
|
227
227
|
|
|
228
|
-
test("counts
|
|
229
|
-
const explorationNames = ["code_search", "file_read", "file_list"];
|
|
228
|
+
test("counts file_read and file_list as exploration tools", async () => {
|
|
230
229
|
const messages: Message[] = [];
|
|
231
230
|
for (let i = 0; i < EXPLORATION_NUDGE_THRESHOLD - 1; i++) {
|
|
232
|
-
const name =
|
|
231
|
+
const name = i % 2 === 0 ? "file_read" : "file_list";
|
|
233
232
|
const id = `${name}-${i}`;
|
|
234
233
|
messages.push(toolUseTurn(id, name, { path: `/tmp/file-${i}` }));
|
|
235
234
|
messages.push(toolResultTurn(id));
|
|
@@ -51,8 +51,6 @@ const createdConversations: Array<{
|
|
|
51
51
|
let conversationIdCounter = 0;
|
|
52
52
|
|
|
53
53
|
mock.module("../memory/conversation-crud.js", () => ({
|
|
54
|
-
setConversationProcessingStartedAt: () => {},
|
|
55
|
-
isConversationProcessing: () => false,
|
|
56
54
|
setConversationOriginChannelIfUnset: () => {},
|
|
57
55
|
updateConversationContextWindow: () => {},
|
|
58
56
|
deleteMessageById: () => {},
|
|
@@ -7,16 +7,6 @@ mock.module("../util/logger.js", () => ({
|
|
|
7
7
|
}),
|
|
8
8
|
}));
|
|
9
9
|
|
|
10
|
-
import type { GuardianDelivery } from "@vellumai/gateway-client";
|
|
11
|
-
|
|
12
|
-
let mockGuardians: GuardianDelivery[] | null = [];
|
|
13
|
-
|
|
14
|
-
mock.module("../contacts/guardian-delivery-reader.js", () => ({
|
|
15
|
-
getGuardianDelivery: async () => mockGuardians,
|
|
16
|
-
guardianForChannel: (list: GuardianDelivery[], channelType: string) =>
|
|
17
|
-
list.find((g) => g.channelType === channelType && g.status === "active"),
|
|
18
|
-
}));
|
|
19
|
-
|
|
20
10
|
import { findGuardianForChannel } from "../contacts/contact-store.js";
|
|
21
11
|
import { getDb } from "../memory/db-connection.js";
|
|
22
12
|
import { initializeDb } from "../memory/db-init.js";
|
|
@@ -31,24 +21,12 @@ function resetTables(): void {
|
|
|
31
21
|
db.run("DELETE FROM contacts");
|
|
32
22
|
}
|
|
33
23
|
|
|
34
|
-
/** Gateway delivery mirroring the local guardian binding's principal. */
|
|
35
|
-
function gatewayGuardian(principalId: string): GuardianDelivery {
|
|
36
|
-
return {
|
|
37
|
-
channelType: "vellum",
|
|
38
|
-
contactId: "guardian-contact",
|
|
39
|
-
principalId,
|
|
40
|
-
address: principalId,
|
|
41
|
-
status: "active",
|
|
42
|
-
};
|
|
43
|
-
}
|
|
44
|
-
|
|
45
24
|
describe("healGuardianBindingDrift", () => {
|
|
46
25
|
beforeEach(() => {
|
|
47
26
|
resetTables();
|
|
48
|
-
mockGuardians = [];
|
|
49
27
|
});
|
|
50
28
|
|
|
51
|
-
test("heals drift when both principals have vellum-principal- prefix",
|
|
29
|
+
test("heals drift when both principals have vellum-principal- prefix", () => {
|
|
52
30
|
// Simulate DB reset: new guardian binding with a different UUID
|
|
53
31
|
createGuardianBinding({
|
|
54
32
|
channel: "vellum",
|
|
@@ -57,10 +35,9 @@ describe("healGuardianBindingDrift", () => {
|
|
|
57
35
|
guardianPrincipalId: "vellum-principal-new-uuid",
|
|
58
36
|
verifiedVia: "startup-migration",
|
|
59
37
|
});
|
|
60
|
-
mockGuardians = [gatewayGuardian("vellum-principal-new-uuid")];
|
|
61
38
|
|
|
62
39
|
// Client arrives with the old JWT principal
|
|
63
|
-
const healed =
|
|
40
|
+
const healed = healGuardianBindingDrift("vellum-principal-old-uuid");
|
|
64
41
|
expect(healed).toBe(true);
|
|
65
42
|
|
|
66
43
|
// Guardian binding now matches the old JWT
|
|
@@ -70,31 +47,7 @@ describe("healGuardianBindingDrift", () => {
|
|
|
70
47
|
expect(guardian!.channel.address).toBe("vellum-principal-old-uuid");
|
|
71
48
|
});
|
|
72
49
|
|
|
73
|
-
test("
|
|
74
|
-
// Gateway binding already matches the incoming JWT principal, but the
|
|
75
|
-
// local mirror is stale — the gateway-source-of-truth drift mode. The
|
|
76
|
-
// /v1/messages trust path still reads the local mirror in this plan, so
|
|
77
|
-
// a stale row must be repaired or the actor stays classified `unknown`.
|
|
78
|
-
createGuardianBinding({
|
|
79
|
-
channel: "vellum",
|
|
80
|
-
guardianExternalUserId: "vellum-principal-stale-local",
|
|
81
|
-
guardianDeliveryChatId: "local",
|
|
82
|
-
guardianPrincipalId: "vellum-principal-stale-local",
|
|
83
|
-
verifiedVia: "startup-migration",
|
|
84
|
-
});
|
|
85
|
-
mockGuardians = [gatewayGuardian("vellum-principal-jwt")];
|
|
86
|
-
|
|
87
|
-
const healed = await healGuardianBindingDrift("vellum-principal-jwt");
|
|
88
|
-
expect(healed).toBe(true);
|
|
89
|
-
|
|
90
|
-
// Local mirror now matches the JWT, so a subsequent local trust
|
|
91
|
-
// resolution classifies the actor as guardian rather than unknown.
|
|
92
|
-
const guardian = findGuardianForChannel("vellum");
|
|
93
|
-
expect(guardian!.contact.principalId).toBe("vellum-principal-jwt");
|
|
94
|
-
expect(guardian!.channel.address).toBe("vellum-principal-jwt");
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
test("no-op when principals already match", async () => {
|
|
50
|
+
test("no-op when principals already match", () => {
|
|
98
51
|
createGuardianBinding({
|
|
99
52
|
channel: "vellum",
|
|
100
53
|
guardianExternalUserId: "vellum-principal-same",
|
|
@@ -102,13 +55,12 @@ describe("healGuardianBindingDrift", () => {
|
|
|
102
55
|
guardianPrincipalId: "vellum-principal-same",
|
|
103
56
|
verifiedVia: "startup-migration",
|
|
104
57
|
});
|
|
105
|
-
mockGuardians = [gatewayGuardian("vellum-principal-same")];
|
|
106
58
|
|
|
107
|
-
const healed =
|
|
59
|
+
const healed = healGuardianBindingDrift("vellum-principal-same");
|
|
108
60
|
expect(healed).toBe(false);
|
|
109
61
|
});
|
|
110
62
|
|
|
111
|
-
test("refuses to heal when incoming principal lacks vellum-principal- prefix",
|
|
63
|
+
test("refuses to heal when incoming principal lacks vellum-principal- prefix", () => {
|
|
112
64
|
createGuardianBinding({
|
|
113
65
|
channel: "vellum",
|
|
114
66
|
guardianExternalUserId: "vellum-principal-aaa",
|
|
@@ -116,10 +68,9 @@ describe("healGuardianBindingDrift", () => {
|
|
|
116
68
|
guardianPrincipalId: "vellum-principal-aaa",
|
|
117
69
|
verifiedVia: "startup-migration",
|
|
118
70
|
});
|
|
119
|
-
mockGuardians = [gatewayGuardian("vellum-principal-aaa")];
|
|
120
71
|
|
|
121
72
|
// External/platform principal — should NOT be adopted
|
|
122
|
-
const healed =
|
|
73
|
+
const healed = healGuardianBindingDrift("platform-user-12345");
|
|
123
74
|
expect(healed).toBe(false);
|
|
124
75
|
|
|
125
76
|
// Guardian unchanged
|
|
@@ -127,7 +78,7 @@ describe("healGuardianBindingDrift", () => {
|
|
|
127
78
|
expect(guardian!.contact.principalId).toBe("vellum-principal-aaa");
|
|
128
79
|
});
|
|
129
80
|
|
|
130
|
-
test("refuses to heal when stored principal lacks vellum-principal- prefix",
|
|
81
|
+
test("refuses to heal when stored principal lacks vellum-principal- prefix", () => {
|
|
131
82
|
createGuardianBinding({
|
|
132
83
|
channel: "vellum",
|
|
133
84
|
guardianExternalUserId: "verified-phone-guardian",
|
|
@@ -135,33 +86,17 @@ describe("healGuardianBindingDrift", () => {
|
|
|
135
86
|
guardianPrincipalId: "verified-phone-guardian",
|
|
136
87
|
verifiedVia: "challenge",
|
|
137
88
|
});
|
|
138
|
-
mockGuardians = [gatewayGuardian("verified-phone-guardian")];
|
|
139
89
|
|
|
140
90
|
// Even with a vellum-principal- incoming, don't overwrite a real binding
|
|
141
|
-
const healed =
|
|
91
|
+
const healed = healGuardianBindingDrift("vellum-principal-attacker");
|
|
142
92
|
expect(healed).toBe(false);
|
|
143
93
|
|
|
144
94
|
const guardian = findGuardianForChannel("vellum");
|
|
145
95
|
expect(guardian!.contact.principalId).toBe("verified-phone-guardian");
|
|
146
96
|
});
|
|
147
97
|
|
|
148
|
-
test("returns false when
|
|
149
|
-
|
|
150
|
-
const healed = await healGuardianBindingDrift("vellum-principal-orphan");
|
|
151
|
-
expect(healed).toBe(false);
|
|
152
|
-
});
|
|
153
|
-
|
|
154
|
-
test("returns false when the gateway is unreachable (null list)", async () => {
|
|
155
|
-
createGuardianBinding({
|
|
156
|
-
channel: "vellum",
|
|
157
|
-
guardianExternalUserId: "vellum-principal-aaa",
|
|
158
|
-
guardianDeliveryChatId: "local",
|
|
159
|
-
guardianPrincipalId: "vellum-principal-aaa",
|
|
160
|
-
verifiedVia: "startup-migration",
|
|
161
|
-
});
|
|
162
|
-
mockGuardians = null;
|
|
163
|
-
|
|
164
|
-
const healed = await healGuardianBindingDrift("vellum-principal-old-uuid");
|
|
98
|
+
test("returns false when no guardian binding exists", () => {
|
|
99
|
+
const healed = healGuardianBindingDrift("vellum-principal-orphan");
|
|
165
100
|
expect(healed).toBe(false);
|
|
166
101
|
});
|
|
167
102
|
});
|
|
@@ -24,11 +24,6 @@ mock.module("../config/loader.js", () => ({
|
|
|
24
24
|
}),
|
|
25
25
|
}));
|
|
26
26
|
|
|
27
|
-
// The pending_question request principal is resolved via the SAME local source
|
|
28
|
-
// the Vellum actor uses — findGuardianForChannel("vellum")?.contact.principalId
|
|
29
|
-
// — so the stamped principal always equals the submitting actor principal. The
|
|
30
|
-
// real contacts DB is seeded in resetTables(); tests model drift / missing
|
|
31
|
-
// guardian by reseeding or clearing that local binding directly.
|
|
32
27
|
const emitCalls: unknown[] = [];
|
|
33
28
|
let conversationCreatedFromMock: ConversationCreatedInfo | null = null;
|
|
34
29
|
let mockEmitResult: {
|
|
@@ -159,18 +154,11 @@ describe("guardian-dispatch", () => {
|
|
|
159
154
|
"SELECT * FROM canonical_guardian_requests WHERE call_session_id = ?",
|
|
160
155
|
)
|
|
161
156
|
.get(session.id) as
|
|
162
|
-
| {
|
|
163
|
-
id: string;
|
|
164
|
-
status: string;
|
|
165
|
-
question_text: string;
|
|
166
|
-
guardian_principal_id: string | null;
|
|
167
|
-
}
|
|
157
|
+
| { id: string; status: string; question_text: string }
|
|
168
158
|
| undefined;
|
|
169
159
|
expect(request).toBeDefined();
|
|
170
160
|
expect(request!.status).toBe("pending");
|
|
171
161
|
expect(request!.question_text).toBe("What is the gate code?");
|
|
172
|
-
// principalId comes from the local guardian binding (same source the actor submits)
|
|
173
|
-
expect(request!.guardian_principal_id).toBe("test-principal-id");
|
|
174
162
|
|
|
175
163
|
const vellumDelivery = raw
|
|
176
164
|
.query(
|
|
@@ -187,88 +175,6 @@ describe("guardian-dispatch", () => {
|
|
|
187
175
|
expect(typeof signalParams.onConversationCreated).toBe("function");
|
|
188
176
|
});
|
|
189
177
|
|
|
190
|
-
test("stamps the request principal from the local source the actor submits, not the (possibly drifted) gateway binding", async () => {
|
|
191
|
-
// Simulate gateway/local binding drift: the local guardian binding (the
|
|
192
|
-
// source the actor submit path reads) carries a different principal than
|
|
193
|
-
// the gateway would. The request must be stamped with that local value so
|
|
194
|
-
// a later actor submission matches (no identity_mismatch under drift).
|
|
195
|
-
const db = getDb();
|
|
196
|
-
db.run("DELETE FROM contact_channels");
|
|
197
|
-
db.run("DELETE FROM contacts");
|
|
198
|
-
createGuardianBinding({
|
|
199
|
-
channel: "vellum",
|
|
200
|
-
guardianExternalUserId: "local-actor-principal",
|
|
201
|
-
guardianDeliveryChatId: "local",
|
|
202
|
-
guardianPrincipalId: "local-actor-principal",
|
|
203
|
-
verifiedVia: "bootstrap",
|
|
204
|
-
});
|
|
205
|
-
|
|
206
|
-
const convId = "conv-dispatch-drift";
|
|
207
|
-
ensureConversation(convId);
|
|
208
|
-
|
|
209
|
-
const session = createCallSession({
|
|
210
|
-
conversationId: convId,
|
|
211
|
-
provider: "twilio",
|
|
212
|
-
fromNumber: "+15550001111",
|
|
213
|
-
toNumber: "+15550002222",
|
|
214
|
-
});
|
|
215
|
-
const pq = createPendingQuestion(session.id, "Drifted bindings?");
|
|
216
|
-
|
|
217
|
-
await dispatchGuardianQuestion({
|
|
218
|
-
callSessionId: session.id,
|
|
219
|
-
conversationId: convId,
|
|
220
|
-
assistantId: "self",
|
|
221
|
-
pendingQuestion: pq,
|
|
222
|
-
});
|
|
223
|
-
|
|
224
|
-
const raw = (db as unknown as { $client: import("bun:sqlite").Database })
|
|
225
|
-
.$client;
|
|
226
|
-
const request = raw
|
|
227
|
-
.query(
|
|
228
|
-
"SELECT * FROM canonical_guardian_requests WHERE call_session_id = ?",
|
|
229
|
-
)
|
|
230
|
-
.get(session.id) as
|
|
231
|
-
| { guardian_principal_id: string | null }
|
|
232
|
-
| undefined;
|
|
233
|
-
expect(request).toBeDefined();
|
|
234
|
-
expect(request!.guardian_principal_id).toBe("local-actor-principal");
|
|
235
|
-
});
|
|
236
|
-
|
|
237
|
-
test("skips dispatch when no local guardian binding exists (no principal to stamp)", async () => {
|
|
238
|
-
const db = getDb();
|
|
239
|
-
db.run("DELETE FROM contact_channels");
|
|
240
|
-
db.run("DELETE FROM contacts");
|
|
241
|
-
|
|
242
|
-
const convId = "conv-dispatch-no-principal";
|
|
243
|
-
ensureConversation(convId);
|
|
244
|
-
|
|
245
|
-
const session = createCallSession({
|
|
246
|
-
conversationId: convId,
|
|
247
|
-
provider: "twilio",
|
|
248
|
-
fromNumber: "+15550001111",
|
|
249
|
-
toNumber: "+15550002222",
|
|
250
|
-
});
|
|
251
|
-
const pq = createPendingQuestion(session.id, "No principal available");
|
|
252
|
-
|
|
253
|
-
await dispatchGuardianQuestion({
|
|
254
|
-
callSessionId: session.id,
|
|
255
|
-
conversationId: convId,
|
|
256
|
-
assistantId: "self",
|
|
257
|
-
pendingQuestion: pq,
|
|
258
|
-
});
|
|
259
|
-
|
|
260
|
-
// No request is created and the pipeline is never invoked.
|
|
261
|
-
const raw = (db as unknown as { $client: import("bun:sqlite").Database })
|
|
262
|
-
.$client;
|
|
263
|
-
const request = raw
|
|
264
|
-
.query(
|
|
265
|
-
"SELECT * FROM canonical_guardian_requests WHERE call_session_id = ?",
|
|
266
|
-
)
|
|
267
|
-
.get(session.id) as { id: string } | null;
|
|
268
|
-
expect(request).toBeNull();
|
|
269
|
-
expect(emitCalls).toHaveLength(0);
|
|
270
|
-
});
|
|
271
|
-
|
|
272
178
|
test("creates a telegram guardian delivery with binding metadata when pipeline sends telegram", async () => {
|
|
273
179
|
const convId = "conv-dispatch-2";
|
|
274
180
|
ensureConversation(convId);
|
|
@@ -84,19 +84,6 @@ globalThis.fetch = (async (
|
|
|
84
84
|
return originalFetch(input, init as never);
|
|
85
85
|
}) as unknown as typeof fetch;
|
|
86
86
|
|
|
87
|
-
// Guardian-delivery reader mock — the inbound challenge guard reads guardian
|
|
88
|
-
// existence from the gateway. These tests seed no binding, so report an empty
|
|
89
|
-
// list (not bound) rather than a null that would fail closed as already-bound.
|
|
90
|
-
mock.module("../contacts/guardian-delivery-reader.js", () => ({
|
|
91
|
-
getGuardianDelivery: async () => [],
|
|
92
|
-
getGuardianDeliveryFresh: async () => [],
|
|
93
|
-
guardianForChannel: (
|
|
94
|
-
list: Array<{ channelType: string; status: string }>,
|
|
95
|
-
channelType: string,
|
|
96
|
-
) =>
|
|
97
|
-
list.find((g) => g.channelType === channelType && g.status === "active"),
|
|
98
|
-
}));
|
|
99
|
-
|
|
100
87
|
// ---------------------------------------------------------------------------
|
|
101
88
|
// Now import modules under test (after mocks are in place)
|
|
102
89
|
// ---------------------------------------------------------------------------
|
|
@@ -70,8 +70,6 @@ mock.module("../schedule/recurrence-engine.js", () => ({
|
|
|
70
70
|
|
|
71
71
|
const createdConversations: Array<{ conversationType: string }> = [];
|
|
72
72
|
mock.module("../memory/conversation-crud.js", () => ({
|
|
73
|
-
setConversationProcessingStartedAt: () => {},
|
|
74
|
-
isConversationProcessing: () => false,
|
|
75
73
|
getConversation: () => null,
|
|
76
74
|
getMessages: () => [],
|
|
77
75
|
createConversation: (opts: { conversationType: string }) => {
|
|
@@ -137,8 +137,6 @@ const mockStoredMessages: Array<{
|
|
|
137
137
|
}> = [];
|
|
138
138
|
|
|
139
139
|
mock.module("../memory/conversation-crud.js", () => ({
|
|
140
|
-
setConversationProcessingStartedAt: () => {},
|
|
141
|
-
isConversationProcessing: () => false,
|
|
142
140
|
setConversationOriginChannelIfUnset: () => {},
|
|
143
141
|
updateConversationContextWindow: () => {},
|
|
144
142
|
deleteMessageById: () => {},
|
|
@@ -138,11 +138,16 @@ function stampTrustVerdict(body: Record<string, unknown>): void {
|
|
|
138
138
|
const channelType = String(body.sourceChannel ?? "");
|
|
139
139
|
const actorExternalId =
|
|
140
140
|
typeof body.actorExternalId === "string" ? body.actorExternalId : undefined;
|
|
141
|
+
const externalChatId =
|
|
142
|
+
typeof body.conversationExternalId === "string"
|
|
143
|
+
? body.conversationExternalId
|
|
144
|
+
: undefined;
|
|
141
145
|
if (!channelType) return;
|
|
142
146
|
|
|
143
147
|
const verdict = resolveLocalTrustVerdict({
|
|
144
148
|
channelType,
|
|
145
149
|
actorExternalId,
|
|
150
|
+
externalChatId,
|
|
146
151
|
});
|
|
147
152
|
body.sourceMetadata = { ...(meta ?? {}), trustVerdict: verdict };
|
|
148
153
|
}
|
|
@@ -151,14 +156,15 @@ function stampTrustVerdict(body: Record<string, unknown>): void {
|
|
|
151
156
|
export function resolveLocalTrustVerdict(input: {
|
|
152
157
|
channelType: string;
|
|
153
158
|
actorExternalId?: string;
|
|
159
|
+
externalChatId?: string;
|
|
154
160
|
}): TrustVerdict {
|
|
155
161
|
const canonicalSenderId = input.actorExternalId ?? null;
|
|
156
162
|
|
|
157
|
-
// Match the gateway's address-only member resolution (no externalChatId).
|
|
158
163
|
const member = input.actorExternalId
|
|
159
164
|
? findContactChannel({
|
|
160
165
|
channelType: input.channelType,
|
|
161
166
|
address: input.actorExternalId,
|
|
167
|
+
externalChatId: input.externalChatId,
|
|
162
168
|
})
|
|
163
169
|
: null;
|
|
164
170
|
const guardian = findGuardianForChannel(input.channelType);
|
|
@@ -62,7 +62,7 @@ afterAll(() => {
|
|
|
62
62
|
|
|
63
63
|
const handleHostAppControlResult = ROUTES.find(
|
|
64
64
|
(r) => r.endpoint === "host-app-control-result",
|
|
65
|
-
)!.handler
|
|
65
|
+
)!.handler;
|
|
66
66
|
|
|
67
67
|
// ── Tests ────────────────────────────────────────────────────────────
|
|
68
68
|
|
|
@@ -395,7 +395,7 @@ describe("handleHostAppControlResult — same-actor guard", () => {
|
|
|
395
395
|
).toThrow(BadRequestError);
|
|
396
396
|
});
|
|
397
397
|
|
|
398
|
-
test("targeted + missing header: interaction is NOT consumed (still pending)",
|
|
398
|
+
test("targeted + missing header: interaction is NOT consumed (still pending)", () => {
|
|
399
399
|
const requestId = "ac-req-targeted-no-header-stays";
|
|
400
400
|
pending.set(requestId, {
|
|
401
401
|
conversationId: "conv-1",
|
|
@@ -404,11 +404,13 @@ describe("handleHostAppControlResult — same-actor guard", () => {
|
|
|
404
404
|
targetActorPrincipalId: "user-1",
|
|
405
405
|
});
|
|
406
406
|
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
407
|
+
try {
|
|
408
|
+
handleHostAppControlResult({
|
|
409
|
+
body: { requestId, state: "running" },
|
|
410
|
+
});
|
|
411
|
+
} catch {
|
|
410
412
|
// expected
|
|
411
|
-
}
|
|
413
|
+
}
|
|
412
414
|
|
|
413
415
|
expect(pending.has(requestId)).toBe(true);
|
|
414
416
|
});
|
|
@@ -435,7 +437,7 @@ describe("handleHostAppControlResult — same-actor guard", () => {
|
|
|
435
437
|
).toThrow(ForbiddenError);
|
|
436
438
|
});
|
|
437
439
|
|
|
438
|
-
test("targeted + wrong client id: interaction is NOT consumed",
|
|
440
|
+
test("targeted + wrong client id: interaction is NOT consumed", () => {
|
|
439
441
|
const requestId = "ac-req-targeted-wrong-client-stays";
|
|
440
442
|
pending.set(requestId, {
|
|
441
443
|
conversationId: "conv-1",
|
|
@@ -444,15 +446,17 @@ describe("handleHostAppControlResult — same-actor guard", () => {
|
|
|
444
446
|
targetActorPrincipalId: "user-1",
|
|
445
447
|
});
|
|
446
448
|
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
449
|
+
try {
|
|
450
|
+
handleHostAppControlResult({
|
|
451
|
+
body: { requestId, state: "running" },
|
|
452
|
+
headers: {
|
|
453
|
+
"x-vellum-client-id": "client-B",
|
|
454
|
+
"x-vellum-actor-principal-id": "user-1",
|
|
455
|
+
},
|
|
456
|
+
});
|
|
457
|
+
} catch {
|
|
454
458
|
// expected
|
|
455
|
-
}
|
|
459
|
+
}
|
|
456
460
|
|
|
457
461
|
expect(pending.has(requestId)).toBe(true);
|
|
458
462
|
});
|
|
@@ -479,7 +483,7 @@ describe("handleHostAppControlResult — same-actor guard", () => {
|
|
|
479
483
|
).toThrow(ForbiddenError);
|
|
480
484
|
});
|
|
481
485
|
|
|
482
|
-
test("targeted + wrong actor principal: interaction is NOT consumed",
|
|
486
|
+
test("targeted + wrong actor principal: interaction is NOT consumed", () => {
|
|
483
487
|
const requestId = "ac-req-targeted-wrong-actor-stays";
|
|
484
488
|
pending.set(requestId, {
|
|
485
489
|
conversationId: "conv-1",
|
|
@@ -488,15 +492,17 @@ describe("handleHostAppControlResult — same-actor guard", () => {
|
|
|
488
492
|
targetActorPrincipalId: "user-1",
|
|
489
493
|
});
|
|
490
494
|
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
495
|
+
try {
|
|
496
|
+
handleHostAppControlResult({
|
|
497
|
+
body: { requestId, state: "running" },
|
|
498
|
+
headers: {
|
|
499
|
+
"x-vellum-client-id": "client-A",
|
|
500
|
+
"x-vellum-actor-principal-id": "user-2",
|
|
501
|
+
},
|
|
502
|
+
});
|
|
503
|
+
} catch {
|
|
498
504
|
// expected
|
|
499
|
-
}
|
|
505
|
+
}
|
|
500
506
|
|
|
501
507
|
expect(pending.has(requestId)).toBe(true);
|
|
502
508
|
});
|