@vellumai/assistant 0.8.5 → 0.8.6
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/AGENTS.md +33 -1
- package/ARCHITECTURE.md +1 -1
- package/bunfig.toml +6 -1
- package/docs/credential-execution-service.md +6 -6
- package/docs/plugins.md +4 -3
- package/node_modules/@vellumai/skill-host-contracts/src/client.ts +12 -13
- package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +4 -1
- package/node_modules/@vellumai/skill-host-contracts/src/tool-types.ts +16 -14
- package/openapi.yaml +1900 -166
- package/package.json +1 -1
- package/src/__tests__/actor-token-service.test.ts +3 -2
- package/src/__tests__/agent-loop-exit-reason.test.ts +102 -9
- package/src/__tests__/agent-loop-override-profile.test.ts +2 -1
- package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +1 -0
- package/src/__tests__/agent-wake-override-profile.test.ts +1 -0
- package/src/__tests__/always-loaded-tools-guard.test.ts +2 -2
- package/src/__tests__/annotate-risk-options.test.ts +1 -0
- package/src/__tests__/approval-cascade.test.ts +1 -0
- package/src/__tests__/approval-routes-http.test.ts +9 -13
- package/src/__tests__/assert-not-live-db.ts +79 -0
- package/src/__tests__/assistant-feature-flags-integration.test.ts +9 -25
- package/src/__tests__/audit-log-rotation.test.ts +2 -2
- package/src/__tests__/auto-analysis-end-to-end.test.ts +6 -6
- package/src/__tests__/background-workers-disk-pressure.test.ts +5 -8
- package/src/__tests__/browser-skill-endstate.test.ts +3 -3
- package/src/__tests__/btw-routes.test.ts +3 -2
- package/src/__tests__/call-controller.test.ts +3 -2
- package/src/__tests__/channel-approval-routes.test.ts +3 -2
- package/src/__tests__/channel-guardian.test.ts +3 -2
- package/src/__tests__/channel-readiness-slack-remote.test.ts +175 -0
- package/src/__tests__/channel-reply-delivery.test.ts +35 -0
- package/src/__tests__/channel-retry-sweep.test.ts +320 -3
- package/src/__tests__/checker.test.ts +12 -12
- package/src/__tests__/compaction-events.test.ts +1 -0
- package/src/__tests__/compaction-trail-store.test.ts +264 -0
- package/src/__tests__/compactor-call-site-logging.test.ts +1 -0
- package/src/__tests__/compactor-preserved-tail-count.test.ts +1 -0
- package/src/__tests__/computer-use-skill-manifest-regression.test.ts +7 -5
- package/src/__tests__/computer-use-tools.test.ts +12 -14
- package/src/__tests__/config-loader-backfill.test.ts +13 -28
- package/src/__tests__/config-loader-corrupt.test.ts +5 -5
- package/src/__tests__/config-loader-platform-defaults.test.ts +93 -26
- package/src/__tests__/config-loader-quarantine-bulletin.test.ts +3 -3
- package/src/__tests__/config-managed-gemini-defaults.test.ts +3 -4
- package/src/__tests__/config-schema.test.ts +10 -10
- package/src/__tests__/connection-model-compat.test.ts +83 -0
- package/src/__tests__/contacts-tools.test.ts +3 -2
- package/src/__tests__/context-token-estimator.test.ts +22 -0
- package/src/__tests__/conversation-abort-tool-results.test.ts +5 -0
- package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +1 -0
- package/src/__tests__/conversation-agent-loop-handlers-max-tokens.test.ts +55 -0
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +1 -0
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +34 -0
- package/src/__tests__/conversation-agent-loop.test.ts +488 -2
- package/src/__tests__/conversation-analysis-routes.test.ts +1 -0
- package/src/__tests__/conversation-app-control-instantiation.test.ts +29 -19
- package/src/__tests__/conversation-app-control-lifecycle.test.ts +1 -0
- package/src/__tests__/conversation-attention-store.test.ts +101 -0
- package/src/__tests__/conversation-attention-telegram.test.ts +3 -2
- package/src/__tests__/conversation-confirmation-signals.test.ts +1 -0
- package/src/__tests__/conversation-error.test.ts +30 -0
- package/src/__tests__/conversation-fork-crud.test.ts +69 -8
- package/src/__tests__/conversation-fork-route.test.ts +3 -2
- package/src/__tests__/conversation-history-web-search.test.ts +1 -0
- package/src/__tests__/conversation-inference-profile-list.test.ts +3 -2
- package/src/__tests__/conversation-inference-profile-route.test.ts +3 -2
- package/src/__tests__/conversation-lifecycle.test.ts +1 -0
- package/src/__tests__/conversation-list-source.test.ts +3 -2
- package/src/__tests__/conversation-load-history-repair.test.ts +2 -1
- package/src/__tests__/conversation-load-history-stripped.test.ts +1 -0
- package/src/__tests__/conversation-pairing.test.ts +53 -0
- package/src/__tests__/conversation-process-app-control-preactivation.test.ts +26 -7
- package/src/__tests__/conversation-process-callsite.test.ts +1 -0
- package/src/__tests__/conversation-provider-retry-repair.test.ts +5 -0
- package/src/__tests__/conversation-queue.test.ts +333 -291
- package/src/__tests__/conversation-routes-disk-view.test.ts +3 -18
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +33 -8
- package/src/__tests__/conversation-routes-slash-commands.test.ts +33 -2
- package/src/__tests__/conversation-runtime-assembly.test.ts +78 -0
- package/src/__tests__/conversation-skill-tools.test.ts +38 -142
- package/src/__tests__/conversation-slash-queue.test.ts +84 -32
- package/src/__tests__/conversation-slash-unknown.test.ts +5 -0
- package/src/__tests__/conversation-speed-override.test.ts +1 -0
- package/src/__tests__/conversation-surfaces-action-delivery.test.ts +46 -0
- package/src/__tests__/conversation-surfaces-data-persist.test.ts +1 -0
- package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +6 -3
- package/src/__tests__/conversation-surfaces-standalone.test.ts +6 -3
- package/src/__tests__/conversation-surfaces-state-update.test.ts +3 -3
- package/src/__tests__/conversation-surfaces-table-action.test.ts +7 -17
- package/src/__tests__/conversation-sync-tags.test.ts +128 -12
- package/src/__tests__/conversation-title-service.test.ts +1 -0
- package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +30 -0
- package/src/__tests__/conversation-usage.test.ts +1 -0
- package/src/__tests__/conversation-workspace-cache-state.test.ts +1 -0
- package/src/__tests__/conversation-workspace-injection.test.ts +5 -0
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +5 -0
- package/src/__tests__/credential-broker-browser-fill.test.ts +3 -3
- package/src/__tests__/credential-broker-server-use.test.ts +5 -5
- package/src/__tests__/credential-execution-client.test.ts +72 -1
- package/src/__tests__/credential-execution-feature-gates.test.ts +10 -12
- package/src/__tests__/credential-health-service.test.ts +252 -3
- package/src/__tests__/credential-security-invariants.test.ts +5 -5
- package/src/__tests__/credential-vault-unit.test.ts +19 -19
- package/src/__tests__/credential-vault.test.ts +5 -5
- package/src/__tests__/cross-provider-web-search.test.ts +56 -2
- package/src/__tests__/db-connection-isolation.test.ts +7 -6
- package/src/__tests__/db-conversation-fork-lineage-migration.test.ts +8 -10
- package/src/__tests__/db-conversation-inference-profile-migration.test.ts +7 -10
- package/src/__tests__/db-llm-request-log-provider-migration.test.ts +9 -15
- package/src/__tests__/db-test-helpers.ts +58 -0
- package/src/__tests__/disk-pressure-guard.test.ts +58 -41
- package/src/__tests__/disk-pressure-lifecycle.test.ts +13 -10
- package/src/__tests__/disk-pressure-routes.test.ts +0 -33
- package/src/__tests__/disk-pressure-tools.test.ts +0 -4
- package/src/__tests__/dm-persistence.test.ts +26 -40
- package/src/__tests__/document-create-dedupe.test.ts +189 -0
- package/src/__tests__/document-find-replace.test.ts +3 -2
- package/src/__tests__/document-tool-security.test.ts +81 -2
- package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +5 -4
- package/src/__tests__/encrypted-store-test-helpers.ts +56 -0
- package/src/__tests__/encrypted-store.test.ts +11 -9
- package/src/__tests__/feature-flag-test-helpers.ts +53 -0
- package/src/__tests__/filing-service.test.ts +1 -0
- package/src/__tests__/first-greeting.test.ts +62 -12
- package/src/__tests__/gateway-flag-listener.test.ts +0 -1
- package/src/__tests__/gemini-provider.test.ts +26 -0
- package/src/__tests__/guardian-action-sweep.test.ts +3 -2
- package/src/__tests__/guardian-outbound-http.test.ts +3 -2
- package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +48 -3
- package/src/__tests__/handlers-user-message-approval-consumption.test.ts +1 -0
- package/src/__tests__/heartbeat-disk-pressure.test.ts +1 -0
- package/src/__tests__/heartbeat-service.test.ts +1 -0
- package/src/__tests__/helpers/mock-logger.ts +26 -0
- package/src/__tests__/host-bash-routes.test.ts +1 -0
- package/src/__tests__/host-cu-routes-targeted.test.ts +1 -0
- package/src/__tests__/host-file-routes-targeted.test.ts +1 -0
- package/src/__tests__/host-shell-tool.test.ts +5 -4
- package/src/__tests__/host-transfer-routes-targeted.test.ts +1 -0
- package/src/__tests__/http-conversation-lineage.test.ts +3 -2
- package/src/__tests__/http-user-message-parity.test.ts +29 -7
- package/src/__tests__/identity-intro-cache.test.ts +133 -22
- package/src/__tests__/inbound-slack-persistence.test.ts +44 -72
- package/src/__tests__/inference-profile-reaper.test.ts +3 -2
- package/src/__tests__/inference-profile-session-ipc.test.ts +3 -2
- package/src/__tests__/injector-disk-pressure.test.ts +3 -17
- package/src/__tests__/inline-skill-load-permissions.test.ts +4 -4
- package/src/__tests__/list-messages-hidden-metadata.test.ts +80 -0
- package/src/__tests__/llm-context-normalization.test.ts +42 -0
- package/src/__tests__/llm-resolver.test.ts +331 -0
- package/src/__tests__/llm-schema.test.ts +1 -1
- package/src/__tests__/manual-token-reconciliation.test.ts +76 -1
- package/src/__tests__/mcp-abort-signal.test.ts +14 -0
- package/src/__tests__/mcp-client-auth.test.ts +14 -0
- package/src/__tests__/messaging-send-tool.test.ts +1 -0
- package/src/__tests__/migration-import-from-url.test.ts +3 -3
- package/src/__tests__/mock-gateway-ipc.ts +18 -2
- package/src/__tests__/model-intents.test.ts +3 -3
- package/src/__tests__/native-web-search.test.ts +30 -2
- package/src/__tests__/notification-deep-link.test.ts +62 -0
- package/src/__tests__/oauth-commands-routes.test.ts +37 -0
- package/src/__tests__/oauth-provider-visibility.test.ts +8 -8
- package/src/__tests__/oauth-store.test.ts +3 -2
- package/src/__tests__/onboarding-template-contract.test.ts +3 -2
- package/src/__tests__/openai-provider.test.ts +8 -9
- package/src/__tests__/openai-responses-provider.test.ts +70 -10
- package/src/__tests__/openrouter-provider-only.test.ts +27 -5
- package/src/__tests__/outbound-slack-persistence.test.ts +46 -1
- package/src/__tests__/persistence-pipeline.test.ts +139 -1
- package/src/__tests__/persistence-secret-redaction.test.ts +83 -12
- package/src/__tests__/plugin-bootstrap.test.ts +9 -11
- package/src/__tests__/plugin-tool-contribution.test.ts +41 -38
- package/src/__tests__/process-message-background-slack.test.ts +21 -16
- package/src/__tests__/process-message-display-content.test.ts +19 -22
- package/src/__tests__/provider-catalog-visibility.test.ts +9 -9
- package/src/__tests__/provider-platform-proxy-integration.test.ts +216 -4
- package/src/__tests__/provider-registry-ollama.test.ts +45 -22
- package/src/__tests__/recording-handler.test.ts +1 -0
- package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +1 -0
- package/src/__tests__/registry.test.ts +82 -76
- package/src/__tests__/relay-server.test.ts +10 -10
- package/src/__tests__/runtime-attachment-metadata.test.ts +3 -2
- package/src/__tests__/schedule-store.test.ts +16 -1
- package/src/__tests__/scheduler-reuse-conversation.test.ts +48 -3
- package/src/__tests__/secret-ingress-http.test.ts +5 -1
- package/src/__tests__/secure-keys.test.ts +3 -3
- package/src/__tests__/send-endpoint-busy.test.ts +81 -42
- package/src/__tests__/server-history-render.test.ts +4 -1
- package/src/__tests__/skill-feature-flags-integration.test.ts +8 -10
- package/src/__tests__/skill-feature-flags.test.ts +14 -16
- package/src/__tests__/skill-load-feature-flag.test.ts +5 -5
- package/src/__tests__/skill-projection-feature-flag.test.ts +44 -30
- package/src/__tests__/skill-projection.benchmark.test.ts +5 -7
- package/src/__tests__/skill-tool-factory.test.ts +96 -95
- package/src/__tests__/slack-channel-config.test.ts +3 -3
- package/src/__tests__/subagent-call-site-routing.test.ts +11 -3
- package/src/__tests__/subagent-disposal.test.ts +27 -8
- package/src/__tests__/subagent-fork-notifications.test.ts +24 -9
- package/src/__tests__/subagent-fork-spawn.test.ts +13 -4
- package/src/__tests__/subagent-manager-notify.test.ts +20 -8
- package/src/__tests__/subagent-notify-parent.test.ts +5 -4
- package/src/__tests__/subagent-spawn-tool-fork.test.ts +58 -0
- package/src/__tests__/subagent-tools.test.ts +2 -1
- package/src/__tests__/suggestion-routes.test.ts +1 -0
- package/src/__tests__/system-prompt.test.ts +38 -0
- package/src/__tests__/test-preload-verifier.ts +68 -0
- package/src/__tests__/test-preload.ts +32 -39
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +20 -7
- package/src/__tests__/tool-executor.test.ts +55 -10
- package/src/__tests__/tool-preview-lifecycle.test.ts +1 -0
- package/src/__tests__/tool-result-metadata-plumbing.test.ts +1 -0
- package/src/__tests__/twilio-routes.test.ts +3 -2
- package/src/__tests__/validate-input.test.ts +381 -0
- package/src/__tests__/verification-control-plane-policy.test.ts +1 -0
- package/src/__tests__/voice-scoped-grant-consumer.test.ts +2 -1
- package/src/__tests__/voice-session-bridge.test.ts +37 -28
- package/src/__tests__/workspace-migration-090-memory-router-cost-optimized-profile.test.ts +326 -0
- package/src/__tests__/workspace-migration-091-retighten-migration-onboarding-thread.test.ts +166 -0
- package/src/acp/session-manager.ts +5 -6
- package/src/agent/loop.ts +80 -0
- package/src/api/README.md +124 -2
- package/src/api/constants/call-sites.ts +27 -0
- package/src/api/events/assistant-outbound-attachment.ts +51 -0
- package/src/api/events/assistant-text-delta.ts +32 -0
- package/src/api/events/assistant-turn-start.ts +33 -0
- package/src/api/events/document-comment-created.ts +48 -0
- package/src/api/events/document-comment-deleted.ts +24 -0
- package/src/api/events/document-comment-reopened.ts +25 -0
- package/src/api/events/document-comment-resolved.ts +27 -0
- package/src/api/events/generation-cancelled.ts +24 -0
- package/src/api/events/generation-handoff.ts +41 -0
- package/src/api/events/message-complete.ts +42 -0
- package/src/api/events/open-url.ts +30 -0
- package/src/{events → api/events}/relationship-state-updated.ts +3 -3
- package/src/api/events/tool-use-start.ts +32 -0
- package/src/api/index.ts +128 -3
- package/src/api/responses/llm-context-response.ts +39 -0
- package/src/api/responses/llm-request-log-entry.ts +93 -0
- package/src/api/responses/memory-recall-log.ts +65 -0
- package/src/api/responses/memory-v2-activation-log.ts +78 -0
- package/src/background-wake/background-wake-routes.test.ts +687 -52
- package/src/background-wake/platform-client.test.ts +308 -0
- package/src/background-wake/platform-client.ts +167 -0
- package/src/background-wake/publisher.ts +91 -0
- package/src/background-wake/runtime-registry.ts +2 -2
- package/src/background-wake/wake-intent-hooks.test.ts +282 -0
- package/src/calls/guardian-dispatch.ts +1 -0
- package/src/calls/voice-session-bridge.ts +4 -4
- package/src/cli/commands/__tests__/conversations-slack.test.ts +16 -0
- package/src/cli/commands/__tests__/notifications.test.ts +184 -40
- package/src/cli/commands/channels/__tests__/channels.test.ts +143 -0
- package/src/cli/commands/channels/index.ts +229 -0
- package/src/cli/commands/memory-v3-render.ts +147 -0
- package/src/cli/commands/memory-v3.ts +255 -4
- package/src/cli/commands/notifications.ts +365 -55
- package/src/cli/lib/open-browser.ts +7 -2
- package/src/cli/program.ts +2 -0
- package/src/config/assistant-feature-flags.ts +23 -42
- package/src/config/bundled-skills/document-editor/SKILL.md +5 -1
- package/src/config/bundled-skills/schedule/SKILL.md +1 -1
- package/src/config/bundled-skills/schedule/TOOLS.json +2 -2
- package/src/config/bundled-skills/settings/tools/open-system-settings.ts +1 -0
- package/src/config/call-site-defaults.ts +1 -1
- package/src/config/feature-flag-cache.ts +86 -0
- package/src/config/feature-flag-registry.json +17 -17
- package/src/config/llm-context-resolution.ts +10 -1
- package/src/config/llm-resolver.ts +121 -15
- package/src/config/loader.ts +4 -5
- package/src/config/schemas/__tests__/memory-v2.test.ts +15 -0
- package/src/config/schemas/heartbeat.ts +1 -1
- package/src/config/schemas/llm.ts +90 -1
- package/src/config/schemas/memory-v2.ts +26 -0
- package/src/config/schemas/services.ts +6 -2
- package/src/config/seed-inference-profiles.ts +36 -16
- package/src/context/token-estimator.ts +10 -5
- package/src/credential-execution/executable-discovery.ts +40 -0
- package/src/credential-execution/process-manager.ts +6 -2
- package/src/credential-health/credential-health-service.ts +125 -40
- package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +3 -6
- package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +13 -15
- package/src/daemon/__tests__/conversation-tool-setup-exclude.test.ts +1 -2
- package/src/daemon/__tests__/daemon-skill-host.test.ts +2 -0
- package/src/daemon/__tests__/meet-manifest-loader.test.ts +25 -12
- package/src/daemon/__tests__/native-web-search-metadata.test.ts +1 -0
- package/src/daemon/__tests__/switch-inference-profile-tool.test.ts +107 -0
- package/src/daemon/__tests__/web-search-status-text.test.ts +1 -0
- package/src/daemon/conversation-agent-loop-handlers.ts +389 -68
- package/src/daemon/conversation-agent-loop.ts +132 -28
- package/src/daemon/conversation-error.ts +33 -5
- package/src/daemon/conversation-messaging.ts +84 -43
- package/src/daemon/conversation-process.ts +74 -37
- package/src/daemon/conversation-runtime-assembly.ts +29 -9
- package/src/daemon/conversation-skill-tools.ts +14 -30
- package/src/daemon/conversation-surfaces.ts +69 -34
- package/src/daemon/conversation-tool-setup.ts +33 -48
- package/src/daemon/conversation.ts +26 -46
- package/src/daemon/daemon-control.ts +1 -1
- package/src/daemon/daemon-skill-host.ts +9 -2
- package/src/daemon/disk-pressure-guard.ts +27 -29
- package/src/daemon/first-greeting.ts +31 -13
- package/src/daemon/handlers/shared.ts +6 -1
- package/src/daemon/lifecycle.ts +12 -12
- package/src/daemon/mcp-reload-service.ts +1 -1
- package/src/daemon/meet-manifest-loader.ts +10 -17
- package/src/daemon/message-types/conversations.ts +20 -22
- package/src/daemon/message-types/document-comments.ts +8 -44
- package/src/daemon/message-types/home.ts +2 -2
- package/src/daemon/message-types/integrations.ts +2 -7
- package/src/daemon/message-types/messages.ts +23 -38
- package/src/daemon/message-types/subagents.ts +6 -0
- package/src/daemon/process-message.ts +9 -9
- package/src/daemon/providers-setup.ts +1 -1
- package/src/daemon/server.ts +16 -0
- package/src/daemon/switch-inference-profile-tool.ts +13 -3
- package/src/daemon/tool-setup-types.ts +0 -6
- package/src/daemon/wake-target-adapter.ts +10 -0
- package/src/documents/document-store.ts +38 -0
- package/src/export/__tests__/transcript-formatter.test.ts +1 -0
- package/src/heartbeat/__tests__/heartbeat-service.test.ts +29 -0
- package/src/heartbeat/heartbeat-service.ts +63 -0
- package/src/home/__tests__/feed-writer.test.ts +161 -0
- package/src/home/__tests__/post-connect-feed.test.ts +1 -0
- package/src/home/__tests__/suggested-prompts.test.ts +55 -59
- package/src/home/feed-writer.ts +146 -7
- package/src/home/suggested-prompts.ts +27 -145
- package/src/ipc/__tests__/cli-ipc.test.ts +1 -0
- package/src/ipc/gateway-client.test.ts +4 -1
- package/src/ipc/skill-routes/__tests__/memory.test.ts +1 -0
- package/src/ipc/skill-routes/__tests__/registries.test.ts +36 -7
- package/src/ipc/skill-routes/memory.ts +4 -3
- package/src/ipc/skill-routes/registries.ts +28 -29
- package/src/memory/__tests__/jobs-store-enqueue-gate.test.ts +1 -0
- package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +26 -5
- package/src/memory/__tests__/memory-retrospective-enqueue.test.ts +1 -0
- package/src/memory/__tests__/memory-retrospective-job.test.ts +1 -0
- package/src/memory/__tests__/memory-retrospective-startup-cleanup.test.ts +1 -0
- package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +31 -0
- package/src/memory/conversation-attention-store.ts +17 -3
- package/src/memory/conversation-crud.ts +352 -112
- package/src/memory/db-connection.ts +29 -19
- package/src/memory/db-init.ts +4 -0
- package/src/memory/db-singleton.ts +77 -0
- package/src/memory/delivery-channels.ts +82 -0
- package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +2 -4
- package/src/memory/graph/retriever.test.ts +3 -3
- package/src/memory/job-handlers/embedding.test.ts +3 -2
- package/src/memory/jobs/__tests__/embed-concept-page.test.ts +5 -2
- package/src/memory/jobs-worker.ts +12 -1
- package/src/memory/llm-request-log-source-clickhouse.ts +80 -0
- package/src/memory/llm-request-log-source-local.ts +24 -0
- package/src/memory/llm-request-log-source.ts +31 -0
- package/src/memory/llm-request-log-store.ts +188 -3
- package/src/memory/memory-v2-activation-log-store.ts +95 -1
- package/src/memory/migrations/265-drop-provider-connection-status.ts +26 -0
- package/src/memory/migrations/266-messages-client-message-id.ts +43 -0
- package/src/memory/migrations/index.ts +2 -0
- package/src/memory/schema/conversations.ts +9 -1
- package/src/memory/schema/inference.ts +0 -1
- package/src/memory/v2/__tests__/backfill-jobs.test.ts +5 -2
- package/src/memory/v2/__tests__/harness-metrics.test.ts +9 -0
- package/src/memory/v2/__tests__/harness-replay-input.test.ts +9 -4
- package/src/memory/v2/__tests__/harness-runner.test.ts +26 -0
- package/src/memory/v2/__tests__/sweep-job.test.ts +6 -3
- package/src/memory/v2/harness/metrics.ts +5 -1
- package/src/memory/v2/harness/replay-input.ts +19 -3
- package/src/memory/v2/harness/runner.ts +6 -0
- package/src/memory/v2/harness/trace.ts +6 -0
- package/src/memory/v3/__tests__/consolidation-job.test.ts +2 -4
- package/src/memory/v3/__tests__/coretrieval-seed.test.ts +270 -0
- package/src/memory/v3/__tests__/edges.test.ts +144 -1
- package/src/memory/v3/__tests__/filter.test.ts +48 -0
- package/src/memory/v3/__tests__/gate.test.ts +96 -33
- package/src/memory/v3/__tests__/index-composition.test.ts +58 -0
- package/src/memory/v3/__tests__/loop.test.ts +250 -5
- package/src/memory/v3/__tests__/scouts.test.ts +49 -0
- package/src/memory/v3/__tests__/shadow-diff.test.ts +225 -0
- package/src/memory/v3/__tests__/shadow-middleware.test.ts +88 -2
- package/src/memory/v3/__tests__/traversal.test.ts +39 -0
- package/src/memory/v3/__tests__/tree-walk.test.ts +77 -0
- package/src/memory/v3/__tests__/validate.test.ts +32 -0
- package/src/memory/v3/coretrieval-seed.ts +240 -0
- package/src/memory/v3/edges.ts +58 -21
- package/src/memory/v3/filter.ts +27 -22
- package/src/memory/v3/gate.ts +51 -36
- package/src/memory/v3/index-composition.ts +18 -5
- package/src/memory/v3/loop.ts +65 -17
- package/src/memory/v3/scouts.ts +15 -4
- package/src/memory/v3/shadow-diff.ts +287 -0
- package/src/memory/v3/shadow-middleware.ts +44 -2
- package/src/memory/v3/traversal.ts +6 -1
- package/src/memory/v3/tree-walk.ts +6 -1
- package/src/memory/v3/validate.ts +56 -33
- package/src/notifications/__tests__/emit-signal-home-feed.test.ts +1 -0
- package/src/notifications/__tests__/home-feed-side-effect.test.ts +1 -0
- package/src/notifications/adapters/slack.ts +45 -11
- package/src/notifications/broadcaster.ts +114 -63
- package/src/notifications/conversation-pairing.ts +23 -3
- package/src/notifications/decisions-store.ts +32 -1
- package/src/notifications/deliveries-store.ts +45 -0
- package/src/notifications/edit-notification.ts +201 -0
- package/src/notifications/emit-signal.ts +11 -1
- package/src/notifications/signal.ts +10 -0
- package/src/notifications/types.ts +37 -0
- package/src/oauth/byo-connection.test.ts +67 -3
- package/src/oauth/byo-connection.ts +32 -5
- package/src/oauth/connect-orchestrator.ts +9 -0
- package/src/oauth/connection-resolver.test.ts +76 -0
- package/src/oauth/connection-resolver.ts +49 -10
- package/src/oauth/manual-token-connection.ts +51 -3
- package/src/oauth/seed-providers.ts +3 -0
- package/src/permissions/approval-policy.test.ts +19 -5
- package/src/permissions/approval-policy.ts +14 -3
- package/src/permissions/checker.ts +21 -8
- package/src/platform/client.test.ts +24 -1
- package/src/platform/client.ts +8 -0
- package/src/platform/feature-gate.ts +15 -0
- package/src/plugins/defaults/injectors.ts +2 -8
- package/src/plugins/defaults/persistence.ts +25 -6
- package/src/plugins/types.ts +57 -13
- package/src/proactive-artifact/job.test.ts +1 -0
- package/src/prompts/__tests__/system-prompt.test.ts +4 -4
- package/src/prompts/system-prompt.ts +38 -40
- package/src/prompts/template-detection.ts +10 -4
- package/src/prompts/templates/BOOTSTRAP.md +7 -11
- package/src/prompts/templates/IDENTITY.md +0 -2
- package/src/providers/__tests__/connection-model-compat.test.ts +3 -4
- package/src/providers/__tests__/registry-native-web-search.test.ts +122 -0
- package/src/providers/call-site-routing.ts +33 -9
- package/src/providers/connection-model-compat.ts +23 -0
- package/src/providers/connection-resolution.ts +39 -20
- package/src/providers/fireworks/client.ts +1 -0
- package/src/providers/gemini/client.ts +24 -3
- package/src/providers/inference/__tests__/adapter-factory-openai-compatible.test.ts +0 -2
- package/src/providers/inference/__tests__/base-url-security.test.ts +2 -3
- package/src/providers/inference/__tests__/{connections-status-label.test.ts → connections-label.test.ts} +12 -111
- package/src/providers/inference/auth.ts +0 -8
- package/src/providers/inference/connections.ts +3 -66
- package/src/providers/inference/resolve-auth.ts +2 -3
- package/src/providers/model-catalog.ts +35 -1
- package/src/providers/model-intents.ts +3 -3
- package/src/providers/openai/__tests__/api-error-detail.test.ts +120 -0
- package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +157 -5
- package/src/providers/openai/chat-completions-provider.ts +110 -12
- package/src/providers/openai/codex-models.ts +2 -0
- package/src/providers/openai/responses-provider.ts +53 -53
- package/src/providers/openrouter/client.ts +13 -8
- package/src/providers/provider-send-message.ts +18 -9
- package/src/providers/registry.ts +48 -8
- package/src/providers/retry.ts +16 -4
- package/src/providers/search-provider-catalog.ts +17 -9
- package/src/providers/types.ts +9 -0
- package/src/runtime/__tests__/agent-wake.test.ts +1 -0
- package/src/runtime/__tests__/background-job-runner.test.ts +1 -0
- package/src/runtime/access-request-helper.ts +1 -0
- package/src/runtime/auth/route-policy.ts +10 -0
- package/src/runtime/channel-readiness-service.ts +68 -0
- package/src/runtime/channel-reply-delivery.ts +23 -0
- package/src/runtime/channel-retry-sweep.ts +47 -14
- package/src/runtime/confirmation-request-guardian-bridge.ts +1 -1
- package/src/runtime/migrations/vbundle-builder.ts +3 -2
- package/src/runtime/routes/__tests__/bookmark-routes.test.ts +1 -0
- package/src/runtime/routes/__tests__/conversation-compaction-routes.test.ts +406 -0
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +98 -0
- package/src/runtime/routes/__tests__/heartbeat-routes.test.ts +1 -1
- package/src/runtime/routes/__tests__/home-feed-routes.test.ts +209 -1
- package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +13 -50
- package/src/runtime/routes/__tests__/memory-v2-simulate-route.test.ts +51 -3
- package/src/runtime/routes/__tests__/memory-v3-simulate-params.test.ts +35 -0
- package/src/runtime/routes/__tests__/slack-channel-routes.test.ts +3 -2
- package/src/runtime/routes/__tests__/surface-content-routes.test.ts +294 -0
- package/src/runtime/routes/__tests__/task-routes.test.ts +48 -3
- package/src/runtime/routes/acp-routes-list.test.ts +3 -0
- package/src/runtime/routes/app-management-routes.ts +111 -4
- package/src/runtime/routes/background-wake-routes.ts +188 -20
- package/src/runtime/routes/btw-routes.ts +4 -4
- package/src/runtime/routes/conversation-analysis-routes.ts +6 -0
- package/src/runtime/routes/conversation-compaction-routes.ts +263 -0
- package/src/runtime/routes/conversation-list-routes.ts +147 -0
- package/src/runtime/routes/conversation-management-routes.ts +39 -14
- package/src/runtime/routes/conversation-query-routes.ts +60 -10
- package/src/runtime/routes/conversation-routes.ts +186 -140
- package/src/runtime/routes/conversations-import-routes.ts +19 -6
- package/src/runtime/routes/documents-routes.ts +10 -1
- package/src/runtime/routes/group-routes.ts +11 -0
- package/src/runtime/routes/home-feed-routes.ts +129 -0
- package/src/runtime/routes/identity-intro-cache.ts +61 -16
- package/src/runtime/routes/identity-routes.ts +30 -9
- package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +530 -6
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +57 -8
- package/src/runtime/routes/index.ts +2 -0
- package/src/runtime/routes/inference-provider-connection-routes.ts +5 -26
- package/src/runtime/routes/integrations/vercel.ts +15 -0
- package/src/runtime/routes/llm-context-normalization.ts +7 -2
- package/src/runtime/routes/memory-v3-routes.ts +160 -2
- package/src/runtime/routes/migration-routes.ts +20 -13
- package/src/runtime/routes/notification-routes.ts +63 -1
- package/src/runtime/routes/oauth-commands-routes.ts +6 -1
- package/src/runtime/routes/surface-action-routes.ts +1 -38
- package/src/runtime/routes/surface-content-routes.ts +12 -5
- package/src/runtime/routes/surface-conversation-resolver.ts +65 -0
- package/src/runtime/routes/wipe-conversation-routes.ts +3 -0
- package/src/runtime/services/__tests__/analyze-conversation.test.ts +2 -0
- package/src/runtime/slack-dm-text-delivery.ts +177 -0
- package/src/runtime/sync/resource-sync-events.ts +1 -1
- package/src/runtime/tool-grant-request-helper.ts +1 -0
- package/src/schedule/schedule-store.ts +8 -1
- package/src/schedule/scheduler.ts +111 -15
- package/src/security/__tests__/provider-key-env-fallback.test.ts +3 -3
- package/src/security/encrypted-store.ts +7 -16
- package/src/security/store-path-override.ts +61 -0
- package/src/signals/user-message.ts +5 -8
- package/src/skills/validate-input.ts +177 -0
- package/src/subagent/manager.ts +13 -13
- package/src/subagent/types.ts +6 -0
- package/src/tasks/tool-sanitizer.ts +2 -2
- package/src/tools/apps/definitions.ts +35 -21
- package/src/tools/browser/__tests__/browser-execution-acquire.test.ts +2 -8
- package/src/tools/computer-use/definitions.ts +268 -266
- package/src/tools/document/document-tool.ts +131 -8
- package/src/tools/execution-target.ts +2 -5
- package/src/tools/executor.ts +18 -55
- package/src/tools/host-filesystem/edit.test.ts +1 -0
- package/src/tools/host-filesystem/read.test.ts +1 -0
- package/src/tools/host-filesystem/transfer.test.ts +31 -6
- package/src/tools/host-filesystem/write.test.ts +1 -0
- package/src/tools/mcp/mcp-tool-factory.ts +0 -2
- package/src/tools/network/__tests__/managed-search-proxy.test.ts +282 -0
- package/src/tools/network/__tests__/web-search.test.ts +211 -3
- package/src/tools/network/managed-search-proxy.ts +183 -0
- package/src/tools/network/web-search.ts +199 -44
- package/src/tools/policy-context.ts +3 -1
- package/src/tools/registry.ts +146 -103
- package/src/tools/schedule/create.ts +1 -1
- package/src/tools/skills/skill-tool-factory.ts +17 -36
- package/src/tools/subagent/spawn.ts +3 -0
- package/src/tools/tool-approval-handler.ts +10 -4
- package/src/tools/tool-name-aliases.ts +72 -14
- package/src/tools/types.ts +17 -15
- package/src/tools/ui-surface/definitions.ts +98 -86
- package/src/types/onboarding-context.ts +6 -0
- package/src/usage/attribution.ts +32 -1
- package/src/util/browser.ts +7 -2
- package/src/workspace/migrations/090-memory-router-cost-optimized-profile.ts +109 -0
- package/src/workspace/migrations/091-retighten-migration-onboarding-thread.ts +41 -0
- package/src/workspace/migrations/registry.ts +4 -0
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import { VellumPlatformClient } from "../../platform/client.js";
|
|
2
|
+
|
|
3
|
+
export type ManagedSearchProxyProvider = "brave";
|
|
4
|
+
|
|
5
|
+
export interface ManagedSearchProxyRequest {
|
|
6
|
+
method: string;
|
|
7
|
+
path: string;
|
|
8
|
+
query?: Record<string, string>;
|
|
9
|
+
headers?: Record<string, string>;
|
|
10
|
+
body?: unknown;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface ManagedSearchProxyResponse {
|
|
14
|
+
status: number;
|
|
15
|
+
headers: Record<string, string>;
|
|
16
|
+
body: unknown;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export type ManagedSearchProxyResult =
|
|
20
|
+
| ({ ok: true } & ManagedSearchProxyResponse)
|
|
21
|
+
| {
|
|
22
|
+
ok: false;
|
|
23
|
+
kind: "unavailable";
|
|
24
|
+
message: string;
|
|
25
|
+
}
|
|
26
|
+
| {
|
|
27
|
+
ok: false;
|
|
28
|
+
kind: "platform-error";
|
|
29
|
+
status: number;
|
|
30
|
+
headers: Record<string, string>;
|
|
31
|
+
body: unknown;
|
|
32
|
+
message: string;
|
|
33
|
+
}
|
|
34
|
+
| {
|
|
35
|
+
ok: false;
|
|
36
|
+
kind: "invalid-response";
|
|
37
|
+
body: unknown;
|
|
38
|
+
message: string;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
interface ManagedSearchProxyEnvelope {
|
|
42
|
+
request: {
|
|
43
|
+
method: string;
|
|
44
|
+
path: string;
|
|
45
|
+
query: Record<string, string>;
|
|
46
|
+
headers: Record<string, string>;
|
|
47
|
+
body: unknown;
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export async function callManagedSearchProxy(
|
|
52
|
+
provider: ManagedSearchProxyProvider,
|
|
53
|
+
request: ManagedSearchProxyRequest,
|
|
54
|
+
signal?: AbortSignal,
|
|
55
|
+
): Promise<ManagedSearchProxyResult> {
|
|
56
|
+
const client = await VellumPlatformClient.create();
|
|
57
|
+
if (!client) {
|
|
58
|
+
return {
|
|
59
|
+
ok: false,
|
|
60
|
+
kind: "unavailable",
|
|
61
|
+
message: "Managed search proxy is unavailable in this environment.",
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (!client.platformAssistantId) {
|
|
66
|
+
return {
|
|
67
|
+
ok: false,
|
|
68
|
+
kind: "unavailable",
|
|
69
|
+
message:
|
|
70
|
+
"Managed search proxy is unavailable: platform assistant ID is missing.",
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const path = `/v1/assistants/${encodeURIComponent(
|
|
75
|
+
client.platformAssistantId,
|
|
76
|
+
)}/managed-search-proxy/${encodeURIComponent(provider)}/`;
|
|
77
|
+
|
|
78
|
+
const envelope: ManagedSearchProxyEnvelope = {
|
|
79
|
+
request: {
|
|
80
|
+
method: request.method,
|
|
81
|
+
path: request.path,
|
|
82
|
+
query: request.query ?? {},
|
|
83
|
+
headers: request.headers ?? {},
|
|
84
|
+
body: request.body ?? null,
|
|
85
|
+
},
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
const response = await client.fetch(path, {
|
|
89
|
+
method: "POST",
|
|
90
|
+
headers: {
|
|
91
|
+
"Content-Type": "application/json",
|
|
92
|
+
},
|
|
93
|
+
body: JSON.stringify(envelope),
|
|
94
|
+
signal,
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
if (!response.ok) {
|
|
98
|
+
const body = await readResponseBody(response);
|
|
99
|
+
return {
|
|
100
|
+
ok: false,
|
|
101
|
+
kind: "platform-error",
|
|
102
|
+
status: response.status,
|
|
103
|
+
headers: responseHeadersToRecord(response.headers),
|
|
104
|
+
body,
|
|
105
|
+
message: platformErrorMessage(response.status, body),
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const body = await readResponseBody(response);
|
|
110
|
+
if (!isManagedSearchProxyResponse(body)) {
|
|
111
|
+
return {
|
|
112
|
+
ok: false,
|
|
113
|
+
kind: "invalid-response",
|
|
114
|
+
body,
|
|
115
|
+
message: "Managed search proxy returned an invalid response envelope.",
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return {
|
|
120
|
+
ok: true,
|
|
121
|
+
status: body.status,
|
|
122
|
+
headers: body.headers,
|
|
123
|
+
body: body.body,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function isManagedSearchProxyResponse(
|
|
128
|
+
value: unknown,
|
|
129
|
+
): value is ManagedSearchProxyResponse {
|
|
130
|
+
if (!isRecord(value)) return false;
|
|
131
|
+
if (typeof value.status !== "number") return false;
|
|
132
|
+
if (!isStringRecord(value.headers)) return false;
|
|
133
|
+
return "body" in value;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
async function readResponseBody(response: Response): Promise<unknown> {
|
|
137
|
+
const text = await response.text().catch(() => "");
|
|
138
|
+
if (!text) return null;
|
|
139
|
+
|
|
140
|
+
const contentType = response.headers.get("content-type") ?? "";
|
|
141
|
+
if (contentType.includes("application/json")) {
|
|
142
|
+
try {
|
|
143
|
+
return JSON.parse(text);
|
|
144
|
+
} catch {
|
|
145
|
+
return text;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return text;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function responseHeadersToRecord(headers: Headers): Record<string, string> {
|
|
153
|
+
return Object.fromEntries(headers.entries());
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function platformErrorMessage(status: number, body: unknown): string {
|
|
157
|
+
const detail = extractErrorDetail(body);
|
|
158
|
+
if (detail) {
|
|
159
|
+
return `Managed search proxy returned status ${status}: ${detail}`;
|
|
160
|
+
}
|
|
161
|
+
return `Managed search proxy returned status ${status}.`;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function extractErrorDetail(body: unknown): string | undefined {
|
|
165
|
+
if (typeof body === "string") return body || undefined;
|
|
166
|
+
if (!isRecord(body)) return undefined;
|
|
167
|
+
|
|
168
|
+
for (const key of ["detail", "error", "message"]) {
|
|
169
|
+
const value = body[key];
|
|
170
|
+
if (typeof value === "string" && value) return value;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
return undefined;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
177
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function isStringRecord(value: unknown): value is Record<string, string> {
|
|
181
|
+
if (!isRecord(value)) return false;
|
|
182
|
+
return Object.values(value).every((entry) => typeof entry === "string");
|
|
183
|
+
}
|
|
@@ -17,14 +17,17 @@ import {
|
|
|
17
17
|
import { registerTool } from "../registry.js";
|
|
18
18
|
import type { Tool, ToolContext, ToolExecutionResult } from "../types.js";
|
|
19
19
|
import { extractDomain } from "./domain-normalize.js";
|
|
20
|
+
import type { ManagedSearchProxyResult } from "./managed-search-proxy.js";
|
|
20
21
|
|
|
21
22
|
const log = getLogger("web-search");
|
|
22
23
|
|
|
23
|
-
const
|
|
24
|
+
const BRAVE_SEARCH_PATH = "/res/v1/web/search";
|
|
25
|
+
const BRAVE_API_URL = `https://api.search.brave.com${BRAVE_SEARCH_PATH}`;
|
|
24
26
|
const PERPLEXITY_API_URL = "https://api.perplexity.ai/chat/completions";
|
|
25
27
|
const TAVILY_API_URL = "https://api.tavily.com/search";
|
|
26
28
|
|
|
27
29
|
type WebSearchProvider = "perplexity" | "brave" | "tavily";
|
|
30
|
+
type WebSearchMode = "managed" | "your-own";
|
|
28
31
|
|
|
29
32
|
/**
|
|
30
33
|
* Arguments passed to every {@link WebSearchAdapter}. The full superset is
|
|
@@ -49,7 +52,7 @@ interface WebSearchAdapter {
|
|
|
49
52
|
/** Stable provider identifier (matches config + secret-catalog values). */
|
|
50
53
|
readonly id: WebSearchProvider;
|
|
51
54
|
/** Secret-catalog key used to look up the API key via `getProviderKeyAsync`. */
|
|
52
|
-
readonly
|
|
55
|
+
readonly providerKeyName: string;
|
|
53
56
|
/**
|
|
54
57
|
* Position in the fallback chain (lower = earlier). Used when the
|
|
55
58
|
* configured provider has no key and we try other BYOK providers.
|
|
@@ -98,17 +101,27 @@ interface TavilySearchResponse {
|
|
|
98
101
|
function getWebSearchProvider(): WebSearchProvider {
|
|
99
102
|
const config = getConfig();
|
|
100
103
|
const configured = config.services["web-search"].provider ?? "perplexity";
|
|
101
|
-
//
|
|
102
|
-
//
|
|
104
|
+
// In Your Own mode, `inference-provider-native` is only executable when the
|
|
105
|
+
// inference provider swaps this tool for a native hosted-search definition.
|
|
106
|
+
// If this app-executed tool is still invoked, fall back to the existing BYOK
|
|
107
|
+
// provider chain. Managed mode short-circuits before this function and uses
|
|
108
|
+
// the platform search proxy instead.
|
|
103
109
|
if (configured === "inference-provider-native") return "perplexity";
|
|
104
110
|
return configured as WebSearchProvider;
|
|
105
111
|
}
|
|
106
112
|
|
|
113
|
+
function getWebSearchMode(): WebSearchMode {
|
|
114
|
+
const config = getConfig();
|
|
115
|
+
return config.services["web-search"].mode === "managed"
|
|
116
|
+
? "managed"
|
|
117
|
+
: "your-own";
|
|
118
|
+
}
|
|
119
|
+
|
|
107
120
|
async function getApiKey(
|
|
108
121
|
provider: WebSearchProvider,
|
|
109
122
|
): Promise<string | undefined> {
|
|
110
123
|
const adapter = WEB_SEARCH_ADAPTERS[provider];
|
|
111
|
-
return (await getProviderKeyAsync(adapter.
|
|
124
|
+
return (await getProviderKeyAsync(adapter.providerKeyName)) ?? undefined;
|
|
112
125
|
}
|
|
113
126
|
|
|
114
127
|
function fallbackProvidersFor(
|
|
@@ -232,6 +245,46 @@ function buildBraveMetadata(
|
|
|
232
245
|
};
|
|
233
246
|
}
|
|
234
247
|
|
|
248
|
+
function braveQueryParams(
|
|
249
|
+
query: string,
|
|
250
|
+
count: number,
|
|
251
|
+
offset: number,
|
|
252
|
+
freshness: string | undefined,
|
|
253
|
+
): Record<string, string> {
|
|
254
|
+
const params: Record<string, string> = {
|
|
255
|
+
q: query,
|
|
256
|
+
count: String(count),
|
|
257
|
+
offset: String(offset),
|
|
258
|
+
};
|
|
259
|
+
|
|
260
|
+
const validFreshness = ["pd", "pw", "pm", "py"];
|
|
261
|
+
if (freshness && validFreshness.includes(freshness)) {
|
|
262
|
+
params.freshness = freshness;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
return params;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
function successfulBraveResult(
|
|
269
|
+
data: BraveSearchResponse,
|
|
270
|
+
query: string,
|
|
271
|
+
startedAt: number,
|
|
272
|
+
): ToolExecutionResult {
|
|
273
|
+
const results = data.web?.results ?? [];
|
|
274
|
+
const durationMs = Date.now() - startedAt;
|
|
275
|
+
return {
|
|
276
|
+
content:
|
|
277
|
+
wrapUntrustedContent(formatBraveResults(results, query), {
|
|
278
|
+
source: "search",
|
|
279
|
+
sourceDetail: "brave",
|
|
280
|
+
}) + CITATION_INSTRUCTION,
|
|
281
|
+
isError: false,
|
|
282
|
+
activityMetadata: {
|
|
283
|
+
webSearch: buildBraveMetadata(results, query, durationMs),
|
|
284
|
+
},
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
|
|
235
288
|
function buildPerplexityMetadata(
|
|
236
289
|
data: PerplexityResponse,
|
|
237
290
|
query: string,
|
|
@@ -332,17 +385,9 @@ async function executeBraveSearch(
|
|
|
332
385
|
apiKey: string,
|
|
333
386
|
signal?: AbortSignal,
|
|
334
387
|
): Promise<ToolExecutionResult> {
|
|
335
|
-
const params = new URLSearchParams(
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
offset: String(offset),
|
|
339
|
-
});
|
|
340
|
-
|
|
341
|
-
const validFreshness = ["pd", "pw", "pm", "py"];
|
|
342
|
-
if (freshness && validFreshness.includes(freshness)) {
|
|
343
|
-
params.set("freshness", freshness);
|
|
344
|
-
}
|
|
345
|
-
|
|
388
|
+
const params = new URLSearchParams(
|
|
389
|
+
braveQueryParams(query, count, offset, freshness),
|
|
390
|
+
);
|
|
346
391
|
const url = `${BRAVE_API_URL}?${params.toString()}`;
|
|
347
392
|
const startedAt = Date.now();
|
|
348
393
|
|
|
@@ -358,19 +403,7 @@ async function executeBraveSearch(
|
|
|
358
403
|
|
|
359
404
|
if (response.ok) {
|
|
360
405
|
const data = (await response.json()) as BraveSearchResponse;
|
|
361
|
-
|
|
362
|
-
const durationMs = Date.now() - startedAt;
|
|
363
|
-
return {
|
|
364
|
-
content:
|
|
365
|
-
wrapUntrustedContent(formatBraveResults(results, query), {
|
|
366
|
-
source: "search",
|
|
367
|
-
sourceDetail: "brave",
|
|
368
|
-
}) + CITATION_INSTRUCTION,
|
|
369
|
-
isError: false,
|
|
370
|
-
activityMetadata: {
|
|
371
|
-
webSearch: buildBraveMetadata(results, query, durationMs),
|
|
372
|
-
},
|
|
373
|
-
};
|
|
406
|
+
return successfulBraveResult(data, query, startedAt);
|
|
374
407
|
}
|
|
375
408
|
|
|
376
409
|
await response.text();
|
|
@@ -417,6 +450,90 @@ async function executeBraveSearch(
|
|
|
417
450
|
);
|
|
418
451
|
}
|
|
419
452
|
|
|
453
|
+
async function executeManagedBraveSearch(
|
|
454
|
+
query: string,
|
|
455
|
+
count: number,
|
|
456
|
+
offset: number,
|
|
457
|
+
freshness: string | undefined,
|
|
458
|
+
signal?: AbortSignal,
|
|
459
|
+
): Promise<ToolExecutionResult> {
|
|
460
|
+
const { callManagedSearchProxy } = await import("./managed-search-proxy.js");
|
|
461
|
+
const startedAt = Date.now();
|
|
462
|
+
const proxyResult = await callManagedSearchProxy(
|
|
463
|
+
"brave",
|
|
464
|
+
{
|
|
465
|
+
method: "GET",
|
|
466
|
+
path: BRAVE_SEARCH_PATH,
|
|
467
|
+
query: braveQueryParams(query, count, offset, freshness),
|
|
468
|
+
headers: {
|
|
469
|
+
Accept: "application/json",
|
|
470
|
+
},
|
|
471
|
+
body: null,
|
|
472
|
+
},
|
|
473
|
+
signal,
|
|
474
|
+
);
|
|
475
|
+
|
|
476
|
+
if (!proxyResult.ok) {
|
|
477
|
+
return errorResult(
|
|
478
|
+
query,
|
|
479
|
+
"brave",
|
|
480
|
+
startedAt,
|
|
481
|
+
managedSearchProxyErrorMessage(proxyResult),
|
|
482
|
+
);
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
if (proxyResult.status >= 200 && proxyResult.status < 300) {
|
|
486
|
+
return successfulBraveResult(
|
|
487
|
+
proxyResult.body as BraveSearchResponse,
|
|
488
|
+
query,
|
|
489
|
+
startedAt,
|
|
490
|
+
);
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
if (proxyResult.status === 401 || proxyResult.status === 403) {
|
|
494
|
+
return errorResult(
|
|
495
|
+
query,
|
|
496
|
+
"brave",
|
|
497
|
+
startedAt,
|
|
498
|
+
"Managed Brave Search is not authenticated correctly. This is a Vellum platform configuration issue.",
|
|
499
|
+
);
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
if (proxyResult.status === 429) {
|
|
503
|
+
return errorResult(
|
|
504
|
+
query,
|
|
505
|
+
"brave",
|
|
506
|
+
startedAt,
|
|
507
|
+
"Managed Brave Search rate limit exceeded. Try again shortly.",
|
|
508
|
+
);
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
return errorResult(
|
|
512
|
+
query,
|
|
513
|
+
"brave",
|
|
514
|
+
startedAt,
|
|
515
|
+
`Managed Brave Search provider returned status ${proxyResult.status}`,
|
|
516
|
+
);
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
function managedSearchProxyErrorMessage(
|
|
520
|
+
result: Exclude<ManagedSearchProxyResult, { ok: true }>,
|
|
521
|
+
): string {
|
|
522
|
+
if (result.kind === "unavailable") {
|
|
523
|
+
return `${result.message} Log in to Vellum or switch web search to Your Own mode.`;
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
if (result.kind === "platform-error" && result.status === 402) {
|
|
527
|
+
return "Managed web search is unavailable because your Vellum account balance is too low. Add funds or switch web search to Your Own mode.";
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
if (result.kind === "platform-error") {
|
|
531
|
+
return `Managed web search platform request failed: ${result.message}`;
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
return result.message;
|
|
535
|
+
}
|
|
536
|
+
|
|
420
537
|
async function executePerplexitySearch(
|
|
421
538
|
query: string,
|
|
422
539
|
apiKey: string,
|
|
@@ -599,7 +716,7 @@ async function executeTavilySearch(
|
|
|
599
716
|
|
|
600
717
|
const perplexitySearchAdapter: WebSearchAdapter = {
|
|
601
718
|
id: "perplexity",
|
|
602
|
-
|
|
719
|
+
providerKeyName: "perplexity",
|
|
603
720
|
fallbackOrder: 1,
|
|
604
721
|
execute: ({ query, apiKey, signal }) =>
|
|
605
722
|
executePerplexitySearch(query, apiKey, signal),
|
|
@@ -607,15 +724,23 @@ const perplexitySearchAdapter: WebSearchAdapter = {
|
|
|
607
724
|
|
|
608
725
|
const braveSearchAdapter: WebSearchAdapter = {
|
|
609
726
|
id: "brave",
|
|
610
|
-
|
|
727
|
+
providerKeyName: "brave",
|
|
611
728
|
fallbackOrder: 2,
|
|
612
729
|
execute: ({ query, count, offset, freshness, apiKey, signal }) =>
|
|
613
730
|
executeBraveSearch(query, count, offset, freshness, apiKey, signal),
|
|
614
731
|
};
|
|
615
732
|
|
|
733
|
+
const managedBraveSearchAdapter: WebSearchAdapter = {
|
|
734
|
+
id: "brave",
|
|
735
|
+
providerKeyName: "brave",
|
|
736
|
+
fallbackOrder: 2,
|
|
737
|
+
execute: ({ query, count, offset, freshness, signal }) =>
|
|
738
|
+
executeManagedBraveSearch(query, count, offset, freshness, signal),
|
|
739
|
+
};
|
|
740
|
+
|
|
616
741
|
const tavilySearchAdapter: WebSearchAdapter = {
|
|
617
742
|
id: "tavily",
|
|
618
|
-
|
|
743
|
+
providerKeyName: "tavily",
|
|
619
744
|
fallbackOrder: 3,
|
|
620
745
|
execute: ({ query, count, freshness, apiKey, signal }) =>
|
|
621
746
|
executeTavilySearch(query, count, freshness, apiKey, signal),
|
|
@@ -690,6 +815,42 @@ class WebSearchTool implements Tool {
|
|
|
690
815
|
}
|
|
691
816
|
|
|
692
817
|
const startedAt = Date.now();
|
|
818
|
+
const mode = getWebSearchMode();
|
|
819
|
+
|
|
820
|
+
const count =
|
|
821
|
+
typeof input.count === "number"
|
|
822
|
+
? Math.min(20, Math.max(1, Math.round(input.count)))
|
|
823
|
+
: 10;
|
|
824
|
+
const offset =
|
|
825
|
+
typeof input.offset === "number"
|
|
826
|
+
? Math.min(9, Math.max(0, Math.round(input.offset)))
|
|
827
|
+
: 0;
|
|
828
|
+
const freshness =
|
|
829
|
+
typeof input.freshness === "string" ? input.freshness : undefined;
|
|
830
|
+
|
|
831
|
+
if (mode === "managed") {
|
|
832
|
+
try {
|
|
833
|
+
log.debug({ query, provider: "brave" }, "Executing managed web search");
|
|
834
|
+
return await managedBraveSearchAdapter.execute({
|
|
835
|
+
query,
|
|
836
|
+
count,
|
|
837
|
+
offset,
|
|
838
|
+
freshness,
|
|
839
|
+
apiKey: "",
|
|
840
|
+
signal: context.signal,
|
|
841
|
+
});
|
|
842
|
+
} catch (err) {
|
|
843
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
844
|
+
log.error({ err }, "Managed web search failed");
|
|
845
|
+
return errorResult(
|
|
846
|
+
query,
|
|
847
|
+
"brave",
|
|
848
|
+
startedAt,
|
|
849
|
+
`Managed web search failed: ${msg}`,
|
|
850
|
+
);
|
|
851
|
+
}
|
|
852
|
+
}
|
|
853
|
+
|
|
693
854
|
let provider = getWebSearchProvider();
|
|
694
855
|
let apiKey = await getApiKey(provider);
|
|
695
856
|
|
|
@@ -723,17 +884,6 @@ class WebSearchTool implements Tool {
|
|
|
723
884
|
try {
|
|
724
885
|
log.debug({ query, provider }, "Executing web search");
|
|
725
886
|
|
|
726
|
-
const count =
|
|
727
|
-
typeof input.count === "number"
|
|
728
|
-
? Math.min(20, Math.max(1, Math.round(input.count)))
|
|
729
|
-
: 10;
|
|
730
|
-
const offset =
|
|
731
|
-
typeof input.offset === "number"
|
|
732
|
-
? Math.min(9, Math.max(0, Math.round(input.offset)))
|
|
733
|
-
: 0;
|
|
734
|
-
const freshness =
|
|
735
|
-
typeof input.freshness === "string" ? input.freshness : undefined;
|
|
736
|
-
|
|
737
887
|
return await WEB_SEARCH_ADAPTERS[provider].execute({
|
|
738
888
|
query,
|
|
739
889
|
count,
|
|
@@ -745,7 +895,12 @@ class WebSearchTool implements Tool {
|
|
|
745
895
|
} catch (err) {
|
|
746
896
|
const msg = err instanceof Error ? err.message : String(err);
|
|
747
897
|
log.error({ err }, "Web search failed");
|
|
748
|
-
return errorResult(
|
|
898
|
+
return errorResult(
|
|
899
|
+
query,
|
|
900
|
+
provider,
|
|
901
|
+
startedAt,
|
|
902
|
+
`Web search failed: ${msg}`,
|
|
903
|
+
);
|
|
749
904
|
}
|
|
750
905
|
}
|
|
751
906
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ExecutionContext } from "../permissions/approval-policy.js";
|
|
2
2
|
import type { PolicyContext } from "../permissions/types.js";
|
|
3
|
+
import { getToolOwner } from "./registry.js";
|
|
3
4
|
import type { Tool, ToolContext } from "./types.js";
|
|
4
5
|
|
|
5
6
|
/**
|
|
@@ -31,7 +32,8 @@ export function buildPolicyContext(
|
|
|
31
32
|
|
|
32
33
|
const conversationId = context?.conversationId;
|
|
33
34
|
|
|
34
|
-
|
|
35
|
+
const ownerKind = getToolOwner(tool.name)?.kind;
|
|
36
|
+
if (ownerKind === "skill" || ownerKind === "plugin") {
|
|
35
37
|
return {
|
|
36
38
|
executionTarget: tool.executionTarget,
|
|
37
39
|
executionContext,
|