@vellumai/assistant 0.10.2 → 0.10.3-dev.202606252046.9075fd5
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 +20 -0
- package/docs/workspace-tools.md +42 -33
- package/eslint-rules/cli-no-daemon-internals.js +6 -0
- package/node_modules/@vellumai/gateway-client/src/__tests__/guardian-delivery-contract.test.ts +91 -0
- package/node_modules/@vellumai/gateway-client/src/__tests__/trust-verdict-contract.test.ts +31 -0
- package/node_modules/@vellumai/gateway-client/src/gateway-ipc-contracts.ts +44 -0
- package/node_modules/@vellumai/gateway-client/src/guardian-delivery-contract.ts +48 -0
- package/node_modules/@vellumai/gateway-client/src/index.ts +14 -0
- package/node_modules/@vellumai/gateway-client/src/trust-verdict-contract.ts +17 -0
- package/node_modules/@vellumai/service-contracts/package.json +1 -0
- package/node_modules/@vellumai/service-contracts/src/__tests__/channels.test.ts +28 -0
- package/node_modules/@vellumai/service-contracts/src/channels.ts +41 -0
- package/node_modules/@vellumai/service-contracts/src/index.ts +1 -0
- package/openapi.yaml +196 -56
- package/package.json +4 -1
- package/scripts/test.sh +36 -15
- package/src/__tests__/actor-token-service.test.ts +36 -14
- package/src/__tests__/actor-trust-resolver-address-fallback.test.ts +83 -31
- package/src/__tests__/agent-loop-override-profile.test.ts +1 -0
- package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +2 -0
- package/src/__tests__/agent-wake-override-profile.test.ts +2 -0
- package/src/__tests__/annotate-activity-metadata.test.ts +2 -0
- package/src/__tests__/annotate-risk-options.test.ts +2 -0
- package/src/__tests__/approval-cascade.test.ts +2 -0
- package/src/__tests__/assistant-attachments.test.ts +42 -0
- package/src/__tests__/background-workers-disk-pressure.test.ts +2 -0
- package/src/__tests__/btw-routes.test.ts +2 -0
- package/src/__tests__/build-persisted-content.test.ts +2 -0
- package/src/__tests__/call-controller.test.ts +19 -0
- package/src/__tests__/channel-approval-routes.test.ts +21 -26
- package/src/__tests__/channel-delivery-store.test.ts +28 -0
- package/src/__tests__/channel-guardian.test.ts +164 -78
- package/src/__tests__/channel-inbound-disk-pressure.test.ts +11 -19
- package/src/__tests__/channel-reply-delivery.test.ts +2 -0
- package/src/__tests__/code-search-tool.test.ts +585 -0
- package/src/__tests__/compaction-events.test.ts +2 -0
- package/src/__tests__/compaction-ledger-store.test.ts +128 -0
- package/src/__tests__/compaction.benchmark.test.ts +2 -0
- package/src/__tests__/compactor-call-site-logging.test.ts +2 -0
- package/src/__tests__/compactor-low-watermark-cut.test.ts +2 -0
- package/src/__tests__/compactor-preserved-tail-count.test.ts +2 -0
- package/src/__tests__/compactor-summary-call-truncation.test.ts +2 -0
- package/src/__tests__/compactor-web-search-strip.test.ts +2 -0
- package/src/__tests__/config-loader-backfill.test.ts +123 -10
- package/src/__tests__/config-schema.test.ts +1 -0
- package/src/__tests__/confirmation-request-guardian-bridge.test.ts +31 -29
- package/src/__tests__/consult-deadline.test.ts +60 -0
- package/src/__tests__/contact-store-interaction-info.test.ts +156 -0
- package/src/__tests__/contact-store-user-file.test.ts +7 -10
- package/src/__tests__/contacts-relay-reads.test.ts +19 -24
- package/src/__tests__/contacts-write.test.ts +0 -2
- package/src/__tests__/conversation-abort-tool-results.test.ts +2 -0
- package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +2 -0
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +2 -0
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +2 -0
- package/src/__tests__/conversation-agent-loop.test.ts +134 -0
- package/src/__tests__/conversation-analysis-routes.test.ts +2 -0
- package/src/__tests__/conversation-app-control-lifecycle.test.ts +2 -0
- package/src/__tests__/conversation-attention-telegram.test.ts +9 -11
- package/src/__tests__/conversation-confirmation-signals.test.ts +2 -0
- package/src/__tests__/conversation-fork-crud.test.ts +354 -24
- package/src/__tests__/conversation-history-web-search.test.ts +2 -0
- package/src/__tests__/conversation-load-history-repair.test.ts +2 -0
- package/src/__tests__/conversation-load-history-stripped.test.ts +2 -0
- package/src/__tests__/conversation-pairing.test.ts +2 -0
- package/src/__tests__/conversation-process-app-control-preactivation.test.ts +2 -0
- package/src/__tests__/conversation-process-callsite.test.ts +2 -0
- package/src/__tests__/conversation-provider-retry-repair.test.ts +2 -0
- package/src/__tests__/conversation-queue.test.ts +91 -0
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +14 -0
- package/src/__tests__/conversation-routes-slash-commands.test.ts +14 -0
- package/src/__tests__/conversation-slash-queue.test.ts +2 -0
- package/src/__tests__/conversation-slash-unknown.test.ts +2 -0
- package/src/__tests__/conversation-speed-override.test.ts +2 -0
- package/src/__tests__/conversation-surfaces-task-progress.test.ts +29 -0
- package/src/__tests__/conversation-title-service.test.ts +2 -0
- package/src/__tests__/conversation-tool-setup-attribution.test.ts +47 -0
- package/src/__tests__/conversation-usage.test.ts +2 -0
- package/src/__tests__/conversation-workspace-cache-state.test.ts +2 -0
- package/src/__tests__/conversation-workspace-injection.test.ts +2 -0
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +2 -0
- package/src/__tests__/credential-security-invariants.test.ts +1 -1
- package/src/__tests__/db-compaction-events-migration.test.ts +129 -0
- package/src/__tests__/db-migration-rollback.test.ts +205 -171
- package/src/__tests__/db-test-helpers.ts +5 -4
- package/src/__tests__/delete-propagation.test.ts +5 -3
- package/src/__tests__/deterministic-verification-control-plane.test.ts +4 -2
- package/src/__tests__/disk-pressure-guard.test.ts +41 -0
- package/src/__tests__/dm-backfill.test.ts +6 -4
- package/src/__tests__/dm-persistence.test.ts +2 -0
- package/src/__tests__/emit-signal-routing-intent.test.ts +7 -6
- package/src/__tests__/events-dev-bypass-actor.test.ts +7 -1
- package/src/__tests__/exploration-drift-hook.test.ts +3 -2
- package/src/__tests__/filing-service.test.ts +2 -0
- package/src/__tests__/guardian-binding-drift-heal.test.ts +104 -19
- package/src/__tests__/guardian-dispatch.test.ts +140 -1
- package/src/__tests__/guardian-expiry-notifier.test.ts +282 -0
- package/src/__tests__/guardian-outbound-http.test.ts +13 -0
- package/src/__tests__/guardian-routing-state.test.ts +6 -10
- package/src/__tests__/heartbeat-disk-pressure.test.ts +2 -0
- package/src/__tests__/heartbeat-service.test.ts +2 -0
- package/src/__tests__/helpers/channel-test-adapter.ts +46 -19
- package/src/__tests__/helpers/create-guardian-binding.ts +15 -23
- package/src/__tests__/helpers/mock-logger.ts +1 -0
- package/src/__tests__/helpers/seed-contact-channel.ts +96 -0
- package/src/__tests__/host-app-control-routes.test.ts +24 -30
- package/src/__tests__/host-bash-routes.test.ts +31 -41
- package/src/__tests__/host-browser-routes.test.ts +26 -32
- package/src/__tests__/host-cu-routes-targeted.test.ts +25 -33
- package/src/__tests__/host-file-routes-targeted.test.ts +40 -52
- package/src/__tests__/host-transfer-routes-targeted.test.ts +31 -43
- package/src/__tests__/http-user-message-parity.test.ts +290 -8
- package/src/__tests__/inbound-invite-redemption.test.ts +115 -10
- package/src/__tests__/inbound-slack-persistence.test.ts +2 -0
- package/src/__tests__/invite-redemption-service.test.ts +471 -53
- package/src/__tests__/invite-routes-http.test.ts +34 -0
- package/src/__tests__/invite-service-ipc.test.ts +65 -2
- package/src/__tests__/llm-context-normalization.test.ts +105 -0
- package/src/__tests__/llm-request-log-error-payload.test.ts +71 -9
- package/src/__tests__/llm-usage-store.test.ts +25 -0
- package/src/__tests__/mcp-config-secret-boundary.test.ts +392 -0
- package/src/__tests__/mcp-health-check.test.ts +2 -1
- package/src/__tests__/media-stream-server-integration.test.ts +127 -0
- package/src/__tests__/memory-retrieval-hook.test.ts +2 -0
- package/src/__tests__/messaging-send-tool.test.ts +2 -0
- package/src/__tests__/migration-import-from-url.test.ts +2 -2
- package/src/__tests__/mtime-cache.test.ts +275 -5
- package/src/__tests__/native-web-search.test.ts +2 -0
- package/src/__tests__/non-member-access-request.test.ts +191 -17
- package/src/__tests__/notification-broadcaster.test.ts +4 -0
- package/src/__tests__/notification-decision-recipient-context.test.ts +33 -32
- package/src/__tests__/notification-deep-link.test.ts +6 -0
- package/src/__tests__/notification-guardian-path.test.ts +19 -0
- package/src/__tests__/onboarding-persona-write.test.ts +52 -22
- package/src/__tests__/openai-provider.test.ts +22 -12
- package/src/__tests__/openai-responses-provider.test.ts +12 -2
- package/src/__tests__/outbound-slack-persistence.test.ts +2 -0
- package/src/__tests__/pending-interactions-resolved-event.test.ts +7 -4
- package/src/__tests__/persist-onboarding-artifacts.test.ts +1 -0
- package/src/__tests__/persistence-secret-redaction.test.ts +2 -0
- package/src/__tests__/persona-resolver.test.ts +75 -45
- package/src/__tests__/plugin-bootstrap.test.ts +21 -83
- package/src/__tests__/plugin-disabled-state.test.ts +190 -0
- package/src/__tests__/plugin-pipeline.test.ts +96 -0
- package/src/__tests__/plugin-route-contribution.test.ts +6 -19
- package/src/__tests__/plugin-tool-contribution.test.ts +5 -20
- package/src/__tests__/plugin-types.test.ts +2 -4
- package/src/__tests__/process-message-background-slack.test.ts +2 -0
- package/src/__tests__/process-message-display-content.test.ts +2 -0
- package/src/__tests__/provider-error-scenarios.test.ts +5 -4
- package/src/__tests__/provider-usage-tracking.test.ts +39 -0
- package/src/__tests__/reaction-intercept-cold-cache-warm.test.ts +135 -0
- package/src/__tests__/reaction-intercept-member-verdict-warm.test.ts +158 -0
- package/src/__tests__/reaction-persistence.test.ts +51 -4
- package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +2 -0
- package/src/__tests__/registry.test.ts +4 -1
- package/src/__tests__/relay-server.test.ts +758 -32
- package/src/__tests__/runtime-attachment-metadata.test.ts +9 -12
- package/src/__tests__/secret-ingress-http.test.ts +14 -0
- package/src/__tests__/send-endpoint-busy.test.ts +30 -8
- package/src/__tests__/settings-routes.test.ts +32 -0
- package/src/__tests__/skills.test.ts +44 -0
- package/src/__tests__/slack-inbound-verification.test.ts +47 -2
- package/src/__tests__/sse-actor-principal-guardian-source.test.ts +79 -0
- package/src/__tests__/steer-on-enqueue-question.test.ts +181 -0
- package/src/__tests__/stt-hints.test.ts +49 -15
- package/src/__tests__/subagent-detail.test.ts +27 -0
- package/src/__tests__/subagent-disposal.test.ts +65 -0
- package/src/__tests__/subagent-fork-prompt-role.test.ts +195 -0
- package/src/__tests__/subagent-fork-spawn.test.ts +6 -7
- package/src/__tests__/subagent-notify-parent.test.ts +2 -0
- package/src/__tests__/subagent-role-registry.test.ts +24 -6
- package/src/__tests__/subagent-spawn-and-await.test.ts +546 -0
- package/src/__tests__/subagent-spawn-tool-fork.test.ts +2 -0
- package/src/__tests__/subagent-tools.test.ts +398 -1
- package/src/__tests__/suggestion-routes.test.ts +2 -0
- package/src/__tests__/thread-backfill.test.ts +3 -3
- package/src/__tests__/title-generate-hook.test.ts +2 -0
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +2 -0
- package/src/__tests__/tool-executor.test.ts +16 -11
- package/src/__tests__/tool-preview-lifecycle.test.ts +2 -0
- package/src/__tests__/tool-result-metadata-plumbing.test.ts +2 -0
- package/src/__tests__/tool-start-timestamp.test.ts +2 -0
- package/src/__tests__/trusted-contact-approval-notifier.test.ts +37 -51
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +12 -12
- package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +9 -7
- package/src/__tests__/trusted-contact-multichannel.test.ts +16 -7
- package/src/__tests__/trusted-contact-verification.test.ts +79 -54
- package/src/__tests__/twilio-routes.test.ts +96 -0
- package/src/__tests__/ui-file-upload-surface.test.ts +86 -0
- package/src/__tests__/verification-control-plane-policy.test.ts +2 -0
- package/src/__tests__/voice-guardian-cold-cache-warm.test.ts +137 -0
- package/src/__tests__/voice-invite-redemption.test.ts +216 -20
- package/src/__tests__/web-search-backend-failure.test.ts +2 -0
- package/src/__tests__/workspace-migration-102-preserve-heartbeat-enabled-for-existing-workspaces.test.ts +3 -3
- package/src/__tests__/workspace-migration-111-prune-seeded-callsite-defaults.test.ts +208 -0
- package/src/__tests__/workspace-migration-112-remove-advisor-callsite-override.test.ts +170 -0
- package/src/__tests__/workspace-migration-drop-user-md.test.ts +196 -238
- package/src/__tests__/workspace-migration-remove-hooks.test.ts +14 -35
- package/src/__tests__/workspace-tool-loader.test.ts +195 -2
- package/src/a2a/__tests__/e2e-a2a-channel.test.ts +35 -47
- package/src/agent/loop-exclusive-tool.test.ts +154 -0
- package/src/agent/loop-native-web-search.test.ts +200 -0
- package/src/agent/loop.ts +164 -1
- package/src/api/constants/sse-replay.ts +41 -0
- package/src/api/events/conversation-notice.ts +26 -0
- package/src/api/index.ts +19 -1
- package/src/api/responses/llm-request-log-entry.ts +29 -0
- package/src/api/responses/subagent-detail.ts +17 -0
- package/src/api/surfaces.ts +39 -3
- package/src/approvals/guardian-channel-delivery.ts +30 -0
- package/src/approvals/guardian-expiry-notifier.ts +148 -0
- package/src/approvals/guardian-request-resolvers.ts +17 -15
- package/src/calls/__tests__/relay-setup-router.test.ts +267 -17
- package/src/calls/call-domain.ts +3 -3
- package/src/calls/guardian-dispatch.ts +14 -9
- package/src/calls/inbound-trust-reader.ts +24 -2
- package/src/calls/media-stream-server.ts +21 -0
- package/src/calls/relay-access-wait.ts +6 -6
- package/src/calls/relay-server.ts +188 -51
- package/src/calls/relay-setup-router.ts +47 -17
- package/src/calls/relay-verification.ts +4 -4
- package/src/calls/stt-hints.ts +9 -12
- package/src/calls/twilio-routes.ts +14 -4
- package/src/channels/types.ts +10 -20
- package/src/cli/commands/__tests__/cache.test.ts +8 -1
- package/src/cli/commands/__tests__/conversations-slack.test.ts +1 -0
- package/src/cli/commands/cache.ts +194 -181
- package/src/cli/commands/contacts.ts +10 -7
- package/src/cli/commands/db/__tests__/repair.test.ts +6 -5
- package/src/cli/commands/db/status.ts +37 -1
- package/src/cli/commands/mcp.ts +252 -218
- package/src/cli/commands/memory/__tests__/worker.test.ts +432 -0
- package/src/cli/commands/memory/index.ts +2 -0
- package/src/cli/commands/memory/worker.ts +242 -0
- package/src/cli/commands/plugins.ts +125 -13
- package/src/cli/lib/__tests__/install-from-github.test.ts +102 -0
- package/src/cli/lib/__tests__/list-installed-plugins.test.ts +160 -1
- package/src/cli/lib/__tests__/publish-plugin.test.ts +404 -0
- package/src/cli/lib/list-installed-plugins.ts +179 -1
- package/src/cli/lib/publish-plugin.ts +633 -0
- package/src/config/__tests__/loader-callsite-strip-fallback.test.ts +143 -0
- package/src/config/__tests__/sync-gated-profiles.test.ts +16 -10
- package/src/config/bundled-skills/contacts/tools/contact-merge.ts +27 -17
- package/src/config/bundled-skills/contacts/tools/contact-search.ts +13 -3
- package/src/config/bundled-skills/subagent/SKILL.md +17 -2
- package/src/config/bundled-skills/subagent/TOOLS.json +5 -4
- package/src/config/call-site-defaults.ts +0 -6
- package/src/config/feature-flag-registry.json +5 -13
- package/src/config/llm-resolver.ts +0 -3
- package/src/config/loader.ts +38 -5
- package/src/config/prune-seeded-callsite-defaults.ts +110 -0
- package/src/config/schemas/__tests__/memory-v3.test.ts +1 -0
- package/src/config/schemas/call-site-catalog.ts +0 -7
- package/src/config/schemas/heartbeat.ts +2 -5
- package/src/config/schemas/llm.ts +3 -12
- package/src/config/schemas/memory-lifecycle.ts +12 -0
- package/src/config/schemas/memory-v3.ts +7 -0
- package/src/config/schemas/memory.ts +4 -0
- package/src/config/schemas/timeouts.ts +8 -0
- package/src/config/seed-inference-profiles.ts +30 -34
- package/src/config/skills.ts +27 -5
- package/src/config/sync-gated-profiles.ts +12 -16
- package/src/contacts/__tests__/contacts-write-revoke-relay.test.ts +128 -0
- package/src/contacts/__tests__/guardian-delivery-reader.test.ts +312 -0
- package/src/contacts/__tests__/member-write-relay.test.ts +226 -0
- package/src/contacts/contact-store.ts +27 -237
- package/src/contacts/contacts-write.ts +18 -55
- package/src/contacts/gateway-channel-read.ts +51 -0
- package/src/contacts/guardian-delivery-reader.ts +223 -0
- package/src/contacts/member-write-relay.ts +183 -0
- package/src/contacts/types.ts +3 -15
- package/src/daemon/__tests__/conversation-tool-setup-exclude.test.ts +35 -0
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +0 -44
- package/src/daemon/assistant-attachments.ts +27 -4
- package/src/daemon/conversation-agent-loop.ts +28 -0
- package/src/daemon/conversation-notices.ts +60 -0
- package/src/daemon/conversation-process.ts +35 -16
- package/src/daemon/conversation-surfaces.ts +111 -38
- package/src/daemon/conversation-tool-setup.ts +71 -30
- package/src/daemon/conversation.ts +23 -1
- package/src/daemon/disk-pressure-guard.ts +12 -2
- package/src/daemon/event-loop-watchdog.ts +28 -1
- package/src/daemon/external-plugins-bootstrap.ts +17 -41
- package/src/daemon/handlers/__tests__/config-a2a-accept.test.ts +0 -1
- package/src/daemon/handlers/__tests__/config-a2a-complete.test.ts +0 -2
- package/src/daemon/handlers/__tests__/config-a2a-redeem.test.ts +25 -2
- package/src/daemon/handlers/__tests__/config-channels.test.ts +220 -0
- package/src/daemon/handlers/config-a2a.ts +6 -14
- package/src/daemon/handlers/config-channels.ts +67 -26
- package/src/daemon/handlers/conversations.ts +77 -0
- package/src/daemon/lifecycle.ts +16 -0
- package/src/daemon/mcp-reload-service.ts +10 -0
- package/src/daemon/memory-v2-startup.test.ts +72 -0
- package/src/daemon/memory-v2-startup.ts +87 -19
- package/src/daemon/message-types/conversations.ts +2 -0
- package/src/daemon/message-types/surfaces.ts +12 -12
- package/src/daemon/server.ts +0 -4
- package/src/daemon/shutdown-handlers.ts +20 -0
- package/src/daemon/tool-setup-types.ts +9 -0
- package/src/heartbeat/heartbeat-service.ts +5 -0
- package/src/home/relationship-state-writer.ts +5 -0
- package/src/hooks/hook-loader.ts +341 -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 +1 -0
- package/src/mcp/client.ts +15 -1
- package/src/mcp/mcp-auth-orchestrator.ts +6 -1
- package/src/mcp/mcp-header-store.ts +134 -0
- package/src/mcp/mcp-oauth-provider.ts +19 -8
- package/src/memory/__tests__/301-create-watchdog-events.test.ts +110 -0
- package/src/memory/__tests__/memory-retrospective-job.test.ts +8 -0
- package/src/memory/__tests__/prompt-override.test.ts +192 -0
- package/src/memory/__tests__/watchdog-events-store.test.ts +161 -0
- package/src/memory/compaction-ledger-store.ts +107 -0
- package/src/memory/conversation-crud.ts +129 -61
- package/src/memory/db-connection.ts +22 -3
- package/src/memory/db-init.ts +37 -503
- package/src/memory/db-singleton.ts +6 -4
- package/src/memory/jobs-worker.ts +104 -0
- package/src/memory/llm-request-log-store.ts +26 -1
- package/src/memory/llm-usage-store.ts +48 -20
- package/src/memory/memory-retrospective-job.ts +14 -8
- package/src/memory/migrations/209-strip-thinking-from-consolidated.ts +152 -56
- package/src/memory/migrations/300-add-processing-started-at.ts +30 -0
- package/src/memory/migrations/301-create-watchdog-events.ts +45 -0
- package/src/memory/migrations/302-create-compaction-events.ts +107 -0
- package/src/memory/migrations/__tests__/209-strip-thinking-from-consolidated.test.ts +297 -0
- package/src/memory/migrations/__tests__/run-migrations.test.ts +2 -2
- package/src/memory/migrations/run-migrations.ts +106 -10
- package/src/memory/migrations/validate-migration-state.ts +105 -67
- package/src/memory/prompt-override.ts +129 -0
- package/src/memory/schema/contacts.ts +6 -2
- package/src/memory/schema/conversations.ts +37 -0
- package/src/memory/schema/infrastructure.ts +20 -0
- package/src/memory/steps.ts +1294 -0
- package/src/memory/v2/__tests__/cli-command-store.test.ts +25 -0
- package/src/memory/v2/__tests__/skill-store.test.ts +80 -0
- package/src/memory/v2/cli-command-store.ts +75 -38
- package/src/memory/v2/prompts/consolidation.ts +13 -82
- package/src/memory/v2/prompts/router.ts +21 -93
- package/src/memory/v2/skill-store.ts +68 -31
- package/src/memory/watchdog-events-store.ts +87 -0
- package/src/memory/worker-control.ts +204 -0
- package/src/memory/worker-process.ts +89 -0
- package/src/messaging/channel-binding-metadata.ts +31 -0
- package/src/messaging/provider-types.ts +8 -0
- package/src/messaging/providers/slack/binding-metadata.ts +60 -0
- package/src/notifications/__tests__/broadcaster.test.ts +8 -8
- package/src/notifications/__tests__/connected-channels.test.ts +86 -0
- package/src/notifications/__tests__/decision-engine.test.ts +78 -9
- package/src/notifications/__tests__/destination-resolver.test.ts +151 -0
- package/src/notifications/broadcaster.ts +8 -1
- package/src/notifications/decision-engine.ts +15 -7
- package/src/notifications/destination-resolver.ts +53 -25
- package/src/notifications/emit-signal.ts +34 -15
- package/src/onboarding/checkin-event.test.ts +222 -0
- package/src/onboarding/checkin-event.ts +321 -0
- package/src/onboarding/schedule-checkin.ts +190 -0
- package/src/permissions/question-prompter.test.ts +1 -1
- package/src/permissions/question-prompter.ts +7 -4
- package/src/plugin-api/index.ts +12 -12
- package/src/plugin-api/types.ts +12 -14
- package/src/plugin-api/vision-support.test.ts +28 -4
- package/src/plugin-api/vision-support.ts +66 -31
- package/src/plugins/defaults/empty-response/hooks/post-model-call.ts +2 -2
- package/src/plugins/defaults/empty-response/hooks/stop.ts +2 -2
- package/src/plugins/defaults/exploration-drift/hooks/post-tool-use.ts +4 -3
- package/src/plugins/defaults/history-repair/hooks/post-model-call.ts +2 -2
- package/src/plugins/defaults/history-repair/hooks/stop.ts +2 -2
- package/src/plugins/defaults/history-repair/hooks/user-prompt-submit.ts +2 -2
- package/src/plugins/defaults/image-fallback/__tests__/image-fallback.test.ts +47 -7
- package/src/plugins/defaults/image-fallback/hooks/post-tool-use.ts +12 -13
- package/src/plugins/defaults/image-fallback/hooks/user-prompt-submit.ts +14 -22
- package/src/plugins/defaults/image-fallback/src/caption-blocks.ts +42 -11
- package/src/plugins/defaults/image-recovery/hooks/post-model-call.ts +2 -2
- package/src/plugins/defaults/image-recovery/hooks/stop.ts +2 -2
- package/src/plugins/defaults/index.ts +0 -35
- package/src/plugins/defaults/max-tokens-continue/hooks/post-model-call.ts +2 -2
- package/src/plugins/defaults/max-tokens-continue/hooks/stop.ts +2 -2
- package/src/plugins/defaults/memory-retrieval/hooks/post-compact.ts +2 -2
- package/src/plugins/defaults/memory-retrieval/hooks/user-prompt-submit.ts +2 -2
- package/src/plugins/defaults/memory-v3-shadow/__tests__/injection.test.ts +33 -3
- package/src/plugins/defaults/memory-v3-shadow/__tests__/pool-select.test.ts +48 -4
- package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-plugin.test.ts +4 -8
- package/src/plugins/defaults/memory-v3-shadow/hooks/post-compact.ts +2 -2
- package/src/plugins/defaults/memory-v3-shadow/hooks/user-prompt-submit.ts +2 -2
- package/src/plugins/defaults/memory-v3-shadow/injector.ts +43 -15
- package/src/plugins/defaults/memory-v3-shadow/orchestrate.ts +11 -2
- package/src/plugins/defaults/memory-v3-shadow/pool-select.test.ts +146 -0
- package/src/plugins/defaults/memory-v3-shadow/pool-select.ts +77 -13
- package/src/plugins/defaults/memory-v3-shadow/shadow-plugin.ts +12 -11
- package/src/plugins/defaults/surface-completion-nudge/hooks/post-model-call.ts +2 -2
- package/src/plugins/defaults/surface-completion-nudge/hooks/stop.ts +2 -2
- package/src/plugins/defaults/task-progress-nudge/hooks/post-tool-use.ts +2 -2
- package/src/plugins/defaults/title-generate/hooks/stop.ts +2 -2
- package/src/plugins/defaults/title-generate/hooks/user-prompt-submit.ts +2 -2
- package/src/plugins/defaults/tool-error/hooks/post-tool-use.ts +2 -2
- package/src/plugins/defaults/tool-result-truncate/hooks/post-tool-use.ts +2 -2
- package/src/plugins/disabled-state.ts +31 -0
- package/src/plugins/external-plugin-loader.ts +2 -2
- package/src/plugins/mtime-cache.ts +186 -330
- package/src/plugins/pipeline.ts +111 -13
- package/src/plugins/registry.ts +59 -16
- package/src/plugins/surface-import.ts +121 -0
- package/src/plugins/types.ts +7 -9
- package/src/prompts/persona-resolver.ts +43 -11
- package/src/providers/anthropic/client.ts +5 -0
- package/src/providers/call-site-routing.ts +45 -0
- package/src/providers/model-catalog.ts +16 -0
- package/src/providers/openai/__tests__/api-error-normalization.test.ts +321 -0
- package/src/providers/openai/api-error-normalization.ts +270 -0
- package/src/providers/openai/chat-completions-provider.ts +37 -83
- package/src/providers/openai/responses-provider.ts +50 -46
- package/src/providers/openrouter/client.ts +5 -0
- package/src/providers/provider-send-message.ts +10 -0
- package/src/providers/ratelimit.ts +10 -0
- package/src/providers/registry.ts +1 -1
- package/src/providers/retry.ts +10 -0
- package/src/providers/types.ts +22 -0
- package/src/providers/usage-tracking.ts +10 -0
- package/src/runtime/__tests__/channel-verification-service.test.ts +133 -0
- package/src/runtime/__tests__/guardian-vellum-migration.test.ts +184 -0
- package/src/runtime/__tests__/is-guardian-bound-for-channel.test.ts +66 -0
- package/src/runtime/__tests__/local-principal-trust.test.ts +162 -0
- package/src/runtime/__tests__/member-verdict-cache.test.ts +119 -0
- package/src/runtime/__tests__/trust-verdict-consumer.test.ts +402 -123
- package/src/runtime/access-request-helper.ts +18 -39
- package/src/runtime/actor-trust-resolver.ts +46 -19
- package/src/runtime/anchored-guardian.test.ts +109 -0
- package/src/runtime/anchored-guardian.ts +86 -0
- package/src/runtime/assistant-event-hub.ts +1 -1
- package/src/runtime/assistant-stream-state.ts +9 -2
- package/src/runtime/auth/__tests__/require-bound-guardian.test.ts +99 -0
- package/src/runtime/auth/require-bound-guardian.ts +21 -11
- package/src/runtime/channel-verification-service.ts +56 -31
- package/src/runtime/confirmation-request-guardian-bridge.ts +3 -3
- package/src/runtime/guardian-vellum-migration.ts +69 -8
- package/src/runtime/invite-redemption-service.ts +213 -187
- package/src/runtime/local-actor-identity.test.ts +108 -0
- package/src/runtime/local-actor-identity.ts +85 -13
- package/src/runtime/local-principal-trust.ts +52 -0
- package/src/runtime/member-verdict-cache.ts +0 -0
- package/src/runtime/pending-interactions.ts +11 -1
- package/src/runtime/routes/__tests__/channel-verification-revoke.test.ts +56 -5
- package/src/runtime/routes/__tests__/channel-verification-routes.test.ts +1 -1
- package/src/runtime/routes/__tests__/contact-routes.test.ts +305 -0
- package/src/runtime/routes/__tests__/global-search-routes.test.ts +92 -0
- package/src/runtime/routes/__tests__/http-adapter-actor-header.test.ts +129 -0
- package/src/runtime/routes/__tests__/surface-action-routes.test.ts +188 -0
- package/src/runtime/routes/browser-routes.ts +1 -1
- package/src/runtime/routes/canonical-guardian-expiry-sweep.ts +13 -5
- package/src/runtime/routes/channel-verification-routes.ts +3 -3
- package/src/runtime/routes/contact-routes.ts +48 -57
- package/src/runtime/routes/conversation-cli-routes.ts +4 -5
- package/src/runtime/routes/conversation-list-routes.ts +4 -7
- package/src/runtime/routes/conversation-query-routes.ts +72 -0
- package/src/runtime/routes/conversation-routes.ts +84 -85
- package/src/runtime/routes/events-routes.ts +2 -2
- package/src/runtime/routes/global-search-routes.ts +3 -1
- package/src/runtime/routes/guardian-action-routes.ts +4 -5
- package/src/runtime/routes/host-app-control-routes.ts +5 -4
- package/src/runtime/routes/host-bash-routes.ts +5 -4
- package/src/runtime/routes/host-browser-routes.ts +9 -11
- package/src/runtime/routes/host-cu-routes.ts +5 -4
- package/src/runtime/routes/host-file-routes.ts +5 -4
- package/src/runtime/routes/host-transfer-routes.ts +6 -6
- package/src/runtime/routes/http-adapter.ts +16 -1
- package/src/runtime/routes/identity-routes.ts +3 -2
- package/src/runtime/routes/inbound-message-handler.ts +5 -5
- package/src/runtime/routes/inbound-stages/acl-enforcement.test.ts +97 -5
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +61 -59
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +13 -5
- package/src/runtime/routes/inbound-stages/escalation-intercept.ts +7 -7
- package/src/runtime/routes/inbound-stages/guardian-activation-intercept.test.ts +21 -8
- package/src/runtime/routes/inbound-stages/guardian-activation-intercept.ts +14 -3
- package/src/runtime/routes/inbound-stages/reaction-intercept.ts +19 -0
- package/src/runtime/routes/index.ts +2 -0
- package/src/runtime/routes/llm-context-normalization.ts +83 -0
- package/src/runtime/routes/mcp-auth-routes.ts +171 -19
- package/src/runtime/routes/migration-rollback-routes.ts +4 -3
- package/src/runtime/routes/migration-routes.ts +4 -1
- package/src/runtime/routes/onboarding-checkin-routes.ts +86 -0
- package/src/runtime/routes/settings-routes.ts +8 -3
- package/src/runtime/routes/subagents-routes.ts +5 -0
- package/src/runtime/routes/surface-action-routes.ts +42 -56
- package/src/runtime/services/__tests__/conversation-serializer.test.ts +1 -0
- package/src/runtime/services/conversation-serializer.ts +13 -58
- package/src/runtime/tool-grant-request-helper.ts +3 -3
- package/src/runtime/trust-verdict-consumer.ts +111 -40
- package/src/runtime/verification-outbound-actions.ts +18 -18
- package/src/signals/user-message.ts +16 -0
- package/src/subagent/__tests__/consult-prompt.test.ts +35 -0
- package/src/{plugins/defaults/advisor/__tests__/transcript.test.ts → subagent/__tests__/consult-transcript.test.ts} +47 -10
- package/src/{plugins/defaults/advisor/steering.ts → subagent/consult-prompt.ts} +22 -32
- package/src/{plugins/defaults/advisor/transcript.ts → subagent/consult-transcript.ts} +18 -8
- package/src/subagent/index.ts +1 -1
- package/src/subagent/manager.ts +254 -33
- package/src/subagent/types.ts +11 -4
- package/src/telemetry/types.ts +34 -1
- package/src/telemetry/usage-telemetry-reporter.test.ts +3 -2
- package/src/telemetry/usage-telemetry-reporter.ts +87 -3
- package/src/tools/ask-question/ask-question-tool.test.ts +29 -0
- package/src/tools/ask-question/ask-question-tool.ts +13 -0
- package/src/tools/executor.ts +4 -4
- package/src/tools/filesystem/search.ts +543 -0
- package/src/tools/registry.ts +38 -0
- package/src/tools/shared/filesystem/path-policy.ts +12 -5
- package/src/tools/subagent/consult-deadline.ts +49 -0
- package/src/tools/subagent/spawn.ts +234 -5
- package/src/tools/tool-approval-handler.ts +1 -1
- package/src/tools/tool-defaults.ts +9 -2
- package/src/tools/tool-manifest.ts +3 -0
- package/src/tools/types.ts +131 -25
- package/src/tools/workspace-tools/loader.ts +348 -244
- package/src/util/errors.ts +26 -1
- package/src/util/logger.ts +9 -0
- package/src/util/platform.ts +19 -0
- package/src/util/telemetry-db-path.ts +24 -0
- package/src/workflows/library.test.ts +140 -0
- package/src/workflows/library.ts +82 -28
- package/src/workspace/migrations/017-seed-persona-dirs.ts +3 -34
- package/src/workspace/migrations/019-scope-journal-to-guardian.ts +3 -24
- package/src/workspace/migrations/031-drop-user-md.ts +232 -148
- package/src/workspace/migrations/048-remove-workspace-hooks.ts +14 -66
- package/src/workspace/migrations/111-prune-seeded-callsite-defaults.ts +134 -0
- package/src/workspace/migrations/112-remove-advisor-callsite-override.ts +64 -0
- package/src/workspace/migrations/registry.ts +4 -0
- package/src/__tests__/workspace-tools-watcher-flag.test.ts +0 -70
- package/src/daemon/workspace-tools-watcher.ts +0 -328
- package/src/memory/migrations/registry.ts +0 -573
- package/src/plugins/defaults/advisor/__tests__/advisor-gate.test.ts +0 -56
- package/src/plugins/defaults/advisor/__tests__/advisor-state-store.test.ts +0 -43
- package/src/plugins/defaults/advisor/__tests__/agent-loop-integration.test.ts +0 -137
- package/src/plugins/defaults/advisor/__tests__/consult.test.ts +0 -153
- package/src/plugins/defaults/advisor/__tests__/hooks.test.ts +0 -138
- package/src/plugins/defaults/advisor/advisor-gate.ts +0 -29
- package/src/plugins/defaults/advisor/advisor-state-store.ts +0 -94
- package/src/plugins/defaults/advisor/config.ts +0 -21
- package/src/plugins/defaults/advisor/consult.ts +0 -93
- package/src/plugins/defaults/advisor/hooks/post-model-call.ts +0 -34
- package/src/plugins/defaults/advisor/hooks/pre-model-call.ts +0 -30
- package/src/plugins/defaults/advisor/hooks/user-prompt-submit.ts +0 -19
- package/src/plugins/defaults/advisor/package.json +0 -14
- package/src/plugins/defaults/advisor/tools/advisor.ts +0 -65
- package/src/providers/openai/__tests__/api-error-detail.test.ts +0 -120
|
@@ -14,7 +14,6 @@
|
|
|
14
14
|
import { z } from "zod";
|
|
15
15
|
|
|
16
16
|
import { isHttpAuthDisabled } from "../../config/env.js";
|
|
17
|
-
import { findGuardianForChannel } from "../../contacts/contact-store.js";
|
|
18
17
|
import {
|
|
19
18
|
type CanonicalGuardianRequest,
|
|
20
19
|
listPendingRequestsByConversationScope,
|
|
@@ -23,6 +22,7 @@ import { ACTOR_PRINCIPALS } from "../auth/route-policy.js";
|
|
|
23
22
|
import { processGuardianDecision } from "../guardian-action-service.js";
|
|
24
23
|
import type { GuardianDecisionPrompt } from "../guardian-decision-types.js";
|
|
25
24
|
import { buildOneTimeDecisionActions } from "../guardian-decision-types.js";
|
|
25
|
+
import { findLocalGuardianPrincipalId } from "../local-actor-identity.js";
|
|
26
26
|
import { BadRequestError, NotFoundError } from "./errors.js";
|
|
27
27
|
import type { RouteDefinition, RouteHandlerArgs } from "./types.js";
|
|
28
28
|
|
|
@@ -73,16 +73,15 @@ async function handleGuardianActionDecision({
|
|
|
73
73
|
// Resolve the actor's guardian principal ID. The HTTP adapter injects it
|
|
74
74
|
// from the AuthContext via the x-vellum-actor-principal-id header.
|
|
75
75
|
// For dev bypass (HTTP auth disabled) the synthetic "dev-bypass" principal
|
|
76
|
-
// won't match the real guardian binding, so
|
|
77
|
-
//
|
|
76
|
+
// won't match the real guardian binding, so resolve the local guardian
|
|
77
|
+
// principal to avoid identity_mismatch.
|
|
78
78
|
let guardianPrincipalId: string | undefined =
|
|
79
79
|
headers["x-vellum-actor-principal-id"] ?? undefined;
|
|
80
80
|
if (
|
|
81
81
|
isHttpAuthDisabled() &&
|
|
82
82
|
headers["x-vellum-actor-principal-id"] === "dev-bypass"
|
|
83
83
|
) {
|
|
84
|
-
|
|
85
|
-
guardianPrincipalId = binding?.contact.principalId ?? undefined;
|
|
84
|
+
guardianPrincipalId = (await findLocalGuardianPrincipalId()) ?? undefined;
|
|
86
85
|
}
|
|
87
86
|
|
|
88
87
|
const result = await processGuardianDecision({
|
|
@@ -39,7 +39,7 @@ const VALID_STATES: ReadonlySet<HostAppControlState> = new Set([
|
|
|
39
39
|
// POST /v1/host-app-control-result
|
|
40
40
|
// ---------------------------------------------------------------------------
|
|
41
41
|
|
|
42
|
-
function handleHostAppControlResult({ body, headers }: RouteHandlerArgs) {
|
|
42
|
+
async function handleHostAppControlResult({ body, headers }: RouteHandlerArgs) {
|
|
43
43
|
if (!body || typeof body !== "object") {
|
|
44
44
|
throw new BadRequestError("Request body is required");
|
|
45
45
|
}
|
|
@@ -95,9 +95,10 @@ function handleHostAppControlResult({ body, headers }: RouteHandlerArgs) {
|
|
|
95
95
|
`Client "${submittingClientId}" is not the target for this request (expected "${peeked.targetClientId}"). The targeted client must submit the result.`,
|
|
96
96
|
);
|
|
97
97
|
}
|
|
98
|
-
const submittingActorPrincipalId =
|
|
99
|
-
|
|
100
|
-
|
|
98
|
+
const submittingActorPrincipalId =
|
|
99
|
+
await resolveActorPrincipalIdForLocalGuardian(
|
|
100
|
+
headerMap["x-vellum-actor-principal-id"]?.trim() || undefined,
|
|
101
|
+
);
|
|
101
102
|
enforceSameActorOrThrow({
|
|
102
103
|
sourceActorPrincipalId: submittingActorPrincipalId,
|
|
103
104
|
targetActorPrincipalId: peeked.targetActorPrincipalId,
|
|
@@ -26,7 +26,7 @@ import type { RouteDefinition, RouteHandlerArgs } from "./types.js";
|
|
|
26
26
|
// POST /v1/host-bash-result
|
|
27
27
|
// ---------------------------------------------------------------------------
|
|
28
28
|
|
|
29
|
-
function handleHostBashResult({ body, headers }: RouteHandlerArgs) {
|
|
29
|
+
async function handleHostBashResult({ body, headers }: RouteHandlerArgs) {
|
|
30
30
|
if (!body || typeof body !== "object") {
|
|
31
31
|
throw new BadRequestError("Request body is required");
|
|
32
32
|
}
|
|
@@ -45,9 +45,10 @@ function handleHostBashResult({ body, headers }: RouteHandlerArgs) {
|
|
|
45
45
|
|
|
46
46
|
const submittingClientId =
|
|
47
47
|
headers?.["x-vellum-client-id"]?.trim() || undefined;
|
|
48
|
-
const submittingActorPrincipalId =
|
|
49
|
-
|
|
50
|
-
|
|
48
|
+
const submittingActorPrincipalId =
|
|
49
|
+
await resolveActorPrincipalIdForLocalGuardian(
|
|
50
|
+
headers?.["x-vellum-actor-principal-id"]?.trim() || undefined,
|
|
51
|
+
);
|
|
51
52
|
|
|
52
53
|
const peeked = pendingInteractions.get(requestId);
|
|
53
54
|
if (!peeked) {
|
|
@@ -61,14 +61,14 @@ export type HostBrowserResultResolution =
|
|
|
61
61
|
* already authenticated the caller (the HTTP route uses
|
|
62
62
|
* `requireBoundGuardian`).
|
|
63
63
|
*/
|
|
64
|
-
export function resolveHostBrowserResultByRequestId(
|
|
64
|
+
export async function resolveHostBrowserResultByRequestId(
|
|
65
65
|
frame: {
|
|
66
66
|
requestId?: unknown;
|
|
67
67
|
content?: unknown;
|
|
68
68
|
isError?: unknown;
|
|
69
69
|
},
|
|
70
70
|
headers?: Record<string, string | undefined>,
|
|
71
|
-
): HostBrowserResultResolution {
|
|
71
|
+
): Promise<HostBrowserResultResolution> {
|
|
72
72
|
const { requestId, content, isError } = frame;
|
|
73
73
|
|
|
74
74
|
if (!requestId || typeof requestId !== "string") {
|
|
@@ -127,9 +127,10 @@ export function resolveHostBrowserResultByRequestId(
|
|
|
127
127
|
// stream. This prevents a different authenticated user with knowledge of
|
|
128
128
|
// both the requestId and target clientId from submitting a result on
|
|
129
129
|
// behalf of the targeted client.
|
|
130
|
-
const submittingActorPrincipalId =
|
|
131
|
-
|
|
132
|
-
|
|
130
|
+
const submittingActorPrincipalId =
|
|
131
|
+
await resolveActorPrincipalIdForLocalGuardian(
|
|
132
|
+
headerMap["x-vellum-actor-principal-id"]?.trim() || undefined,
|
|
133
|
+
);
|
|
133
134
|
try {
|
|
134
135
|
enforceSameActorOrThrow({
|
|
135
136
|
sourceActorPrincipalId: submittingActorPrincipalId,
|
|
@@ -260,12 +261,12 @@ export function resolveHostBrowserSessionInvalidated(frame: {
|
|
|
260
261
|
// POST /v1/host-browser-result
|
|
261
262
|
// ---------------------------------------------------------------------------
|
|
262
263
|
|
|
263
|
-
function handleHostBrowserResult({ body, headers }: RouteHandlerArgs) {
|
|
264
|
+
async function handleHostBrowserResult({ body, headers }: RouteHandlerArgs) {
|
|
264
265
|
if (!body || typeof body !== "object") {
|
|
265
266
|
throw new BadRequestError("Request body is required");
|
|
266
267
|
}
|
|
267
268
|
|
|
268
|
-
const resolution = resolveHostBrowserResultByRequestId(
|
|
269
|
+
const resolution = await resolveHostBrowserResultByRequestId(
|
|
269
270
|
body,
|
|
270
271
|
headers as Record<string, string | undefined> | undefined,
|
|
271
272
|
);
|
|
@@ -399,10 +400,7 @@ export const ROUTES: RouteDefinition[] = [
|
|
|
399
400
|
"Marks the target as invalidated in the runtime-side browser session registry.",
|
|
400
401
|
tags: ["host"],
|
|
401
402
|
requestBody: z.object({
|
|
402
|
-
targetId: z
|
|
403
|
-
.string()
|
|
404
|
-
.optional()
|
|
405
|
-
.describe("CDP target that was detached"),
|
|
403
|
+
targetId: z.string().optional().describe("CDP target that was detached"),
|
|
406
404
|
reason: z.string().optional().describe("Detach reason"),
|
|
407
405
|
clientId: z
|
|
408
406
|
.string()
|
|
@@ -26,7 +26,7 @@ import type { RouteDefinition, RouteHandlerArgs } from "./types.js";
|
|
|
26
26
|
// POST /v1/host-cu-result
|
|
27
27
|
// ---------------------------------------------------------------------------
|
|
28
28
|
|
|
29
|
-
function handleHostCuResult({ body, headers }: RouteHandlerArgs) {
|
|
29
|
+
async function handleHostCuResult({ body, headers }: RouteHandlerArgs) {
|
|
30
30
|
if (!body || typeof body !== "object") {
|
|
31
31
|
throw new BadRequestError("Request body is required");
|
|
32
32
|
}
|
|
@@ -95,9 +95,10 @@ function handleHostCuResult({ body, headers }: RouteHandlerArgs) {
|
|
|
95
95
|
// stream. This prevents a different authenticated user with knowledge of
|
|
96
96
|
// both the requestId and target clientId from submitting a result on
|
|
97
97
|
// behalf of the targeted client.
|
|
98
|
-
const submittingActorPrincipalId =
|
|
99
|
-
|
|
100
|
-
|
|
98
|
+
const submittingActorPrincipalId =
|
|
99
|
+
await resolveActorPrincipalIdForLocalGuardian(
|
|
100
|
+
headerMap["x-vellum-actor-principal-id"]?.trim() || undefined,
|
|
101
|
+
);
|
|
101
102
|
enforceSameActorOrThrow({
|
|
102
103
|
sourceActorPrincipalId: submittingActorPrincipalId,
|
|
103
104
|
targetActorPrincipalId: peeked.targetActorPrincipalId,
|
|
@@ -26,7 +26,7 @@ import type { RouteDefinition, RouteHandlerArgs } from "./types.js";
|
|
|
26
26
|
// POST /v1/host-file-result
|
|
27
27
|
// ---------------------------------------------------------------------------
|
|
28
28
|
|
|
29
|
-
function handleHostFileResult({ body, headers }: RouteHandlerArgs) {
|
|
29
|
+
async function handleHostFileResult({ body, headers }: RouteHandlerArgs) {
|
|
30
30
|
if (!body || typeof body !== "object") {
|
|
31
31
|
throw new BadRequestError("Request body is required");
|
|
32
32
|
}
|
|
@@ -76,9 +76,10 @@ function handleHostFileResult({ body, headers }: RouteHandlerArgs) {
|
|
|
76
76
|
// match the actor that opened the target client's SSE stream. This blocks
|
|
77
77
|
// cross-user submissions even if a different user somehow obtains the
|
|
78
78
|
// target client id.
|
|
79
|
-
const submittingActorPrincipalId =
|
|
80
|
-
|
|
81
|
-
|
|
79
|
+
const submittingActorPrincipalId =
|
|
80
|
+
await resolveActorPrincipalIdForLocalGuardian(
|
|
81
|
+
headerMap["x-vellum-actor-principal-id"]?.trim() || undefined,
|
|
82
|
+
);
|
|
82
83
|
enforceSameActorOrThrow({
|
|
83
84
|
sourceActorPrincipalId: submittingActorPrincipalId,
|
|
84
85
|
targetActorPrincipalId: peeked.targetActorPrincipalId,
|
|
@@ -39,10 +39,10 @@ function findProxyByTransferId(transferId: string) {
|
|
|
39
39
|
// GET /v1/transfers/:transferId/content
|
|
40
40
|
// ---------------------------------------------------------------------------
|
|
41
41
|
|
|
42
|
-
function handleTransferContentGet({
|
|
42
|
+
async function handleTransferContentGet({
|
|
43
43
|
pathParams = {},
|
|
44
44
|
headers = {},
|
|
45
|
-
}: RouteHandlerArgs): Uint8Array {
|
|
45
|
+
}: RouteHandlerArgs): Promise<Uint8Array> {
|
|
46
46
|
const transferId = pathParams.transferId;
|
|
47
47
|
if (!transferId) {
|
|
48
48
|
throw new BadRequestError("transferId path parameter is required");
|
|
@@ -72,7 +72,7 @@ function handleTransferContentGet({
|
|
|
72
72
|
// the value persisted at registration time so a brief reconnect does
|
|
73
73
|
// not 403 a legitimate fetch.
|
|
74
74
|
enforceSameActorOrThrow({
|
|
75
|
-
sourceActorPrincipalId: resolveActorPrincipalIdForLocalGuardian(
|
|
75
|
+
sourceActorPrincipalId: await resolveActorPrincipalIdForLocalGuardian(
|
|
76
76
|
headerMap["x-vellum-actor-principal-id"]?.trim() || undefined,
|
|
77
77
|
),
|
|
78
78
|
targetActorPrincipalId:
|
|
@@ -151,7 +151,7 @@ async function handleTransferContentPut({
|
|
|
151
151
|
);
|
|
152
152
|
|
|
153
153
|
enforceSameActorOrThrow({
|
|
154
|
-
sourceActorPrincipalId: resolveActorPrincipalIdForLocalGuardian(
|
|
154
|
+
sourceActorPrincipalId: await resolveActorPrincipalIdForLocalGuardian(
|
|
155
155
|
headerMap["x-vellum-actor-principal-id"]?.trim() || undefined,
|
|
156
156
|
),
|
|
157
157
|
targetActorPrincipalId:
|
|
@@ -181,7 +181,7 @@ async function handleTransferContentPut({
|
|
|
181
181
|
// POST /v1/host-transfer-result
|
|
182
182
|
// ---------------------------------------------------------------------------
|
|
183
183
|
|
|
184
|
-
function handleTransferResult({ body, headers }: RouteHandlerArgs) {
|
|
184
|
+
async function handleTransferResult({ body, headers }: RouteHandlerArgs) {
|
|
185
185
|
if (!body || typeof body !== "object") {
|
|
186
186
|
throw new BadRequestError("Request body is required");
|
|
187
187
|
}
|
|
@@ -222,7 +222,7 @@ function handleTransferResult({ body, headers }: RouteHandlerArgs) {
|
|
|
222
222
|
);
|
|
223
223
|
|
|
224
224
|
enforceSameActorOrThrow({
|
|
225
|
-
sourceActorPrincipalId: resolveActorPrincipalIdForLocalGuardian(
|
|
225
|
+
sourceActorPrincipalId: await resolveActorPrincipalIdForLocalGuardian(
|
|
226
226
|
headerMap["x-vellum-actor-principal-id"]?.trim() || undefined,
|
|
227
227
|
),
|
|
228
228
|
targetActorPrincipalId: peeked.targetActorPrincipalId,
|
|
@@ -51,7 +51,7 @@ export function routeDefinitionsToHTTPRoutes(
|
|
|
51
51
|
handler: async ({ req, url, params, authContext }) => {
|
|
52
52
|
try {
|
|
53
53
|
if (r.requireGuardian) {
|
|
54
|
-
const guardianError = requireBoundGuardian(authContext);
|
|
54
|
+
const guardianError = await requireBoundGuardian(authContext);
|
|
55
55
|
if (guardianError) return guardianError;
|
|
56
56
|
}
|
|
57
57
|
|
|
@@ -96,6 +96,21 @@ export function routeDefinitionsToHTTPRoutes(
|
|
|
96
96
|
headers[key] = value;
|
|
97
97
|
});
|
|
98
98
|
|
|
99
|
+
// Strip any caller-supplied identity headers before deriving them
|
|
100
|
+
// from the verified AuthContext. On the HTTP path the actor identity
|
|
101
|
+
// always comes from the validated JWT — never from inbound headers —
|
|
102
|
+
// so a request that carries these headers is either confused or
|
|
103
|
+
// hostile. Without this, a caller whose token carries no
|
|
104
|
+
// actorPrincipalId (svc_gateway / svc_daemon / local principals) could
|
|
105
|
+
// spoof another principal — e.g. the guardian — by setting the header
|
|
106
|
+
// explicitly, because the override below only fires when the context
|
|
107
|
+
// supplies a value. Handlers that gate on principal identity (surface
|
|
108
|
+
// action `apr:*` guardian decisions, guardian actions, host proxies)
|
|
109
|
+
// would then apply a decision as the impersonated principal. Mirrors
|
|
110
|
+
// the gateway IPC proxy (gateway/src/http/routes/ipc-runtime-proxy.ts).
|
|
111
|
+
delete headers["x-vellum-actor-principal-id"];
|
|
112
|
+
delete headers["x-vellum-principal-type"];
|
|
113
|
+
|
|
99
114
|
// Inject auth context fields so transport-agnostic handlers can
|
|
100
115
|
// resolve trust context without importing auth internals.
|
|
101
116
|
if (authContext?.actorPrincipalId) {
|
|
@@ -10,7 +10,8 @@ import { z } from "zod";
|
|
|
10
10
|
import { getCpuLimit, getIsPlatform } from "../../config/env-registry.js";
|
|
11
11
|
import { parseIdentityFields } from "../../daemon/handlers/identity.js";
|
|
12
12
|
import { getProfilerRuntimeStatus } from "../../daemon/profiler-run-store.js";
|
|
13
|
-
import {
|
|
13
|
+
import { getMaxRollbackVersion } from "../../memory/migrations/run-migrations.js";
|
|
14
|
+
import { migrationSteps } from "../../memory/steps.js";
|
|
14
15
|
import { getCesClient } from "../../security/secure-keys.js";
|
|
15
16
|
import {
|
|
16
17
|
getDiskUsageInfo,
|
|
@@ -335,7 +336,7 @@ function getDetailedHealth() {
|
|
|
335
336
|
memory: getMemoryInfo(),
|
|
336
337
|
cpu: getCpuInfo(),
|
|
337
338
|
migrations: {
|
|
338
|
-
dbVersion:
|
|
339
|
+
dbVersion: getMaxRollbackVersion(migrationSteps),
|
|
339
340
|
lastWorkspaceMigrationId:
|
|
340
341
|
getLastWorkspaceMigrationId(WORKSPACE_MIGRATIONS),
|
|
341
342
|
},
|
|
@@ -680,7 +680,7 @@ export async function handleChannelInbound({
|
|
|
680
680
|
canonicalAssistantId,
|
|
681
681
|
assistantId,
|
|
682
682
|
content,
|
|
683
|
-
channelId: resolvedMember?.
|
|
683
|
+
channelId: resolvedMember?.channelId,
|
|
684
684
|
});
|
|
685
685
|
}
|
|
686
686
|
|
|
@@ -761,7 +761,7 @@ export async function handleChannelInbound({
|
|
|
761
761
|
: enforceAdmissionPolicy({
|
|
762
762
|
sourceChannel,
|
|
763
763
|
trustClass: trustCtx.trustClass,
|
|
764
|
-
memberStatus: resolvedMember?.
|
|
764
|
+
memberStatus: resolvedMember?.status,
|
|
765
765
|
policy: admissionPolicyFromGateway,
|
|
766
766
|
});
|
|
767
767
|
if (!admissionResult.admitted) {
|
|
@@ -801,7 +801,7 @@ export async function handleChannelInbound({
|
|
|
801
801
|
// guardian sees "previously pending" etc.
|
|
802
802
|
let guardianNotified = false;
|
|
803
803
|
try {
|
|
804
|
-
const accessResult = notifyGuardianOfAccessRequest({
|
|
804
|
+
const accessResult = await notifyGuardianOfAccessRequest({
|
|
805
805
|
canonicalAssistantId,
|
|
806
806
|
sourceChannel,
|
|
807
807
|
conversationExternalId,
|
|
@@ -811,7 +811,7 @@ export async function handleChannelInbound({
|
|
|
811
811
|
...(resolvedMember
|
|
812
812
|
? {
|
|
813
813
|
previousMemberStatus: channelStatusToMemberStatus(
|
|
814
|
-
resolvedMember.
|
|
814
|
+
resolvedMember.status,
|
|
815
815
|
),
|
|
816
816
|
}
|
|
817
817
|
: {}),
|
|
@@ -935,7 +935,7 @@ export async function handleChannelInbound({
|
|
|
935
935
|
}
|
|
936
936
|
|
|
937
937
|
// ── Ingress escalation ──
|
|
938
|
-
const escalationResponse = handleEscalationIntercept({
|
|
938
|
+
const escalationResponse = await handleEscalationIntercept({
|
|
939
939
|
resolvedMember,
|
|
940
940
|
canonicalAssistantId,
|
|
941
941
|
sourceChannel,
|
|
@@ -19,14 +19,28 @@ mock.module("../../../util/logger.js", () => ({
|
|
|
19
19
|
}));
|
|
20
20
|
|
|
21
21
|
// Track contact-store reads to prove findContactChannel is NOT used on the
|
|
22
|
-
// verdict path.
|
|
22
|
+
// verdict path.
|
|
23
23
|
const findContactChannelCalls: unknown[] = [];
|
|
24
24
|
mock.module("../../../contacts/contact-store.js", () => ({
|
|
25
25
|
findContactChannel: (params: unknown) => {
|
|
26
26
|
findContactChannelCalls.push(params);
|
|
27
27
|
return null;
|
|
28
28
|
},
|
|
29
|
-
|
|
29
|
+
}));
|
|
30
|
+
|
|
31
|
+
// resolveGuardianLabel resolves the guardian via the gateway delivery reader.
|
|
32
|
+
let guardianDeliveryList: Array<Record<string, unknown>> = [];
|
|
33
|
+
mock.module("../../../contacts/guardian-delivery-reader.js", () => ({
|
|
34
|
+
getGuardianDelivery: async () => guardianDeliveryList,
|
|
35
|
+
guardianForChannel: (
|
|
36
|
+
list: Array<Record<string, unknown>>,
|
|
37
|
+
channelType: string,
|
|
38
|
+
) => list.find((g) => g.channelType === channelType && g.status === "active"),
|
|
39
|
+
}));
|
|
40
|
+
|
|
41
|
+
mock.module("../../../prompts/user-reference.js", () => ({
|
|
42
|
+
resolveGuardianName: (displayName?: string | null) =>
|
|
43
|
+
displayName && displayName.trim().length > 0 ? displayName.trim() : "my human",
|
|
30
44
|
}));
|
|
31
45
|
|
|
32
46
|
const deliverReplyCalls: Array<{ url: string; payload: unknown }> = [];
|
|
@@ -126,6 +140,7 @@ beforeEach(() => {
|
|
|
126
140
|
deliverReplyCalls.length = 0;
|
|
127
141
|
accessRequestCalls.length = 0;
|
|
128
142
|
inviteTokenForTest = undefined;
|
|
143
|
+
guardianDeliveryList = [];
|
|
129
144
|
});
|
|
130
145
|
|
|
131
146
|
afterEach(() => {
|
|
@@ -140,8 +155,8 @@ describe("enforceIngressAcl — verdict-sourced member resolution", () => {
|
|
|
140
155
|
|
|
141
156
|
expect(result.earlyResponse).toBeUndefined();
|
|
142
157
|
expect(result.resolvedMember).not.toBeNull();
|
|
143
|
-
expect(result.resolvedMember!.
|
|
144
|
-
expect(result.resolvedMember!.
|
|
158
|
+
expect(result.resolvedMember!.status).toBe("active");
|
|
159
|
+
expect(result.resolvedMember!.policy).toBe("allow");
|
|
145
160
|
// Member came from the verdict, never the local contact store.
|
|
146
161
|
expect(findContactChannelCalls.length).toBe(0);
|
|
147
162
|
});
|
|
@@ -156,7 +171,8 @@ describe("enforceIngressAcl — verdict-sourced member resolution", () => {
|
|
|
156
171
|
);
|
|
157
172
|
|
|
158
173
|
expect(result.earlyResponse).toBeUndefined();
|
|
159
|
-
expect(result.resolvedMember
|
|
174
|
+
expect(result.resolvedMember).not.toBeNull();
|
|
175
|
+
expect(result.resolvedMember!.status).toBe("active");
|
|
160
176
|
expect(findContactChannelCalls.length).toBe(0);
|
|
161
177
|
});
|
|
162
178
|
});
|
|
@@ -249,6 +265,82 @@ describe("enforceIngressAcl — fail-closed on absent verdict", () => {
|
|
|
249
265
|
});
|
|
250
266
|
});
|
|
251
267
|
|
|
268
|
+
describe("enforceIngressAcl — fail-closed on resolutionFailed verdict", () => {
|
|
269
|
+
test("resolutionFailed verdict → not_a_member deny, does not flow to intercepts", async () => {
|
|
270
|
+
inviteTokenForTest = "iv_token123";
|
|
271
|
+
const result = await enforceIngressAcl(
|
|
272
|
+
makeParams({
|
|
273
|
+
sourceMetadata: withVerdict({
|
|
274
|
+
trustClass: "unknown",
|
|
275
|
+
canonicalSenderId: "sender-1",
|
|
276
|
+
resolutionFailed: true,
|
|
277
|
+
}),
|
|
278
|
+
effectiveAdmissionPolicy: "strangers",
|
|
279
|
+
}),
|
|
280
|
+
);
|
|
281
|
+
|
|
282
|
+
expect(result.earlyResponse).toBeDefined();
|
|
283
|
+
expect(result.earlyResponse!.reason).toBe("not_a_member");
|
|
284
|
+
expect(result.resolvedMember).toBeNull();
|
|
285
|
+
// Distinct from a stranger: no invite redemption, onboarding, or
|
|
286
|
+
// guardian notification fires.
|
|
287
|
+
expect(result.earlyResponse!.inviteRedemption).toBeUndefined();
|
|
288
|
+
expect(deliverReplyCalls.length).toBe(0);
|
|
289
|
+
expect(accessRequestCalls.length).toBe(0);
|
|
290
|
+
expect(findContactChannelCalls.length).toBe(0);
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
test("real unknown stranger (no resolutionFailed) still redeems via intercept", async () => {
|
|
294
|
+
inviteTokenForTest = "iv_token123";
|
|
295
|
+
const result = await enforceIngressAcl(
|
|
296
|
+
makeParams({
|
|
297
|
+
sourceMetadata: withVerdict({
|
|
298
|
+
trustClass: "unknown",
|
|
299
|
+
canonicalSenderId: "sender-1",
|
|
300
|
+
}),
|
|
301
|
+
}),
|
|
302
|
+
);
|
|
303
|
+
|
|
304
|
+
expect(result.earlyResponse!.inviteRedemption).toBe("redeemed");
|
|
305
|
+
expect(result.resolvedMember).toBeNull();
|
|
306
|
+
});
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
describe("enforceIngressAcl — deny copy names the gateway guardian", () => {
|
|
310
|
+
test("non-member deny reply uses the guardian displayName from the gateway list", async () => {
|
|
311
|
+
guardianDeliveryList = [
|
|
312
|
+
{
|
|
313
|
+
channelType: "vellum",
|
|
314
|
+
contactId: "c-1",
|
|
315
|
+
principalId: "p-anchor",
|
|
316
|
+
displayName: "Alice Guardian",
|
|
317
|
+
address: "p-anchor",
|
|
318
|
+
status: "active",
|
|
319
|
+
},
|
|
320
|
+
];
|
|
321
|
+
|
|
322
|
+
const result = await enforceIngressAcl(
|
|
323
|
+
makeParams({
|
|
324
|
+
sourceMetadata: withVerdict({
|
|
325
|
+
trustClass: "unknown",
|
|
326
|
+
canonicalSenderId: "stranger-1",
|
|
327
|
+
}),
|
|
328
|
+
}),
|
|
329
|
+
);
|
|
330
|
+
|
|
331
|
+
expect(result.earlyResponse!.reason).toBe("not_a_member");
|
|
332
|
+
const denyReply = deliverReplyCalls.find((c) =>
|
|
333
|
+
String((c.payload as { text?: string }).text ?? "").includes(
|
|
334
|
+
"tried talking to me",
|
|
335
|
+
),
|
|
336
|
+
);
|
|
337
|
+
expect(denyReply).toBeDefined();
|
|
338
|
+
expect((denyReply!.payload as { text: string }).text).toContain(
|
|
339
|
+
"Alice Guardian",
|
|
340
|
+
);
|
|
341
|
+
});
|
|
342
|
+
});
|
|
343
|
+
|
|
252
344
|
describe("enforceIngressAcl — fail-closed on malformed member verdict", () => {
|
|
253
345
|
test("member identity + unknown policy → not_a_member deny even under strangers", async () => {
|
|
254
346
|
const result = await enforceIngressAcl(
|