@vellumai/assistant 0.9.0 → 0.10.0-staging.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ARCHITECTURE.md +18 -34
- 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 +976 -63
- 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__/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__/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__/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-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-lifecycle.test.ts +7 -9
- package/src/__tests__/conversation-load-history-repair.test.ts +101 -0
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +15 -12
- package/src/__tests__/conversation-surfaces-activation-emit.test.ts +6 -3
- package/src/__tests__/conversation-title-service.test.ts +62 -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-usage.test.ts +65 -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__/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-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__/skill-execute-input.test.ts +51 -1
- 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__/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 +49 -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/{__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 +197 -4
- 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__/merge-plugin-tree.test.ts +443 -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 +105 -17
- package/src/cli/lib/merge-plugin-tree.ts +328 -0
- package/src/cli/lib/plugin-fingerprint.ts +14 -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/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/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/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 +27 -14
- package/src/daemon/conversation.ts +66 -14
- 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/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/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__/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-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/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/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/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__/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/atlascloud/client.ts +85 -0
- package/src/providers/fetch-provider-catalog.ts +85 -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/retry.ts +53 -12
- package/src/providers/search-provider-catalog.ts +10 -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 +181 -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 +52 -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 +123 -0
- package/src/runtime/migrations/vbundle-builder.ts +49 -20
- package/src/runtime/pending-interactions.ts +15 -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 +240 -1
- package/src/runtime/routes/app-routes.ts +1 -1
- 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 +202 -3
- package/src/runtime/routes/schedule-routes.ts +0 -22
- package/src/runtime/routes/secret-routes.ts +10 -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 +2 -3
- 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 +33 -0
- package/src/tools/subagent/spawn.ts +61 -12
- 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 +9 -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/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
|
@@ -36,10 +36,6 @@ import {
|
|
|
36
36
|
import * as approvalMessageComposer from "../runtime/approval-message-composer.js";
|
|
37
37
|
import * as gatewayClient from "../runtime/gateway-client.js";
|
|
38
38
|
import * as pendingInteractions from "../runtime/pending-interactions.js";
|
|
39
|
-
import {
|
|
40
|
-
_clearApprovalPromptTsTrackerForTesting,
|
|
41
|
-
trackApprovalPromptTs,
|
|
42
|
-
} from "../runtime/routes/approval-prompt-ts-tracker.js";
|
|
43
39
|
import { handleApprovalInterception } from "../runtime/routes/guardian-approval-interception.js";
|
|
44
40
|
import { computeToolApprovalDigest } from "../security/tool-approval-digest.js";
|
|
45
41
|
|
|
@@ -69,7 +65,6 @@ function resetTables(): void {
|
|
|
69
65
|
/* tables may not exist yet */
|
|
70
66
|
}
|
|
71
67
|
pendingInteractions.clear();
|
|
72
|
-
_clearApprovalPromptTsTrackerForTesting();
|
|
73
68
|
}
|
|
74
69
|
|
|
75
70
|
function createTestGuardianApproval(
|
|
@@ -224,36 +219,9 @@ describe("guardian grant minting on tool-approval decisions", () => {
|
|
|
224
219
|
composeSpy.mockRestore();
|
|
225
220
|
});
|
|
226
221
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
conversationId: CONVERSATION_ID,
|
|
231
|
-
channel: "slack",
|
|
232
|
-
guardianChatId: GUARDIAN_CHAT,
|
|
233
|
-
});
|
|
234
|
-
registerPendingInteraction(requestId, CONVERSATION_ID, TOOL_NAME);
|
|
235
|
-
const approvalMessageTs = "1700000000.000100";
|
|
236
|
-
trackApprovalPromptTs("slack", GUARDIAN_CHAT, approvalMessageTs);
|
|
237
|
-
|
|
238
|
-
const result = await handleApprovalInterception({
|
|
239
|
-
conversationId: "guardian-conv-1",
|
|
240
|
-
callbackData: "reaction:white_check_mark",
|
|
241
|
-
content: "",
|
|
242
|
-
conversationExternalId: GUARDIAN_CHAT,
|
|
243
|
-
sourceChannel: "slack",
|
|
244
|
-
actorExternalId: GUARDIAN_USER,
|
|
245
|
-
replyCallbackUrl: "https://gateway.test/deliver",
|
|
246
|
-
trustCtx: makeTrustContext(),
|
|
247
|
-
assistantId: ASSISTANT_ID,
|
|
248
|
-
approvalMessageTs,
|
|
249
|
-
});
|
|
250
|
-
|
|
251
|
-
// white_check_mark is mapped to approve_once (backward compat) — the
|
|
252
|
-
// pending approval is resolved and a grant is minted.
|
|
253
|
-
expect(result.handled).toBe(true);
|
|
254
|
-
expect(result.type).toBe("guardian_decision_applied");
|
|
255
|
-
expect(countGrants()).toBe(1);
|
|
256
|
-
});
|
|
222
|
+
// Reaction-based approvals are exercised against the canonical pipeline in
|
|
223
|
+
// slack-reaction-canonical-approval.test.ts — reactions route through
|
|
224
|
+
// routeGuardianReply, not handleApprovalInterception.
|
|
257
225
|
|
|
258
226
|
// ── 2. approve_once for non-tool-approval does NOT mint a grant ──
|
|
259
227
|
|
|
@@ -828,7 +828,7 @@ describe("routing invariant: disambiguation stays fail-closed", () => {
|
|
|
828
828
|
replyCtx({
|
|
829
829
|
messageText: "approve",
|
|
830
830
|
conversationId: "conv-guardian-conversation",
|
|
831
|
-
|
|
831
|
+
pendingScope: { mode: "scoped", requestIds: [req.id] },
|
|
832
832
|
approvalConversationGenerator: undefined,
|
|
833
833
|
}),
|
|
834
834
|
);
|
|
@@ -857,7 +857,7 @@ describe("routing invariant: disambiguation stays fail-closed", () => {
|
|
|
857
857
|
replyCtx({
|
|
858
858
|
messageText: "ok, what is this for?",
|
|
859
859
|
conversationId: "conv-guardian-conversation",
|
|
860
|
-
|
|
860
|
+
pendingScope: { mode: "scoped", requestIds: [req.id] },
|
|
861
861
|
approvalConversationGenerator: undefined,
|
|
862
862
|
}),
|
|
863
863
|
);
|
|
@@ -870,7 +870,7 @@ describe("routing invariant: disambiguation stays fail-closed", () => {
|
|
|
870
870
|
expect(unchanged!.status).toBe("pending");
|
|
871
871
|
});
|
|
872
872
|
|
|
873
|
-
test("explicit
|
|
873
|
+
test("explicit blocked scope stays fail-closed for desktop actors", async () => {
|
|
874
874
|
createCanonicalGuardianRequest({
|
|
875
875
|
kind: "tool_approval",
|
|
876
876
|
sourceType: "channel",
|
|
@@ -887,7 +887,7 @@ describe("routing invariant: disambiguation stays fail-closed", () => {
|
|
|
887
887
|
messageText: "approve",
|
|
888
888
|
actor: trustedActor(),
|
|
889
889
|
conversationId: "conv-unrelated",
|
|
890
|
-
|
|
890
|
+
pendingScope: { mode: "blocked" },
|
|
891
891
|
approvalConversationGenerator: undefined,
|
|
892
892
|
}),
|
|
893
893
|
);
|
|
@@ -897,6 +897,38 @@ describe("routing invariant: disambiguation stays fail-closed", () => {
|
|
|
897
897
|
expect(result.decisionApplied).toBe(false);
|
|
898
898
|
});
|
|
899
899
|
|
|
900
|
+
test("explicit request code still resolves under a blocked scope (cross-chat carve-out)", async () => {
|
|
901
|
+
// The Slack cross-chat guard blocks identity fallback, but an explicit
|
|
902
|
+
// request code carries its own target and must still resolve — otherwise a
|
|
903
|
+
// guardian could not approve-by-code from a chat where no card was delivered.
|
|
904
|
+
const req = createCanonicalGuardianRequest({
|
|
905
|
+
kind: "tool_approval",
|
|
906
|
+
sourceType: "channel",
|
|
907
|
+
conversationId: "conv-other",
|
|
908
|
+
guardianExternalUserId: "guardian-1",
|
|
909
|
+
guardianPrincipalId: TEST_PRINCIPAL_ID,
|
|
910
|
+
requestCode: "ABC123",
|
|
911
|
+
toolName: "shell",
|
|
912
|
+
expiresAt: Date.now() + 60_000,
|
|
913
|
+
});
|
|
914
|
+
registerPendingToolApprovalInteraction(req.id, "conv-other", "shell");
|
|
915
|
+
|
|
916
|
+
const result = await routeGuardianReply(
|
|
917
|
+
replyCtx({
|
|
918
|
+
messageText: "ABC123 approve",
|
|
919
|
+
actor: trustedActor(),
|
|
920
|
+
conversationId: "conv-unrelated",
|
|
921
|
+
pendingScope: { mode: "blocked" },
|
|
922
|
+
approvalConversationGenerator: undefined,
|
|
923
|
+
}),
|
|
924
|
+
);
|
|
925
|
+
|
|
926
|
+
expect(result.consumed).toBe(true);
|
|
927
|
+
expect(result.requestId).toBe(req.id);
|
|
928
|
+
expect(result.decisionApplied).toBe(true);
|
|
929
|
+
expect(getCanonicalGuardianRequest(req.id)!.status).toBe("approved");
|
|
930
|
+
});
|
|
931
|
+
|
|
900
932
|
test("multiple hinted pending requests with plain-text approve returns disambiguation", async () => {
|
|
901
933
|
const req1 = createCanonicalGuardianRequest({
|
|
902
934
|
kind: "tool_approval",
|
|
@@ -924,7 +956,7 @@ describe("routing invariant: disambiguation stays fail-closed", () => {
|
|
|
924
956
|
replyCtx({
|
|
925
957
|
messageText: "approve",
|
|
926
958
|
conversationId: "conv-guardian-conversation",
|
|
927
|
-
|
|
959
|
+
pendingScope: { mode: "scoped", requestIds: [req1.id, req2.id] },
|
|
928
960
|
approvalConversationGenerator: undefined,
|
|
929
961
|
}),
|
|
930
962
|
);
|
|
@@ -977,7 +1009,7 @@ describe("routing invariant: disambiguation stays fail-closed", () => {
|
|
|
977
1009
|
replyCtx({
|
|
978
1010
|
messageText: "yes approve it",
|
|
979
1011
|
conversationId: "conv-1",
|
|
980
|
-
|
|
1012
|
+
pendingScope: { mode: "scoped", requestIds: [req1.id, req2.id] },
|
|
981
1013
|
approvalConversationGenerator: mockGenerator as any,
|
|
982
1014
|
}),
|
|
983
1015
|
);
|
|
@@ -1031,7 +1063,10 @@ describe("routing invariant: disambiguation stays fail-closed", () => {
|
|
|
1031
1063
|
replyCtx({
|
|
1032
1064
|
messageText: "approve",
|
|
1033
1065
|
conversationId: "conv-guardian-conversation",
|
|
1034
|
-
|
|
1066
|
+
pendingScope: {
|
|
1067
|
+
mode: "scoped",
|
|
1068
|
+
requestIds: [answerRequest.id, approvalRequest.id],
|
|
1069
|
+
},
|
|
1035
1070
|
approvalConversationGenerator: undefined,
|
|
1036
1071
|
}),
|
|
1037
1072
|
);
|
|
@@ -1075,7 +1110,7 @@ describe("routing invariant: disambiguation stays fail-closed", () => {
|
|
|
1075
1110
|
replyCtx({
|
|
1076
1111
|
messageText: "yes",
|
|
1077
1112
|
conversationId: "conv-1",
|
|
1078
|
-
|
|
1113
|
+
pendingScope: { mode: "scoped", requestIds: [req.id] },
|
|
1079
1114
|
approvalConversationGenerator: mockGenerator as any,
|
|
1080
1115
|
}),
|
|
1081
1116
|
);
|
|
@@ -1104,7 +1139,7 @@ describe("routing invariant: disambiguation stays fail-closed", () => {
|
|
|
1104
1139
|
replyCtx({
|
|
1105
1140
|
messageText: "go for it",
|
|
1106
1141
|
conversationId: "conv-1",
|
|
1107
|
-
|
|
1142
|
+
pendingScope: { mode: "scoped", requestIds: [req.id] },
|
|
1108
1143
|
approvalConversationGenerator: undefined,
|
|
1109
1144
|
}),
|
|
1110
1145
|
);
|
|
@@ -1117,7 +1152,7 @@ describe("routing invariant: disambiguation stays fail-closed", () => {
|
|
|
1117
1152
|
expect(resolved!.status).toBe("approved");
|
|
1118
1153
|
});
|
|
1119
1154
|
|
|
1120
|
-
test("code-based routing is constrained to caller-provided
|
|
1155
|
+
test("code-based routing is constrained to caller-provided scope", async () => {
|
|
1121
1156
|
const inScope = createCanonicalGuardianRequest({
|
|
1122
1157
|
kind: "tool_approval",
|
|
1123
1158
|
sourceType: "channel",
|
|
@@ -1145,7 +1180,7 @@ describe("routing invariant: disambiguation stays fail-closed", () => {
|
|
|
1145
1180
|
replyCtx({
|
|
1146
1181
|
messageText: "222BBB approve",
|
|
1147
1182
|
conversationId: "conv-guardian-conversation",
|
|
1148
|
-
|
|
1183
|
+
pendingScope: { mode: "scoped", requestIds: [inScope.id] },
|
|
1149
1184
|
approvalConversationGenerator: undefined,
|
|
1150
1185
|
}),
|
|
1151
1186
|
);
|
|
@@ -1438,7 +1473,7 @@ describe("routing invariant: directResolve interactions resolve via guardian dec
|
|
|
1438
1473
|
describe("routing invariant: destination hints do not bypass tool_approval principal binding", () => {
|
|
1439
1474
|
beforeEach(() => resetTables());
|
|
1440
1475
|
|
|
1441
|
-
test("explicit
|
|
1476
|
+
test("explicit scope still fails closed when guardianPrincipalId does not match", async () => {
|
|
1442
1477
|
// Voice-originated tool approval with a different principal than the actor.
|
|
1443
1478
|
const req = createCanonicalGuardianRequest({
|
|
1444
1479
|
kind: "tool_approval",
|
|
@@ -1452,15 +1487,15 @@ describe("routing invariant: destination hints do not bypass tool_approval princ
|
|
|
1452
1487
|
});
|
|
1453
1488
|
registerPendingToolApprovalInteraction(req.id, "conv-voice-1", "shell");
|
|
1454
1489
|
|
|
1455
|
-
// The channel inbound router would compute
|
|
1456
|
-
// delivery-scoped lookup and pass
|
|
1490
|
+
// The channel inbound router would compute the pending scope from
|
|
1491
|
+
// delivery-scoped lookup and pass it here. Simulate that.
|
|
1457
1492
|
const result = await routeGuardianReply(
|
|
1458
1493
|
replyCtx({
|
|
1459
1494
|
messageText: "approve",
|
|
1460
1495
|
channel: "telegram",
|
|
1461
1496
|
actor: guardianActor({ guardianPrincipalId: "different-principal" }),
|
|
1462
1497
|
conversationId: "conv-guardian-chat",
|
|
1463
|
-
|
|
1498
|
+
pendingScope: { mode: "scoped", requestIds: [req.id] },
|
|
1464
1499
|
approvalConversationGenerator: undefined,
|
|
1465
1500
|
}),
|
|
1466
1501
|
);
|
|
@@ -1486,7 +1521,7 @@ describe("routing invariant: destination hints do not bypass tool_approval princ
|
|
|
1486
1521
|
expiresAt: Date.now() + 60_000,
|
|
1487
1522
|
});
|
|
1488
1523
|
|
|
1489
|
-
// No
|
|
1524
|
+
// No pendingScope passed — identity-based fallback uses
|
|
1490
1525
|
// actor.actorExternalUserId which does not match any request's
|
|
1491
1526
|
// guardianExternalUserId (since it's null).
|
|
1492
1527
|
const result = await routeGuardianReply(
|
|
@@ -1495,7 +1530,7 @@ describe("routing invariant: destination hints do not bypass tool_approval princ
|
|
|
1495
1530
|
channel: "telegram",
|
|
1496
1531
|
actor: guardianActor({ actorExternalUserId: "guardian-tg-user" }),
|
|
1497
1532
|
conversationId: "conv-guardian-chat",
|
|
1498
|
-
//
|
|
1533
|
+
// pendingScope omitted — no delivery hints
|
|
1499
1534
|
approvalConversationGenerator: undefined,
|
|
1500
1535
|
}),
|
|
1501
1536
|
);
|
|
@@ -1534,7 +1569,7 @@ describe("routing invariant: invite handoff bypass for access requests", () => {
|
|
|
1534
1569
|
replyCtx({
|
|
1535
1570
|
messageText: "open invite flow",
|
|
1536
1571
|
conversationId: "conv-guardian-conversation",
|
|
1537
|
-
|
|
1572
|
+
pendingScope: { mode: "scoped", requestIds: [req.id] },
|
|
1538
1573
|
approvalConversationGenerator: undefined,
|
|
1539
1574
|
}),
|
|
1540
1575
|
);
|
|
@@ -1569,7 +1604,7 @@ describe("routing invariant: invite handoff bypass for access requests", () => {
|
|
|
1569
1604
|
replyCtx({
|
|
1570
1605
|
messageText: phrase,
|
|
1571
1606
|
conversationId: "conv-test",
|
|
1572
|
-
|
|
1607
|
+
pendingScope: { mode: "scoped", requestIds: [req.id] },
|
|
1573
1608
|
approvalConversationGenerator: undefined,
|
|
1574
1609
|
}),
|
|
1575
1610
|
);
|
|
@@ -1595,7 +1630,7 @@ describe("routing invariant: invite handoff bypass for access requests", () => {
|
|
|
1595
1630
|
replyCtx({
|
|
1596
1631
|
messageText: "open invite flow",
|
|
1597
1632
|
conversationId: "conv-guardian-conversation",
|
|
1598
|
-
|
|
1633
|
+
pendingScope: { mode: "scoped", requestIds: [req.id] },
|
|
1599
1634
|
approvalConversationGenerator: undefined,
|
|
1600
1635
|
}),
|
|
1601
1636
|
);
|
|
@@ -1625,7 +1660,7 @@ describe("routing invariant: invite handoff bypass for access requests", () => {
|
|
|
1625
1660
|
replyCtx({
|
|
1626
1661
|
messageText: "A00B01 approve",
|
|
1627
1662
|
conversationId: "conv-guardian-conversation",
|
|
1628
|
-
|
|
1663
|
+
pendingScope: { mode: "scoped", requestIds: [req.id] },
|
|
1629
1664
|
approvalConversationGenerator: undefined,
|
|
1630
1665
|
}),
|
|
1631
1666
|
);
|
|
@@ -1655,7 +1690,7 @@ describe("routing invariant: invite handoff bypass for access requests", () => {
|
|
|
1655
1690
|
channel: "vellum",
|
|
1656
1691
|
actor: trustedActor({ channel: "vellum" }),
|
|
1657
1692
|
conversationId: "conv-guardian-conversation",
|
|
1658
|
-
|
|
1693
|
+
pendingScope: { mode: "scoped", requestIds: [req.id] },
|
|
1659
1694
|
approvalConversationGenerator: undefined,
|
|
1660
1695
|
});
|
|
1661
1696
|
|
|
@@ -1694,7 +1729,7 @@ describe("routing invariant: invite handoff bypass for access requests", () => {
|
|
|
1694
1729
|
channel: "vellum",
|
|
1695
1730
|
actor: trustedActor({ channel: "vellum" }),
|
|
1696
1731
|
conversationId: "conv-guardian-conversation",
|
|
1697
|
-
|
|
1732
|
+
pendingScope: { mode: "scoped", requestIds: [req.id] },
|
|
1698
1733
|
approvalConversationGenerator: approvalConversationGenerator as any,
|
|
1699
1734
|
});
|
|
1700
1735
|
|
|
@@ -1746,7 +1781,7 @@ describe("routing invariant: expired requests are excluded from pending discover
|
|
|
1746
1781
|
replyCtx({
|
|
1747
1782
|
messageText: "approve",
|
|
1748
1783
|
conversationId: "conv-guardian-conversation",
|
|
1749
|
-
|
|
1784
|
+
pendingScope: { mode: "scoped", requestIds: [expired.id, active.id] },
|
|
1750
1785
|
approvalConversationGenerator: undefined,
|
|
1751
1786
|
}),
|
|
1752
1787
|
);
|
|
@@ -1781,7 +1816,7 @@ describe("routing invariant: expired requests are excluded from pending discover
|
|
|
1781
1816
|
replyCtx({
|
|
1782
1817
|
messageText: "`approve`",
|
|
1783
1818
|
conversationId: "conv-guardian-conversation",
|
|
1784
|
-
|
|
1819
|
+
pendingScope: { mode: "scoped", requestIds: [req.id] },
|
|
1785
1820
|
approvalConversationGenerator: undefined,
|
|
1786
1821
|
}),
|
|
1787
1822
|
);
|
|
@@ -1821,7 +1856,10 @@ describe("routing invariant: expired requests are excluded from pending discover
|
|
|
1821
1856
|
replyCtx({
|
|
1822
1857
|
messageText: "approve",
|
|
1823
1858
|
conversationId: "conv-guardian-conversation",
|
|
1824
|
-
|
|
1859
|
+
pendingScope: {
|
|
1860
|
+
mode: "scoped",
|
|
1861
|
+
requestIds: [expired1.id, expired2.id],
|
|
1862
|
+
},
|
|
1825
1863
|
approvalConversationGenerator: undefined,
|
|
1826
1864
|
}),
|
|
1827
1865
|
);
|
|
@@ -75,6 +75,16 @@ mock.module("../tools/browser/cdp-client/factory.js", () => ({
|
|
|
75
75
|
},
|
|
76
76
|
}));
|
|
77
77
|
|
|
78
|
+
// The real proxy is an always-present singleton; stub the grace wait so
|
|
79
|
+
// extension-pinned acquisition doesn't poll for the full window here.
|
|
80
|
+
mock.module("../daemon/host-browser-proxy.js", () => ({
|
|
81
|
+
HostBrowserProxy: {
|
|
82
|
+
get instance() {
|
|
83
|
+
return { waitForExtensionClient: async () => true };
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
}));
|
|
87
|
+
|
|
78
88
|
// ── Minimal browserManager stub ──────────────────────────────────────
|
|
79
89
|
|
|
80
90
|
/** Mutable memo shared between mock methods and tests. */
|
|
@@ -58,9 +58,14 @@ let mockExtensionAvailable = false;
|
|
|
58
58
|
mock.module("../daemon/host-browser-proxy.js", () => ({
|
|
59
59
|
HostBrowserProxy: {
|
|
60
60
|
get instance() {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
61
|
+
// The real proxy is a lazily-created singleton that always exists;
|
|
62
|
+
// `isAvailable`/`waitForExtensionClient` reflect whether an extension
|
|
63
|
+
// is connected rather than the instance being absent.
|
|
64
|
+
return {
|
|
65
|
+
isAvailable: () => mockExtensionAvailable,
|
|
66
|
+
waitForExtensionClient: async () => mockExtensionAvailable,
|
|
67
|
+
request: mock(async () => ({})),
|
|
68
|
+
};
|
|
64
69
|
},
|
|
65
70
|
},
|
|
66
71
|
}));
|
|
@@ -46,6 +46,8 @@ mock.module("../runtime/assistant-event-hub.js", () => ({
|
|
|
46
46
|
mockClients.filter((c) => c.capabilities.includes(cap)),
|
|
47
47
|
listClientsByInterface: (interfaceId: string) =>
|
|
48
48
|
mockClients.filter((c) => c.interfaceId === interfaceId),
|
|
49
|
+
getClientById: (clientId: string) =>
|
|
50
|
+
mockClients.find((c) => c.clientId === clientId),
|
|
49
51
|
getActorPrincipalIdForClient: (clientId: string) =>
|
|
50
52
|
mockClients.find((c) => c.clientId === clientId)?.actorPrincipalId,
|
|
51
53
|
},
|
|
@@ -108,6 +110,91 @@ describe("HostBrowserProxy", () => {
|
|
|
108
110
|
pendingInteractions.clear();
|
|
109
111
|
});
|
|
110
112
|
|
|
113
|
+
describe("waitForExtensionClient", () => {
|
|
114
|
+
const EXTENSION: MockClient = {
|
|
115
|
+
clientId: "ext-client",
|
|
116
|
+
interfaceId: "chrome-extension",
|
|
117
|
+
capabilities: ["host_browser"],
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
test("returns true immediately when an extension is connected", async () => {
|
|
121
|
+
mockClients = [EXTENSION];
|
|
122
|
+
expect(await proxy.waitForExtensionClient(undefined, undefined, 1_000)).toBe(
|
|
123
|
+
true,
|
|
124
|
+
);
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
test("returns false after the timeout when none connects", async () => {
|
|
128
|
+
mockClients = [DEFAULT_CLIENT]; // macos only, no extension
|
|
129
|
+
expect(await proxy.waitForExtensionClient(undefined, undefined, 100)).toBe(
|
|
130
|
+
false,
|
|
131
|
+
);
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
test("returns true when an extension appears within the window", async () => {
|
|
135
|
+
mockClients = [DEFAULT_CLIENT];
|
|
136
|
+
setTimeout(() => {
|
|
137
|
+
mockClients = [DEFAULT_CLIENT, EXTENSION];
|
|
138
|
+
}, 50);
|
|
139
|
+
expect(await proxy.waitForExtensionClient(undefined, undefined, 2_000)).toBe(
|
|
140
|
+
true,
|
|
141
|
+
);
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
test("respects sourceActorPrincipalId", async () => {
|
|
145
|
+
mockClients = [
|
|
146
|
+
{
|
|
147
|
+
clientId: "other-actor-ext",
|
|
148
|
+
interfaceId: "chrome-extension",
|
|
149
|
+
actorPrincipalId: "actor-b",
|
|
150
|
+
capabilities: ["host_browser"],
|
|
151
|
+
},
|
|
152
|
+
];
|
|
153
|
+
// Caller is actor-a; the connected extension belongs to actor-b.
|
|
154
|
+
expect(await proxy.waitForExtensionClient("actor-a", undefined, 100)).toBe(
|
|
155
|
+
false,
|
|
156
|
+
);
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
test("with a targetClientId, waits for that exact client (not a sibling)", async () => {
|
|
160
|
+
// A sibling extension is connected, but the targeted client is not —
|
|
161
|
+
// the wait must not return early on the sibling's presence.
|
|
162
|
+
mockClients = [
|
|
163
|
+
{
|
|
164
|
+
clientId: "sibling-ext",
|
|
165
|
+
interfaceId: "chrome-extension",
|
|
166
|
+
capabilities: ["host_browser"],
|
|
167
|
+
},
|
|
168
|
+
];
|
|
169
|
+
expect(
|
|
170
|
+
await proxy.waitForExtensionClient(undefined, "target-ext", 100),
|
|
171
|
+
).toBe(false);
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
test("with a targetClientId, returns true once that client appears", async () => {
|
|
175
|
+
mockClients = [
|
|
176
|
+
{
|
|
177
|
+
clientId: "sibling-ext",
|
|
178
|
+
interfaceId: "chrome-extension",
|
|
179
|
+
capabilities: ["host_browser"],
|
|
180
|
+
},
|
|
181
|
+
];
|
|
182
|
+
setTimeout(() => {
|
|
183
|
+
mockClients = [
|
|
184
|
+
...mockClients,
|
|
185
|
+
{
|
|
186
|
+
clientId: "target-ext",
|
|
187
|
+
interfaceId: "chrome-extension",
|
|
188
|
+
capabilities: ["host_browser"],
|
|
189
|
+
},
|
|
190
|
+
];
|
|
191
|
+
}, 50);
|
|
192
|
+
expect(
|
|
193
|
+
await proxy.waitForExtensionClient(undefined, "target-ext", 2_000),
|
|
194
|
+
).toBe(true);
|
|
195
|
+
});
|
|
196
|
+
});
|
|
197
|
+
|
|
111
198
|
describe("request/resolve lifecycle (happy path)", () => {
|
|
112
199
|
test("sends host_browser_request and resolves with content", async () => {
|
|
113
200
|
const resultPromise = proxy.request(
|