@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
|
@@ -34,38 +34,19 @@ mock.module("../../prompts/system-prompt.js", () => ({
|
|
|
34
34
|
buildCoreIdentityContext: () => null,
|
|
35
35
|
}));
|
|
36
36
|
|
|
37
|
-
// Guardian binding (ACL) is resolved via the gateway pull; notes (INFO) are
|
|
38
|
-
// joined locally by contactId. Tests drive both via mutable slots.
|
|
39
|
-
let guardianDeliveryFixture: Array<{ contactId: string }> = [];
|
|
40
|
-
let contactInfoFixture: Record<string, { notes: string | null } | null> = {};
|
|
41
|
-
|
|
42
|
-
mock.module("../../contacts/guardian-delivery-reader.js", () => ({
|
|
43
|
-
getGuardianDelivery: async () => guardianDeliveryFixture,
|
|
44
|
-
anyGuardian: (list: Array<{ contactId: string }>) => list[0],
|
|
45
|
-
}));
|
|
46
|
-
|
|
47
37
|
mock.module("../../contacts/contact-store.js", () => ({
|
|
48
|
-
|
|
49
|
-
contactInfoFixture[contactId] ?? null,
|
|
38
|
+
listGuardianChannels: () => null,
|
|
50
39
|
}));
|
|
51
40
|
|
|
52
|
-
// Provider mock
|
|
53
|
-
// pass-through path
|
|
54
|
-
//
|
|
55
|
-
let providerSendMessage: (
|
|
56
|
-
messages: unknown[],
|
|
57
|
-
opts: { systemPrompt?: string },
|
|
58
|
-
) => Promise<unknown> = () => {
|
|
59
|
-
throw new Error(
|
|
60
|
-
"provider.sendMessage should NOT be invoked for assistant_tool pass-through",
|
|
61
|
-
);
|
|
62
|
-
};
|
|
63
|
-
|
|
41
|
+
// Provider mock — if `getConfiguredProvider` is ever called by the
|
|
42
|
+
// assistant_tool pass-through path, this throw makes the test fail
|
|
43
|
+
// loudly instead of silently exercising the LLM path.
|
|
64
44
|
mock.module("../../providers/provider-send-message.js", () => ({
|
|
65
|
-
getConfiguredProvider: async () =>
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
45
|
+
getConfiguredProvider: async () => {
|
|
46
|
+
throw new Error(
|
|
47
|
+
"getConfiguredProvider should NOT be invoked for assistant_tool pass-through",
|
|
48
|
+
);
|
|
49
|
+
},
|
|
69
50
|
createTimeout: () => ({
|
|
70
51
|
signal: new AbortController().signal,
|
|
71
52
|
cleanup: () => {},
|
|
@@ -300,53 +281,3 @@ describe("assistant_tool pass-through in notification decision engine", () => {
|
|
|
300
281
|
expect(decision.renderedCopy.vellum?.body).toBe("fyi");
|
|
301
282
|
});
|
|
302
283
|
});
|
|
303
|
-
|
|
304
|
-
describe("recipient notes injection (ACL from gateway, notes joined locally)", () => {
|
|
305
|
-
function makeLlmSignal(): NotificationSignal {
|
|
306
|
-
return {
|
|
307
|
-
signalId: "sig-llm-notes-1",
|
|
308
|
-
createdAt: Date.now(),
|
|
309
|
-
sourceChannel: "scheduler",
|
|
310
|
-
sourceContextId: "schedule-1",
|
|
311
|
-
sourceEventName: "schedule.notify",
|
|
312
|
-
contextPayload: {},
|
|
313
|
-
attentionHints: {
|
|
314
|
-
requiresAction: false,
|
|
315
|
-
urgency: "low",
|
|
316
|
-
isAsyncBackground: false,
|
|
317
|
-
visibleInSourceNow: false,
|
|
318
|
-
},
|
|
319
|
-
};
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
test("injects the guardian's local notes, resolved via the gateway contactId", async () => {
|
|
323
|
-
guardianDeliveryFixture = [{ contactId: "contact-42" }];
|
|
324
|
-
contactInfoFixture = { "contact-42": { notes: "Prefers terse updates." } };
|
|
325
|
-
|
|
326
|
-
let capturedSystemPrompt: string | undefined;
|
|
327
|
-
providerSendMessage = async (_messages, opts) => {
|
|
328
|
-
capturedSystemPrompt = opts.systemPrompt;
|
|
329
|
-
return {};
|
|
330
|
-
};
|
|
331
|
-
|
|
332
|
-
await evaluateSignal(makeLlmSignal(), ["vellum"] as NotificationChannel[]);
|
|
333
|
-
|
|
334
|
-
expect(capturedSystemPrompt).toContain("<recipient-context>");
|
|
335
|
-
expect(capturedSystemPrompt).toContain("Prefers terse updates.");
|
|
336
|
-
});
|
|
337
|
-
|
|
338
|
-
test("omits recipient context when no guardian is bound", async () => {
|
|
339
|
-
guardianDeliveryFixture = [];
|
|
340
|
-
contactInfoFixture = {};
|
|
341
|
-
|
|
342
|
-
let capturedSystemPrompt: string | undefined;
|
|
343
|
-
providerSendMessage = async (_messages, opts) => {
|
|
344
|
-
capturedSystemPrompt = opts.systemPrompt;
|
|
345
|
-
return {};
|
|
346
|
-
};
|
|
347
|
-
|
|
348
|
-
await evaluateSignal(makeLlmSignal(), ["vellum"] as NotificationChannel[]);
|
|
349
|
-
|
|
350
|
-
expect(capturedSystemPrompt).not.toContain("<recipient-context>");
|
|
351
|
-
});
|
|
352
|
-
});
|
|
@@ -11,7 +11,6 @@
|
|
|
11
11
|
|
|
12
12
|
import { v4 as uuid } from "uuid";
|
|
13
13
|
|
|
14
|
-
import { getGuardianDelivery } from "../contacts/guardian-delivery-reader.js";
|
|
15
14
|
import { getConversation } from "../memory/conversation-crud.js";
|
|
16
15
|
import type { ApprovalUIMetadata } from "../runtime/channel-approval-types.js";
|
|
17
16
|
import { getLogger } from "../util/logger.js";
|
|
@@ -172,13 +171,7 @@ export class NotificationBroadcaster {
|
|
|
172
171
|
decision: NotificationDecision,
|
|
173
172
|
options?: BroadcastDecisionOptions,
|
|
174
173
|
): Promise<NotificationDeliveryResult[]> {
|
|
175
|
-
|
|
176
|
-
// (gateway unreachable) falls back to the local contacts read.
|
|
177
|
-
const guardians = await getGuardianDelivery();
|
|
178
|
-
const destinations = resolveDestinations(
|
|
179
|
-
decision.selectedChannels,
|
|
180
|
-
guardians,
|
|
181
|
-
);
|
|
174
|
+
const destinations = resolveDestinations(decision.selectedChannels);
|
|
182
175
|
|
|
183
176
|
// Ensure vellum is processed first so the notification_conversation_created
|
|
184
177
|
// event fires immediately, before slower channel sends (e.g. Telegram 30s
|
|
@@ -12,11 +12,7 @@
|
|
|
12
12
|
import { v4 as uuid } from "uuid";
|
|
13
13
|
|
|
14
14
|
import { getDeliverableChannels } from "../channels/config.js";
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
anyGuardian,
|
|
18
|
-
getGuardianDelivery,
|
|
19
|
-
} from "../contacts/guardian-delivery-reader.js";
|
|
15
|
+
import { listGuardianChannels } from "../contacts/contact-store.js";
|
|
20
16
|
import { buildCoreIdentityContext } from "../prompts/system-prompt.js";
|
|
21
17
|
import {
|
|
22
18
|
createTimeout,
|
|
@@ -967,19 +963,15 @@ async function classifyWithLLM(
|
|
|
967
963
|
? truncate(rawIdentityContext, MAX_IDENTITY_CONTEXT_CHARS, "\n…[truncated]")
|
|
968
964
|
: undefined;
|
|
969
965
|
|
|
970
|
-
// Resolve guardian contact notes for recipient context.
|
|
971
|
-
//
|
|
972
|
-
//
|
|
973
|
-
// stay local and are joined by contactId.
|
|
966
|
+
// Resolve guardian contact notes for recipient context. Use the channel-
|
|
967
|
+
// agnostic guardian lookup so notes are available even when the only
|
|
968
|
+
// deliverable channel is "vellum" (which has no contact channel type).
|
|
974
969
|
let recipientNotes: string | undefined;
|
|
975
970
|
try {
|
|
976
|
-
const
|
|
977
|
-
|
|
978
|
-
? findContactInfoById(guardian.contactId)?.notes
|
|
979
|
-
: undefined;
|
|
980
|
-
if (notes) {
|
|
971
|
+
const guardianResult = listGuardianChannels();
|
|
972
|
+
if (guardianResult?.contact.notes) {
|
|
981
973
|
recipientNotes = truncate(
|
|
982
|
-
notes,
|
|
974
|
+
guardianResult.contact.notes,
|
|
983
975
|
MAX_IDENTITY_CONTEXT_CHARS,
|
|
984
976
|
"\n…[truncated]",
|
|
985
977
|
);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Resolves per-channel destination endpoints for notification delivery.
|
|
3
3
|
*
|
|
4
|
-
* Reads guardian delivery info from the
|
|
4
|
+
* Reads guardian delivery info from the contacts table.
|
|
5
5
|
*
|
|
6
6
|
* - Vellum: no external endpoint needed — delivery goes through the event
|
|
7
7
|
* broadcast mechanism to connected desktop/mobile clients. The
|
|
@@ -11,54 +11,14 @@
|
|
|
11
11
|
* sourced from the guardian contact's channel record.
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
-
import type { GuardianDelivery } from "@vellumai/gateway-client";
|
|
15
|
-
|
|
16
14
|
import { isNotificationDeliverable } from "../channels/config.js";
|
|
17
15
|
import type { ChannelId } from "../channels/types.js";
|
|
18
16
|
import { findGuardianForChannel } from "../contacts/contact-store.js";
|
|
19
|
-
import { guardianForChannel } from "../contacts/guardian-delivery-reader.js";
|
|
20
17
|
import { getLogger } from "../util/logger.js";
|
|
21
18
|
import type { ChannelDestination, NotificationChannel } from "./types.js";
|
|
22
19
|
|
|
23
20
|
const log = getLogger("destination-resolver");
|
|
24
21
|
|
|
25
|
-
/** Guardian delivery endpoint for a channel, flattened from either source. */
|
|
26
|
-
interface ResolvedGuardian {
|
|
27
|
-
principalId?: string;
|
|
28
|
-
address: string;
|
|
29
|
-
externalChatId?: string;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Resolve the guardian delivery endpoint for a channel: gateway list first,
|
|
34
|
-
* else the local contacts read. The local read is the transitional
|
|
35
|
-
* dual-written mirror and covers a transient gateway failure (null list) or a
|
|
36
|
-
* gateway list missing this channel, so a soft-failed gateway read does not
|
|
37
|
-
* drop a binding the local store still holds. Removed in Combo 11.
|
|
38
|
-
*/
|
|
39
|
-
function resolveGuardian(
|
|
40
|
-
guardians: GuardianDelivery[] | null,
|
|
41
|
-
channelType: string,
|
|
42
|
-
): ResolvedGuardian | undefined {
|
|
43
|
-
const g = guardians
|
|
44
|
-
? guardianForChannel(guardians, channelType)
|
|
45
|
-
: undefined;
|
|
46
|
-
if (g) {
|
|
47
|
-
return {
|
|
48
|
-
principalId: g.principalId ?? undefined,
|
|
49
|
-
address: g.address,
|
|
50
|
-
externalChatId: g.externalChatId ?? undefined,
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
const local = findGuardianForChannel(channelType);
|
|
54
|
-
if (!local) return undefined;
|
|
55
|
-
return {
|
|
56
|
-
principalId: local.contact.principalId ?? undefined,
|
|
57
|
-
address: local.channel.address,
|
|
58
|
-
externalChatId: local.channel.externalChatId ?? undefined,
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
|
-
|
|
62
22
|
/**
|
|
63
23
|
* Resolve destination information for each requested channel.
|
|
64
24
|
*
|
|
@@ -66,14 +26,9 @@ function resolveGuardian(
|
|
|
66
26
|
* the function skips non-deliverable channels via `isNotificationDeliverable`.
|
|
67
27
|
* Returns a map keyed by `NotificationChannel`. Channels that cannot be
|
|
68
28
|
* resolved (e.g. no Telegram binding configured) are omitted from the result.
|
|
69
|
-
*
|
|
70
|
-
* `guardians` is the gateway-resolved guardian list; per channel, a missing
|
|
71
|
-
* match (null list or no entry for the channel) falls back to the local
|
|
72
|
-
* contacts read for this release.
|
|
73
29
|
*/
|
|
74
30
|
export function resolveDestinations(
|
|
75
31
|
channels: readonly (ChannelId | NotificationChannel)[],
|
|
76
|
-
guardians: GuardianDelivery[] | null,
|
|
77
32
|
): Map<NotificationChannel, ChannelDestination> {
|
|
78
33
|
const result = new Map<NotificationChannel, ChannelDestination>();
|
|
79
34
|
|
|
@@ -88,10 +43,10 @@ export function resolveDestinations(
|
|
|
88
43
|
// Vellum delivery is local — no external endpoint required.
|
|
89
44
|
// Include the guardianPrincipalId so the adapter can annotate
|
|
90
45
|
// guardian-sensitive notifications for scoped delivery.
|
|
91
|
-
const
|
|
46
|
+
const guardianResult = findGuardianForChannel("vellum");
|
|
92
47
|
const metadata: Record<string, unknown> = {};
|
|
93
|
-
if (
|
|
94
|
-
metadata.guardianPrincipalId =
|
|
48
|
+
if (guardianResult) {
|
|
49
|
+
metadata.guardianPrincipalId = guardianResult.contact.principalId;
|
|
95
50
|
}
|
|
96
51
|
result.set("vellum", {
|
|
97
52
|
channel: "vellum",
|
|
@@ -100,7 +55,7 @@ export function resolveDestinations(
|
|
|
100
55
|
log.debug(
|
|
101
56
|
{
|
|
102
57
|
channel: "vellum",
|
|
103
|
-
source: "
|
|
58
|
+
source: "contacts",
|
|
104
59
|
hasEndpoint: false,
|
|
105
60
|
},
|
|
106
61
|
"destination resolved",
|
|
@@ -108,52 +63,52 @@ export function resolveDestinations(
|
|
|
108
63
|
break;
|
|
109
64
|
}
|
|
110
65
|
case "telegram": {
|
|
111
|
-
const
|
|
112
|
-
if (
|
|
113
|
-
const externalChatId =
|
|
66
|
+
const guardianResult = findGuardianForChannel(channel);
|
|
67
|
+
if (guardianResult && guardianResult.channel.externalChatId) {
|
|
68
|
+
const externalChatId = guardianResult.channel.externalChatId;
|
|
114
69
|
result.set(channel as NotificationChannel, {
|
|
115
70
|
channel: channel as NotificationChannel,
|
|
116
71
|
endpoint: externalChatId,
|
|
117
72
|
metadata: {
|
|
118
|
-
externalUserId:
|
|
73
|
+
externalUserId: guardianResult.channel.address,
|
|
119
74
|
},
|
|
120
75
|
bindingContext: {
|
|
121
76
|
sourceChannel: channel as NotificationChannel,
|
|
122
77
|
externalChatId,
|
|
123
|
-
externalUserId:
|
|
78
|
+
externalUserId: guardianResult.channel.address,
|
|
124
79
|
},
|
|
125
80
|
});
|
|
126
81
|
}
|
|
127
82
|
log.debug(
|
|
128
83
|
{
|
|
129
84
|
channel,
|
|
130
|
-
source: "
|
|
131
|
-
hasEndpoint: !!
|
|
85
|
+
source: "contacts",
|
|
86
|
+
hasEndpoint: !!guardianResult?.channel.externalChatId,
|
|
132
87
|
},
|
|
133
88
|
"destination resolved",
|
|
134
89
|
);
|
|
135
90
|
break;
|
|
136
91
|
}
|
|
137
92
|
case "slack": {
|
|
138
|
-
const
|
|
139
|
-
const chatId =
|
|
93
|
+
const guardianResult = findGuardianForChannel("slack");
|
|
94
|
+
const chatId = guardianResult?.channel.externalChatId;
|
|
140
95
|
// Slack bindings can originate from app_mention in shared channels.
|
|
141
96
|
// Only route notifications to DM channels (IDs starting with "D")
|
|
142
97
|
// to prevent leaking notifications into shared workspaces.
|
|
143
|
-
if (
|
|
98
|
+
if (guardianResult && chatId && isSlackDmChannel(chatId)) {
|
|
144
99
|
result.set("slack", {
|
|
145
100
|
channel: "slack",
|
|
146
101
|
endpoint: chatId,
|
|
147
102
|
metadata: {
|
|
148
|
-
externalUserId:
|
|
103
|
+
externalUserId: guardianResult.channel.address,
|
|
149
104
|
},
|
|
150
105
|
bindingContext: {
|
|
151
106
|
sourceChannel: "slack",
|
|
152
107
|
externalChatId: chatId,
|
|
153
|
-
externalUserId:
|
|
108
|
+
externalUserId: guardianResult.channel.address,
|
|
154
109
|
},
|
|
155
110
|
});
|
|
156
|
-
} else if (
|
|
111
|
+
} else if (guardianResult && chatId) {
|
|
157
112
|
log.warn(
|
|
158
113
|
{ channel: "slack", chatId },
|
|
159
114
|
"skipping non-DM Slack channel for notification delivery",
|
|
@@ -162,7 +117,7 @@ export function resolveDestinations(
|
|
|
162
117
|
log.debug(
|
|
163
118
|
{
|
|
164
119
|
channel: "slack",
|
|
165
|
-
source: "
|
|
120
|
+
source: "contacts",
|
|
166
121
|
hasEndpoint: !!(chatId && isSlackDmChannel(chatId)),
|
|
167
122
|
},
|
|
168
123
|
"destination resolved",
|
|
@@ -173,10 +128,11 @@ export function resolveDestinations(
|
|
|
173
128
|
// Platform delivery goes through the daemon's VellumPlatformClient —
|
|
174
129
|
// no external binding needed. Include guardianPrincipalId so the
|
|
175
130
|
// adapter can scope guardian-sensitive notifications.
|
|
176
|
-
const platformGuardian =
|
|
131
|
+
const platformGuardian = findGuardianForChannel("vellum");
|
|
177
132
|
const platformMeta: Record<string, unknown> = {};
|
|
178
|
-
if (platformGuardian
|
|
179
|
-
platformMeta.guardianPrincipalId =
|
|
133
|
+
if (platformGuardian) {
|
|
134
|
+
platformMeta.guardianPrincipalId =
|
|
135
|
+
platformGuardian.contact.principalId;
|
|
180
136
|
}
|
|
181
137
|
result.set("platform", {
|
|
182
138
|
channel: "platform",
|
|
@@ -184,7 +140,7 @@ export function resolveDestinations(
|
|
|
184
140
|
Object.keys(platformMeta).length > 0 ? platformMeta : undefined,
|
|
185
141
|
});
|
|
186
142
|
log.debug(
|
|
187
|
-
{ channel: "platform", source: "
|
|
143
|
+
{ channel: "platform", source: "contacts", hasEndpoint: false },
|
|
188
144
|
"destination resolved",
|
|
189
145
|
);
|
|
190
146
|
break;
|
|
@@ -9,15 +9,10 @@
|
|
|
9
9
|
* propagated unless `throwOnError` is enabled.
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
import type { GuardianDelivery } from "@vellumai/gateway-client";
|
|
13
12
|
import { v4 as uuid } from "uuid";
|
|
14
13
|
|
|
15
14
|
import { getDeliverableChannels } from "../channels/config.js";
|
|
16
15
|
import { findGuardianForChannel } from "../contacts/contact-store.js";
|
|
17
|
-
import {
|
|
18
|
-
getGuardianDelivery,
|
|
19
|
-
guardianForChannel,
|
|
20
|
-
} from "../contacts/guardian-delivery-reader.js";
|
|
21
16
|
import type { ConversationCreateType } from "../memory/conversation-crud.js";
|
|
22
17
|
import { broadcastMessage } from "../runtime/assistant-event-hub.js";
|
|
23
18
|
import { getLogger } from "../util/logger.js";
|
|
@@ -94,33 +89,9 @@ export function getBroadcaster(): NotificationBroadcaster {
|
|
|
94
89
|
|
|
95
90
|
// ── Connected channels resolution ──────────────────────────────────────
|
|
96
91
|
|
|
97
|
-
|
|
98
|
-
* Resolve a binding-based channel's delivery endpoint (externalChatId) the
|
|
99
|
-
* SAME way destination-resolver's `resolveGuardian` does: gateway match first,
|
|
100
|
-
* falling back to the LOCAL contacts read on ANY per-channel no-match — gateway
|
|
101
|
-
* list null (unreachable) OR no active gateway entry for this channel. The
|
|
102
|
-
* local read is the transitional dual-written mirror, removed in Combo 11.
|
|
103
|
-
* Keeping connectivity aligned with delivery prevents a channel being marked
|
|
104
|
-
* connected but then skipped with no destination (or vice-versa).
|
|
105
|
-
*/
|
|
106
|
-
function resolveChannelChatId(
|
|
107
|
-
guardians: GuardianDelivery[] | null,
|
|
108
|
-
channelType: string,
|
|
109
|
-
): string | undefined {
|
|
110
|
-
const g = guardians ? guardianForChannel(guardians, channelType) : undefined;
|
|
111
|
-
if (g) {
|
|
112
|
-
return g.externalChatId ?? undefined;
|
|
113
|
-
}
|
|
114
|
-
return findGuardianForChannel(channelType)?.channel.externalChatId ?? undefined;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
export async function getConnectedChannels(): Promise<NotificationChannel[]> {
|
|
92
|
+
function getConnectedChannels(): NotificationChannel[] {
|
|
118
93
|
const channels: NotificationChannel[] = [];
|
|
119
94
|
|
|
120
|
-
// Guardian bindings (ACL) come from the gateway pull; null ⇒ gateway
|
|
121
|
-
// unreachable, so binding-based connectivity falls back to the local read.
|
|
122
|
-
const guardians = await getGuardianDelivery();
|
|
123
|
-
|
|
124
95
|
// getDeliverableChannels() returns ChannelId[] but every returned channel
|
|
125
96
|
// has deliveryEnabled: true, making it a valid NotificationChannel at
|
|
126
97
|
// runtime. We iterate over the broad type and narrow via the switch.
|
|
@@ -139,20 +110,24 @@ export async function getConnectedChannels(): Promise<NotificationChannel[]> {
|
|
|
139
110
|
channels.push(channel);
|
|
140
111
|
break;
|
|
141
112
|
case "telegram": {
|
|
142
|
-
//
|
|
143
|
-
//
|
|
144
|
-
//
|
|
145
|
-
|
|
113
|
+
// A binding-based channel is connected when the guardian has an
|
|
114
|
+
// active channel entry with a valid delivery endpoint. The
|
|
115
|
+
// externalChatId check ensures we don't report a channel as
|
|
116
|
+
// connected when the contacts record exists but lacks the
|
|
117
|
+
// delivery address the destination-resolver needs.
|
|
118
|
+
const guardian = findGuardianForChannel(channel);
|
|
119
|
+
if (guardian && guardian.channel.externalChatId) {
|
|
146
120
|
channels.push(channel);
|
|
147
121
|
}
|
|
148
122
|
break;
|
|
149
123
|
}
|
|
150
124
|
case "slack": {
|
|
151
125
|
// Slack bindings can originate from shared channels (app_mention).
|
|
152
|
-
// Only consider Slack connected when the
|
|
153
|
-
// channel (D-prefixed)
|
|
154
|
-
const
|
|
155
|
-
|
|
126
|
+
// Only consider Slack connected when the stored chat ID is a DM
|
|
127
|
+
// channel (D-prefixed) to prevent leaking notifications.
|
|
128
|
+
const slackGuardian = findGuardianForChannel("slack");
|
|
129
|
+
const chatId = slackGuardian?.channel.externalChatId;
|
|
130
|
+
if (slackGuardian && chatId && chatId.startsWith("D")) {
|
|
156
131
|
channels.push(channel);
|
|
157
132
|
}
|
|
158
133
|
break;
|
|
@@ -315,7 +290,7 @@ export async function emitNotificationSignal<TEventName extends string>(
|
|
|
315
290
|
}
|
|
316
291
|
|
|
317
292
|
// Step 2: Evaluate the signal through the decision engine
|
|
318
|
-
const connectedChannels =
|
|
293
|
+
const connectedChannels = getConnectedChannels();
|
|
319
294
|
|
|
320
295
|
log.debug(
|
|
321
296
|
{
|
|
@@ -9,7 +9,7 @@ import type {
|
|
|
9
9
|
|
|
10
10
|
// Use a tiny timeout so the setTimeout branch fires quickly in tests
|
|
11
11
|
const mockConfig = {
|
|
12
|
-
timeouts: {
|
|
12
|
+
timeouts: { permissionTimeoutSec: 0.05 },
|
|
13
13
|
};
|
|
14
14
|
// Preserve every other export from the real config/loader so other
|
|
15
15
|
// tests in the same `bun test` run (which share module-level mocks)
|
|
@@ -156,12 +156,9 @@ export interface QuestionBatchMetadata {
|
|
|
156
156
|
* the whole batch to `/v1/question-response` when the user is done — no
|
|
157
157
|
* per-question accumulator, no partial state machine.
|
|
158
158
|
*
|
|
159
|
-
*
|
|
160
|
-
*
|
|
161
|
-
*
|
|
162
|
-
* supersedes the open prompt at the enqueue handler (see conversation-routes.ts);
|
|
163
|
-
* a non-interactive turn resolves immediately at the tool. The backstop only
|
|
164
|
-
* fires when a prompt is left open with no response and no follow-up message.
|
|
159
|
+
* Timeout reuses `getConfig().timeouts.permissionTimeoutSec` (default 5 min) —
|
|
160
|
+
* questions are user-prompts in the same UX family as permission prompts and
|
|
161
|
+
* secret prompts, so they share the same idle-timeout knob.
|
|
165
162
|
*/
|
|
166
163
|
export class QuestionPrompter {
|
|
167
164
|
async prompt(params: QuestionPromptParams): Promise<QuestionPromptResult> {
|
|
@@ -202,7 +199,7 @@ export class QuestionPrompter {
|
|
|
202
199
|
const requestId = uuid();
|
|
203
200
|
|
|
204
201
|
return new Promise<QuestionPromptResult>((resolve, reject) => {
|
|
205
|
-
const timeoutMs = getConfig().timeouts.
|
|
202
|
+
const timeoutMs = getConfig().timeouts.permissionTimeoutSec * 1000;
|
|
206
203
|
|
|
207
204
|
// Closure-scoped idempotency guard. Every resolution path (timeout,
|
|
208
205
|
// abort, route resolution via `rpcResolve`/`rpcReject`) routes through
|
package/src/plugin-api/index.ts
CHANGED
|
@@ -130,12 +130,12 @@ export type {
|
|
|
130
130
|
} from "../runtime/assistant-event-hub.js";
|
|
131
131
|
export { assistantEventHub } from "../runtime/assistant-event-hub.js";
|
|
132
132
|
export { getModelProfiles } from "./model-profiles.js";
|
|
133
|
-
// Check whether a
|
|
134
|
-
//
|
|
135
|
-
//
|
|
136
|
-
//
|
|
137
|
-
//
|
|
138
|
-
//
|
|
133
|
+
// Check whether a profile's resolved model can process image input. Resolves
|
|
134
|
+
// the effective (provider, model) by merging over the workspace default and
|
|
135
|
+
// inferring the provider for model-only profiles, then looks up the model
|
|
136
|
+
// catalog's `supportsVision` flag. Handles mix profiles (true if any arm
|
|
137
|
+
// supports vision). Fail-open for unknown models. Pair with
|
|
138
|
+
// `getModelProfiles()` to inspect the active or candidate profiles.
|
|
139
139
|
export { doesSupportVision } from "./vision-support.js";
|
|
140
140
|
// Resolve a provider for a call site (optionally overriding the profile) so a
|
|
141
141
|
// plugin can run inference through the workspace's configured profiles and
|
package/src/plugin-api/types.ts
CHANGED
|
@@ -72,13 +72,15 @@ export type PluginHookFn<TCtx = unknown> = (
|
|
|
72
72
|
// ─── Init context ────────────────────────────────────────────────────────────
|
|
73
73
|
|
|
74
74
|
/**
|
|
75
|
-
* Context passed to `Plugin.init()` during bootstrap. Carries
|
|
76
|
-
* config, a pino-compatible logger scoped to the plugin, a
|
|
77
|
-
* writable data directory, and the assistant's version metadata.
|
|
75
|
+
* Context passed to `Plugin.init()` during bootstrap. Carries resolved
|
|
76
|
+
* config/credentials, a pino-compatible logger scoped to the plugin, a
|
|
77
|
+
* per-plugin writable data directory, and the assistant's version metadata.
|
|
78
78
|
*/
|
|
79
79
|
export interface PluginInitContext {
|
|
80
80
|
/** Parsed config for this plugin (may be `unknown` until the manifest validates). */
|
|
81
81
|
config: unknown;
|
|
82
|
+
/** Resolved credential values keyed by the entries of `manifest.requiresCredential`. */
|
|
83
|
+
credentials: Record<string, string>;
|
|
82
84
|
/** Pino-compatible child logger bound to `{ plugin: <name> }`. */
|
|
83
85
|
logger: PluginLogger;
|
|
84
86
|
/** Absolute path to `<workspaceDir>/plugins-data/<plugin>/` (created by bootstrap). */
|
|
@@ -84,16 +84,16 @@ describe("doesSupportVision", () => {
|
|
|
84
84
|
expect(doesSupportVision(profile("text-profile"))).toBe(false);
|
|
85
85
|
});
|
|
86
86
|
|
|
87
|
-
test("
|
|
87
|
+
test("fails open (true) for an unknown profile key not in config", () => {
|
|
88
88
|
setMockConfig({});
|
|
89
|
-
expect(doesSupportVision(profile("nonexistent"))).toBe(
|
|
89
|
+
expect(doesSupportVision(profile("nonexistent"))).toBe(true);
|
|
90
90
|
});
|
|
91
91
|
|
|
92
|
-
test("
|
|
92
|
+
test("fails open (true) for an unknown provider/model pair", () => {
|
|
93
93
|
setMockConfig({
|
|
94
94
|
"unknown-model": { provider: "unknown-provider", model: "unknown-model" },
|
|
95
95
|
});
|
|
96
|
-
expect(doesSupportVision(profile("unknown-model"))).toBe(
|
|
96
|
+
expect(doesSupportVision(profile("unknown-model"))).toBe(true);
|
|
97
97
|
});
|
|
98
98
|
|
|
99
99
|
test("inherits provider from llm.default when profile only sets model", () => {
|
|
@@ -147,27 +147,3 @@ describe("doesSupportVision", () => {
|
|
|
147
147
|
expect(doesSupportVision(profile("mix-profile"))).toBe(false);
|
|
148
148
|
});
|
|
149
149
|
});
|
|
150
|
-
|
|
151
|
-
describe("doesSupportVision with a bare string", () => {
|
|
152
|
-
test("returns true for a known vision-capable model id", () => {
|
|
153
|
-
expect(doesSupportVision("claude-opus-4-6")).toBe(true);
|
|
154
|
-
});
|
|
155
|
-
|
|
156
|
-
test("returns false for a known text-only model id", () => {
|
|
157
|
-
expect(doesSupportVision("accounts/fireworks/models/glm-5p2")).toBe(false);
|
|
158
|
-
});
|
|
159
|
-
|
|
160
|
-
test("falls back to resolving the string as a profile key", () => {
|
|
161
|
-
// "vision-profile" is not a catalog model id, so it resolves as a profile
|
|
162
|
-
// key → anthropic/claude-opus-4-6 (vision-capable).
|
|
163
|
-
setMockConfig({
|
|
164
|
-
"vision-profile": { provider: "anthropic", model: "claude-opus-4-6" },
|
|
165
|
-
});
|
|
166
|
-
expect(doesSupportVision("vision-profile")).toBe(true);
|
|
167
|
-
});
|
|
168
|
-
|
|
169
|
-
test("returns false for a string that is neither a model nor a profile", () => {
|
|
170
|
-
setMockConfig({});
|
|
171
|
-
expect(doesSupportVision("some-unknown-string")).toBe(false);
|
|
172
|
-
});
|
|
173
|
-
});
|