@vellumai/assistant 0.4.52 → 0.4.54
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 +2 -2
- package/bun.lock +62 -349
- package/docs/architecture/integrations.md +1 -1
- package/docs/architecture/keychain-broker.md +91 -40
- package/docs/architecture/memory.md +3 -3
- package/docs/architecture/security.md +2 -2
- package/knip.json +7 -29
- package/package.json +2 -9
- package/src/__tests__/agent-loop.test.ts +1 -1
- package/src/__tests__/app-git-history.test.ts +0 -2
- package/src/__tests__/app-git-service.test.ts +1 -6
- package/src/__tests__/approval-cascade.test.ts +3 -2
- package/src/__tests__/approval-routes-http.test.ts +0 -1
- package/src/__tests__/asset-materialize-tool.test.ts +0 -1
- package/src/__tests__/asset-search-tool.test.ts +0 -1
- package/src/__tests__/assistant-events-sse-hardening.test.ts +0 -1
- package/src/__tests__/attachments-store.test.ts +0 -1
- package/src/__tests__/avatar-e2e.test.ts +5 -1
- package/src/__tests__/browser-fill-credential.test.ts +4 -6
- package/src/__tests__/btw-routes.test.ts +39 -0
- package/src/__tests__/call-controller.test.ts +0 -1
- package/src/__tests__/call-domain.test.ts +1 -1
- package/src/__tests__/call-routes-http.test.ts +1 -3
- package/src/__tests__/canonical-guardian-store.test.ts +33 -2
- package/src/__tests__/channel-guardian.test.ts +4 -4
- package/src/__tests__/channel-readiness-routes.test.ts +0 -1
- package/src/__tests__/channel-readiness-service.test.ts +1 -1
- package/src/__tests__/checker.test.ts +13 -11
- package/src/__tests__/claude-code-skill-regression.test.ts +5 -2
- package/src/__tests__/claude-code-tool-profiles.test.ts +7 -3
- package/src/__tests__/config-loader-backfill.test.ts +1 -5
- package/src/__tests__/config-schema.test.ts +9 -46
- package/src/__tests__/config-watcher.test.ts +11 -3
- package/src/__tests__/conversation-routes-slash-commands.test.ts +0 -1
- package/src/__tests__/credential-broker-browser-fill.test.ts +27 -24
- package/src/__tests__/credential-broker-server-use.test.ts +76 -40
- package/src/__tests__/credential-security-e2e.test.ts +1 -6
- package/src/__tests__/credential-security-invariants.test.ts +27 -8
- package/src/__tests__/credential-vault-unit.test.ts +32 -16
- package/src/__tests__/credential-vault.test.ts +40 -28
- package/src/__tests__/credentials-cli.test.ts +1 -21
- package/src/__tests__/email-invite-adapter.test.ts +0 -1
- package/src/__tests__/error-handler-friendly-messages.test.ts +4 -5
- package/src/__tests__/fixtures/credential-security-fixtures.ts +3 -3
- package/src/__tests__/fixtures/media-reuse-fixtures.ts +3 -79
- package/src/__tests__/gateway-only-enforcement.test.ts +1 -23
- package/src/__tests__/guardian-action-conversation-turn.test.ts +8 -8
- package/src/__tests__/guardian-action-late-reply.test.ts +13 -14
- package/src/__tests__/guardian-action-store.test.ts +0 -57
- package/src/__tests__/guardian-outbound-http.test.ts +1 -1
- package/src/__tests__/guardian-verification-voice-binding.test.ts +1 -3
- package/src/__tests__/hooks-blocking.test.ts +1 -1
- package/src/__tests__/hooks-config.test.ts +5 -29
- package/src/__tests__/hooks-discovery.test.ts +1 -1
- package/src/__tests__/hooks-integration.test.ts +1 -1
- package/src/__tests__/hooks-manager.test.ts +1 -1
- package/src/__tests__/hooks-runner.test.ts +1 -23
- package/src/__tests__/hooks-settings.test.ts +1 -1
- package/src/__tests__/hooks-templates.test.ts +1 -1
- package/src/__tests__/host-shell-tool.test.ts +0 -1
- package/src/__tests__/http-user-message-parity.test.ts +19 -0
- package/src/__tests__/integration-status.test.ts +0 -1
- package/src/__tests__/invite-routes-http.test.ts +0 -3
- package/src/__tests__/list-messages-attachments.test.ts +0 -1
- package/src/__tests__/llm-usage-store.test.ts +50 -0
- package/src/__tests__/log-export-workspace.test.ts +233 -0
- package/src/__tests__/managed-proxy-context.test.ts +41 -41
- package/src/__tests__/managed-skill-lifecycle.test.ts +0 -1
- package/src/__tests__/media-generate-image.test.ts +9 -4
- package/src/__tests__/media-reuse-story.e2e.test.ts +1 -7
- package/src/__tests__/memory-regressions.experimental.test.ts +4 -4
- package/src/__tests__/memory-regressions.test.ts +27 -28
- package/src/__tests__/memory-retrieval.benchmark.test.ts +1 -1
- package/src/__tests__/memory-upsert-concurrency.test.ts +4 -4
- package/src/__tests__/migration-cross-version-compatibility.test.ts +0 -1
- package/src/__tests__/migration-export-http.test.ts +0 -1
- package/src/__tests__/migration-import-commit-http.test.ts +0 -1
- package/src/__tests__/migration-import-preflight-http.test.ts +0 -1
- package/src/__tests__/migration-validate-http.test.ts +0 -1
- package/src/__tests__/notification-decision-fallback.test.ts +1 -1
- package/src/__tests__/notification-schedule-dedup.test.ts +237 -0
- package/src/__tests__/oauth-cli.test.ts +2 -14
- package/src/__tests__/oauth-store.test.ts +3 -7
- package/src/__tests__/oauth2-gateway-transport.test.ts +5 -4
- package/src/__tests__/onboarding-starter-tasks.test.ts +1 -1
- package/src/__tests__/onboarding-template-contract.test.ts +1 -2
- package/src/__tests__/openai-provider.test.ts +7 -7
- package/src/__tests__/platform.test.ts +14 -4
- package/src/__tests__/pricing.test.ts +0 -234
- package/src/__tests__/provider-commit-message-generator.test.ts +19 -15
- package/src/__tests__/provider-fail-open-selection.test.ts +67 -62
- package/src/__tests__/provider-managed-proxy-integration.test.ts +88 -85
- package/src/__tests__/provider-registry-ollama.test.ts +10 -4
- package/src/__tests__/public-ingress-urls.test.ts +1 -1
- package/src/__tests__/recording-handler.test.ts +0 -1
- package/src/__tests__/registry.test.ts +3 -103
- package/src/__tests__/relay-server.test.ts +0 -1
- package/src/__tests__/runtime-attachment-metadata.test.ts +0 -1
- package/src/__tests__/runtime-events-sse-parity.test.ts +0 -1
- package/src/__tests__/runtime-events-sse.test.ts +0 -1
- package/src/__tests__/script-proxy-injection-runtime.test.ts +2 -7
- package/src/__tests__/secret-onetime-send.test.ts +1 -6
- package/src/__tests__/secret-routes-managed-proxy.test.ts +6 -14
- package/src/__tests__/secret-scanner-executor.test.ts +0 -1
- package/src/__tests__/secure-keys.test.ts +241 -229
- package/src/__tests__/send-endpoint-busy.test.ts +0 -1
- package/src/__tests__/session-abort-tool-results.test.ts +3 -2
- package/src/__tests__/session-agent-loop-overflow.test.ts +1012 -838
- package/src/__tests__/session-agent-loop.test.ts +2 -2
- package/src/__tests__/session-confirmation-signals.test.ts +3 -2
- package/src/__tests__/session-error.test.ts +5 -4
- package/src/__tests__/session-history-web-search.test.ts +34 -9
- package/src/__tests__/session-messaging-secret-redirect.test.ts +1 -7
- package/src/__tests__/session-pre-run-repair.test.ts +3 -2
- package/src/__tests__/session-provider-retry-repair.test.ts +31 -27
- package/src/__tests__/session-queue.test.ts +5 -5
- package/src/__tests__/session-runtime-assembly.test.ts +118 -0
- package/src/__tests__/session-slash-known.test.ts +31 -14
- package/src/__tests__/session-slash-queue.test.ts +3 -2
- package/src/__tests__/session-slash-unknown.test.ts +3 -2
- package/src/__tests__/session-workspace-cache-state.test.ts +3 -1
- package/src/__tests__/session-workspace-injection.test.ts +3 -2
- package/src/__tests__/session-workspace-tool-tracking.test.ts +3 -2
- package/src/__tests__/shell-tool-proxy-mode.test.ts +0 -1
- package/src/__tests__/skill-projection-feature-flag.test.ts +0 -1
- package/src/__tests__/skill-script-runner-sandbox.test.ts +0 -1
- package/src/__tests__/skillssh-registry.test.ts +21 -0
- package/src/__tests__/slack-channel-config.test.ts +1 -7
- package/src/__tests__/slack-share-routes.test.ts +1 -1
- package/src/__tests__/swarm-recursion.test.ts +4 -1
- package/src/__tests__/swarm-session-integration.test.ts +24 -14
- package/src/__tests__/swarm-tool.test.ts +4 -2
- package/src/__tests__/task-compiler.test.ts +1 -1
- package/src/__tests__/telegram-bot-username-resolution.test.ts +2 -4
- package/src/__tests__/test-support/browser-skill-harness.ts +0 -18
- package/src/__tests__/test-support/computer-use-skill-harness.ts +0 -23
- package/src/__tests__/token-estimator-accuracy.benchmark.test.ts +1521 -0
- package/src/__tests__/tool-execution-abort-cleanup.test.ts +0 -1
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +0 -1
- package/src/__tests__/tool-executor-shell-integration.test.ts +0 -1
- package/src/__tests__/tool-executor.test.ts +1 -2
- package/src/__tests__/trust-store.test.ts +8 -83
- package/src/__tests__/twilio-config.test.ts +0 -1
- package/src/__tests__/twilio-provider.test.ts +0 -5
- package/src/__tests__/twilio-routes.test.ts +2 -3
- package/src/__tests__/usage-cache-backfill-migration.test.ts +10 -10
- package/src/__tests__/verification-control-plane-policy.test.ts +0 -1
- package/src/__tests__/voice-quality.test.ts +2 -1
- package/src/__tests__/voice-scoped-grant-consumer.test.ts +0 -1
- package/src/__tests__/web-search.test.ts +1 -1
- package/src/agent/loop.ts +17 -1
- package/src/bundler/app-bundler.ts +40 -24
- package/src/calls/call-controller.ts +16 -0
- package/src/calls/guardian-question-copy.ts +1 -1
- package/src/calls/relay-server.ts +29 -13
- package/src/calls/voice-control-protocol.ts +1 -0
- package/src/calls/voice-quality.ts +1 -1
- package/src/calls/voice-session-bridge.ts +9 -3
- package/src/channels/types.ts +16 -0
- package/src/cli/commands/bash.ts +173 -0
- package/src/cli/commands/doctor.ts +15 -57
- package/src/cli/commands/memory.ts +3 -5
- package/src/cli/commands/oauth/connections.ts +4 -2
- package/src/cli/commands/oauth/providers.ts +1 -13
- package/src/cli/commands/sessions.ts +1 -1
- package/src/cli/commands/usage.ts +359 -0
- package/src/cli/http-client.ts +22 -12
- package/src/cli/program.ts +4 -0
- package/src/cli/reference.ts +2 -0
- package/src/cli.ts +251 -181
- package/src/config/assistant-feature-flags.ts +0 -7
- package/src/config/bundled-skills/chatgpt-import/tools/chatgpt-import.ts +1 -1
- package/src/config/bundled-skills/claude-code/SKILL.md +1 -1
- package/src/config/bundled-skills/claude-code/TOOLS.json +1 -1
- package/src/config/bundled-skills/gmail/SKILL.md +0 -1
- package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +4 -3
- package/src/config/bundled-skills/media-processing/services/reduce.ts +1 -1
- package/src/config/bundled-skills/media-processing/tools/analyze-keyframes.ts +3 -5
- package/src/config/bundled-skills/media-processing/tools/extract-keyframes.ts +2 -3
- package/src/config/bundled-skills/messaging/SKILL.md +0 -1
- package/src/config/bundled-skills/phone-calls/references/CONFIG.md +1 -1
- package/src/config/bundled-skills/sequences/SKILL.md +0 -1
- package/src/config/bundled-skills/transcribe/tools/transcribe-media.ts +5 -6
- package/src/config/env.ts +13 -0
- package/src/config/feature-flag-registry.json +15 -39
- package/src/config/loader.ts +7 -135
- package/src/config/schema.ts +0 -6
- package/src/config/schemas/channels.ts +1 -0
- package/src/config/schemas/elevenlabs.ts +2 -2
- package/src/config/schemas/security.ts +1 -2
- package/src/config/skills.ts +1 -1
- package/src/contacts/contact-store.ts +21 -75
- package/src/contacts/contacts-write.ts +6 -6
- package/src/contacts/types.ts +2 -0
- package/src/context/token-estimator.ts +35 -2
- package/src/context/window-manager.ts +16 -2
- package/src/daemon/approved-devices-store.ts +0 -44
- package/src/daemon/classifier.ts +1 -1
- package/src/daemon/config-watcher.ts +35 -11
- package/src/daemon/context-overflow-reducer.ts +13 -2
- package/src/daemon/handlers/config-ingress.ts +25 -8
- package/src/daemon/handlers/config-model.ts +22 -16
- package/src/daemon/handlers/config-telegram.ts +18 -6
- package/src/daemon/handlers/dictation.ts +0 -429
- package/src/daemon/handlers/sessions.ts +4 -116
- package/src/daemon/handlers/skills.ts +2 -201
- package/src/daemon/lifecycle.ts +21 -20
- package/src/daemon/message-types/contacts.ts +2 -0
- package/src/daemon/message-types/integrations.ts +1 -0
- package/src/daemon/message-types/sessions.ts +2 -0
- package/src/daemon/parse-actual-tokens-from-error.test.ts +75 -0
- package/src/daemon/providers-setup.ts +1 -1
- package/src/daemon/server.ts +42 -5
- package/src/daemon/session-agent-loop-handlers.ts +1 -1
- package/src/daemon/session-agent-loop.ts +27 -79
- package/src/daemon/session-error.ts +5 -4
- package/src/daemon/session-process.ts +17 -10
- package/src/daemon/session-runtime-assembly.ts +50 -0
- package/src/daemon/session-slash.ts +34 -22
- package/src/daemon/session.ts +1 -0
- package/src/daemon/shutdown-handlers.ts +15 -0
- package/src/daemon/watch-handler.ts +2 -2
- package/src/email/guardrails.ts +1 -1
- package/src/email/service.ts +0 -5
- package/src/events/domain-events.ts +1 -0
- package/src/hooks/templates.ts +1 -1
- package/src/media/app-icon-generator.ts +4 -3
- package/src/media/avatar-router.ts +5 -4
- package/src/media/gemini-image-service.ts +5 -5
- package/src/memory/admin.ts +2 -2
- package/src/memory/app-git-service.ts +0 -7
- package/src/memory/canonical-guardian-store.ts +25 -3
- package/src/memory/conversation-crud.ts +1 -1
- package/src/memory/conversation-title-service.ts +2 -2
- package/src/memory/db-init.ts +12 -0
- package/src/memory/embedding-backend.ts +46 -33
- package/src/memory/external-conversation-store.ts +0 -30
- package/src/memory/guardian-action-store.ts +0 -31
- package/src/memory/guardian-approvals.ts +1 -56
- package/src/memory/indexer.ts +4 -3
- package/src/memory/items-extractor.ts +1 -1
- package/src/memory/job-handlers/backfill.ts +5 -2
- package/src/memory/job-handlers/index-maintenance.ts +2 -2
- package/src/memory/job-handlers/media-processing.ts +2 -2
- package/src/memory/job-handlers/summarization.ts +1 -1
- package/src/memory/job-utils.ts +1 -2
- package/src/memory/jobs-worker.ts +2 -2
- package/src/memory/llm-usage-store.ts +57 -11
- package/src/memory/media-store.ts +4 -535
- package/src/memory/migrations/032-guardian-delivery-conversation-index.ts +2 -2
- package/src/memory/migrations/110-channel-guardian.ts +0 -1
- package/src/memory/migrations/158-channel-interaction-columns.ts +18 -0
- package/src/memory/migrations/159-drop-contact-interaction-columns.ts +16 -0
- package/src/memory/migrations/160-drop-loopback-port-column.ts +13 -0
- package/src/memory/migrations/index.ts +3 -0
- package/src/memory/published-pages-store.ts +0 -83
- package/src/memory/qdrant-circuit-breaker.ts +0 -8
- package/src/memory/retriever.test.ts +19 -12
- package/src/memory/retriever.ts +1 -1
- package/src/memory/schema/contacts.ts +2 -2
- package/src/memory/schema/oauth.ts +0 -1
- package/src/memory/search/semantic.ts +1 -8
- package/src/memory/shared-app-links-store.ts +0 -15
- package/src/messaging/registry.ts +0 -5
- package/src/messaging/style-analyzer.ts +1 -1
- package/src/notifications/copy-composer.ts +5 -13
- package/src/notifications/decision-engine.ts +2 -2
- package/src/notifications/deliveries-store.ts +0 -39
- package/src/notifications/guardian-question-mode.ts +6 -10
- package/src/notifications/preference-extractor.ts +1 -1
- package/src/oauth/byo-connection.test.ts +29 -20
- package/src/oauth/connect-orchestrator.ts +5 -3
- package/src/oauth/connect-types.ts +9 -2
- package/src/oauth/manual-token-connection.ts +9 -7
- package/src/oauth/oauth-store.ts +2 -8
- package/src/oauth/provider-behaviors.ts +11 -1
- package/src/oauth/seed-providers.ts +13 -5
- package/src/permissions/checker.ts +21 -2
- package/src/permissions/shell-identity.ts +0 -5
- package/src/permissions/trust-store.ts +0 -37
- package/src/prompts/__tests__/build-cli-reference-section.test.ts +1 -1
- package/src/prompts/system-prompt.ts +5 -14
- package/src/prompts/templates/BOOTSTRAP.md +1 -3
- package/src/providers/anthropic/client.ts +16 -8
- package/src/providers/managed-proxy/constants.ts +9 -11
- package/src/providers/managed-proxy/context.ts +14 -9
- package/src/providers/provider-send-message.ts +4 -52
- package/src/providers/registry.ts +29 -57
- package/src/providers/types.ts +1 -1
- package/src/runtime/actor-token-store.ts +0 -23
- package/src/runtime/auth/route-policy.ts +4 -0
- package/src/runtime/channel-invite-transports/telegram.ts +12 -6
- package/src/runtime/channel-retry-sweep.ts +6 -0
- package/src/runtime/http-router.ts +5 -1
- package/src/runtime/http-server.ts +101 -4
- package/src/runtime/http-types.ts +1 -0
- package/src/runtime/invite-instruction-generator.ts +25 -51
- package/src/runtime/invite-service.ts +0 -20
- package/src/runtime/middleware/error-handler.ts +1 -2
- package/src/runtime/routes/app-management-routes.ts +1 -0
- package/src/runtime/routes/attachment-routes.ts +1 -1
- package/src/runtime/routes/brain-graph-routes.ts +1 -1
- package/src/runtime/routes/btw-routes.ts +20 -1
- package/src/runtime/routes/call-routes.ts +1 -1
- package/src/runtime/routes/conversation-routes.ts +64 -24
- package/src/runtime/routes/debug-routes.ts +1 -1
- package/src/runtime/routes/diagnostics-routes.ts +2 -2
- package/src/runtime/routes/documents-routes.ts +3 -3
- package/src/runtime/routes/global-search-routes.ts +1 -1
- package/src/runtime/routes/guardian-bootstrap-routes.ts +0 -20
- package/src/runtime/routes/guardian-refresh-routes.ts +0 -20
- package/src/runtime/routes/inbound-message-handler.ts +10 -2
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +4 -0
- package/src/runtime/routes/inbound-stages/edit-intercept.ts +5 -5
- package/src/runtime/routes/integrations/slack/share.ts +5 -5
- package/src/runtime/routes/log-export-routes.ts +122 -10
- package/src/runtime/routes/secret-routes.ts +4 -4
- package/src/runtime/routes/session-query-routes.ts +3 -3
- package/src/runtime/routes/settings-routes.ts +53 -0
- package/src/runtime/routes/trust-rules-routes.ts +1 -1
- package/src/runtime/routes/workspace-routes.ts +3 -0
- package/src/runtime/verification-templates.ts +1 -1
- package/src/security/credential-backend.ts +148 -0
- package/src/security/oauth2.ts +5 -5
- package/src/security/secret-allowlist.ts +1 -1
- package/src/security/secure-keys.ts +98 -160
- package/src/security/token-manager.ts +0 -7
- package/src/sequence/guardrails.ts +0 -4
- package/src/sequence/store.ts +1 -20
- package/src/sequence/types.ts +1 -36
- package/src/signals/bash.ts +157 -0
- package/src/signals/cancel.ts +69 -0
- package/src/signals/conversation-undo.ts +127 -0
- package/src/signals/trust-rule.ts +174 -0
- package/src/skills/clawhub.ts +5 -5
- package/src/skills/managed-store.ts +4 -4
- package/src/skills/skillssh-registry.ts +6 -1
- package/src/swarm/backend-claude-code.ts +6 -6
- package/src/swarm/worker-backend.ts +1 -1
- package/src/swarm/worker-runner.ts +1 -1
- package/src/telegram/bot-username.ts +11 -0
- package/src/telemetry/usage-telemetry-reporter.test.ts +366 -0
- package/src/telemetry/usage-telemetry-reporter.ts +181 -0
- package/src/tools/claude-code/claude-code.ts +6 -6
- package/src/tools/credentials/broker.ts +7 -5
- package/src/tools/credentials/vault.ts +11 -6
- package/src/tools/memory/handlers.test.ts +24 -26
- package/src/tools/memory/handlers.ts +1 -13
- package/src/tools/network/__tests__/web-search.test.ts +18 -86
- package/src/tools/network/web-search.ts +9 -15
- package/src/tools/registry.ts +5 -100
- package/src/tools/terminal/parser.ts +34 -4
- package/src/tools/tool-manifest.ts +0 -10
- package/src/usage/actors.ts +0 -12
- package/src/util/canonicalize-identity.ts +0 -9
- package/src/util/errors.ts +0 -3
- package/src/util/platform.ts +31 -8
- package/src/util/pricing.ts +0 -39
- package/src/watcher/constants.ts +0 -7
- package/src/watcher/providers/linear.ts +1 -1
- package/src/work-items/work-item-store.ts +4 -4
- package/src/workspace/commit-message-provider.ts +1 -1
- package/src/workspace/git-service.ts +44 -1
- package/src/workspace/provider-commit-message-generator.ts +11 -7
- package/src/__tests__/fixtures/proxy-fixtures.ts +0 -147
- package/src/browser-extension-relay/client.ts +0 -155
- package/src/contacts/index.ts +0 -18
- package/src/daemon/tls-certs.ts +0 -270
- package/src/errors.ts +0 -41
- package/src/events/index.ts +0 -18
- package/src/followups/index.ts +0 -10
- package/src/playbooks/index.ts +0 -10
- package/src/runtime/auth/index.ts +0 -44
- package/src/tasks/candidate-store.ts +0 -95
- package/src/tools/browser/api-map.ts +0 -313
- package/src/tools/browser/auto-navigate.ts +0 -469
- package/src/tools/browser/headless-browser.ts +0 -590
- package/src/tools/browser/recording-store.ts +0 -75
- package/src/tools/computer-use/registry.ts +0 -21
- package/src/tools/tasks/index.ts +0 -27
|
@@ -39,17 +39,18 @@ mock.module("@google/genai", () => ({
|
|
|
39
39
|
// ---------------------------------------------------------------------------
|
|
40
40
|
let mockPlatformBaseUrl = "";
|
|
41
41
|
let mockAssistantApiKey: string | null = null;
|
|
42
|
+
let mockProviderKeys: Record<string, string> = {};
|
|
42
43
|
|
|
43
44
|
mock.module("../config/env.js", () => ({
|
|
44
45
|
getPlatformBaseUrl: () => mockPlatformBaseUrl,
|
|
45
46
|
}));
|
|
46
47
|
|
|
47
48
|
mock.module("../security/secure-keys.js", () => ({
|
|
48
|
-
|
|
49
|
+
getSecureKeyAsync: async (key: string) => {
|
|
49
50
|
if (key === credentialKey("vellum", "assistant_api_key")) {
|
|
50
51
|
return mockAssistantApiKey;
|
|
51
52
|
}
|
|
52
|
-
return null;
|
|
53
|
+
return mockProviderKeys[key] ?? null;
|
|
53
54
|
},
|
|
54
55
|
}));
|
|
55
56
|
|
|
@@ -67,13 +68,14 @@ import {
|
|
|
67
68
|
const PLATFORM_BASE = "https://platform.example.com";
|
|
68
69
|
const MANAGED_API_KEY = "ast-managed-key-123";
|
|
69
70
|
|
|
70
|
-
const
|
|
71
|
+
const DIRECT_OR_MANAGED_PROVIDER_KEYS: string[] = [
|
|
71
72
|
"openai",
|
|
72
73
|
"anthropic",
|
|
73
74
|
"gemini",
|
|
74
75
|
"fireworks",
|
|
75
76
|
"openrouter",
|
|
76
77
|
];
|
|
78
|
+
const MANAGED_FALLBACK_PROVIDERS: string[] = ["anthropic", "gemini"];
|
|
77
79
|
|
|
78
80
|
function enableManagedProxy() {
|
|
79
81
|
mockPlatformBaseUrl = PLATFORM_BASE;
|
|
@@ -86,14 +88,13 @@ function disableManagedProxy() {
|
|
|
86
88
|
}
|
|
87
89
|
|
|
88
90
|
/**
|
|
89
|
-
*
|
|
91
|
+
* Set mock secure keys with a user key for every provider in `names`.
|
|
90
92
|
*/
|
|
91
|
-
function
|
|
92
|
-
|
|
93
|
+
function setUserKeysFor(...names: string[]): void {
|
|
94
|
+
mockProviderKeys = {};
|
|
93
95
|
for (const n of names) {
|
|
94
|
-
|
|
96
|
+
mockProviderKeys[n] = `user-key-${n}`;
|
|
95
97
|
}
|
|
96
|
-
return keys;
|
|
97
98
|
}
|
|
98
99
|
|
|
99
100
|
// ---------------------------------------------------------------------------
|
|
@@ -102,17 +103,18 @@ function userKeysFor(...names: string[]): Record<string, string> {
|
|
|
102
103
|
|
|
103
104
|
beforeEach(() => {
|
|
104
105
|
disableManagedProxy();
|
|
106
|
+
mockProviderKeys = {};
|
|
105
107
|
lastGeminiConstructorOpts = null;
|
|
106
108
|
});
|
|
107
109
|
|
|
108
110
|
describe("managed proxy integration — credential precedence", () => {
|
|
109
111
|
describe("user keys present → providers use direct connections (not proxy)", () => {
|
|
110
|
-
test.each(
|
|
112
|
+
test.each(DIRECT_OR_MANAGED_PROVIDER_KEYS)(
|
|
111
113
|
"%s routes via user-key when user key is provided regardless of managed context",
|
|
112
|
-
(provider: string) => {
|
|
114
|
+
async (provider: string) => {
|
|
113
115
|
enableManagedProxy();
|
|
114
|
-
|
|
115
|
-
|
|
116
|
+
setUserKeysFor(provider);
|
|
117
|
+
await initializeProviders({
|
|
116
118
|
provider,
|
|
117
119
|
model: "test-model",
|
|
118
120
|
});
|
|
@@ -121,29 +123,29 @@ describe("managed proxy integration — credential precedence", () => {
|
|
|
121
123
|
},
|
|
122
124
|
);
|
|
123
125
|
|
|
124
|
-
test("all five
|
|
126
|
+
test("all five configured providers route via user-key when user keys exist", async () => {
|
|
125
127
|
enableManagedProxy();
|
|
126
|
-
|
|
127
|
-
|
|
128
|
+
setUserKeysFor(...DIRECT_OR_MANAGED_PROVIDER_KEYS);
|
|
129
|
+
await initializeProviders({
|
|
128
130
|
provider: "anthropic",
|
|
129
131
|
model: "test-model",
|
|
130
132
|
});
|
|
131
133
|
const registered = listProviders();
|
|
132
|
-
for (const p of
|
|
134
|
+
for (const p of DIRECT_OR_MANAGED_PROVIDER_KEYS) {
|
|
133
135
|
expect(registered).toContain(p);
|
|
134
136
|
expect(getProviderRoutingSource(p)).toBe("user-key");
|
|
135
137
|
}
|
|
136
138
|
});
|
|
137
139
|
|
|
138
|
-
test("user keys still route via user-key when managed context is disabled", () => {
|
|
140
|
+
test("user keys still route via user-key when managed context is disabled", async () => {
|
|
139
141
|
disableManagedProxy();
|
|
140
|
-
|
|
141
|
-
|
|
142
|
+
setUserKeysFor(...DIRECT_OR_MANAGED_PROVIDER_KEYS);
|
|
143
|
+
await initializeProviders({
|
|
142
144
|
provider: "anthropic",
|
|
143
145
|
model: "test-model",
|
|
144
146
|
});
|
|
145
147
|
const registered = listProviders();
|
|
146
|
-
for (const p of
|
|
148
|
+
for (const p of DIRECT_OR_MANAGED_PROVIDER_KEYS) {
|
|
147
149
|
expect(registered).toContain(p);
|
|
148
150
|
expect(getProviderRoutingSource(p)).toBe("user-key");
|
|
149
151
|
}
|
|
@@ -151,14 +153,13 @@ describe("managed proxy integration — credential precedence", () => {
|
|
|
151
153
|
});
|
|
152
154
|
|
|
153
155
|
describe("user keys absent + managed context available → providers use managed proxy", () => {
|
|
154
|
-
test.each(
|
|
156
|
+
test.each(MANAGED_FALLBACK_PROVIDERS)(
|
|
155
157
|
"%s routes via managed-proxy when no user key",
|
|
156
|
-
(provider: string) => {
|
|
158
|
+
async (provider: string) => {
|
|
157
159
|
enableManagedProxy();
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
provider: provider === "openai" ? "openai" : "anthropic",
|
|
160
|
+
mockProviderKeys = {};
|
|
161
|
+
await initializeProviders({
|
|
162
|
+
provider: "anthropic",
|
|
162
163
|
model: "test-model",
|
|
163
164
|
});
|
|
164
165
|
expect(listProviders()).toContain(provider);
|
|
@@ -166,24 +167,25 @@ describe("managed proxy integration — credential precedence", () => {
|
|
|
166
167
|
},
|
|
167
168
|
);
|
|
168
169
|
|
|
169
|
-
test("
|
|
170
|
+
test("managed bootstrap registers anthropic and gemini only", async () => {
|
|
170
171
|
enableManagedProxy();
|
|
171
|
-
|
|
172
|
-
|
|
172
|
+
mockProviderKeys = {};
|
|
173
|
+
await initializeProviders({
|
|
173
174
|
provider: "anthropic",
|
|
174
175
|
model: "test-model",
|
|
175
176
|
});
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
177
|
+
expect(listProviders()).toEqual(["anthropic", "gemini"]);
|
|
178
|
+
expect(getProviderRoutingSource("anthropic")).toBe("managed-proxy");
|
|
179
|
+
expect(getProviderRoutingSource("gemini")).toBe("managed-proxy");
|
|
180
|
+
for (const p of ["openai", "fireworks", "openrouter"]) {
|
|
181
|
+
expect(getProviderRoutingSource(p)).toBeUndefined();
|
|
180
182
|
}
|
|
181
183
|
});
|
|
182
184
|
|
|
183
|
-
test("managed anthropic uses
|
|
185
|
+
test("managed anthropic uses anthropic proxy path", async () => {
|
|
184
186
|
enableManagedProxy();
|
|
185
|
-
|
|
186
|
-
|
|
187
|
+
mockProviderKeys = {};
|
|
188
|
+
await initializeProviders({
|
|
187
189
|
provider: "anthropic",
|
|
188
190
|
model: "claude-opus-4-6",
|
|
189
191
|
});
|
|
@@ -200,20 +202,17 @@ describe("managed proxy integration — credential precedence", () => {
|
|
|
200
202
|
|
|
201
203
|
expect(anthropicClient).toBeDefined();
|
|
202
204
|
const baseURL: string = anthropicClient.baseURL;
|
|
203
|
-
expect(baseURL).toContain("/v1/runtime-proxy/
|
|
204
|
-
expect(baseURL).not.toContain("/v1/runtime-proxy/anthropic");
|
|
205
|
+
expect(baseURL).toContain("/v1/runtime-proxy/anthropic");
|
|
205
206
|
});
|
|
206
207
|
|
|
207
|
-
test("managed gemini uses vertex proxy path
|
|
208
|
+
test("managed gemini uses vertex proxy path", async () => {
|
|
208
209
|
enableManagedProxy();
|
|
209
|
-
|
|
210
|
-
|
|
210
|
+
mockProviderKeys = {};
|
|
211
|
+
await initializeProviders({
|
|
211
212
|
provider: "anthropic",
|
|
212
213
|
model: "test-model",
|
|
213
214
|
});
|
|
214
215
|
|
|
215
|
-
// The GoogleGenAI constructor was captured by the mock — verify it
|
|
216
|
-
// received httpOptions.baseUrl pointing at the vertex proxy path.
|
|
217
216
|
expect(lastGeminiConstructorOpts).toBeDefined();
|
|
218
217
|
const httpOptions = lastGeminiConstructorOpts!.httpOptions as
|
|
219
218
|
| { baseUrl?: string }
|
|
@@ -225,12 +224,12 @@ describe("managed proxy integration — credential precedence", () => {
|
|
|
225
224
|
});
|
|
226
225
|
|
|
227
226
|
describe("neither user keys nor managed context → providers not initialized", () => {
|
|
228
|
-
test.each(
|
|
227
|
+
test.each(DIRECT_OR_MANAGED_PROVIDER_KEYS)(
|
|
229
228
|
"%s is NOT registered when no user key and no managed context",
|
|
230
|
-
(provider: string) => {
|
|
229
|
+
async (provider: string) => {
|
|
231
230
|
disableManagedProxy();
|
|
232
|
-
|
|
233
|
-
|
|
231
|
+
mockProviderKeys = {};
|
|
232
|
+
await initializeProviders({
|
|
234
233
|
provider: "anthropic",
|
|
235
234
|
model: "test-model",
|
|
236
235
|
});
|
|
@@ -239,10 +238,10 @@ describe("managed proxy integration — credential precedence", () => {
|
|
|
239
238
|
},
|
|
240
239
|
);
|
|
241
240
|
|
|
242
|
-
test("registry is empty when no keys and no managed context (non-ollama primary)", () => {
|
|
241
|
+
test("registry is empty when no keys and no managed context (non-ollama primary)", async () => {
|
|
243
242
|
disableManagedProxy();
|
|
244
|
-
|
|
245
|
-
|
|
243
|
+
mockProviderKeys = {};
|
|
244
|
+
await initializeProviders({
|
|
246
245
|
provider: "anthropic",
|
|
247
246
|
model: "test-model",
|
|
248
247
|
});
|
|
@@ -251,65 +250,71 @@ describe("managed proxy integration — credential precedence", () => {
|
|
|
251
250
|
});
|
|
252
251
|
|
|
253
252
|
describe("mixed: some user keys + managed fallback fills gaps", () => {
|
|
254
|
-
test("user key for anthropic routes direct
|
|
253
|
+
test("user key for anthropic routes direct and managed fallback only fills gemini", async () => {
|
|
255
254
|
enableManagedProxy();
|
|
256
|
-
|
|
257
|
-
|
|
255
|
+
setUserKeysFor("anthropic");
|
|
256
|
+
await initializeProviders({
|
|
258
257
|
provider: "anthropic",
|
|
259
258
|
model: "test-model",
|
|
260
259
|
});
|
|
261
260
|
const registered = listProviders();
|
|
262
261
|
expect(registered).toContain("anthropic");
|
|
263
262
|
expect(getProviderRoutingSource("anthropic")).toBe("user-key");
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
263
|
+
expect(registered).toContain("gemini");
|
|
264
|
+
expect(getProviderRoutingSource("gemini")).toBe("managed-proxy");
|
|
265
|
+
for (const p of ["openai", "fireworks", "openrouter"]) {
|
|
266
|
+
expect(registered).not.toContain(p);
|
|
267
|
+
expect(getProviderRoutingSource(p)).toBeUndefined();
|
|
267
268
|
}
|
|
268
269
|
});
|
|
269
270
|
|
|
270
|
-
test("user key for openai routes direct
|
|
271
|
+
test("user key for openai routes direct while anthropic and gemini still bootstrap via managed proxy", async () => {
|
|
271
272
|
enableManagedProxy();
|
|
272
|
-
|
|
273
|
-
|
|
273
|
+
setUserKeysFor("openai");
|
|
274
|
+
await initializeProviders({
|
|
274
275
|
provider: "openai",
|
|
275
276
|
model: "test-model",
|
|
276
277
|
});
|
|
277
278
|
const registered = listProviders();
|
|
278
279
|
expect(registered).toContain("openai");
|
|
279
280
|
expect(getProviderRoutingSource("openai")).toBe("user-key");
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
281
|
+
expect(registered).toContain("anthropic");
|
|
282
|
+
expect(getProviderRoutingSource("anthropic")).toBe("managed-proxy");
|
|
283
|
+
expect(registered).toContain("gemini");
|
|
284
|
+
expect(getProviderRoutingSource("gemini")).toBe("managed-proxy");
|
|
285
|
+
for (const p of ["fireworks", "openrouter"]) {
|
|
286
|
+
expect(registered).not.toContain(p);
|
|
287
|
+
expect(getProviderRoutingSource(p)).toBeUndefined();
|
|
283
288
|
}
|
|
284
289
|
});
|
|
285
290
|
});
|
|
286
291
|
});
|
|
287
292
|
|
|
288
293
|
describe("managed proxy integration — ollama exclusion", () => {
|
|
289
|
-
test("ollama is never registered via managed proxy fallback", () => {
|
|
294
|
+
test("ollama is never registered via managed proxy fallback", async () => {
|
|
290
295
|
enableManagedProxy();
|
|
291
|
-
|
|
292
|
-
|
|
296
|
+
mockProviderKeys = {};
|
|
297
|
+
await initializeProviders({
|
|
293
298
|
provider: "anthropic",
|
|
294
299
|
model: "test-model",
|
|
295
300
|
});
|
|
296
301
|
expect(listProviders()).not.toContain("ollama");
|
|
297
302
|
});
|
|
298
303
|
|
|
299
|
-
test("ollama registers only when explicitly configured as provider", () => {
|
|
304
|
+
test("ollama registers only when explicitly configured as provider", async () => {
|
|
300
305
|
enableManagedProxy();
|
|
301
|
-
|
|
302
|
-
|
|
306
|
+
mockProviderKeys = {};
|
|
307
|
+
await initializeProviders({
|
|
303
308
|
provider: "ollama",
|
|
304
309
|
model: "test-model",
|
|
305
310
|
});
|
|
306
311
|
expect(listProviders()).toContain("ollama");
|
|
307
312
|
});
|
|
308
313
|
|
|
309
|
-
test("ollama registers with explicit API key", () => {
|
|
314
|
+
test("ollama registers with explicit API key", async () => {
|
|
310
315
|
enableManagedProxy();
|
|
311
|
-
|
|
312
|
-
|
|
316
|
+
mockProviderKeys = { ollama: "ollama-key" };
|
|
317
|
+
await initializeProviders({
|
|
313
318
|
provider: "anthropic",
|
|
314
319
|
model: "test-model",
|
|
315
320
|
});
|
|
@@ -325,8 +330,8 @@ describe("managed proxy integration — ollama exclusion", () => {
|
|
|
325
330
|
});
|
|
326
331
|
|
|
327
332
|
describe("managed proxy integration — constants integrity", () => {
|
|
328
|
-
test("
|
|
329
|
-
for (const provider of
|
|
333
|
+
test("anthropic, gemini, and vertex have metadata with managed=true and a proxyPath", () => {
|
|
334
|
+
for (const provider of ["anthropic", "gemini", "vertex"]) {
|
|
330
335
|
const meta = MANAGED_PROVIDER_META[provider];
|
|
331
336
|
expect(meta).toBeDefined();
|
|
332
337
|
expect(meta.managed).toBe(true);
|
|
@@ -335,24 +340,22 @@ describe("managed proxy integration — constants integrity", () => {
|
|
|
335
340
|
}
|
|
336
341
|
});
|
|
337
342
|
|
|
338
|
-
test("anthropic
|
|
343
|
+
test("anthropic routes through anthropic proxy path", () => {
|
|
339
344
|
expect(MANAGED_PROVIDER_META.anthropic.proxyPath).toBe(
|
|
340
|
-
"/v1/runtime-proxy/
|
|
345
|
+
"/v1/runtime-proxy/anthropic",
|
|
341
346
|
);
|
|
347
|
+
});
|
|
348
|
+
|
|
349
|
+
test("gemini routes through vertex proxy path", () => {
|
|
342
350
|
expect(MANAGED_PROVIDER_META.gemini.proxyPath).toBe(
|
|
343
351
|
"/v1/runtime-proxy/vertex",
|
|
344
352
|
);
|
|
345
353
|
});
|
|
346
354
|
|
|
347
|
-
test("
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
"/v1/runtime-proxy/fireworks",
|
|
353
|
-
);
|
|
354
|
-
expect(MANAGED_PROVIDER_META.openrouter.proxyPath).toBe(
|
|
355
|
-
"/v1/runtime-proxy/openrouter",
|
|
356
|
-
);
|
|
355
|
+
test("openai-compatible providers are not managed proxy capable", () => {
|
|
356
|
+
for (const provider of ["openai", "fireworks", "openrouter"]) {
|
|
357
|
+
expect(MANAGED_PROVIDER_META[provider].managed).toBe(false);
|
|
358
|
+
expect(MANAGED_PROVIDER_META[provider].proxyPath).toBeUndefined();
|
|
359
|
+
}
|
|
357
360
|
});
|
|
358
361
|
});
|
|
@@ -1,4 +1,11 @@
|
|
|
1
|
-
import { describe, expect, test } from "bun:test";
|
|
1
|
+
import { describe, expect, mock, test } from "bun:test";
|
|
2
|
+
|
|
3
|
+
// Mock secure-keys so tests don't depend on the developer's local secure storage.
|
|
4
|
+
const actualSecureKeys = await import("../security/secure-keys.js");
|
|
5
|
+
mock.module("../security/secure-keys.js", () => ({
|
|
6
|
+
...actualSecureKeys,
|
|
7
|
+
getSecureKeyAsync: async () => undefined,
|
|
8
|
+
}));
|
|
2
9
|
|
|
3
10
|
import {
|
|
4
11
|
getProvider,
|
|
@@ -7,9 +14,8 @@ import {
|
|
|
7
14
|
} from "../providers/registry.js";
|
|
8
15
|
|
|
9
16
|
describe("provider registry (ollama)", () => {
|
|
10
|
-
test("registers ollama when selected provider has no API key", () => {
|
|
11
|
-
initializeProviders({
|
|
12
|
-
apiKeys: {},
|
|
17
|
+
test("registers ollama when selected provider has no API key", async () => {
|
|
18
|
+
await initializeProviders({
|
|
13
19
|
provider: "ollama",
|
|
14
20
|
model: "claude-opus-4-6",
|
|
15
21
|
});
|
|
@@ -98,7 +98,7 @@ describe("getPublicBaseUrl", () => {
|
|
|
98
98
|
).toThrow(/Public ingress is disabled/);
|
|
99
99
|
});
|
|
100
100
|
|
|
101
|
-
test("returns URL when enabled is undefined
|
|
101
|
+
test("returns URL when enabled is undefined", () => {
|
|
102
102
|
const result = getPublicBaseUrl({
|
|
103
103
|
ingress: { enabled: undefined, publicBaseUrl: "https://example.com" },
|
|
104
104
|
});
|
|
@@ -24,7 +24,6 @@ mock.module("../config/loader.js", () => ({
|
|
|
24
24
|
daemon: { standaloneRecording: true },
|
|
25
25
|
provider: "mock-provider",
|
|
26
26
|
permissions: { mode: "workspace" },
|
|
27
|
-
apiKeys: {},
|
|
28
27
|
sandbox: { enabled: false },
|
|
29
28
|
timeouts: { toolExecutionTimeoutSec: 30, permissionTimeoutSec: 5 },
|
|
30
29
|
skills: { load: { extraDirs: [] } },
|
|
@@ -2,8 +2,6 @@ import { afterAll, beforeEach, describe, expect, test } from "bun:test";
|
|
|
2
2
|
|
|
3
3
|
import { RiskLevel } from "../permissions/types.js";
|
|
4
4
|
import type { ToolDefinition } from "../providers/types.js";
|
|
5
|
-
// We cannot import the private LazyTool class directly, so we test through
|
|
6
|
-
// registerLazyTool + getTool which exercise the same code path.
|
|
7
5
|
import {
|
|
8
6
|
__clearRegistryForTesting,
|
|
9
7
|
__resetRegistryForTesting,
|
|
@@ -13,16 +11,11 @@ import {
|
|
|
13
11
|
getSkillToolNames,
|
|
14
12
|
getTool,
|
|
15
13
|
initializeTools,
|
|
16
|
-
registerLazyTool,
|
|
17
14
|
registerSkillTools,
|
|
18
15
|
registerTool,
|
|
19
16
|
unregisterSkillTools,
|
|
20
17
|
} from "../tools/registry.js";
|
|
21
|
-
import {
|
|
22
|
-
eagerModuleToolNames,
|
|
23
|
-
explicitTools,
|
|
24
|
-
lazyTools,
|
|
25
|
-
} from "../tools/tool-manifest.js";
|
|
18
|
+
import { eagerModuleToolNames, explicitTools } from "../tools/tool-manifest.js";
|
|
26
19
|
import type { Tool, ToolContext, ToolExecutionResult } from "../tools/types.js";
|
|
27
20
|
|
|
28
21
|
// Clean up global registry after this file completes to prevent
|
|
@@ -61,48 +54,6 @@ function makeSkillTool(name: string, ownerSkillId: string): Tool {
|
|
|
61
54
|
};
|
|
62
55
|
}
|
|
63
56
|
|
|
64
|
-
describe("LazyTool", () => {
|
|
65
|
-
test("clears cached promise on load failure so subsequent call can retry", async () => {
|
|
66
|
-
let callCount = 0;
|
|
67
|
-
|
|
68
|
-
registerLazyTool({
|
|
69
|
-
name: "test-retry-tool",
|
|
70
|
-
description: "A tool that fails on first load then succeeds",
|
|
71
|
-
category: "test",
|
|
72
|
-
defaultRiskLevel: RiskLevel.Low,
|
|
73
|
-
definition: {
|
|
74
|
-
name: "test-retry-tool",
|
|
75
|
-
description: "A tool that fails on first load then succeeds",
|
|
76
|
-
input_schema: { type: "object", properties: {}, required: [] },
|
|
77
|
-
},
|
|
78
|
-
loader: async () => {
|
|
79
|
-
callCount++;
|
|
80
|
-
if (callCount === 1) {
|
|
81
|
-
throw new Error("transient load failure");
|
|
82
|
-
}
|
|
83
|
-
return makeFakeTool("test-retry-tool");
|
|
84
|
-
},
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
const tool = getTool("test-retry-tool")!;
|
|
88
|
-
expect(tool).toBeDefined();
|
|
89
|
-
|
|
90
|
-
const dummyContext = {} as ToolContext;
|
|
91
|
-
|
|
92
|
-
// First call should throw the transient error
|
|
93
|
-
await expect(tool.execute({}, dummyContext)).rejects.toThrow(
|
|
94
|
-
"transient load failure",
|
|
95
|
-
);
|
|
96
|
-
expect(callCount).toBe(1);
|
|
97
|
-
|
|
98
|
-
// Second call should retry the loader and succeed
|
|
99
|
-
const result = await tool.execute({}, dummyContext);
|
|
100
|
-
expect(result.content).toBe("ok");
|
|
101
|
-
expect(result.isError).toBe(false);
|
|
102
|
-
expect(callCount).toBe(2);
|
|
103
|
-
});
|
|
104
|
-
});
|
|
105
|
-
|
|
106
57
|
describe("tool registry host tools", () => {
|
|
107
58
|
test("registers host tools and exposes them in tool definitions", async () => {
|
|
108
59
|
await initializeTools();
|
|
@@ -157,29 +108,6 @@ describe("tool registry dynamic-tools tools", () => {
|
|
|
157
108
|
});
|
|
158
109
|
|
|
159
110
|
describe("tool manifest", () => {
|
|
160
|
-
test("all manifest lazy tools are registered after init", async () => {
|
|
161
|
-
await initializeTools();
|
|
162
|
-
const registered = new Set(getAllTools().map((t) => t.name));
|
|
163
|
-
|
|
164
|
-
for (const descriptor of lazyTools) {
|
|
165
|
-
expect(registered.has(descriptor.name)).toBe(true);
|
|
166
|
-
}
|
|
167
|
-
});
|
|
168
|
-
|
|
169
|
-
test("manifest declares expected core lazy tools", () => {
|
|
170
|
-
// bash moved from lazy to eager registration
|
|
171
|
-
// swarm_delegate moved to the orchestration bundled skill
|
|
172
|
-
const lazyNames = new Set(lazyTools.map((t) => t.name));
|
|
173
|
-
expect(lazyNames.has("bash")).toBe(false);
|
|
174
|
-
expect(lazyNames.has("evaluate_typescript_code")).toBe(false);
|
|
175
|
-
expect(lazyNames.has("claude_code")).toBe(false);
|
|
176
|
-
expect(lazyNames.has("swarm_delegate")).toBe(false);
|
|
177
|
-
// bash is in eager tools; swarm_delegate is now a bundled skill tool
|
|
178
|
-
expect(eagerModuleToolNames).toContain("bash");
|
|
179
|
-
expect(eagerModuleToolNames).not.toContain("swarm_delegate");
|
|
180
|
-
expect(eagerModuleToolNames).not.toContain("version");
|
|
181
|
-
});
|
|
182
|
-
|
|
183
111
|
test("eager module tool names list contains expected count", () => {
|
|
184
112
|
expect(eagerModuleToolNames.length).toBe(11);
|
|
185
113
|
});
|
|
@@ -193,12 +121,10 @@ describe("tool manifest", () => {
|
|
|
193
121
|
expect(names).not.toContain("start_screen_watch");
|
|
194
122
|
});
|
|
195
123
|
|
|
196
|
-
test("registered tool count is at least eager +
|
|
124
|
+
test("registered tool count is at least eager + host", async () => {
|
|
197
125
|
await initializeTools();
|
|
198
126
|
const tools = getAllTools();
|
|
199
|
-
expect(tools.length).toBeGreaterThanOrEqual(
|
|
200
|
-
eagerModuleToolNames.length + lazyTools.length,
|
|
201
|
-
);
|
|
127
|
+
expect(tools.length).toBeGreaterThanOrEqual(eagerModuleToolNames.length);
|
|
202
128
|
});
|
|
203
129
|
});
|
|
204
130
|
|
|
@@ -253,11 +179,6 @@ describe("baseline characterization: hardcoded tool loading", () => {
|
|
|
253
179
|
const tool = getTool("claude_code");
|
|
254
180
|
expect(tool).toBeUndefined();
|
|
255
181
|
});
|
|
256
|
-
|
|
257
|
-
test("claude_code is NOT in lazyTools manifest", () => {
|
|
258
|
-
const lazyNames = lazyTools.map((t) => t.name);
|
|
259
|
-
expect(lazyNames).not.toContain("claude_code");
|
|
260
|
-
});
|
|
261
182
|
});
|
|
262
183
|
|
|
263
184
|
describe("baseline characterization: core app tool surface", () => {
|
|
@@ -505,24 +426,3 @@ describe("skill tool reference counting", () => {
|
|
|
505
426
|
expect(getSkillRefCount("nonexistent-skill")).toBe(0);
|
|
506
427
|
});
|
|
507
428
|
});
|
|
508
|
-
|
|
509
|
-
describe("computer-use registration split", () => {
|
|
510
|
-
// Start each test from a completely empty registry so assertions are
|
|
511
|
-
// non-vacuous — the split functions must actually register tools.
|
|
512
|
-
|
|
513
|
-
test("registerComputerUseActionTools registers all 11 CU action tools and nothing else", async () => {
|
|
514
|
-
const { registerComputerUseActionTools } =
|
|
515
|
-
await import("../tools/computer-use/registry.js");
|
|
516
|
-
|
|
517
|
-
__clearRegistryForTesting();
|
|
518
|
-
expect(getAllTools()).toHaveLength(0);
|
|
519
|
-
|
|
520
|
-
registerComputerUseActionTools();
|
|
521
|
-
|
|
522
|
-
const registered = getAllTools();
|
|
523
|
-
expect(registered).toHaveLength(11);
|
|
524
|
-
expect(registered.every((t) => t.name.startsWith("computer_use_"))).toBe(
|
|
525
|
-
true,
|
|
526
|
-
);
|
|
527
|
-
});
|
|
528
|
-
});
|
|
@@ -27,21 +27,16 @@ mock.module("../tools/credentials/metadata-store.js", () => ({
|
|
|
27
27
|
listCredentialMetadata: () => credentialMetadataList,
|
|
28
28
|
}));
|
|
29
29
|
|
|
30
|
-
// Track
|
|
30
|
+
// Track getSecureKeyAsync return values per storage key
|
|
31
31
|
let secureKeyValues = new Map<string, string | undefined>();
|
|
32
32
|
|
|
33
33
|
mock.module("../security/secure-keys.js", () => ({
|
|
34
|
-
getSecureKey: (account: string) => secureKeyValues.get(account),
|
|
35
34
|
getSecureKeyAsync: (account: string) =>
|
|
36
35
|
Promise.resolve(secureKeyValues.get(account)),
|
|
37
|
-
setSecureKey: () => true,
|
|
38
36
|
setSecureKeyAsync: () => Promise.resolve(true),
|
|
39
|
-
deleteSecureKey: () => "deleted",
|
|
40
37
|
deleteSecureKeyAsync: () => Promise.resolve("deleted"),
|
|
41
|
-
|
|
42
|
-
getBackendType: () => "encrypted",
|
|
38
|
+
listSecureKeysAsync: async () => [],
|
|
43
39
|
_resetBackend: () => {},
|
|
44
|
-
_setBackend: () => {},
|
|
45
40
|
}));
|
|
46
41
|
|
|
47
42
|
// Stub ensureLocalCA / certs so tests never run openssl
|
|
@@ -42,16 +42,11 @@ mock.module("../security/secure-keys.js", () => {
|
|
|
42
42
|
return "not-found" as const;
|
|
43
43
|
};
|
|
44
44
|
return {
|
|
45
|
-
getSecureKey: (key: string) => storedKeys.get(key) ?? null,
|
|
46
45
|
getSecureKeyAsync: async (key: string) => storedKeys.get(key) ?? undefined,
|
|
47
|
-
setSecureKey: syncSet,
|
|
48
46
|
setSecureKeyAsync: async (key: string, value: string) =>
|
|
49
47
|
syncSet(key, value),
|
|
50
|
-
deleteSecureKey: syncDelete,
|
|
51
48
|
deleteSecureKeyAsync: async (key: string) => syncDelete(key),
|
|
52
|
-
|
|
53
|
-
getBackendType: () => "encrypted",
|
|
54
|
-
isDowngradedFromKeychain: () => false,
|
|
49
|
+
listSecureKeysAsync: async () => [],
|
|
55
50
|
};
|
|
56
51
|
});
|
|
57
52
|
|