@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
|
@@ -1,312 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tests for the gateway-backed guardian delivery reader.
|
|
3
|
-
*
|
|
4
|
-
* Guardian binding is near-static, so the reader caches behind a minutes-scale
|
|
5
|
-
* TTL, clears event-driven on invalidation, and coalesces concurrent cold-cache
|
|
6
|
-
* reads single-flight. These tests pin the parse contract plus all three cache
|
|
7
|
-
* behaviors (TTL hit, invalidation, single-flight) and the failure-no-poison
|
|
8
|
-
* rule.
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
import { beforeEach, describe, expect, mock, test } from "bun:test";
|
|
12
|
-
|
|
13
|
-
import type { GuardianDelivery } from "@vellumai/gateway-client";
|
|
14
|
-
|
|
15
|
-
// ── Controllable IPC mock ────────────────────────────────────────────────────
|
|
16
|
-
|
|
17
|
-
type IpcHandler = (params?: Record<string, unknown>) => unknown;
|
|
18
|
-
|
|
19
|
-
const ipcHandlers = new Map<string, IpcHandler>();
|
|
20
|
-
const ipcCallLog: Array<{
|
|
21
|
-
method: string;
|
|
22
|
-
params?: Record<string, unknown>;
|
|
23
|
-
timeoutMs?: number;
|
|
24
|
-
}> = [];
|
|
25
|
-
|
|
26
|
-
mock.module("../../ipc/gateway-client.js", () => ({
|
|
27
|
-
ipcCall: async (
|
|
28
|
-
method: string,
|
|
29
|
-
params?: Record<string, unknown>,
|
|
30
|
-
timeoutMs?: number,
|
|
31
|
-
) => {
|
|
32
|
-
ipcCallLog.push({ method, params, timeoutMs });
|
|
33
|
-
const handler = ipcHandlers.get(method);
|
|
34
|
-
return handler ? handler(params) : undefined;
|
|
35
|
-
},
|
|
36
|
-
ipcCallPersistent: async () => undefined,
|
|
37
|
-
resetPersistentClient: () => {},
|
|
38
|
-
}));
|
|
39
|
-
|
|
40
|
-
import { emitContactChange } from "../contact-events.js";
|
|
41
|
-
import {
|
|
42
|
-
__resetGuardianDeliveryCacheForTest,
|
|
43
|
-
anyGuardian,
|
|
44
|
-
getGuardianDelivery,
|
|
45
|
-
getGuardianDeliveryFresh,
|
|
46
|
-
guardianForChannel,
|
|
47
|
-
invalidateGuardianDeliveryCache,
|
|
48
|
-
} from "../guardian-delivery-reader.js";
|
|
49
|
-
|
|
50
|
-
const METHOD = "resolve_guardian_delivery";
|
|
51
|
-
|
|
52
|
-
function countCalls(method: string): number {
|
|
53
|
-
return ipcCallLog.filter((c) => c.method === method).length;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
const telegramGuardian: GuardianDelivery = {
|
|
57
|
-
channelType: "telegram",
|
|
58
|
-
contactId: "contact-123",
|
|
59
|
-
address: "@guardian",
|
|
60
|
-
status: "active",
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
const emailGuardian: GuardianDelivery = {
|
|
64
|
-
channelType: "email",
|
|
65
|
-
contactId: "contact-456",
|
|
66
|
-
address: "guardian@example.com",
|
|
67
|
-
status: "active",
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
describe("getGuardianDelivery", () => {
|
|
71
|
-
beforeEach(() => {
|
|
72
|
-
__resetGuardianDeliveryCacheForTest();
|
|
73
|
-
ipcHandlers.clear();
|
|
74
|
-
ipcCallLog.length = 0;
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
test("returns the parsed guardian list", async () => {
|
|
78
|
-
ipcHandlers.set(METHOD, () => ({ guardians: [telegramGuardian] }));
|
|
79
|
-
|
|
80
|
-
expect(await getGuardianDelivery()).toEqual([telegramGuardian]);
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
test("bounds the IPC read with a short timeout", async () => {
|
|
84
|
-
ipcHandlers.set(METHOD, () => ({ guardians: [] }));
|
|
85
|
-
|
|
86
|
-
await getGuardianDelivery();
|
|
87
|
-
|
|
88
|
-
const call = ipcCallLog.find((c) => c.method === METHOD);
|
|
89
|
-
expect(call?.timeoutMs).toBe(2_000);
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
test("returns null when IPC transport fails (undefined)", async () => {
|
|
93
|
-
ipcHandlers.set(METHOD, () => undefined);
|
|
94
|
-
expect(await getGuardianDelivery()).toBeNull();
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
test("returns null when the IPC call throws", async () => {
|
|
98
|
-
ipcHandlers.set(METHOD, () => {
|
|
99
|
-
throw new Error("socket exploded");
|
|
100
|
-
});
|
|
101
|
-
expect(await getGuardianDelivery()).toBeNull();
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
test("returns null for a malformed response shape", async () => {
|
|
105
|
-
ipcHandlers.set(METHOD, () => ({ guardians: "not-an-array" }));
|
|
106
|
-
expect(await getGuardianDelivery()).toBeNull();
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
test("two calls within the TTL issue only ONE IPC call (cache hit)", async () => {
|
|
110
|
-
ipcHandlers.set(METHOD, () => ({ guardians: [telegramGuardian] }));
|
|
111
|
-
|
|
112
|
-
await getGuardianDelivery();
|
|
113
|
-
await getGuardianDelivery();
|
|
114
|
-
|
|
115
|
-
expect(countCalls(METHOD)).toBe(1);
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
test("caches per channelTypes filter key", async () => {
|
|
119
|
-
ipcHandlers.set(METHOD, () => ({ guardians: [telegramGuardian] }));
|
|
120
|
-
|
|
121
|
-
await getGuardianDelivery();
|
|
122
|
-
await getGuardianDelivery({ channelTypes: ["telegram"] });
|
|
123
|
-
|
|
124
|
-
// Distinct keys ("ALL" vs "telegram") miss each other → two IPC calls.
|
|
125
|
-
expect(countCalls(METHOD)).toBe(2);
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
test("invalidateGuardianDeliveryCache() forces the next call to re-fetch", async () => {
|
|
129
|
-
ipcHandlers.set(METHOD, () => ({ guardians: [telegramGuardian] }));
|
|
130
|
-
|
|
131
|
-
await getGuardianDelivery();
|
|
132
|
-
invalidateGuardianDeliveryCache();
|
|
133
|
-
await getGuardianDelivery();
|
|
134
|
-
|
|
135
|
-
expect(countCalls(METHOD)).toBe(2);
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
test("a contact-change event clears the cache", async () => {
|
|
139
|
-
ipcHandlers.set(METHOD, () => ({ guardians: [telegramGuardian] }));
|
|
140
|
-
|
|
141
|
-
await getGuardianDelivery();
|
|
142
|
-
emitContactChange();
|
|
143
|
-
await getGuardianDelivery();
|
|
144
|
-
|
|
145
|
-
expect(countCalls(METHOD)).toBe(2);
|
|
146
|
-
});
|
|
147
|
-
|
|
148
|
-
test("a burst of concurrent cold-cache calls issues only ONE IPC call (single-flight)", async () => {
|
|
149
|
-
let resolveIpc: ((value: unknown) => void) | undefined;
|
|
150
|
-
ipcHandlers.set(
|
|
151
|
-
METHOD,
|
|
152
|
-
() =>
|
|
153
|
-
new Promise((resolve) => {
|
|
154
|
-
resolveIpc = resolve;
|
|
155
|
-
}),
|
|
156
|
-
);
|
|
157
|
-
|
|
158
|
-
const burst = Promise.all([
|
|
159
|
-
getGuardianDelivery(),
|
|
160
|
-
getGuardianDelivery(),
|
|
161
|
-
getGuardianDelivery(),
|
|
162
|
-
]);
|
|
163
|
-
resolveIpc?.({ guardians: [telegramGuardian] });
|
|
164
|
-
const results = await burst;
|
|
165
|
-
|
|
166
|
-
expect(countCalls(METHOD)).toBe(1);
|
|
167
|
-
expect(results).toEqual([
|
|
168
|
-
[telegramGuardian],
|
|
169
|
-
[telegramGuardian],
|
|
170
|
-
[telegramGuardian],
|
|
171
|
-
]);
|
|
172
|
-
});
|
|
173
|
-
|
|
174
|
-
test("an invalidation DURING an in-flight fetch is not masked — the next call re-fetches", async () => {
|
|
175
|
-
let resolveIpc: ((value: unknown) => void) | undefined;
|
|
176
|
-
ipcHandlers.set(
|
|
177
|
-
METHOD,
|
|
178
|
-
() =>
|
|
179
|
-
new Promise((resolve) => {
|
|
180
|
-
resolveIpc = resolve;
|
|
181
|
-
}),
|
|
182
|
-
);
|
|
183
|
-
|
|
184
|
-
// Start a cold fetch, invalidate before it resolves, then resolve it.
|
|
185
|
-
const inFlight = getGuardianDelivery();
|
|
186
|
-
invalidateGuardianDeliveryCache();
|
|
187
|
-
resolveIpc?.({ guardians: [telegramGuardian] });
|
|
188
|
-
expect(await inFlight).toEqual([telegramGuardian]);
|
|
189
|
-
|
|
190
|
-
// The pre-invalidation result must NOT have been cached: the next read
|
|
191
|
-
// issues a fresh IPC rather than serving the now-stale value.
|
|
192
|
-
ipcHandlers.set(METHOD, () => ({ guardians: [emailGuardian] }));
|
|
193
|
-
expect(await getGuardianDelivery()).toEqual([emailGuardian]);
|
|
194
|
-
expect(countCalls(METHOD)).toBe(2);
|
|
195
|
-
});
|
|
196
|
-
|
|
197
|
-
test("a failure does NOT poison the cache — the next call retries", async () => {
|
|
198
|
-
ipcHandlers.set(METHOD, () => undefined);
|
|
199
|
-
expect(await getGuardianDelivery()).toBeNull();
|
|
200
|
-
|
|
201
|
-
ipcHandlers.set(METHOD, () => ({ guardians: [telegramGuardian] }));
|
|
202
|
-
expect(await getGuardianDelivery()).toEqual([telegramGuardian]);
|
|
203
|
-
expect(countCalls(METHOD)).toBe(2);
|
|
204
|
-
});
|
|
205
|
-
|
|
206
|
-
test("fresh read ignores a stale cached entry and re-fetches", async () => {
|
|
207
|
-
// Seed the cache with an empty list (the stale gateway-side view).
|
|
208
|
-
ipcHandlers.set(METHOD, () => ({ guardians: [] }));
|
|
209
|
-
expect(await getGuardianDelivery()).toEqual([]);
|
|
210
|
-
|
|
211
|
-
// A cached read still serves the stale empty list (no new IPC)...
|
|
212
|
-
expect(await getGuardianDelivery()).toEqual([]);
|
|
213
|
-
expect(countCalls(METHOD)).toBe(1);
|
|
214
|
-
|
|
215
|
-
// ...but a fresh read bypasses the cache and sees the now-present guardian.
|
|
216
|
-
ipcHandlers.set(METHOD, () => ({ guardians: [telegramGuardian] }));
|
|
217
|
-
expect(await getGuardianDeliveryFresh()).toEqual([telegramGuardian]);
|
|
218
|
-
expect(countCalls(METHOD)).toBe(2);
|
|
219
|
-
});
|
|
220
|
-
|
|
221
|
-
test("fresh read updates the cache with the fresh result", async () => {
|
|
222
|
-
ipcHandlers.set(METHOD, () => ({ guardians: [] }));
|
|
223
|
-
await getGuardianDelivery();
|
|
224
|
-
|
|
225
|
-
ipcHandlers.set(METHOD, () => ({ guardians: [telegramGuardian] }));
|
|
226
|
-
await getGuardianDeliveryFresh();
|
|
227
|
-
|
|
228
|
-
// A subsequent cached read serves the refreshed value without a new IPC.
|
|
229
|
-
expect(await getGuardianDelivery()).toEqual([telegramGuardian]);
|
|
230
|
-
expect(countCalls(METHOD)).toBe(2);
|
|
231
|
-
});
|
|
232
|
-
|
|
233
|
-
test("getGuardianDeliveryFresh bypasses a stale cached empty list", async () => {
|
|
234
|
-
ipcHandlers.set(METHOD, () => ({ guardians: [] }));
|
|
235
|
-
expect(
|
|
236
|
-
await getGuardianDelivery({ channelTypes: ["telegram"] }),
|
|
237
|
-
).toEqual([]);
|
|
238
|
-
|
|
239
|
-
ipcHandlers.set(METHOD, () => ({ guardians: [telegramGuardian] }));
|
|
240
|
-
expect(
|
|
241
|
-
await getGuardianDeliveryFresh({ channelTypes: ["telegram"] }),
|
|
242
|
-
).toEqual([telegramGuardian]);
|
|
243
|
-
expect(countCalls(METHOD)).toBe(2);
|
|
244
|
-
});
|
|
245
|
-
|
|
246
|
-
test("a burst of forceRefresh reads still coalesces single-flight", async () => {
|
|
247
|
-
let resolveIpc: ((value: unknown) => void) | undefined;
|
|
248
|
-
ipcHandlers.set(
|
|
249
|
-
METHOD,
|
|
250
|
-
() =>
|
|
251
|
-
new Promise((resolve) => {
|
|
252
|
-
resolveIpc = resolve;
|
|
253
|
-
}),
|
|
254
|
-
);
|
|
255
|
-
|
|
256
|
-
const burst = Promise.all([
|
|
257
|
-
getGuardianDeliveryFresh(),
|
|
258
|
-
getGuardianDeliveryFresh(),
|
|
259
|
-
getGuardianDeliveryFresh(),
|
|
260
|
-
]);
|
|
261
|
-
resolveIpc?.({ guardians: [telegramGuardian] });
|
|
262
|
-
await burst;
|
|
263
|
-
|
|
264
|
-
expect(countCalls(METHOD)).toBe(1);
|
|
265
|
-
});
|
|
266
|
-
|
|
267
|
-
test("a fresh read does NOT coalesce with an in-flight non-force fetch (issues its own IPC)", async () => {
|
|
268
|
-
// A normal read starts a fetch that will resolve to the pre-write empty
|
|
269
|
-
// list and is still in flight when the fresh read arrives.
|
|
270
|
-
let resolveStale: ((value: unknown) => void) | undefined;
|
|
271
|
-
ipcHandlers.set(
|
|
272
|
-
METHOD,
|
|
273
|
-
() =>
|
|
274
|
-
new Promise((resolve) => {
|
|
275
|
-
resolveStale = resolve;
|
|
276
|
-
}),
|
|
277
|
-
);
|
|
278
|
-
const stale = getGuardianDelivery();
|
|
279
|
-
|
|
280
|
-
// The gateway-side write lands (not reflected in the in-flight fetch). The
|
|
281
|
-
// fresh read must NOT reuse the stale in-flight promise — it issues its own
|
|
282
|
-
// IPC observing the post-write guardian.
|
|
283
|
-
ipcHandlers.set(METHOD, () => ({ guardians: [telegramGuardian] }));
|
|
284
|
-
const fresh = await getGuardianDeliveryFresh();
|
|
285
|
-
expect(fresh).toEqual([telegramGuardian]);
|
|
286
|
-
|
|
287
|
-
// Release the stale fetch last; it must not have masked the fresh result.
|
|
288
|
-
resolveStale?.({ guardians: [] });
|
|
289
|
-
expect(await stale).toEqual([]);
|
|
290
|
-
expect(countCalls(METHOD)).toBe(2);
|
|
291
|
-
});
|
|
292
|
-
});
|
|
293
|
-
|
|
294
|
-
describe("selectors", () => {
|
|
295
|
-
test("guardianForChannel picks the first active match for the type", () => {
|
|
296
|
-
const inactive: GuardianDelivery = {
|
|
297
|
-
...telegramGuardian,
|
|
298
|
-
contactId: "contact-999",
|
|
299
|
-
status: "revoked",
|
|
300
|
-
};
|
|
301
|
-
const list = [inactive, telegramGuardian, emailGuardian];
|
|
302
|
-
|
|
303
|
-
expect(guardianForChannel(list, "telegram")).toBe(telegramGuardian);
|
|
304
|
-
expect(guardianForChannel(list, "email")).toBe(emailGuardian);
|
|
305
|
-
expect(guardianForChannel(list, "phone")).toBeUndefined();
|
|
306
|
-
});
|
|
307
|
-
|
|
308
|
-
test("anyGuardian returns the first overall", () => {
|
|
309
|
-
expect(anyGuardian([emailGuardian, telegramGuardian])).toBe(emailGuardian);
|
|
310
|
-
expect(anyGuardian([])).toBeUndefined();
|
|
311
|
-
});
|
|
312
|
-
});
|
|
@@ -1,202 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tests for the gateway-first member-activation relay.
|
|
3
|
-
*
|
|
4
|
-
* activateMemberChannel writes the activated channel through the gateway
|
|
5
|
-
* (source of truth) via `ipcCallPersistent("upsert_verified_channel", ...)`
|
|
6
|
-
* first, then mirrors the activation to the assistant DB best-effort. A local
|
|
7
|
-
* mirror failure is swallowed so the gateway-owned outcome stands; a gateway
|
|
8
|
-
* refusal (verified:false) skips the local mirror entirely.
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
import { beforeEach, describe, expect, mock, test } from "bun:test";
|
|
12
|
-
|
|
13
|
-
import type { ContactWriteResult } from "../types.js";
|
|
14
|
-
|
|
15
|
-
type IpcCall = { method: string; params?: Record<string, unknown> };
|
|
16
|
-
|
|
17
|
-
let ipcCalls: IpcCall[] = [];
|
|
18
|
-
let ipcVerified = true;
|
|
19
|
-
let ipcThrows = false;
|
|
20
|
-
|
|
21
|
-
const ipcCallPersistentMock = mock(
|
|
22
|
-
async (method: string, params?: Record<string, unknown>) => {
|
|
23
|
-
ipcCalls.push({ method, params });
|
|
24
|
-
if (ipcThrows) throw new Error("gateway unavailable");
|
|
25
|
-
return {
|
|
26
|
-
ok: true,
|
|
27
|
-
verified: ipcVerified,
|
|
28
|
-
channel: ipcVerified
|
|
29
|
-
? {
|
|
30
|
-
id: "gw-ch1",
|
|
31
|
-
contactId: (params?.contactId as string) ?? "gw-c1",
|
|
32
|
-
type: (params?.type as string) ?? "telegram",
|
|
33
|
-
address: (params?.address as string) ?? "addr",
|
|
34
|
-
status: "active",
|
|
35
|
-
verifiedAt: 1,
|
|
36
|
-
verifiedVia: (params?.verifiedVia as string) ?? "invite",
|
|
37
|
-
}
|
|
38
|
-
: undefined,
|
|
39
|
-
};
|
|
40
|
-
},
|
|
41
|
-
);
|
|
42
|
-
const actualGatewayClient = await import("../../ipc/gateway-client.js");
|
|
43
|
-
mock.module("../../ipc/gateway-client.js", () => ({
|
|
44
|
-
...actualGatewayClient,
|
|
45
|
-
ipcCallPersistent: ipcCallPersistentMock,
|
|
46
|
-
}));
|
|
47
|
-
|
|
48
|
-
// Local-mirror primitive.
|
|
49
|
-
const localResult: ContactWriteResult = {
|
|
50
|
-
contact: { id: "c1" } as ContactWriteResult["contact"],
|
|
51
|
-
channel: { id: "ch1", status: "active" } as ContactWriteResult["channel"],
|
|
52
|
-
};
|
|
53
|
-
let mirrorCallOrder = -1;
|
|
54
|
-
const upsertContactChannelMock = mock(
|
|
55
|
-
(_params: Record<string, unknown>): ContactWriteResult | null => {
|
|
56
|
-
mirrorCallOrder = ipcCalls.length;
|
|
57
|
-
return localResult;
|
|
58
|
-
},
|
|
59
|
-
);
|
|
60
|
-
const actualContactsWrite = await import("../contacts-write.js");
|
|
61
|
-
mock.module("../contacts-write.js", () => ({
|
|
62
|
-
...actualContactsWrite,
|
|
63
|
-
upsertContactChannel: upsertContactChannelMock,
|
|
64
|
-
}));
|
|
65
|
-
|
|
66
|
-
const { activateMemberChannel } = await import("../member-write-relay.js");
|
|
67
|
-
|
|
68
|
-
describe("activateMemberChannel gateway-first relay", () => {
|
|
69
|
-
beforeEach(() => {
|
|
70
|
-
ipcCalls = [];
|
|
71
|
-
ipcVerified = true;
|
|
72
|
-
ipcThrows = false;
|
|
73
|
-
mirrorCallOrder = -1;
|
|
74
|
-
ipcCallPersistentMock.mockClear();
|
|
75
|
-
upsertContactChannelMock.mockClear();
|
|
76
|
-
upsertContactChannelMock.mockImplementation(() => {
|
|
77
|
-
mirrorCallOrder = ipcCalls.length;
|
|
78
|
-
return localResult;
|
|
79
|
-
});
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
test("relays to the gateway before mirroring locally, threading the target contact", async () => {
|
|
83
|
-
const result = await activateMemberChannel({
|
|
84
|
-
sourceChannel: "telegram",
|
|
85
|
-
externalUserId: "user-1",
|
|
86
|
-
externalChatId: "chat-1",
|
|
87
|
-
displayName: "Mom",
|
|
88
|
-
contactId: "target-mom",
|
|
89
|
-
inviteId: "inv-1",
|
|
90
|
-
verifiedVia: "invite",
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
expect(ipcCalls).toEqual([
|
|
94
|
-
{
|
|
95
|
-
method: "upsert_verified_channel",
|
|
96
|
-
params: {
|
|
97
|
-
type: "telegram",
|
|
98
|
-
address: "user-1",
|
|
99
|
-
externalChatId: "chat-1",
|
|
100
|
-
displayName: "Mom",
|
|
101
|
-
username: undefined,
|
|
102
|
-
verifiedVia: "invite",
|
|
103
|
-
contactId: "target-mom",
|
|
104
|
-
allowRevokedReactivation: true,
|
|
105
|
-
},
|
|
106
|
-
},
|
|
107
|
-
]);
|
|
108
|
-
// The local mirror ran AFTER the gateway relay.
|
|
109
|
-
expect(mirrorCallOrder).toBe(1);
|
|
110
|
-
expect(upsertContactChannelMock).toHaveBeenCalledTimes(1);
|
|
111
|
-
expect(result).toEqual({
|
|
112
|
-
status: "activated",
|
|
113
|
-
memberId: "ch1",
|
|
114
|
-
member: localResult,
|
|
115
|
-
});
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
test("fails open and still mirrors locally when the gateway relay throws", async () => {
|
|
119
|
-
ipcThrows = true;
|
|
120
|
-
|
|
121
|
-
const result = await activateMemberChannel({
|
|
122
|
-
sourceChannel: "telegram",
|
|
123
|
-
externalUserId: "user-1",
|
|
124
|
-
externalChatId: "chat-1",
|
|
125
|
-
contactId: "target-mom",
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
expect(ipcCalls).toHaveLength(1);
|
|
129
|
-
expect(upsertContactChannelMock).toHaveBeenCalledTimes(1);
|
|
130
|
-
expect(result).toEqual({
|
|
131
|
-
status: "activated",
|
|
132
|
-
memberId: "ch1",
|
|
133
|
-
member: localResult,
|
|
134
|
-
});
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
test("returns the gateway channel id when the gateway verifies but the local mirror throws", async () => {
|
|
138
|
-
upsertContactChannelMock.mockImplementation(() => {
|
|
139
|
-
throw new Error("local mirror exploded");
|
|
140
|
-
});
|
|
141
|
-
|
|
142
|
-
const result = await activateMemberChannel({
|
|
143
|
-
sourceChannel: "telegram",
|
|
144
|
-
externalUserId: "user-1",
|
|
145
|
-
externalChatId: "chat-1",
|
|
146
|
-
});
|
|
147
|
-
|
|
148
|
-
expect(ipcCalls).toHaveLength(1);
|
|
149
|
-
// Gateway activation stands: the gateway channel id is returned even though
|
|
150
|
-
// the best-effort local mirror produced no row.
|
|
151
|
-
expect(result).toEqual({
|
|
152
|
-
status: "activated",
|
|
153
|
-
memberId: "gw-ch1",
|
|
154
|
-
member: null,
|
|
155
|
-
});
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
test("refuses when the gateway throws AND the local mirror yields no row", async () => {
|
|
159
|
-
ipcThrows = true;
|
|
160
|
-
upsertContactChannelMock.mockImplementation(() => {
|
|
161
|
-
throw new Error("local mirror exploded");
|
|
162
|
-
});
|
|
163
|
-
|
|
164
|
-
const result = await activateMemberChannel({
|
|
165
|
-
sourceChannel: "telegram",
|
|
166
|
-
externalUserId: "user-1",
|
|
167
|
-
externalChatId: "chat-1",
|
|
168
|
-
});
|
|
169
|
-
|
|
170
|
-
// No gateway channel (relay threw) and no local mirror: no stable id, so the
|
|
171
|
-
// caller maps this to a non-redeemed outcome rather than crashing.
|
|
172
|
-
expect(result).toEqual({ status: "refused" });
|
|
173
|
-
});
|
|
174
|
-
|
|
175
|
-
test("refuses the activation when the gateway denies the actor (verified:false)", async () => {
|
|
176
|
-
ipcVerified = false;
|
|
177
|
-
|
|
178
|
-
const result = await activateMemberChannel({
|
|
179
|
-
sourceChannel: "telegram",
|
|
180
|
-
externalUserId: "user-1",
|
|
181
|
-
externalChatId: "chat-1",
|
|
182
|
-
contactId: "target-mom",
|
|
183
|
-
});
|
|
184
|
-
|
|
185
|
-
expect(ipcCalls).toHaveLength(1);
|
|
186
|
-
expect(upsertContactChannelMock).not.toHaveBeenCalled();
|
|
187
|
-
expect(result).toEqual({ status: "refused" });
|
|
188
|
-
});
|
|
189
|
-
|
|
190
|
-
test("derives the address from externalChatId when no externalUserId is present", async () => {
|
|
191
|
-
await activateMemberChannel({
|
|
192
|
-
sourceChannel: "phone",
|
|
193
|
-
externalChatId: "+15551234567",
|
|
194
|
-
});
|
|
195
|
-
|
|
196
|
-
expect(ipcCalls[0]?.params).toMatchObject({
|
|
197
|
-
type: "phone",
|
|
198
|
-
address: "+15551234567",
|
|
199
|
-
externalChatId: "+15551234567",
|
|
200
|
-
});
|
|
201
|
-
});
|
|
202
|
-
});
|