@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
|
@@ -1,14 +1,24 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { randomBytes } from "node:crypto";
|
|
2
|
+
import { existsSync, mkdirSync, mkdtempSync, rmSync } from "node:fs";
|
|
2
3
|
import { tmpdir } from "node:os";
|
|
3
4
|
import { join } from "node:path";
|
|
4
5
|
import { afterEach, beforeEach, describe, expect, test } from "bun:test";
|
|
5
6
|
|
|
6
7
|
import { credentialKey } from "../security/credential-key.js";
|
|
8
|
+
import { _resetBackend, setSecureKeyAsync } from "../security/secure-keys.js";
|
|
7
9
|
import { CredentialBroker } from "../tools/credentials/broker.js";
|
|
8
10
|
import {
|
|
9
11
|
_setMetadataPath,
|
|
10
12
|
upsertCredentialMetadata,
|
|
11
13
|
} from "../tools/credentials/metadata-store.js";
|
|
14
|
+
import { BROWSER_FILL_CAPABILITY } from "../tools/credentials/tool-policy.js";
|
|
15
|
+
import { setStorePathForTesting } from "./encrypted-store-test-helpers.js";
|
|
16
|
+
|
|
17
|
+
const TEST_DIR = join(
|
|
18
|
+
tmpdir(),
|
|
19
|
+
`vellum-broker-test-${randomBytes(4).toString("hex")}`,
|
|
20
|
+
);
|
|
21
|
+
const STORE_PATH = join(TEST_DIR, "keys.enc");
|
|
12
22
|
|
|
13
23
|
describe("CredentialBroker", () => {
|
|
14
24
|
let broker: CredentialBroker;
|
|
@@ -222,3 +232,441 @@ describe("CredentialBroker", () => {
|
|
|
222
232
|
});
|
|
223
233
|
});
|
|
224
234
|
});
|
|
235
|
+
|
|
236
|
+
// ---------------------------------------------------------------------------
|
|
237
|
+
// Behavior that reads stored secret values, exercised against the encrypted
|
|
238
|
+
// store backend (transient injection, multi-template serverUseById, revokeAll,
|
|
239
|
+
// and canonical/legacy capability-key resolution).
|
|
240
|
+
// ---------------------------------------------------------------------------
|
|
241
|
+
|
|
242
|
+
describe("CredentialBroker (encrypted store backend)", () => {
|
|
243
|
+
let broker: CredentialBroker;
|
|
244
|
+
|
|
245
|
+
beforeEach(() => {
|
|
246
|
+
if (existsSync(TEST_DIR)) rmSync(TEST_DIR, { recursive: true });
|
|
247
|
+
mkdirSync(TEST_DIR, { recursive: true });
|
|
248
|
+
setStorePathForTesting(STORE_PATH);
|
|
249
|
+
_resetBackend();
|
|
250
|
+
_setMetadataPath(join(TEST_DIR, "metadata.json"));
|
|
251
|
+
broker = new CredentialBroker();
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
afterEach(() => {
|
|
255
|
+
_setMetadataPath(null);
|
|
256
|
+
setStorePathForTesting(null);
|
|
257
|
+
_resetBackend();
|
|
258
|
+
rmSync(TEST_DIR, { recursive: true, force: true });
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
describe("transient credentials", () => {
|
|
262
|
+
test("consume returns transient value and deletes it", () => {
|
|
263
|
+
// GIVEN a credential with metadata and an injected one-time transient value
|
|
264
|
+
upsertCredentialMetadata("svc", "key", { allowedTools: ["tool1"] });
|
|
265
|
+
broker.injectTransient("svc", "key", "one-time-secret");
|
|
266
|
+
|
|
267
|
+
// WHEN the credential is authorized and consumed
|
|
268
|
+
const auth = broker.authorize({
|
|
269
|
+
service: "svc",
|
|
270
|
+
field: "key",
|
|
271
|
+
toolName: "tool1",
|
|
272
|
+
});
|
|
273
|
+
expect(auth.authorized).toBe(true);
|
|
274
|
+
if (!auth.authorized) return;
|
|
275
|
+
const result = broker.consume(auth.token.tokenId);
|
|
276
|
+
|
|
277
|
+
// THEN the transient value is returned alongside the storage key
|
|
278
|
+
expect(result.success).toBe(true);
|
|
279
|
+
expect(result.value).toBe("one-time-secret");
|
|
280
|
+
expect(result.storageKey).toBe(credentialKey("svc", "key"));
|
|
281
|
+
|
|
282
|
+
// AND a subsequent authorize+consume no longer has the transient value
|
|
283
|
+
const auth2 = broker.authorize({
|
|
284
|
+
service: "svc",
|
|
285
|
+
field: "key",
|
|
286
|
+
toolName: "tool1",
|
|
287
|
+
});
|
|
288
|
+
expect(auth2.authorized).toBe(true);
|
|
289
|
+
if (!auth2.authorized) return;
|
|
290
|
+
const result2 = broker.consume(auth2.token.tokenId);
|
|
291
|
+
expect(result2.success).toBe(true);
|
|
292
|
+
expect(result2.value).toBeUndefined();
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
test("browserFill uses transient value when available", async () => {
|
|
296
|
+
// GIVEN a credential with a transient value and no stored value
|
|
297
|
+
upsertCredentialMetadata("github", "token", {
|
|
298
|
+
allowedTools: ["browser_fill_credential"],
|
|
299
|
+
});
|
|
300
|
+
broker.injectTransient("github", "token", "transient-ghp-123");
|
|
301
|
+
|
|
302
|
+
// WHEN browserFill runs
|
|
303
|
+
let filledValue: string | undefined;
|
|
304
|
+
const result = await broker.browserFill({
|
|
305
|
+
service: "github",
|
|
306
|
+
field: "token",
|
|
307
|
+
toolName: "browser_fill_credential",
|
|
308
|
+
fill: async (v) => {
|
|
309
|
+
filledValue = v;
|
|
310
|
+
},
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
// THEN the transient value is filled
|
|
314
|
+
expect(result.success).toBe(true);
|
|
315
|
+
expect(filledValue).toBe("transient-ghp-123");
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
test("browserFill consumes transient value — second fill falls back to stored", async () => {
|
|
319
|
+
// GIVEN a credential with both a stored value and a transient value
|
|
320
|
+
upsertCredentialMetadata("github", "token", {
|
|
321
|
+
allowedTools: ["browser_fill_credential"],
|
|
322
|
+
});
|
|
323
|
+
await setSecureKeyAsync(credentialKey("github", "token"), "stored-value");
|
|
324
|
+
broker.injectTransient("github", "token", "transient-value");
|
|
325
|
+
|
|
326
|
+
// WHEN browserFill runs twice
|
|
327
|
+
let filled1: string | undefined;
|
|
328
|
+
await broker.browserFill({
|
|
329
|
+
service: "github",
|
|
330
|
+
field: "token",
|
|
331
|
+
toolName: "browser_fill_credential",
|
|
332
|
+
fill: async (v) => {
|
|
333
|
+
filled1 = v;
|
|
334
|
+
},
|
|
335
|
+
});
|
|
336
|
+
let filled2: string | undefined;
|
|
337
|
+
await broker.browserFill({
|
|
338
|
+
service: "github",
|
|
339
|
+
field: "token",
|
|
340
|
+
toolName: "browser_fill_credential",
|
|
341
|
+
fill: async (v) => {
|
|
342
|
+
filled2 = v;
|
|
343
|
+
},
|
|
344
|
+
});
|
|
345
|
+
|
|
346
|
+
// THEN the first fill uses the transient and the second falls back to stored
|
|
347
|
+
expect(filled1).toBe("transient-value");
|
|
348
|
+
expect(filled2).toBe("stored-value");
|
|
349
|
+
});
|
|
350
|
+
|
|
351
|
+
test("browserFill preserves transient value on fill failure", async () => {
|
|
352
|
+
// GIVEN a credential with a transient value
|
|
353
|
+
upsertCredentialMetadata("github", "token", {
|
|
354
|
+
allowedTools: ["browser_fill_credential"],
|
|
355
|
+
});
|
|
356
|
+
broker.injectTransient("github", "token", "transient-preserved");
|
|
357
|
+
|
|
358
|
+
// WHEN the first fill throws
|
|
359
|
+
const result1 = await broker.browserFill({
|
|
360
|
+
service: "github",
|
|
361
|
+
field: "token",
|
|
362
|
+
toolName: "browser_fill_credential",
|
|
363
|
+
fill: async () => {
|
|
364
|
+
throw new Error("Playwright timeout");
|
|
365
|
+
},
|
|
366
|
+
});
|
|
367
|
+
expect(result1.success).toBe(false);
|
|
368
|
+
let filled: string | undefined;
|
|
369
|
+
const result2 = await broker.browserFill({
|
|
370
|
+
service: "github",
|
|
371
|
+
field: "token",
|
|
372
|
+
toolName: "browser_fill_credential",
|
|
373
|
+
fill: async (v) => {
|
|
374
|
+
filled = v;
|
|
375
|
+
},
|
|
376
|
+
});
|
|
377
|
+
|
|
378
|
+
// THEN the transient value survives for the second fill
|
|
379
|
+
expect(result2.success).toBe(true);
|
|
380
|
+
expect(filled).toBe("transient-preserved");
|
|
381
|
+
});
|
|
382
|
+
|
|
383
|
+
test("serverUse uses transient value when available", async () => {
|
|
384
|
+
// GIVEN a credential with a transient value
|
|
385
|
+
upsertCredentialMetadata("vercel", "api_token", {
|
|
386
|
+
allowedTools: ["deploy"],
|
|
387
|
+
});
|
|
388
|
+
broker.injectTransient("vercel", "api_token", "transient-vercel-tok");
|
|
389
|
+
|
|
390
|
+
// WHEN serverUse runs
|
|
391
|
+
const result = await broker.serverUse({
|
|
392
|
+
service: "vercel",
|
|
393
|
+
field: "api_token",
|
|
394
|
+
toolName: "deploy",
|
|
395
|
+
execute: async (v) => {
|
|
396
|
+
expect(v).toBe("transient-vercel-tok");
|
|
397
|
+
return "deployed";
|
|
398
|
+
},
|
|
399
|
+
});
|
|
400
|
+
|
|
401
|
+
// THEN the transient value is used for execution
|
|
402
|
+
expect(result.success).toBe(true);
|
|
403
|
+
expect(result.result).toBe("deployed");
|
|
404
|
+
});
|
|
405
|
+
|
|
406
|
+
test("serverUse consumes transient — subsequent call has no value without stored key", async () => {
|
|
407
|
+
// GIVEN a credential with only a transient value (no stored value)
|
|
408
|
+
upsertCredentialMetadata("vercel", "api_token", {
|
|
409
|
+
allowedTools: ["deploy"],
|
|
410
|
+
});
|
|
411
|
+
broker.injectTransient("vercel", "api_token", "transient-only");
|
|
412
|
+
|
|
413
|
+
// WHEN serverUse runs twice
|
|
414
|
+
await broker.serverUse({
|
|
415
|
+
service: "vercel",
|
|
416
|
+
field: "api_token",
|
|
417
|
+
toolName: "deploy",
|
|
418
|
+
execute: async () => "ok",
|
|
419
|
+
});
|
|
420
|
+
const result = await broker.serverUse({
|
|
421
|
+
service: "vercel",
|
|
422
|
+
field: "api_token",
|
|
423
|
+
toolName: "deploy",
|
|
424
|
+
execute: async () => {
|
|
425
|
+
throw new Error("should not be called");
|
|
426
|
+
},
|
|
427
|
+
});
|
|
428
|
+
|
|
429
|
+
// THEN the second call fails because no stored value remains
|
|
430
|
+
expect(result.success).toBe(false);
|
|
431
|
+
expect(result.reason).toContain("no stored value");
|
|
432
|
+
});
|
|
433
|
+
|
|
434
|
+
test("injectTransient replaces previous transient for same key", () => {
|
|
435
|
+
// GIVEN two transient values injected for the same credential
|
|
436
|
+
upsertCredentialMetadata("svc", "key", { allowedTools: ["t"] });
|
|
437
|
+
broker.injectTransient("svc", "key", "first");
|
|
438
|
+
broker.injectTransient("svc", "key", "second");
|
|
439
|
+
|
|
440
|
+
// WHEN the credential is authorized and consumed
|
|
441
|
+
const auth = broker.authorize({
|
|
442
|
+
service: "svc",
|
|
443
|
+
field: "key",
|
|
444
|
+
toolName: "t",
|
|
445
|
+
});
|
|
446
|
+
if (!auth.authorized) return;
|
|
447
|
+
const result = broker.consume(auth.token.tokenId);
|
|
448
|
+
|
|
449
|
+
// THEN the most recent transient value wins
|
|
450
|
+
expect(result.value).toBe("second");
|
|
451
|
+
});
|
|
452
|
+
|
|
453
|
+
test("transient value for one credential does not affect another", () => {
|
|
454
|
+
// GIVEN a transient value injected for svcA only
|
|
455
|
+
upsertCredentialMetadata("svcA", "key", { allowedTools: ["t"] });
|
|
456
|
+
upsertCredentialMetadata("svcB", "key", { allowedTools: ["t"] });
|
|
457
|
+
broker.injectTransient("svcA", "key", "val-a");
|
|
458
|
+
|
|
459
|
+
// WHEN both credentials are authorized and consumed
|
|
460
|
+
const authB = broker.authorize({
|
|
461
|
+
service: "svcB",
|
|
462
|
+
field: "key",
|
|
463
|
+
toolName: "t",
|
|
464
|
+
});
|
|
465
|
+
if (!authB.authorized) return;
|
|
466
|
+
const resultB = broker.consume(authB.token.tokenId);
|
|
467
|
+
const authA = broker.authorize({
|
|
468
|
+
service: "svcA",
|
|
469
|
+
field: "key",
|
|
470
|
+
toolName: "t",
|
|
471
|
+
});
|
|
472
|
+
if (!authA.authorized) return;
|
|
473
|
+
const resultA = broker.consume(authA.token.tokenId);
|
|
474
|
+
|
|
475
|
+
// THEN only svcA carries the transient value
|
|
476
|
+
expect(resultB.success).toBe(true);
|
|
477
|
+
expect(resultB.value).toBeUndefined();
|
|
478
|
+
expect(resultA.value).toBe("val-a");
|
|
479
|
+
});
|
|
480
|
+
});
|
|
481
|
+
|
|
482
|
+
describe("serverUseById edge cases", () => {
|
|
483
|
+
test("serverUseById with multiple injection templates returns all", async () => {
|
|
484
|
+
// GIVEN a credential with two injection templates and a stored value
|
|
485
|
+
const meta = upsertCredentialMetadata("multi", "api_key", {
|
|
486
|
+
allowedTools: ["proxy"],
|
|
487
|
+
injectionTemplates: [
|
|
488
|
+
{
|
|
489
|
+
hostPattern: "*.fal.ai",
|
|
490
|
+
injectionType: "header",
|
|
491
|
+
headerName: "Authorization",
|
|
492
|
+
valuePrefix: "Key ",
|
|
493
|
+
},
|
|
494
|
+
{
|
|
495
|
+
hostPattern: "gateway.fal.ai",
|
|
496
|
+
injectionType: "header",
|
|
497
|
+
headerName: "X-Fal-Key",
|
|
498
|
+
},
|
|
499
|
+
],
|
|
500
|
+
});
|
|
501
|
+
await setSecureKeyAsync(
|
|
502
|
+
credentialKey("multi", "api_key"),
|
|
503
|
+
"multi-secret",
|
|
504
|
+
);
|
|
505
|
+
|
|
506
|
+
// WHEN serverUseById resolves the credential by id
|
|
507
|
+
const result = await broker.serverUseById({
|
|
508
|
+
credentialId: meta.credentialId,
|
|
509
|
+
requestingTool: "proxy",
|
|
510
|
+
});
|
|
511
|
+
|
|
512
|
+
// THEN both injection templates are returned without leaking the secret
|
|
513
|
+
expect(result.success).toBe(true);
|
|
514
|
+
if (!result.success) return;
|
|
515
|
+
expect(result.injectionTemplates).toHaveLength(2);
|
|
516
|
+
expect(result.injectionTemplates[0].hostPattern).toBe("*.fal.ai");
|
|
517
|
+
expect(result.injectionTemplates[1].hostPattern).toBe("gateway.fal.ai");
|
|
518
|
+
expect(JSON.stringify(result)).not.toContain("multi-secret");
|
|
519
|
+
});
|
|
520
|
+
});
|
|
521
|
+
|
|
522
|
+
describe("revokeAll", () => {
|
|
523
|
+
test("revokeAll clears all tokens and subsequent consume fails", () => {
|
|
524
|
+
// GIVEN two active tokens for a credential
|
|
525
|
+
upsertCredentialMetadata("svc", "key", { allowedTools: ["t1", "t2"] });
|
|
526
|
+
const a1 = broker.authorize({
|
|
527
|
+
service: "svc",
|
|
528
|
+
field: "key",
|
|
529
|
+
toolName: "t1",
|
|
530
|
+
});
|
|
531
|
+
const a2 = broker.authorize({
|
|
532
|
+
service: "svc",
|
|
533
|
+
field: "key",
|
|
534
|
+
toolName: "t2",
|
|
535
|
+
});
|
|
536
|
+
expect(broker.activeTokenCount).toBe(2);
|
|
537
|
+
|
|
538
|
+
// WHEN revokeAll is called
|
|
539
|
+
broker.revokeAll();
|
|
540
|
+
|
|
541
|
+
// THEN the token count is zero and consuming either token fails
|
|
542
|
+
expect(broker.activeTokenCount).toBe(0);
|
|
543
|
+
if (a1.authorized) {
|
|
544
|
+
expect(broker.consume(a1.token.tokenId).success).toBe(false);
|
|
545
|
+
}
|
|
546
|
+
if (a2.authorized) {
|
|
547
|
+
expect(broker.consume(a2.token.tokenId).success).toBe(false);
|
|
548
|
+
}
|
|
549
|
+
});
|
|
550
|
+
|
|
551
|
+
test("revokeAll on empty broker is a no-op", () => {
|
|
552
|
+
// GIVEN a broker with no active tokens
|
|
553
|
+
expect(broker.activeTokenCount).toBe(0);
|
|
554
|
+
|
|
555
|
+
// WHEN revokeAll is called
|
|
556
|
+
broker.revokeAll();
|
|
557
|
+
|
|
558
|
+
// THEN the token count remains zero
|
|
559
|
+
expect(broker.activeTokenCount).toBe(0);
|
|
560
|
+
});
|
|
561
|
+
});
|
|
562
|
+
|
|
563
|
+
describe("canonical capability key", () => {
|
|
564
|
+
test("authorize succeeds with canonical key when metadata has canonical key", () => {
|
|
565
|
+
// GIVEN metadata allowing the canonical browser-fill capability key
|
|
566
|
+
upsertCredentialMetadata("github", "token", {
|
|
567
|
+
allowedTools: [BROWSER_FILL_CAPABILITY],
|
|
568
|
+
});
|
|
569
|
+
|
|
570
|
+
// WHEN authorizing with the canonical key
|
|
571
|
+
const result = broker.authorize({
|
|
572
|
+
service: "github",
|
|
573
|
+
field: "token",
|
|
574
|
+
toolName: BROWSER_FILL_CAPABILITY,
|
|
575
|
+
});
|
|
576
|
+
|
|
577
|
+
// THEN authorization succeeds
|
|
578
|
+
expect(result.authorized).toBe(true);
|
|
579
|
+
});
|
|
580
|
+
|
|
581
|
+
test("authorize succeeds with canonical key when metadata has legacy alias", () => {
|
|
582
|
+
// GIVEN metadata stored under the legacy browser_fill_credential alias
|
|
583
|
+
upsertCredentialMetadata("github", "token", {
|
|
584
|
+
allowedTools: ["browser_fill_credential"],
|
|
585
|
+
});
|
|
586
|
+
|
|
587
|
+
// WHEN authorizing with the canonical key
|
|
588
|
+
const result = broker.authorize({
|
|
589
|
+
service: "github",
|
|
590
|
+
field: "token",
|
|
591
|
+
toolName: BROWSER_FILL_CAPABILITY,
|
|
592
|
+
});
|
|
593
|
+
|
|
594
|
+
// THEN authorization succeeds
|
|
595
|
+
expect(result.authorized).toBe(true);
|
|
596
|
+
});
|
|
597
|
+
|
|
598
|
+
test("authorize succeeds with legacy alias when metadata has canonical key", () => {
|
|
599
|
+
// GIVEN metadata allowing the canonical capability key
|
|
600
|
+
upsertCredentialMetadata("github", "token", {
|
|
601
|
+
allowedTools: [BROWSER_FILL_CAPABILITY],
|
|
602
|
+
});
|
|
603
|
+
|
|
604
|
+
// WHEN authorizing with the legacy alias
|
|
605
|
+
const result = broker.authorize({
|
|
606
|
+
service: "github",
|
|
607
|
+
field: "token",
|
|
608
|
+
toolName: "browser_fill_credential",
|
|
609
|
+
});
|
|
610
|
+
|
|
611
|
+
// THEN authorization succeeds
|
|
612
|
+
expect(result.authorized).toBe(true);
|
|
613
|
+
});
|
|
614
|
+
|
|
615
|
+
test("serverUse with canonical key works when metadata has legacy alias", async () => {
|
|
616
|
+
// GIVEN metadata stored under the legacy alias with a stored value
|
|
617
|
+
upsertCredentialMetadata("vercel", "api_token", {
|
|
618
|
+
allowedTools: ["browser_fill_credential"],
|
|
619
|
+
});
|
|
620
|
+
await setSecureKeyAsync(
|
|
621
|
+
credentialKey("vercel", "api_token"),
|
|
622
|
+
"vercel-tok",
|
|
623
|
+
);
|
|
624
|
+
|
|
625
|
+
// WHEN serverUse runs with the canonical key
|
|
626
|
+
const result = await broker.serverUse({
|
|
627
|
+
service: "vercel",
|
|
628
|
+
field: "api_token",
|
|
629
|
+
toolName: BROWSER_FILL_CAPABILITY,
|
|
630
|
+
execute: async (v) => v,
|
|
631
|
+
});
|
|
632
|
+
|
|
633
|
+
// THEN execution succeeds with the stored value
|
|
634
|
+
expect(result.success).toBe(true);
|
|
635
|
+
expect(result.result).toBe("vercel-tok");
|
|
636
|
+
});
|
|
637
|
+
|
|
638
|
+
test("non-aliased tool names are unaffected by alias resolution", () => {
|
|
639
|
+
// GIVEN metadata allowing a non-aliased custom tool
|
|
640
|
+
upsertCredentialMetadata("svc", "key", {
|
|
641
|
+
allowedTools: ["custom_tool"],
|
|
642
|
+
});
|
|
643
|
+
|
|
644
|
+
// WHEN authorizing with that custom tool
|
|
645
|
+
const result = broker.authorize({
|
|
646
|
+
service: "svc",
|
|
647
|
+
field: "key",
|
|
648
|
+
toolName: "custom_tool",
|
|
649
|
+
});
|
|
650
|
+
|
|
651
|
+
// THEN authorization succeeds
|
|
652
|
+
expect(result.authorized).toBe(true);
|
|
653
|
+
});
|
|
654
|
+
|
|
655
|
+
test("non-aliased tool denied when only canonical key is allowed", () => {
|
|
656
|
+
// GIVEN metadata allowing only the canonical capability key
|
|
657
|
+
upsertCredentialMetadata("svc", "key", {
|
|
658
|
+
allowedTools: [BROWSER_FILL_CAPABILITY],
|
|
659
|
+
});
|
|
660
|
+
|
|
661
|
+
// WHEN authorizing with an unrelated tool
|
|
662
|
+
const result = broker.authorize({
|
|
663
|
+
service: "svc",
|
|
664
|
+
field: "key",
|
|
665
|
+
toolName: "unrelated_tool",
|
|
666
|
+
});
|
|
667
|
+
|
|
668
|
+
// THEN authorization is denied
|
|
669
|
+
expect(result.authorized).toBe(false);
|
|
670
|
+
});
|
|
671
|
+
});
|
|
672
|
+
});
|
|
@@ -11,27 +11,33 @@
|
|
|
11
11
|
|
|
12
12
|
import { describe, expect, test } from "bun:test";
|
|
13
13
|
|
|
14
|
-
import {
|
|
14
|
+
import { resolveCapabilities } from "../runtime/capabilities.js";
|
|
15
15
|
|
|
16
16
|
// ---------------------------------------------------------------------------
|
|
17
17
|
// Trust class categorization (foundational for lockdown decisions)
|
|
18
18
|
// ---------------------------------------------------------------------------
|
|
19
19
|
|
|
20
20
|
describe("trust class categorization for CES lockdown", () => {
|
|
21
|
-
test("guardian
|
|
22
|
-
expect(
|
|
21
|
+
test("guardian runs an unsandboxed shell", () => {
|
|
22
|
+
expect(resolveCapabilities("guardian").canRunUnsandboxedShell).toBe(true);
|
|
23
23
|
});
|
|
24
24
|
|
|
25
|
-
test("trusted_contact is
|
|
26
|
-
expect(
|
|
25
|
+
test("trusted_contact shell is sandboxed", () => {
|
|
26
|
+
expect(resolveCapabilities("trusted_contact").canRunUnsandboxedShell).toBe(false);
|
|
27
27
|
});
|
|
28
28
|
|
|
29
|
-
test("
|
|
30
|
-
expect(
|
|
29
|
+
test("unverified_contact shell is sandboxed", () => {
|
|
30
|
+
expect(resolveCapabilities("unverified_contact").canRunUnsandboxedShell).toBe(
|
|
31
|
+
false,
|
|
32
|
+
);
|
|
31
33
|
});
|
|
32
34
|
|
|
33
|
-
test("
|
|
34
|
-
expect(
|
|
35
|
+
test("unknown shell is sandboxed", () => {
|
|
36
|
+
expect(resolveCapabilities("unknown").canRunUnsandboxedShell).toBe(false);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
test("undefined shell is sandboxed", () => {
|
|
40
|
+
expect(resolveCapabilities(undefined).canRunUnsandboxedShell).toBe(false);
|
|
35
41
|
});
|
|
36
42
|
});
|
|
37
43
|
|
|
@@ -91,7 +97,7 @@ describe("VELLUM_UNTRUSTED_SHELL env flag", () => {
|
|
|
91
97
|
describe("CES shell lockdown activation", () => {
|
|
92
98
|
test("lockdown is active only when both flag is enabled AND actor is untrusted", () => {
|
|
93
99
|
// Simulates the condition used in shell.ts:
|
|
94
|
-
// const shellLockdownActive = isCesShellLockdownEnabled(config) &&
|
|
100
|
+
// const shellLockdownActive = isCesShellLockdownEnabled(config) && !resolveCapabilities(context.trustClass).canRunUnsandboxedShell;
|
|
95
101
|
const cases: Array<{
|
|
96
102
|
flagEnabled: boolean;
|
|
97
103
|
trustClass: "guardian" | "trusted_contact" | "unknown";
|
|
@@ -106,7 +112,8 @@ describe("CES shell lockdown activation", () => {
|
|
|
106
112
|
];
|
|
107
113
|
|
|
108
114
|
for (const { flagEnabled, trustClass, expected } of cases) {
|
|
109
|
-
const active =
|
|
115
|
+
const active =
|
|
116
|
+
flagEnabled && !resolveCapabilities(trustClass).canRunUnsandboxedShell;
|
|
110
117
|
expect(active).toBe(expected);
|
|
111
118
|
}
|
|
112
119
|
});
|
|
@@ -136,7 +136,6 @@ describe("secure tool installation is separate from credential grants", () => {
|
|
|
136
136
|
test("manage_secure_command_tool does not share tool name with grant tools", () => {
|
|
137
137
|
// The tool name must not collide with existing credential grant tools
|
|
138
138
|
const grantToolNames = [
|
|
139
|
-
"credential_store",
|
|
140
139
|
"credential_grant",
|
|
141
140
|
"credential_revoke",
|
|
142
141
|
"credential_list",
|
|
@@ -110,6 +110,7 @@ function slackResult(
|
|
|
110
110
|
hasAppToken: false,
|
|
111
111
|
hasUserToken: false,
|
|
112
112
|
connected: false,
|
|
113
|
+
threadMode: "mention_only",
|
|
113
114
|
...overrides,
|
|
114
115
|
};
|
|
115
116
|
}
|
|
@@ -138,10 +139,9 @@ describe("credentials/prompt route", () => {
|
|
|
138
139
|
|
|
139
140
|
test("forwards usageDescription as the prompt purpose and to metadata", async () => {
|
|
140
141
|
/**
|
|
141
|
-
* The CLI `credentials prompt` command exposes `--usage-description
|
|
142
|
-
*
|
|
143
|
-
* it to
|
|
144
|
-
* to credential metadata (as `usageDescription`).
|
|
142
|
+
* The CLI `credentials prompt` command exposes `--usage-description`. The
|
|
143
|
+
* route must thread it to the secure prompt (as `purpose`, shown to the
|
|
144
|
+
* user) and persist it to credential metadata (as `usageDescription`).
|
|
145
145
|
*/
|
|
146
146
|
// GIVEN the credentials/prompt route is registered
|
|
147
147
|
expect(promptRoute).toBeDefined();
|