@vellumai/assistant 0.9.0 → 0.10.0-dev.202606192226.8ed8a6a
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/ARCHITECTURE.md +19 -35
- package/bun.lock +7 -8
- package/docs/activation-funnel-telemetry.md +28 -22
- package/docs/architecture/security.md +29 -28
- package/docs/stt-provider-onboarding.md +3 -5
- package/docs/workflows-testing.md +13 -44
- package/docs/workflows.md +3 -5
- package/node_modules/@vellumai/ces-client/src/__tests__/ces-client.test.ts +47 -0
- package/node_modules/@vellumai/ces-client/src/rpc-client.ts +28 -5
- package/node_modules/@vellumai/environments/src/seeds.ts +2 -5
- package/node_modules/@vellumai/gateway-client/src/admission-policy-contract.ts +97 -0
- package/node_modules/@vellumai/gateway-client/src/inbound-contract.ts +10 -0
- package/node_modules/@vellumai/gateway-client/src/index.ts +32 -6
- package/node_modules/@vellumai/gateway-client/src/outbound-contract.ts +119 -0
- package/node_modules/@vellumai/gateway-client/src/types.ts +15 -84
- package/openapi.yaml +1128 -119
- package/package.json +2 -1
- package/scripts/sync-llm-catalog.ts +6 -15
- package/scripts/sync-web-search-catalog.ts +3 -11
- package/src/__tests__/access-request-card-view.test.ts +98 -0
- package/src/__tests__/access-request-seed-content-blocks.test.ts +2 -4
- package/src/__tests__/actor-trust-resolver-address-fallback.test.ts +72 -32
- package/src/__tests__/agent-loop-compaction-strip.test.ts +241 -0
- package/src/__tests__/agent-loop-mutable-latest-user-message.test.ts +16 -13
- package/src/__tests__/agent-loop-output-hooks.test.ts +69 -0
- package/src/__tests__/agent-loop-override-profile.test.ts +25 -0
- package/src/__tests__/agent-loop-pushes-post-hook-prompt.test.ts +306 -0
- package/src/__tests__/always-loaded-tools-guard.test.ts +2 -3
- package/src/__tests__/app-compiler.test.ts +15 -1
- package/src/__tests__/app-dir-path-guard.test.ts +0 -1
- package/src/__tests__/approval-cascade.test.ts +6 -0
- package/src/__tests__/approval-routes-http.test.ts +128 -0
- package/src/__tests__/assistant-feature-flag-guard.test.ts +1 -4
- package/src/__tests__/assistant-feature-flag-guardrails.test.ts +0 -2
- package/src/__tests__/auth-fallback-events-store.test.ts +6 -14
- package/src/__tests__/avatar-identity-sync.test.ts +2 -27
- package/src/__tests__/btw-routes.test.ts +6 -8
- package/src/__tests__/call-pointer-messages.test.ts +28 -0
- package/src/__tests__/cancel-clears-processing.test.ts +89 -0
- package/src/__tests__/channel-approval-routes.test.ts +0 -4
- package/src/__tests__/channel-inbound-disk-pressure.test.ts +5 -15
- package/src/__tests__/checker.test.ts +0 -3
- package/src/__tests__/cli-memory-v2-reembed-skills.test.ts +3 -4
- package/src/__tests__/compaction-events.test.ts +6 -0
- package/src/__tests__/compactor-image-manifest-trust.test.ts +21 -1
- package/src/__tests__/compactor-summary-call-truncation.test.ts +223 -0
- package/src/__tests__/config-loader-backfill.test.ts +268 -27
- package/src/__tests__/config-schema.test.ts +35 -0
- package/src/__tests__/config-watcher.test.ts +0 -18
- package/src/__tests__/confirmation-request-guardian-bridge.test.ts +2 -2
- package/src/__tests__/contact-store-user-file.test.ts +0 -6
- package/src/__tests__/contacts-tools.test.ts +29 -0
- package/src/__tests__/conversation-abort-tool-results.test.ts +6 -0
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +22 -0
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +1 -0
- package/src/__tests__/conversation-agent-loop.test.ts +58 -0
- package/src/__tests__/conversation-attention-telegram.test.ts +0 -1
- package/src/__tests__/conversation-confirmation-signals.test.ts +6 -0
- package/src/__tests__/conversation-lifecycle.test.ts +7 -9
- package/src/__tests__/conversation-load-history-repair.test.ts +101 -0
- package/src/__tests__/conversation-process-callsite.test.ts +6 -0
- package/src/__tests__/conversation-provider-retry-repair.test.ts +6 -0
- package/src/__tests__/conversation-queue.test.ts +6 -0
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +15 -12
- package/src/__tests__/conversation-slash-queue.test.ts +6 -0
- package/src/__tests__/conversation-slash-unknown.test.ts +6 -0
- package/src/__tests__/conversation-speed-override.test.ts +6 -0
- package/src/__tests__/conversation-surfaces-activation-emit.test.ts +6 -3
- package/src/__tests__/conversation-title-service.test.ts +62 -0
- package/src/__tests__/conversation-workspace-cache-state.test.ts +6 -0
- package/src/__tests__/conversation-workspace-injection.test.ts +6 -0
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +6 -0
- package/src/__tests__/credential-broker.test.ts +449 -1
- package/src/__tests__/credential-execution-shell-lockdown.test.ts +18 -11
- package/src/__tests__/credential-execution-tools.test.ts +0 -1
- package/src/__tests__/credential-prompt-route.test.ts +4 -4
- package/src/__tests__/credential-routes.test.ts +360 -0
- package/src/__tests__/credential-security-invariants.test.ts +4 -13
- package/src/__tests__/disk-pressure-policy.test.ts +12 -0
- package/src/__tests__/disk-pressure-tools.test.ts +41 -1
- package/src/__tests__/disk-usage.test.ts +65 -0
- package/src/__tests__/document-tool-security.test.ts +9 -6
- package/src/__tests__/document-update-default-surface.test.ts +202 -0
- package/src/__tests__/dynamic-page-surface.test.ts +152 -1
- package/src/__tests__/fixtures/credential-security-fixtures.ts +2 -33
- package/src/__tests__/gateway-flag-listener.test.ts +110 -1
- package/src/__tests__/gateway-only-guard.test.ts +3 -7
- package/src/__tests__/gemini-count-tokens.test.ts +70 -0
- package/src/__tests__/guardian-binding-drift-heal.test.ts +1 -1
- package/src/__tests__/guardian-card-withdrawal.test.ts +403 -0
- package/src/__tests__/guardian-decision-primitive-canonical.test.ts +5 -3
- package/src/__tests__/guardian-grant-minting.test.ts +3 -35
- package/src/__tests__/guardian-routing-invariants.test.ts +64 -26
- package/src/__tests__/guardian-routing-state.test.ts +0 -1
- package/src/__tests__/headless-browser-mode.test.ts +10 -0
- package/src/__tests__/headless-browser-navigate.test.ts +8 -3
- package/src/__tests__/helpers/create-guardian-binding.ts +0 -1
- package/src/__tests__/host-browser-proxy.test.ts +87 -0
- package/src/__tests__/identity-routes.test.ts +0 -189
- package/src/__tests__/inbound-invite-redemption.test.ts +4 -4
- package/src/__tests__/injector-disk-pressure.test.ts +10 -5
- package/src/__tests__/injector-v3-suppression.test.ts +27 -20
- package/src/__tests__/internal-telemetry-routes.test.ts +6 -14
- package/src/__tests__/invite-redemption-service.test.ts +4 -7
- package/src/__tests__/llm-callsite-catalog.test.ts +5 -6
- package/src/__tests__/llm-catalog-parity.test.ts +30 -23
- package/src/__tests__/llm-resolver.test.ts +70 -24
- package/src/__tests__/llm-schema.test.ts +1 -0
- package/src/__tests__/managed-profile-guard.test.ts +163 -4
- package/src/__tests__/mcp-health-check.test.ts +6 -7
- package/src/__tests__/media-stream-server-integration.test.ts +317 -13
- package/src/__tests__/oauth-provider-seed-logos.test.ts +4 -6
- package/src/__tests__/onboarding-persona-write.test.ts +1 -1
- package/src/__tests__/path-policy.test.ts +34 -0
- package/src/__tests__/persona-resolver.test.ts +49 -14
- package/src/__tests__/plugin-api-model-profiles.test.ts +178 -0
- package/src/__tests__/plugin-api-provider.test.ts +24 -0
- package/src/__tests__/plugin-tool-contribution.test.ts +6 -3
- package/src/__tests__/post-compaction-reinjection-idempotency.test.ts +214 -0
- package/src/__tests__/provider-send-message-override-profile.test.ts +76 -0
- package/src/__tests__/reaction-persistence.test.ts +150 -29
- package/src/__tests__/registry.test.ts +2 -7
- package/src/__tests__/relay-server.test.ts +285 -0
- package/src/__tests__/runtime-attachment-metadata.test.ts +0 -1
- package/src/__tests__/schedule-routes-workflow-validation.test.ts +1 -10
- package/src/__tests__/schedule-routes.test.ts +0 -30
- package/src/__tests__/schedule-tools.test.ts +2 -18
- package/src/__tests__/scheduler-reuse-conversation.test.ts +8 -5
- package/src/__tests__/secret-response-routing.test.ts +35 -0
- package/src/__tests__/secret-routes-platform-proxy.test.ts +16 -2
- package/src/__tests__/skill-execute-input.test.ts +177 -1
- package/src/__tests__/skill-load-tool.test.ts +72 -0
- package/src/__tests__/skill-runtime-path.test.ts +2 -3
- package/src/__tests__/skills.test.ts +51 -0
- package/src/__tests__/slack-notification-approval-card.test.ts +176 -0
- package/src/__tests__/slack-reaction-canonical-approval.test.ts +285 -0
- package/src/__tests__/subagent-tools.test.ts +266 -0
- package/src/__tests__/surface-completion-nudge-hook.test.ts +367 -0
- package/src/__tests__/system-storage-cleanup-skill.test.ts +56 -0
- package/src/__tests__/task-progress-nudge-hook.test.ts +1 -1
- package/src/__tests__/title-generate-hook.test.ts +100 -3
- package/src/__tests__/token-estimator-accuracy.benchmark.test.ts +1 -29
- package/src/__tests__/token-manager.test.ts +519 -0
- package/src/__tests__/tool-approval-seed-content-blocks.test.ts +1 -1
- package/src/__tests__/tool-audit-listener.test.ts +7 -7
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +6 -3
- package/src/__tests__/tool-executor.test.ts +0 -79
- package/src/__tests__/trusted-contact-approval-notifier.test.ts +4 -2
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +220 -3
- package/src/__tests__/trusted-contact-multichannel.test.ts +3 -3
- package/src/__tests__/trusted-contact-verification.test.ts +8 -10
- package/src/__tests__/twilio-routes.test.ts +81 -1
- package/src/__tests__/voice-invite-redemption.test.ts +2 -3
- package/src/__tests__/weak-open-model.test.ts +30 -0
- package/src/__tests__/web-search-catalog-parity.test.ts +6 -25
- package/src/__tests__/workspace-greetings.test.ts +152 -0
- package/src/__tests__/workspace-migration-105-enable-memory-v3-live-for-new-workspaces.test.ts +149 -0
- package/src/__tests__/workspace-migration-108-drop-balanced-economy-profile.test.ts +285 -0
- package/src/__tests__/workspace-migration-add-send-diagnostics.test.ts +1 -1
- package/src/__tests__/workspace-migration-drop-collect-usage-data.test.ts +118 -0
- package/src/__tests__/workspace-migration-drop-send-diagnostics.test.ts +118 -0
- package/src/a2a/__tests__/e2e-a2a-channel.test.ts +0 -4
- package/src/agent/loop.ts +75 -29
- package/src/api/README.md +6 -6
- package/src/api/events/tool-result.ts +6 -0
- package/src/api/events/workflow-completed.ts +53 -0
- package/src/api/events/workflow-leaf-finished.ts +38 -0
- package/src/api/events/workflow-leaf-started.ts +35 -0
- package/src/api/events/workflow-progress.ts +32 -0
- package/src/api/events/workflow-started.ts +31 -0
- package/src/api/index.ts +40 -0
- package/src/api/responses/conversation-message.ts +28 -4
- package/src/api/responses/home.ts +26 -4
- package/src/api/responses/workflow-journal.ts +53 -0
- package/src/approvals/guardian-card-withdrawal.ts +145 -0
- package/src/approvals/guardian-decision-primitive.ts +26 -3
- package/src/approvals/guardian-request-resolvers.ts +183 -80
- package/src/calls/__tests__/channel-admission-reader.test.ts +132 -0
- package/src/calls/__tests__/relay-setup-router.test.ts +350 -0
- package/src/calls/call-pointer-messages.ts +10 -4
- package/src/calls/channel-admission-reader.ts +104 -0
- package/src/calls/guardian-dispatch.ts +17 -45
- package/src/calls/media-stream-server.ts +84 -2
- package/src/calls/relay-access-wait.ts +1 -1
- package/src/calls/relay-server.ts +66 -0
- package/src/calls/relay-setup-router.ts +82 -1
- package/src/calls/twilio-routes.ts +17 -8
- package/src/calls/voice-session-bridge.ts +2 -2
- package/src/cli/commands/clients.ts +3 -0
- package/src/cli/commands/db/status.ts +37 -3
- package/src/cli/commands/{__tests__ → memory/__tests__}/memory-v2-compare-render.test.ts +1 -1
- package/src/cli/commands/{__tests__ → memory/__tests__}/memory-v2.test.ts +8 -7
- package/src/cli/commands/{__tests__ → memory/__tests__}/memory-v3.test.ts +5 -4
- package/src/cli/commands/memory/index.ts +30 -0
- package/src/cli/commands/{memory-v2-compare-render.ts → memory/memory-v2-compare-render.ts} +1 -1
- package/src/cli/commands/{memory-v2.ts → memory/memory-v2.ts} +6 -15
- package/src/cli/commands/{memory-v3.ts → memory/memory-v3.ts} +97 -11
- package/src/cli/commands/oauth/status.test.ts +36 -0
- package/src/cli/commands/oauth/status.ts +23 -3
- package/src/cli/commands/plugins.ts +400 -14
- package/src/cli/lib/__tests__/diff-plugin.test.ts +443 -0
- package/src/cli/lib/__tests__/inspect-plugin.test.ts +54 -0
- package/src/cli/lib/__tests__/install-from-github.test.ts +31 -0
- package/src/cli/lib/__tests__/merge-plugin-tree.test.ts +443 -0
- package/src/cli/lib/__tests__/plugin-pin-history.test.ts +162 -0
- package/src/cli/lib/__tests__/plugin-surfaces.test.ts +111 -0
- package/src/cli/lib/__tests__/upgrade-plugin.test.ts +295 -2
- package/src/cli/lib/diff-plugin.ts +346 -0
- package/src/cli/lib/inspect-plugin.ts +12 -1
- package/src/cli/lib/install-from-github.ts +128 -19
- package/src/cli/lib/merge-plugin-tree.ts +328 -0
- package/src/cli/lib/plugin-fingerprint.ts +14 -0
- package/src/cli/lib/plugin-marketplace.ts +11 -0
- package/src/cli/lib/plugin-pin-history.ts +257 -0
- package/src/cli/lib/plugin-surfaces.ts +104 -0
- package/src/cli/lib/upgrade-plugin.ts +298 -10
- package/src/cli/program.ts +2 -6
- package/src/config/__tests__/sync-gated-profiles.test.ts +368 -0
- package/src/config/assistant-feature-flags.ts +22 -7
- package/src/config/bundled-skills/contacts/tools/contact-search.ts +0 -1
- package/src/config/bundled-skills/document-editor/SKILL.md +3 -3
- package/src/config/bundled-skills/document-editor/TOOLS.json +2 -2
- package/src/config/bundled-skills/messaging/SKILL.md +6 -4
- package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +9 -8
- package/src/config/bundled-skills/subagent/SKILL.md +4 -0
- package/src/config/bundled-skills/subagent/TOOLS.json +4 -0
- package/src/config/bundled-skills/system-storage-cleanup/SKILL.md +74 -0
- package/src/config/bundled-skills/workflows/SKILL.md +14 -8
- package/src/config/bundled-tool-registry.ts +2 -7
- package/src/config/call-site-defaults.ts +15 -2
- package/src/config/feature-flag-registry.json +46 -31
- package/src/config/inference-profile-validation.ts +26 -0
- package/src/config/llm-resolver.ts +3 -0
- package/src/config/loader.ts +4 -0
- package/src/config/memory-v3-gate.ts +11 -0
- package/src/config/profile-order.ts +28 -0
- package/src/config/schema.ts +8 -6
- package/src/config/schemas/__tests__/memory-v3.test.ts +1 -0
- package/src/config/schemas/call-site-catalog.ts +7 -0
- package/src/config/schemas/channels.ts +11 -0
- package/src/config/schemas/elevenlabs.ts +0 -1
- package/src/config/schemas/llm.ts +31 -0
- package/src/config/schemas/memory-lifecycle.ts +3 -7
- package/src/config/schemas/memory-v3.ts +6 -0
- package/src/config/schemas/platform.ts +0 -8
- package/src/config/schemas/services.ts +18 -0
- package/src/config/seed-inference-profiles.ts +109 -44
- package/src/config/skills.ts +21 -0
- package/src/config/sync-gated-profiles.ts +220 -0
- package/src/contacts/contact-store.ts +89 -106
- package/src/contacts/contacts-write.ts +5 -22
- package/src/contacts/types.ts +0 -1
- package/src/context/compactor.ts +88 -54
- package/src/context/strip-injections.ts +58 -10
- package/src/context/token-estimator.ts +1 -1
- package/src/credential-execution/process-manager.ts +55 -14
- package/src/credential-execution/prompted-credential.ts +2 -3
- package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +3 -2
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +44 -0
- package/src/daemon/config-watcher.ts +0 -4
- package/src/daemon/conversation-agent-loop-handlers.ts +2 -0
- package/src/daemon/conversation-agent-loop.ts +114 -22
- package/src/daemon/conversation-history.ts +1 -1
- package/src/daemon/conversation-lifecycle.ts +3 -5
- package/src/daemon/conversation-process.ts +13 -5
- package/src/daemon/conversation-runtime-assembly.ts +13 -15
- package/src/daemon/conversation-slash.ts +2 -23
- package/src/daemon/conversation-surfaces.ts +26 -0
- package/src/daemon/conversation-tool-setup.ts +53 -19
- package/src/daemon/conversation.ts +131 -20
- package/src/daemon/disk-pressure-policy.ts +5 -3
- package/src/daemon/handlers/__tests__/config-a2a-complete.test.ts +0 -1
- package/src/daemon/handlers/__tests__/config-a2a-redeem.test.ts +0 -1
- package/src/daemon/handlers/config-a2a.ts +0 -2
- package/src/daemon/handlers/config-channels.ts +15 -16
- package/src/daemon/handlers/config-slack-channel.ts +22 -3
- package/src/daemon/handlers/conversations.ts +107 -0
- package/src/daemon/host-browser-proxy.ts +41 -0
- package/src/daemon/lifecycle.ts +55 -27
- package/src/daemon/memory-v2-startup.test.ts +131 -0
- package/src/daemon/memory-v2-startup.ts +100 -1
- package/src/daemon/message-provenance.ts +2 -0
- package/src/daemon/message-types/contacts.ts +0 -1
- package/src/daemon/message-types/conversations.ts +3 -3
- package/src/daemon/message-types/sync.ts +0 -1
- package/src/daemon/message-types/web-activity.ts +7 -1
- package/src/daemon/message-types/workflows.ts +83 -1
- package/src/daemon/orphan-reaper.test.ts +0 -19
- package/src/daemon/orphan-reaper.ts +2 -24
- package/src/daemon/server.ts +0 -10
- package/src/daemon/tool-setup-types.ts +4 -0
- package/src/daemon/trust-context.ts +1 -1
- package/src/daemon/wake-conversation-ops.ts +1 -0
- package/src/events/tool-audit-listener.ts +2 -2
- package/src/home/feed-source-enrichment.test.ts +151 -0
- package/src/home/feed-source-enrichment.ts +176 -0
- package/src/home/relationship-state.ts +2 -4
- package/src/instrument.ts +18 -6
- package/src/ipc/__tests__/binary-result-ipc.test.ts +81 -0
- package/src/ipc/__tests__/clients-list-ipc.test.ts +20 -0
- package/src/ipc/assistant-server.ts +37 -4
- package/src/ipc/gateway-flag-listener.ts +18 -2
- package/src/memory/__tests__/auto-analysis-enqueue.test.ts +5 -16
- package/src/memory/__tests__/db-logs-attach.test.ts +122 -0
- package/src/memory/__tests__/jobs-store-enqueue-gate.test.ts +7 -11
- package/src/memory/__tests__/memory-retrospective-enqueue.test.ts +37 -7
- package/src/memory/__tests__/memory-retrospective-job.test.ts +229 -401
- package/src/memory/__tests__/onboarding-events-store.test.ts +7 -7
- package/src/memory/auth-fallback-events-store.ts +2 -2
- package/src/memory/auto-analysis-enqueue.ts +3 -5
- package/src/memory/bookmark-crud.ts +1 -2
- package/src/memory/canonical-guardian-store.ts +39 -1
- package/src/memory/conversation-crud.ts +9 -4
- package/src/memory/conversation-key-store.ts +17 -2
- package/src/memory/conversation-title-service.ts +64 -7
- package/src/memory/db-async-query.ts +20 -2
- package/src/memory/db-connection.ts +49 -5
- package/src/memory/db-init.ts +17 -17
- package/src/memory/embedding-backend.ts +38 -1
- package/src/memory/embedding-billing-breaker.ts +96 -0
- package/src/memory/jobs-store.ts +25 -13
- package/src/memory/jobs-worker.ts +54 -1
- package/src/memory/lifecycle-events-store.ts +2 -2
- package/src/memory/memory-retrospective-constants.ts +4 -4
- package/src/memory/memory-retrospective-enqueue.ts +31 -6
- package/src/memory/memory-retrospective-job.ts +28 -227
- package/src/memory/migrations/129-contact-channels-access-fields.ts +18 -9
- package/src/memory/migrations/131-drop-legacy-member-guardian-tables.ts +14 -2
- package/src/memory/migrations/289-contact-channels-unique-ext-user.ts +10 -0
- package/src/memory/migrations/291-contact-channels-renormalize-addresses.ts +72 -0
- package/src/memory/migrations/292-schedule-default-no-reuse-conversation.test.ts +67 -0
- package/src/memory/migrations/292-schedule-default-no-reuse-conversation.ts +25 -0
- package/src/memory/migrations/293-workflow-journal-leaf-tokens.ts +32 -0
- package/src/memory/migrations/294-drop-external-user-id.ts +31 -0
- package/src/memory/migrations/295-drop-approval-prompt-ts-tracker.ts +20 -0
- package/src/memory/migrations/296-rewrite-balanced-economy-profile-pins.test.ts +110 -0
- package/src/memory/migrations/296-rewrite-balanced-economy-profile-pins.ts +68 -0
- package/src/memory/migrations/__tests__/131-drop-legacy-member-guardian-tables.test.ts +154 -0
- package/src/memory/migrations/__tests__/289-contact-channels-unique-ext-user.test.ts +31 -0
- package/src/memory/migrations/__tests__/291-contact-channels-renormalize-addresses.test.ts +341 -0
- package/src/memory/migrations/__tests__/run-migrations.test.ts +52 -0
- package/src/memory/migrations/index.ts +6 -0
- package/src/memory/migrations/run-migrations.ts +41 -0
- package/src/memory/migrations/validate-migration-state.ts +1 -1
- package/src/memory/onboarding-events-store.ts +3 -3
- package/src/memory/schema/contacts.ts +0 -5
- package/src/memory/skill-loaded-events-store.test.ts +7 -15
- package/src/memory/skill-loaded-events-store.ts +2 -2
- package/src/memory/tool-executed-events-store.test.ts +7 -7
- package/src/memory/turn-trace-store.test.ts +736 -0
- package/src/memory/turn-trace-store.ts +364 -0
- package/src/memory/v2/__tests__/consolidation-job.test.ts +8 -0
- package/src/memory/v2/__tests__/skill-content.test.ts +30 -0
- package/src/memory/v2/consolidation-job.ts +2 -2
- package/src/memory/v2/skill-content.ts +25 -7
- package/src/memory/v2/skill-store.ts +7 -1
- package/src/memory/v3-eval/__tests__/eval-packets.test.ts +248 -0
- package/src/memory/v3-eval/eval-packets.ts +546 -0
- package/src/messaging/providers/slack/adapter.ts +1 -1
- package/src/messaging/providers/slack/api.ts +31 -0
- package/src/messaging/providers/slack/send.test.ts +114 -2
- package/src/messaging/providers/slack/send.ts +30 -7
- package/src/messaging/providers/slack/withdraw.test.ts +200 -0
- package/src/messaging/providers/slack/withdraw.ts +161 -0
- package/src/notifications/AGENTS.md +2 -0
- package/src/notifications/access-request-copy.ts +72 -59
- package/src/notifications/adapters/shared.ts +29 -0
- package/src/notifications/adapters/slack.ts +58 -103
- package/src/notifications/adapters/telegram.ts +2 -20
- package/src/notifications/approval-card-data.ts +333 -0
- package/src/notifications/broadcaster.ts +16 -3
- package/src/notifications/canonical-delivery-recorder.ts +139 -0
- package/src/notifications/copy-composer.ts +3 -3
- package/src/notifications/decision-engine.ts +4 -2
- package/src/notifications/destination-resolver.ts +4 -6
- package/src/notifications/guardian-question-mode.ts +10 -0
- package/src/notifications/home-feed-side-effect.ts +7 -16
- package/src/notifications/notification-utils.ts +19 -20
- package/src/notifications/signal.ts +79 -43
- package/src/notifications/types.ts +98 -121
- package/src/oauth/AGENTS.md +5 -24
- package/src/permissions/checker.test.ts +51 -0
- package/src/permissions/checker.ts +185 -26
- package/src/permissions/ipc-risk-types.ts +24 -0
- package/src/permissions/question-prompter.test.ts +27 -0
- package/src/permissions/question-prompter.ts +4 -0
- package/src/permissions/secret-prompter.ts +15 -1
- package/src/platform/client.test.ts +119 -0
- package/src/platform/client.ts +66 -0
- package/src/platform/consent-cache.test.ts +267 -0
- package/src/platform/consent-cache.ts +174 -0
- package/src/plugin-api/constants.ts +1 -1
- package/src/plugin-api/index.ts +33 -1
- package/src/plugin-api/model-profiles.ts +33 -0
- package/src/plugin-api/types.ts +50 -2
- package/src/plugins/defaults/advisor/__tests__/advisor-gate.test.ts +56 -0
- package/src/plugins/defaults/advisor/__tests__/advisor-state-store.test.ts +43 -0
- package/src/plugins/defaults/advisor/__tests__/agent-loop-integration.test.ts +137 -0
- package/src/plugins/defaults/advisor/__tests__/consult.test.ts +153 -0
- package/src/plugins/defaults/advisor/__tests__/hooks.test.ts +138 -0
- package/src/plugins/defaults/advisor/__tests__/transcript.test.ts +147 -0
- package/src/plugins/defaults/advisor/advisor-gate.ts +29 -0
- package/src/plugins/defaults/advisor/advisor-state-store.ts +94 -0
- package/src/plugins/defaults/advisor/config.ts +21 -0
- package/src/plugins/defaults/advisor/consult.ts +93 -0
- package/src/plugins/defaults/advisor/hooks/post-model-call.ts +34 -0
- package/src/plugins/defaults/advisor/hooks/pre-model-call.ts +30 -0
- package/src/plugins/defaults/advisor/hooks/user-prompt-submit.ts +19 -0
- package/src/plugins/defaults/advisor/package.json +14 -0
- package/src/plugins/defaults/advisor/steering.ts +67 -0
- package/src/plugins/defaults/advisor/tools/advisor.ts +65 -0
- package/src/plugins/defaults/advisor/transcript.ts +76 -0
- package/src/plugins/defaults/compaction/window-manager.ts +18 -0
- package/src/plugins/defaults/index.ts +60 -0
- package/src/plugins/defaults/memory-retrieval/hooks/post-compact.ts +22 -9
- package/src/plugins/defaults/memory-retrieval/hooks/user-prompt-submit.ts +2 -2
- package/src/plugins/defaults/memory-retrieval/injectors.ts +4 -4
- package/src/plugins/defaults/memory-retrieval/tail-reinjection-strip.ts +64 -0
- package/src/plugins/defaults/memory-retrieval/unified-turn-context.ts +29 -21
- package/src/plugins/defaults/memory-v3-shadow/__tests__/carry-integration.test.ts +1 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/injection.test.ts +1 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/maintain-job.test.ts +129 -9
- package/src/plugins/defaults/memory-v3-shadow/__tests__/orchestrate.test.ts +31 -4
- package/src/plugins/defaults/memory-v3-shadow/__tests__/selection-log-store.test.ts +77 -2
- package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-plugin.test.ts +1 -0
- package/src/plugins/defaults/memory-v3-shadow/injector.ts +7 -10
- package/src/plugins/defaults/memory-v3-shadow/maintain-job.ts +144 -11
- package/src/plugins/defaults/memory-v3-shadow/orchestrate.ts +32 -20
- package/src/plugins/defaults/memory-v3-shadow/selection-log-store.ts +56 -3
- package/src/plugins/defaults/memory-v3-shadow/shadow-plugin.ts +23 -2
- package/src/plugins/defaults/surface-completion-nudge/hooks/post-model-call.ts +276 -0
- package/src/plugins/defaults/surface-completion-nudge/hooks/stop.ts +22 -0
- package/src/plugins/defaults/surface-completion-nudge/nudge-state-store.ts +46 -0
- package/src/plugins/defaults/surface-completion-nudge/package.json +14 -0
- package/src/plugins/defaults/task-progress-nudge/hooks/post-tool-use.ts +3 -13
- package/src/plugins/defaults/title-generate/hooks/stop.ts +56 -21
- package/src/prompts/persona-resolver.ts +14 -4
- package/src/prompts/templates/system-sections.ts +7 -2
- package/src/providers/__tests__/count-tokens-forwarding.test.ts +98 -0
- package/src/providers/__tests__/provider-env-vars.test.ts +6 -0
- package/src/providers/__tests__/provider-secret-catalog.test.ts +1 -0
- package/src/providers/__tests__/retry-callsite.test.ts +176 -0
- package/src/providers/anthropic/client.ts +230 -175
- package/src/providers/atlascloud/client.ts +85 -0
- package/src/providers/call-site-routing.ts +10 -0
- package/src/providers/fetch-provider-catalog.ts +85 -0
- package/src/providers/gemini/client.ts +43 -0
- package/src/providers/inference/adapter-factory.ts +3 -0
- package/src/providers/model-catalog.ts +58 -0
- package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +33 -0
- package/src/providers/openai/chat-completions-provider.ts +7 -0
- package/src/providers/openai/responses-provider.ts +10 -0
- package/src/providers/provider-send-message.ts +11 -3
- package/src/providers/ratelimit.ts +9 -0
- package/src/providers/retry.ts +62 -12
- package/src/providers/search-provider-catalog.ts +10 -0
- package/src/providers/types.ts +16 -0
- package/src/providers/usage-tracking.ts +7 -0
- package/src/providers/weak-open-model.ts +22 -0
- package/src/runtime/AGENTS.md +0 -1
- package/src/runtime/__tests__/agent-wake.test.ts +227 -0
- package/src/runtime/__tests__/client-health.test.ts +44 -0
- package/src/runtime/access-request-helper.ts +21 -53
- package/src/runtime/actor-trust-resolver.ts +59 -63
- package/src/runtime/agent-wake.ts +71 -0
- package/src/runtime/assistant-event-hub.ts +18 -4
- package/src/runtime/auth/__tests__/route-policy.test.ts +12 -0
- package/src/runtime/auth/require-bound-guardian.ts +1 -4
- package/src/runtime/btw-sidechain.ts +3 -6
- package/src/runtime/capabilities.test.ts +120 -0
- package/src/runtime/capabilities.ts +197 -0
- package/src/runtime/channel-approval-types.ts +22 -45
- package/src/runtime/channel-invite-transports/telegram.ts +4 -4
- package/src/runtime/channel-retry-sweep.ts +1 -0
- package/src/runtime/channel-verification-service.ts +3 -3
- package/src/runtime/client-health.ts +26 -0
- package/src/runtime/confirmation-request-guardian-bridge.ts +38 -29
- package/src/runtime/effective-capabilities.test.ts +128 -0
- package/src/runtime/effective-capabilities.ts +84 -0
- package/src/runtime/guardian-reply-router.ts +106 -21
- package/src/runtime/invite-redemption-service.ts +9 -25
- package/src/runtime/migrations/__tests__/vbundle-builder-fd-leak.test.ts +126 -0
- package/src/runtime/migrations/vbundle-builder.ts +49 -20
- package/src/runtime/pending-interactions.ts +35 -0
- package/src/runtime/routes/__tests__/client-routes.test.ts +13 -0
- package/src/runtime/routes/__tests__/conversation-management-routes.test.ts +67 -0
- package/src/runtime/routes/__tests__/plugins-routes.test.ts +383 -1
- package/src/runtime/routes/app-routes.ts +1 -1
- package/src/runtime/routes/approval-routes.ts +40 -9
- package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +2 -2
- package/src/runtime/routes/assets/vellum-design-system.css +1959 -0
- package/src/runtime/routes/browser-tabs-routes.ts +9 -0
- package/src/runtime/routes/btw-routes.ts +1 -27
- package/src/runtime/routes/canonical-guardian-expiry-sweep.ts +17 -8
- package/src/runtime/routes/client-routes.ts +10 -0
- package/src/runtime/routes/contact-routes.ts +31 -8
- package/src/runtime/routes/conversation-compaction-routes.ts +1 -1
- package/src/runtime/routes/conversation-management-routes.ts +80 -1
- package/src/runtime/routes/conversation-query-routes.ts +68 -22
- package/src/runtime/routes/conversation-routes.ts +39 -14
- package/src/runtime/routes/credential-routes.ts +40 -16
- package/src/runtime/routes/empty-state-greeting-cache.ts +1 -2
- package/src/runtime/routes/events-routes.ts +1 -3
- package/src/runtime/routes/guardian-approval-interception.ts +14 -73
- package/src/runtime/routes/guardian-approval-prompt.ts +22 -4
- package/src/runtime/routes/home-feed-routes.ts +8 -3
- package/src/runtime/routes/identity-routes.ts +1 -296
- package/src/runtime/routes/inbound-message-handler.ts +214 -228
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +89 -7
- package/src/runtime/routes/inbound-stages/admission-policy.test.ts +154 -0
- package/src/runtime/routes/inbound-stages/admission-policy.ts +140 -0
- package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +3 -3
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +11 -6
- package/src/runtime/routes/inbound-stages/escalation-intercept.ts +1 -2
- package/src/runtime/routes/inbound-stages/guardian-activation-intercept.ts +1 -2
- package/src/runtime/routes/inbound-stages/guardian-reply-intercept.test.ts +7 -7
- package/src/runtime/routes/inbound-stages/guardian-reply-intercept.ts +47 -28
- package/src/runtime/routes/inbound-stages/reaction-intercept.ts +358 -0
- package/src/runtime/routes/index.ts +2 -0
- package/src/runtime/routes/integrations/slack/__tests__/channel.test.ts +8 -0
- package/src/runtime/routes/integrations/slack/channel.ts +36 -0
- package/src/runtime/routes/internal-telemetry-routes.ts +1 -1
- package/src/runtime/routes/mcp-auth-routes.ts +233 -41
- package/src/runtime/routes/memory-eval-routes.ts +87 -0
- package/src/runtime/routes/notification-routes.ts +122 -133
- package/src/runtime/routes/platform-routes.ts +2 -2
- package/src/runtime/routes/plugins-routes.ts +366 -11
- package/src/runtime/routes/schedule-routes.ts +0 -22
- package/src/runtime/routes/secret-routes.ts +15 -0
- package/src/runtime/routes/surface-action-routes.ts +2 -1
- package/src/runtime/routes/tool-call-question-enrichment.test.ts +146 -0
- package/src/runtime/routes/tool-call-question-enrichment.ts +66 -0
- package/src/runtime/routes/workflow-routes.test.ts +229 -44
- package/src/runtime/routes/workflow-routes.ts +131 -29
- package/src/runtime/routes/workspace-greetings.ts +55 -0
- package/src/runtime/sync/resource-sync-events.ts +1 -11
- package/src/runtime/tool-grant-request-helper.ts +18 -16
- package/src/runtime/trust-context-resolver.ts +8 -5
- package/src/schedule/inference-profile.ts +2 -14
- package/src/schedule/schedule-store.ts +1 -1
- package/src/schedule/scheduler-types.ts +5 -1
- package/src/security/__tests__/provider-key-env-fallback.test.ts +6 -0
- package/src/security/secret-patterns.ts +3 -0
- package/src/subagent/manager.ts +17 -4
- package/src/subagent/types.ts +6 -0
- package/src/telemetry/trace-collection-policy.test.ts +28 -0
- package/src/telemetry/trace-collection-policy.ts +30 -0
- package/src/telemetry/types.ts +89 -0
- package/src/telemetry/usage-telemetry-reporter.test.ts +586 -36
- package/src/telemetry/usage-telemetry-reporter.ts +148 -41
- package/src/tools/AGENTS.md +3 -3
- package/src/tools/browser/__tests__/browser-execution-acquire.test.ts +31 -0
- package/src/tools/browser/browser-execution.ts +30 -19
- package/src/tools/document/document-tool.ts +30 -6
- package/src/tools/executor.ts +5 -3
- package/src/tools/host-terminal/host-shell.ts +5 -4
- package/src/tools/memory/register.ts +2 -2
- package/src/tools/network/__tests__/web-fetch-firecrawl.test.ts +360 -0
- package/src/tools/network/__tests__/web-search.test.ts +143 -0
- package/src/tools/network/web-fetch.ts +372 -1
- package/src/tools/network/web-search-error.ts +1 -1
- package/src/tools/network/web-search.ts +213 -10
- package/src/tools/permission-checker.ts +4 -3
- package/src/tools/registry.ts +20 -0
- package/src/tools/schedule/create.ts +7 -12
- package/src/tools/schedule/update.ts +4 -11
- package/src/tools/shared/filesystem/path-policy.ts +39 -13
- package/src/tools/side-effects.ts +2 -17
- package/src/tools/skills/execute.ts +99 -2
- package/src/tools/skills/load.ts +43 -2
- package/src/tools/subagent/spawn.ts +64 -15
- package/src/tools/terminal/shell.ts +10 -4
- package/src/tools/tool-approval-handler.ts +18 -13
- package/src/tools/tool-manifest.ts +0 -2
- package/src/tools/types.ts +10 -0
- package/src/tools/ui-surface/definitions.ts +64 -3
- package/src/tools/verification-control-plane-policy.ts +3 -1
- package/src/tools/workflows/run-workflow.test.ts +8 -18
- package/src/tools/workflows/run-workflow.ts +1 -0
- package/src/util/disk-usage.ts +78 -23
- package/src/util/logs-db-path.ts +22 -0
- package/src/util/platform.ts +10 -3
- package/src/watcher/telemetry.ts +2 -2
- package/src/workflows/capabilities.ts +2 -3
- package/src/workflows/engine.test.ts +175 -1
- package/src/workflows/engine.ts +82 -0
- package/src/workflows/journal-store.test.ts +70 -0
- package/src/workflows/journal-store.ts +18 -3
- package/src/workflows/run-manager.test.ts +171 -28
- package/src/workflows/run-manager.ts +66 -24
- package/src/workspace/migrations/105-enable-memory-v3-live-for-new-workspaces.ts +63 -0
- package/src/workspace/migrations/106-drop-collect-usage-data.ts +47 -0
- package/src/workspace/migrations/107-drop-send-diagnostics.ts +47 -0
- package/src/workspace/migrations/108-drop-balanced-economy-profile.ts +129 -0
- package/src/workspace/migrations/registry.ts +8 -0
- package/src/__tests__/app-control-no-global-cgevent.test.ts +0 -98
- package/src/__tests__/credential-security-e2e.test.ts +0 -362
- package/src/__tests__/credential-vault-unit.test.ts +0 -1528
- package/src/__tests__/credential-vault.test.ts +0 -1706
- package/src/__tests__/identity-intro-cache.test.ts +0 -315
- package/src/__tests__/secret-onetime-send.test.ts +0 -182
- package/src/cli/commands/__tests__/task.test.ts +0 -914
- package/src/cli/commands/task.ts +0 -771
- package/src/config/bundled-skills/personal-page/SKILL.md +0 -57
- package/src/config/bundled-skills/personal-page/TOOLS.json +0 -27
- package/src/config/bundled-skills/personal-page/tools/app-refresh.ts +0 -17
- package/src/config/preloaded-apps/personal-page/src/components/About.tsx +0 -22
- package/src/config/preloaded-apps/personal-page/src/components/App.tsx +0 -16
- package/src/config/preloaded-apps/personal-page/src/components/Features.tsx +0 -77
- package/src/config/preloaded-apps/personal-page/src/components/Hero.tsx +0 -57
- package/src/config/preloaded-apps/personal-page/src/components/Pending.tsx +0 -28
- package/src/config/preloaded-apps/personal-page/src/components/animations.tsx +0 -234
- package/src/config/preloaded-apps/personal-page/src/components/icons.tsx +0 -48
- package/src/config/preloaded-apps/personal-page/src/components/media.ts +0 -16
- package/src/config/preloaded-apps/personal-page/src/index.html +0 -20
- package/src/config/preloaded-apps/personal-page/src/main.tsx +0 -7
- package/src/config/preloaded-apps/personal-page/src/profile-data.ts +0 -82
- package/src/config/preloaded-apps/personal-page/src/styles.css +0 -759
- package/src/memory/__tests__/preloaded-apps.test.ts +0 -85
- package/src/memory/preloaded-apps.ts +0 -116
- package/src/notifications/tool-approval-copy.ts +0 -142
- package/src/runtime/routes/approval-prompt-ts-tracker.ts +0 -78
- package/src/runtime/routes/identity-intro-cache.ts +0 -172
- package/src/tools/credentials/vault.ts +0 -712
|
@@ -689,6 +689,82 @@ describe("standalone approval endpoints — HTTP layer", () => {
|
|
|
689
689
|
await stopServer();
|
|
690
690
|
});
|
|
691
691
|
|
|
692
|
+
test("cancels a secret request when value is omitted", async () => {
|
|
693
|
+
let secretRequestId: string | undefined;
|
|
694
|
+
let secretValue: string | undefined;
|
|
695
|
+
|
|
696
|
+
const session = makeIdleSession({
|
|
697
|
+
onSecret: (reqId, val) => {
|
|
698
|
+
secretRequestId = reqId;
|
|
699
|
+
secretValue = val;
|
|
700
|
+
},
|
|
701
|
+
});
|
|
702
|
+
|
|
703
|
+
await startServer(() => session);
|
|
704
|
+
|
|
705
|
+
pendingInteractions.register("secret-cancel-1", {
|
|
706
|
+
conversationId: "conv-1",
|
|
707
|
+
kind: "secret",
|
|
708
|
+
});
|
|
709
|
+
|
|
710
|
+
const res = await fetch(url("secret"), {
|
|
711
|
+
method: "POST",
|
|
712
|
+
headers: { "Content-Type": "application/json", ...AUTH_HEADERS },
|
|
713
|
+
body: JSON.stringify({ requestId: "secret-cancel-1" }),
|
|
714
|
+
});
|
|
715
|
+
const body = (await res.json()) as { accepted: boolean };
|
|
716
|
+
|
|
717
|
+
expect(res.status).toBe(200);
|
|
718
|
+
expect(body.accepted).toBe(true);
|
|
719
|
+
expect(secretRequestId).toBe("secret-cancel-1");
|
|
720
|
+
expect(secretValue).toBeUndefined();
|
|
721
|
+
expect(pendingInteractions.get("secret-cancel-1")).toBeUndefined();
|
|
722
|
+
|
|
723
|
+
await stopServer();
|
|
724
|
+
});
|
|
725
|
+
|
|
726
|
+
test('legacy delivery "none" cancels the request without 400', async () => {
|
|
727
|
+
let secretRequestId: string | undefined;
|
|
728
|
+
let secretValue: string | undefined;
|
|
729
|
+
let secretDelivery: string | undefined;
|
|
730
|
+
|
|
731
|
+
const session = makeIdleSession({
|
|
732
|
+
onSecret: (reqId, val, del) => {
|
|
733
|
+
secretRequestId = reqId;
|
|
734
|
+
secretValue = val;
|
|
735
|
+
secretDelivery = del;
|
|
736
|
+
},
|
|
737
|
+
});
|
|
738
|
+
|
|
739
|
+
await startServer(() => session);
|
|
740
|
+
|
|
741
|
+
pendingInteractions.register("secret-legacy-cancel-1", {
|
|
742
|
+
conversationId: "conv-1",
|
|
743
|
+
kind: "secret",
|
|
744
|
+
});
|
|
745
|
+
|
|
746
|
+
const res = await fetch(url("secret"), {
|
|
747
|
+
method: "POST",
|
|
748
|
+
headers: { "Content-Type": "application/json", ...AUTH_HEADERS },
|
|
749
|
+
body: JSON.stringify({
|
|
750
|
+
requestId: "secret-legacy-cancel-1",
|
|
751
|
+
value: "ignored-by-cancel",
|
|
752
|
+
delivery: "none",
|
|
753
|
+
}),
|
|
754
|
+
});
|
|
755
|
+
const body = (await res.json()) as { accepted: boolean };
|
|
756
|
+
|
|
757
|
+
expect(res.status).toBe(200);
|
|
758
|
+
expect(body.accepted).toBe(true);
|
|
759
|
+
expect(secretRequestId).toBe("secret-legacy-cancel-1");
|
|
760
|
+
// delivery "none" normalizes to the cancellation path: value/delivery dropped.
|
|
761
|
+
expect(secretValue).toBeUndefined();
|
|
762
|
+
expect(secretDelivery).toBeUndefined();
|
|
763
|
+
expect(pendingInteractions.get("secret-legacy-cancel-1")).toBeUndefined();
|
|
764
|
+
|
|
765
|
+
await stopServer();
|
|
766
|
+
});
|
|
767
|
+
|
|
692
768
|
test("rejects a non-secret requestId without consuming it", async () => {
|
|
693
769
|
/**
|
|
694
770
|
* /v1/secret only settles secret prompts. A confirmation (or any other
|
|
@@ -790,6 +866,58 @@ describe("standalone approval endpoints — HTTP layer", () => {
|
|
|
790
866
|
});
|
|
791
867
|
});
|
|
792
868
|
|
|
869
|
+
// ── GET /v1/pending-interactions ─────────────────────────────────────
|
|
870
|
+
|
|
871
|
+
describe("GET /v1/pending-interactions", () => {
|
|
872
|
+
test("returns full secret prompt metadata for a registered secret", async () => {
|
|
873
|
+
const session = makeIdleSession();
|
|
874
|
+
await startServer(() => session);
|
|
875
|
+
|
|
876
|
+
pendingInteractions.register("secret-meta-1", {
|
|
877
|
+
conversationId: "conv-meta",
|
|
878
|
+
kind: "secret",
|
|
879
|
+
secretDetails: {
|
|
880
|
+
service: "github",
|
|
881
|
+
field: "token",
|
|
882
|
+
label: "GitHub Token",
|
|
883
|
+
description: "Personal access token",
|
|
884
|
+
placeholder: "ghp_...",
|
|
885
|
+
purpose: "Push commits",
|
|
886
|
+
allowedTools: ["git_push"],
|
|
887
|
+
allowedDomains: ["github.com"],
|
|
888
|
+
allowOneTimeSend: true,
|
|
889
|
+
},
|
|
890
|
+
});
|
|
891
|
+
|
|
892
|
+
const res = await fetch(
|
|
893
|
+
url("pending-interactions?conversationId=conv-meta"),
|
|
894
|
+
{
|
|
895
|
+
method: "GET",
|
|
896
|
+
headers: { ...AUTH_HEADERS },
|
|
897
|
+
},
|
|
898
|
+
);
|
|
899
|
+
const body = (await res.json()) as {
|
|
900
|
+
pendingSecret: Record<string, unknown> | null;
|
|
901
|
+
};
|
|
902
|
+
|
|
903
|
+
expect(res.status).toBe(200);
|
|
904
|
+
expect(body.pendingSecret).toEqual({
|
|
905
|
+
requestId: "secret-meta-1",
|
|
906
|
+
service: "github",
|
|
907
|
+
field: "token",
|
|
908
|
+
label: "GitHub Token",
|
|
909
|
+
description: "Personal access token",
|
|
910
|
+
placeholder: "ghp_...",
|
|
911
|
+
purpose: "Push commits",
|
|
912
|
+
allowedTools: ["git_push"],
|
|
913
|
+
allowedDomains: ["github.com"],
|
|
914
|
+
allowOneTimeSend: true,
|
|
915
|
+
});
|
|
916
|
+
|
|
917
|
+
await stopServer();
|
|
918
|
+
});
|
|
919
|
+
});
|
|
920
|
+
|
|
793
921
|
// ── getByConversation ────────────────────────────────────────────────
|
|
794
922
|
|
|
795
923
|
describe("getByConversation", () => {
|
|
@@ -60,10 +60,7 @@ const CANONICAL_KEY_RE = /^[a-z0-9][a-z0-9-]*$/;
|
|
|
60
60
|
* Keep this list minimal — only files that genuinely need to reference
|
|
61
61
|
* the legacy format for backward compatibility.
|
|
62
62
|
*/
|
|
63
|
-
const LEGACY_KEY_ALLOWLIST = new Set([
|
|
64
|
-
// macOS client: fallback reads from legacy config section
|
|
65
|
-
"clients/macos/vellum-assistant/Features/Settings/SettingsAccountTab.swift",
|
|
66
|
-
]);
|
|
63
|
+
const LEGACY_KEY_ALLOWLIST = new Set<string>([]);
|
|
67
64
|
|
|
68
65
|
function isTestFile(filePath: string): boolean {
|
|
69
66
|
return (
|
|
@@ -58,8 +58,6 @@ function loadRegistry(): Registry {
|
|
|
58
58
|
const LEGACY_KEY_ALLOWLIST = new Set([
|
|
59
59
|
// Type definitions documenting the legacy format
|
|
60
60
|
"assistant/src/config/types.ts",
|
|
61
|
-
// macOS client: fallback reads from legacy config section
|
|
62
|
-
"clients/macos/vellum-assistant/Features/Settings/SettingsAccountTab.swift",
|
|
63
61
|
]);
|
|
64
62
|
|
|
65
63
|
function isTestFile(filePath: string): boolean {
|
|
@@ -7,18 +7,10 @@ mock.module("../util/logger.js", () => ({
|
|
|
7
7
|
}),
|
|
8
8
|
}));
|
|
9
9
|
|
|
10
|
-
let
|
|
10
|
+
let shareAnalytics = true;
|
|
11
11
|
|
|
12
|
-
mock.module("../
|
|
13
|
-
|
|
14
|
-
ui: {},
|
|
15
|
-
model: "test",
|
|
16
|
-
provider: "test",
|
|
17
|
-
memory: { enabled: false },
|
|
18
|
-
rateLimit: { maxRequestsPerMinute: 0 },
|
|
19
|
-
secretDetection: { enabled: false },
|
|
20
|
-
collectUsageData,
|
|
21
|
-
}),
|
|
12
|
+
mock.module("../platform/consent-cache.js", () => ({
|
|
13
|
+
getCachedShareAnalytics: () => shareAnalytics,
|
|
22
14
|
}));
|
|
23
15
|
|
|
24
16
|
import {
|
|
@@ -53,7 +45,7 @@ const SAMPLE: AuthFallbackCount[] = [
|
|
|
53
45
|
|
|
54
46
|
describe("auth-fallback-events-store", () => {
|
|
55
47
|
beforeEach(() => {
|
|
56
|
-
|
|
48
|
+
shareAnalytics = true;
|
|
57
49
|
resetTable();
|
|
58
50
|
});
|
|
59
51
|
|
|
@@ -78,8 +70,8 @@ describe("auth-fallback-events-store", () => {
|
|
|
78
70
|
});
|
|
79
71
|
});
|
|
80
72
|
|
|
81
|
-
test("honors the
|
|
82
|
-
|
|
73
|
+
test("honors the share_analytics opt-out (records nothing)", () => {
|
|
74
|
+
shareAnalytics = false;
|
|
83
75
|
const recorded = recordAuthFallbackCounts(1000, 2000, SAMPLE);
|
|
84
76
|
expect(recorded).toBe(0);
|
|
85
77
|
expect(queryUnreportedAuthFallbackEvents(0, undefined, 100).length).toBe(0);
|
|
@@ -4,10 +4,7 @@ import { SYNC_TAGS } from "../daemon/message-types/sync.js";
|
|
|
4
4
|
import type { AssistantEvent } from "../runtime/assistant-event.js";
|
|
5
5
|
import { assistantEventHub } from "../runtime/assistant-event-hub.js";
|
|
6
6
|
import { ROUTES as AVATAR_ROUTES } from "../runtime/routes/avatar-routes.js";
|
|
7
|
-
import {
|
|
8
|
-
publishIdentityChanged,
|
|
9
|
-
publishIdentityIntroChanged,
|
|
10
|
-
} from "../runtime/sync/resource-sync-events.js";
|
|
7
|
+
import { publishIdentityChanged } from "../runtime/sync/resource-sync-events.js";
|
|
11
8
|
|
|
12
9
|
async function waitFor(predicate: () => boolean): Promise<void> {
|
|
13
10
|
const deadline = Date.now() + 500;
|
|
@@ -81,29 +78,7 @@ describe("avatar and identity sync events", () => {
|
|
|
81
78
|
});
|
|
82
79
|
expect(received[1].message).toEqual({
|
|
83
80
|
type: "sync_changed",
|
|
84
|
-
tags: [SYNC_TAGS.assistantIdentity
|
|
85
|
-
});
|
|
86
|
-
} finally {
|
|
87
|
-
subscription.dispose();
|
|
88
|
-
}
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
test("identity intro changes emit only the identity intro sync tag", async () => {
|
|
92
|
-
const received: AssistantEvent[] = [];
|
|
93
|
-
const subscription = assistantEventHub.subscribe({
|
|
94
|
-
type: "process",
|
|
95
|
-
callback: (event) => {
|
|
96
|
-
received.push(event);
|
|
97
|
-
},
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
try {
|
|
101
|
-
publishIdentityIntroChanged();
|
|
102
|
-
await waitFor(() => received.length === 1);
|
|
103
|
-
|
|
104
|
-
expect(received[0].message).toEqual({
|
|
105
|
-
type: "sync_changed",
|
|
106
|
-
tags: [SYNC_TAGS.assistantIdentityIntro],
|
|
81
|
+
tags: [SYNC_TAGS.assistantIdentity],
|
|
107
82
|
});
|
|
108
83
|
} finally {
|
|
109
84
|
subscription.dispose();
|
|
@@ -78,10 +78,8 @@ mock.module("../prompts/persona-resolver.js", () => ({
|
|
|
78
78
|
resolveUserSlug: () => null,
|
|
79
79
|
}));
|
|
80
80
|
|
|
81
|
-
mock.module("../runtime/routes/
|
|
82
|
-
|
|
83
|
-
readWorkspaceIdentityIntro: () => null,
|
|
84
|
-
setCachedIntro: () => {},
|
|
81
|
+
mock.module("../runtime/routes/workspace-greetings.js", () => ({
|
|
82
|
+
readWorkspaceGreetings: () => null,
|
|
85
83
|
}));
|
|
86
84
|
|
|
87
85
|
// Mock getOrCreateConversation from conversation-store so the handler
|
|
@@ -345,13 +343,13 @@ describe("POST /v1/btw", () => {
|
|
|
345
343
|
expect(options!.config!.callSite).toBe("emptyStateGreeting");
|
|
346
344
|
});
|
|
347
345
|
|
|
348
|
-
test("
|
|
346
|
+
test("generic requests pass the default callSite", async () => {
|
|
349
347
|
const provider = makeMockProvider();
|
|
350
348
|
const session = makeMockSession(provider);
|
|
351
349
|
mockGetOrCreateConversation.mockImplementationOnce(async () => session);
|
|
352
350
|
|
|
353
351
|
const { result } = await callHandler({
|
|
354
|
-
conversationKey: "
|
|
352
|
+
conversationKey: "profile-intro",
|
|
355
353
|
content: "Generate an intro",
|
|
356
354
|
});
|
|
357
355
|
await readStream(result as ReadableStream<Uint8Array>);
|
|
@@ -361,7 +359,7 @@ describe("POST /v1/btw", () => {
|
|
|
361
359
|
expect(options!.config!.callSite).toBe("identityIntro");
|
|
362
360
|
});
|
|
363
361
|
|
|
364
|
-
test("
|
|
362
|
+
test("generic requests do not synthesize a static name greeting", async () => {
|
|
365
363
|
const identityPath = join(getWorkspaceDir(), "IDENTITY.md");
|
|
366
364
|
writeFileSync(
|
|
367
365
|
identityPath,
|
|
@@ -375,7 +373,7 @@ describe("POST /v1/btw", () => {
|
|
|
375
373
|
mockGetOrCreateConversation.mockImplementationOnce(async () => session);
|
|
376
374
|
|
|
377
375
|
const { result } = await callHandler({
|
|
378
|
-
conversationKey: "
|
|
376
|
+
conversationKey: "profile-intro",
|
|
379
377
|
content: "Generate an intro",
|
|
380
378
|
});
|
|
381
379
|
const text = await readStream(result as ReadableStream<Uint8Array>);
|
|
@@ -343,6 +343,34 @@ describe("addPointerMessage", () => {
|
|
|
343
343
|
expect(processorCalled).toBe(true);
|
|
344
344
|
});
|
|
345
345
|
|
|
346
|
+
test("unverified_contact provenance round-trips through the metadata schema and is treated as trusted audience", async () => {
|
|
347
|
+
// Persisted unverified_contact metadata must survive the schema parse so
|
|
348
|
+
// downstream consumers (e.g. memory write gate, pointer audience trust)
|
|
349
|
+
// see the durable trust snapshot rather than a silently-dropped undefined.
|
|
350
|
+
const convId = "conv-ptr-uvc-provenance";
|
|
351
|
+
ensureConversation(convId);
|
|
352
|
+
await addMessage(convId, "user", "hello", {
|
|
353
|
+
metadata: { provenanceTrustClass: "unverified_contact" },
|
|
354
|
+
});
|
|
355
|
+
|
|
356
|
+
// Confirm the durable snapshot round-trips through the schema parser.
|
|
357
|
+
const { getConversationRecentProvenanceTrustClass } = await import(
|
|
358
|
+
"../memory/conversation-crud.js"
|
|
359
|
+
);
|
|
360
|
+
expect(getConversationRecentProvenanceTrustClass(convId)).toBe(
|
|
361
|
+
"unverified_contact",
|
|
362
|
+
);
|
|
363
|
+
|
|
364
|
+
// And that pointer-audience trust treats it identically to trusted_contact.
|
|
365
|
+
let processorCalled = false;
|
|
366
|
+
setPointerMessageProcessor(async () => {
|
|
367
|
+
processorCalled = true;
|
|
368
|
+
});
|
|
369
|
+
|
|
370
|
+
await addPointerMessage(convId, "completed", "+15559876543");
|
|
371
|
+
expect(processorCalled).toBe(true);
|
|
372
|
+
});
|
|
373
|
+
|
|
346
374
|
test("unknown provenance trust class does not grant trusted audience", () => {
|
|
347
375
|
const convId = "conv-ptr-unknown-provenance";
|
|
348
376
|
ensureConversation(convId);
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cancel contract: a user cancel raises the conversation's AbortController and
|
|
3
|
+
* defers clearing the `processing` flag to the in-flight turn's `finally`.
|
|
4
|
+
*
|
|
5
|
+
* `cancelGeneration` no longer force-clears `processing` itself. Abort now
|
|
6
|
+
* propagates into the provider call and tool execution — and is backed by the
|
|
7
|
+
* agent loop's abort watchdog — so a cancelled turn always reaches its
|
|
8
|
+
* `finally` within a bounded time and tears down its own state there. The
|
|
9
|
+
* watchdog-driven path (turn reaches `finally`, processing clears) is covered
|
|
10
|
+
* by `conversation-agent-loop.test.ts`; this file pins the handler-side
|
|
11
|
+
* contract: cancel signals abort and leaves the flag to the turn.
|
|
12
|
+
*/
|
|
13
|
+
import { afterEach, describe, expect, test } from "bun:test";
|
|
14
|
+
|
|
15
|
+
import type { Conversation } from "../daemon/conversation.js";
|
|
16
|
+
import {
|
|
17
|
+
deleteConversation,
|
|
18
|
+
setConversation,
|
|
19
|
+
} from "../daemon/conversation-registry.js";
|
|
20
|
+
import { cancelGeneration } from "../daemon/handlers/conversations.js";
|
|
21
|
+
|
|
22
|
+
interface CancelledConversation {
|
|
23
|
+
isProcessing: () => boolean;
|
|
24
|
+
setProcessingCalls: () => boolean[];
|
|
25
|
+
abortCount: () => number;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Register a conversation whose in-flight turn is processing. The fake records
|
|
30
|
+
* abort calls and any `setProcessing` writes so the test can assert that
|
|
31
|
+
* `cancelGeneration` signals abort without flipping the flag itself.
|
|
32
|
+
*/
|
|
33
|
+
function registerProcessingTurn(id: string): CancelledConversation {
|
|
34
|
+
let processing = true;
|
|
35
|
+
let abortCount = 0;
|
|
36
|
+
const setProcessingCalls: boolean[] = [];
|
|
37
|
+
const fake = {
|
|
38
|
+
isProcessing: () => processing,
|
|
39
|
+
setProcessing: (value: boolean) => {
|
|
40
|
+
setProcessingCalls.push(value);
|
|
41
|
+
processing = value;
|
|
42
|
+
},
|
|
43
|
+
abort: () => {
|
|
44
|
+
abortCount += 1;
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
setConversation(id, fake as unknown as Conversation);
|
|
48
|
+
return {
|
|
49
|
+
isProcessing: () => processing,
|
|
50
|
+
setProcessingCalls: () => setProcessingCalls,
|
|
51
|
+
abortCount: () => abortCount,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
describe("cancelGeneration", () => {
|
|
56
|
+
const conversationId = "cancel-clears-processing-test-conversation";
|
|
57
|
+
|
|
58
|
+
afterEach(() => {
|
|
59
|
+
deleteConversation(conversationId);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
test("raises abort and defers clearing processing to the turn's finally", () => {
|
|
63
|
+
// GIVEN a registered conversation that is processing
|
|
64
|
+
const fake = registerProcessingTurn(conversationId);
|
|
65
|
+
expect(fake.isProcessing()).toBe(true);
|
|
66
|
+
|
|
67
|
+
// WHEN the user cancels generation
|
|
68
|
+
const cancelled = cancelGeneration(conversationId);
|
|
69
|
+
|
|
70
|
+
// THEN the cancel is acknowledged
|
|
71
|
+
expect(cancelled).toBe(true);
|
|
72
|
+
// AND the abort signal is raised on the conversation
|
|
73
|
+
expect(fake.abortCount()).toBe(1);
|
|
74
|
+
// AND cancelGeneration does NOT force-clear the flag itself — the in-flight
|
|
75
|
+
// turn's `finally` owns that teardown once abort drives it there.
|
|
76
|
+
expect(fake.setProcessingCalls()).not.toContain(false);
|
|
77
|
+
expect(fake.isProcessing()).toBe(true);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
test("returns false for a conversation that is not registered", () => {
|
|
81
|
+
// GIVEN no conversation registered under the id
|
|
82
|
+
|
|
83
|
+
// WHEN the user cancels generation for the unknown id
|
|
84
|
+
const cancelled = cancelGeneration("cancel-clears-processing-unknown-id");
|
|
85
|
+
|
|
86
|
+
// THEN the cancel reports that nothing was found
|
|
87
|
+
expect(cancelled).toBe(false);
|
|
88
|
+
});
|
|
89
|
+
});
|
|
@@ -224,14 +224,12 @@ function ensureTestContact(): void {
|
|
|
224
224
|
{
|
|
225
225
|
type: "telegram",
|
|
226
226
|
address: "telegram-user-default",
|
|
227
|
-
externalUserId: "telegram-user-default",
|
|
228
227
|
status: "active",
|
|
229
228
|
policy: "allow",
|
|
230
229
|
},
|
|
231
230
|
{
|
|
232
231
|
type: "slack",
|
|
233
232
|
address: "slack-user-default",
|
|
234
|
-
externalUserId: "slack-user-default",
|
|
235
233
|
status: "active",
|
|
236
234
|
policy: "allow",
|
|
237
235
|
},
|
|
@@ -2054,7 +2052,6 @@ describe("requester cancel of guardian-gated pending request", () => {
|
|
|
2054
2052
|
{
|
|
2055
2053
|
type: "telegram",
|
|
2056
2054
|
address: "requester-cancel-user",
|
|
2057
|
-
externalUserId: "requester-cancel-user",
|
|
2058
2055
|
status: "active",
|
|
2059
2056
|
policy: "allow",
|
|
2060
2057
|
},
|
|
@@ -2981,7 +2978,6 @@ describe("trusted-contact self-approval blocked before guardian approval row exi
|
|
|
2981
2978
|
{
|
|
2982
2979
|
type: "telegram",
|
|
2983
2980
|
address: "tc-selfapproval-user",
|
|
2984
|
-
externalUserId: "tc-selfapproval-user",
|
|
2985
2981
|
status: "active",
|
|
2986
2982
|
policy: "allow",
|
|
2987
2983
|
},
|
|
@@ -97,7 +97,6 @@ function seedTrustedContact(policy: "allow" | "escalate" = "allow"): void {
|
|
|
97
97
|
{
|
|
98
98
|
type: "telegram",
|
|
99
99
|
address: "telegram-user-1",
|
|
100
|
-
externalUserId: "telegram-user-1",
|
|
101
100
|
status: "active",
|
|
102
101
|
policy,
|
|
103
102
|
},
|
|
@@ -237,14 +236,13 @@ describe("channel inbound disk pressure gate", () => {
|
|
|
237
236
|
expect(db.select().from(messages).all()).toHaveLength(0);
|
|
238
237
|
});
|
|
239
238
|
|
|
240
|
-
test("blocks non-guardian Slack reactions before persistence while locked", async () => {
|
|
239
|
+
test("blocks non-guardian Slack reactions silently (no reply) before persistence while locked", async () => {
|
|
241
240
|
upsertContact({
|
|
242
241
|
displayName: "Example Slack User",
|
|
243
242
|
channels: [
|
|
244
243
|
{
|
|
245
244
|
type: "slack",
|
|
246
245
|
address: "slack-user-1",
|
|
247
|
-
externalUserId: "slack-user-1",
|
|
248
246
|
status: "active",
|
|
249
247
|
policy: "allow",
|
|
250
248
|
},
|
|
@@ -276,18 +274,10 @@ describe("channel inbound disk pressure gate", () => {
|
|
|
276
274
|
reason: "trusted-contact",
|
|
277
275
|
});
|
|
278
276
|
expect(processMessage).not.toHaveBeenCalled();
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
chatId: "slack-channel-1",
|
|
284
|
-
text: expectedRemoteBlockReply,
|
|
285
|
-
assistantId: "self",
|
|
286
|
-
ephemeral: true,
|
|
287
|
-
user: "slack-user-1",
|
|
288
|
-
},
|
|
289
|
-
],
|
|
290
|
-
]);
|
|
277
|
+
// Reactions are blocked silently during disk pressure: a passive signal
|
|
278
|
+
// has nothing to "try again", so no block reply is delivered (unlike the
|
|
279
|
+
// message path, which does reply).
|
|
280
|
+
expect(deliverChannelReplyMock).not.toHaveBeenCalled();
|
|
291
281
|
|
|
292
282
|
const db = getDb();
|
|
293
283
|
const event = db
|
|
@@ -790,9 +790,6 @@ describe("Permission Checker", () => {
|
|
|
790
790
|
const workingDir = join(homedir(), "projects", "myapp");
|
|
791
791
|
expect(generateScopeOptions(workingDir, "web_fetch")).toHaveLength(0);
|
|
792
792
|
expect(generateScopeOptions(workingDir, "skill_load")).toHaveLength(0);
|
|
793
|
-
expect(generateScopeOptions(workingDir, "credential_store")).toHaveLength(
|
|
794
|
-
0,
|
|
795
|
-
);
|
|
796
793
|
expect(
|
|
797
794
|
generateScopeOptions(workingDir, "computer_use_click"),
|
|
798
795
|
).toHaveLength(0);
|
|
@@ -52,7 +52,7 @@ mock.module("../memory/v2/skill-store.js", () => ({
|
|
|
52
52
|
// ---------------------------------------------------------------------------
|
|
53
53
|
|
|
54
54
|
const { registerMemoryV2Command } =
|
|
55
|
-
await import("../cli/commands/memory-v2.js");
|
|
55
|
+
await import("../cli/commands/memory/memory-v2.js");
|
|
56
56
|
const { ROUTES: memoryV2Routes, MEMORY_V2_DISABLED_CODE } =
|
|
57
57
|
await import("../runtime/routes/memory-v2-routes.js");
|
|
58
58
|
const { RouteError } = await import("../runtime/routes/errors.js");
|
|
@@ -68,9 +68,8 @@ function buildProgram(): Command {
|
|
|
68
68
|
writeErr: () => {},
|
|
69
69
|
writeOut: () => {},
|
|
70
70
|
});
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
registerMemoryV2Command(program);
|
|
71
|
+
const memory = program.command("memory");
|
|
72
|
+
registerMemoryV2Command(memory);
|
|
74
73
|
return program;
|
|
75
74
|
}
|
|
76
75
|
|
|
@@ -196,6 +196,12 @@ const updateConfigCalls: Array<{ maxInputTokens?: number }> = [];
|
|
|
196
196
|
|
|
197
197
|
mock.module("../plugins/defaults/compaction/window-manager.js", () => ({
|
|
198
198
|
ContextWindowManager: class {
|
|
199
|
+
estimateInputTokens() {
|
|
200
|
+
return 0;
|
|
201
|
+
}
|
|
202
|
+
get tokenCountInputs() {
|
|
203
|
+
return { systemPrompt: "", tools: undefined };
|
|
204
|
+
}
|
|
199
205
|
nonPersistedPrefixCount = 0;
|
|
200
206
|
constructor() {}
|
|
201
207
|
updateConfig(cfg: { maxInputTokens?: number }) {
|
|
@@ -41,7 +41,11 @@ function resetTables(): void {
|
|
|
41
41
|
|
|
42
42
|
async function addImageMessage(
|
|
43
43
|
conversationId: string,
|
|
44
|
-
provenanceTrustClass:
|
|
44
|
+
provenanceTrustClass:
|
|
45
|
+
| "guardian"
|
|
46
|
+
| "trusted_contact"
|
|
47
|
+
| "unverified_contact"
|
|
48
|
+
| "unknown",
|
|
45
49
|
filename: string,
|
|
46
50
|
): Promise<void> {
|
|
47
51
|
const inserted = await addMessage(
|
|
@@ -109,4 +113,20 @@ describe("collectImageManifest trust filtering", () => {
|
|
|
109
113
|
expect(filenames).toContain("contact.png");
|
|
110
114
|
expect(filenames).not.toContain("guardian-secret.png");
|
|
111
115
|
});
|
|
116
|
+
|
|
117
|
+
test("unverified_contact actor manifest excludes guardian images but keeps unverified-provenance images", async () => {
|
|
118
|
+
// GIVEN a conversation with a guardian image and an unverified-contact image
|
|
119
|
+
const conv = createConversation();
|
|
120
|
+
await addImageMessage(conv.id, "guardian", "guardian-secret.png");
|
|
121
|
+
await addImageMessage(conv.id, "unverified_contact", "unverified.png");
|
|
122
|
+
|
|
123
|
+
// WHEN the manifest is built for an unverified_contact actor
|
|
124
|
+
const manifest = collectImageManifest(conv.id, "unverified_contact");
|
|
125
|
+
|
|
126
|
+
// THEN the unverified-provenance image is listed and the guardian image
|
|
127
|
+
// is excluded — unverified_contact is treated as untrusted downstream.
|
|
128
|
+
const filenames = manifest.map((e) => e.filename);
|
|
129
|
+
expect(filenames).toContain("unverified.png");
|
|
130
|
+
expect(filenames).not.toContain("guardian-secret.png");
|
|
131
|
+
});
|
|
112
132
|
});
|