@vellumai/assistant 0.4.46 → 0.4.49
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 +7 -7
- package/README.md +2 -23
- package/docs/architecture/integrations.md +45 -41
- package/docs/architecture/keychain-broker.md +3 -3
- package/docs/architecture/security.md +5 -5
- package/docs/runbook-trusted-contacts.md +3 -8
- package/hook-templates/debug-prompt-logger/hook.json +1 -1
- package/hook-templates/debug-prompt-logger/run.sh +1 -3
- package/package.json +1 -1
- package/src/__tests__/actor-token-service.test.ts +0 -1
- package/src/__tests__/anthropic-provider.test.ts +156 -0
- package/src/__tests__/approval-cascade.test.ts +810 -0
- package/src/__tests__/approval-primitive.test.ts +0 -1
- package/src/__tests__/approval-routes-http.test.ts +2 -0
- package/src/__tests__/assistant-attachments.test.ts +12 -34
- package/src/__tests__/assistant-feature-flag-guardrails.test.ts +76 -0
- package/src/__tests__/assistant-feature-flags-integration.test.ts +0 -1
- package/src/__tests__/browser-fill-credential.test.ts +5 -2
- package/src/__tests__/browser-skill-baseline-tool-payload.test.ts +2 -2
- package/src/__tests__/bundled-skill-retrieval-guard.test.ts +2 -1
- package/src/__tests__/channel-guardian.test.ts +0 -2
- package/src/__tests__/channel-readiness-routes.test.ts +35 -25
- package/src/__tests__/channel-readiness-service.test.ts +10 -9
- package/src/__tests__/checker.test.ts +9 -29
- package/src/__tests__/cli.test.ts +23 -0
- package/src/__tests__/computer-use-skill-manifest-regression.test.ts +1 -1
- package/src/__tests__/computer-use-tools.test.ts +2 -19
- package/src/__tests__/config-watcher.test.ts +0 -1
- package/src/__tests__/confirmation-request-guardian-bridge.test.ts +0 -1
- package/src/__tests__/context-image-dimensions.test.ts +332 -0
- package/src/__tests__/context-token-estimator.test.ts +196 -13
- package/src/__tests__/conversation-attention-store.test.ts +0 -1
- package/src/__tests__/conversation-attention-telegram.test.ts +0 -1
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +144 -0
- package/src/__tests__/conversation-routes-slash-commands.test.ts +1 -0
- package/src/__tests__/credential-broker-browser-fill.test.ts +23 -22
- package/src/__tests__/credential-broker-server-use.test.ts +22 -21
- package/src/__tests__/credential-broker.test.ts +2 -1
- package/src/__tests__/credential-metadata-store.test.ts +239 -26
- package/src/__tests__/credential-resolve.test.ts +5 -4
- package/src/__tests__/credential-security-e2e.test.ts +8 -8
- package/src/__tests__/credential-security-invariants.test.ts +111 -7
- package/src/__tests__/credential-vault-unit.test.ts +287 -54
- package/src/__tests__/credential-vault.test.ts +406 -12
- package/src/__tests__/credentials-cli.test.ts +82 -6
- package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +0 -1
- package/src/__tests__/ephemeral-permissions.test.ts +3 -3
- package/src/__tests__/gateway-only-enforcement.test.ts +4 -2
- package/src/__tests__/gateway-only-guard.test.ts +0 -1
- package/src/__tests__/gemini-image-service.test.ts +75 -45
- package/src/__tests__/gemini-provider.test.ts +9 -6
- package/src/__tests__/guardian-action-conversation-turn.test.ts +1 -33
- package/src/__tests__/guardian-action-copy-generator.test.ts +0 -20
- package/src/__tests__/guardian-action-followup-executor.test.ts +1 -28
- package/src/__tests__/guardian-action-followup-store.test.ts +1 -1
- package/src/__tests__/guardian-action-grant-mint-consume.test.ts +0 -1
- package/src/__tests__/guardian-decision-primitive-canonical.test.ts +0 -1
- package/src/__tests__/guardian-grant-minting.test.ts +35 -0
- package/src/__tests__/guardian-routing-invariants.test.ts +0 -1
- package/src/__tests__/guardian-verification-voice-binding.test.ts +0 -1
- package/src/__tests__/handlers-user-message-approval-consumption.test.ts +0 -39
- package/src/__tests__/heartbeat-service.test.ts +0 -1
- package/src/__tests__/host-cu-proxy.test.ts +629 -0
- package/src/__tests__/host-shell-tool.test.ts +27 -15
- package/src/__tests__/http-user-message-parity.test.ts +1 -0
- package/src/__tests__/ingress-url-consistency.test.ts +14 -21
- package/src/__tests__/integration-status.test.ts +38 -25
- package/src/__tests__/intent-routing.test.ts +0 -1
- package/src/__tests__/invite-routes-http.test.ts +10 -9
- package/src/__tests__/keychain-broker-client.test.ts +11 -43
- package/src/__tests__/managed-proxy-context.test.ts +5 -3
- package/src/__tests__/media-generate-image.test.ts +63 -2
- package/src/__tests__/media-reuse-story.e2e.test.ts +7 -3
- package/src/__tests__/messaging-send-tool.test.ts +4 -6
- package/src/__tests__/notification-routing-intent.test.ts +0 -1
- package/src/__tests__/oauth-cli.test.ts +373 -14
- package/src/__tests__/oauth-provider-profiles.test.ts +9 -9
- package/src/__tests__/oauth-scope-policy.test.ts +4 -6
- package/src/__tests__/oauth-store.test.ts +756 -0
- package/src/__tests__/onboarding-starter-tasks.test.ts +0 -1
- package/src/__tests__/provider-error-scenarios.test.ts +0 -1
- package/src/__tests__/provider-fail-open-selection.test.ts +3 -1
- package/src/__tests__/provider-managed-proxy-integration.test.ts +70 -6
- package/src/__tests__/provider-streaming.benchmark.test.ts +0 -1
- package/src/__tests__/public-ingress-urls.test.ts +15 -21
- package/src/__tests__/recording-handler.test.ts +3 -4
- package/src/__tests__/registry.test.ts +2 -2
- package/src/__tests__/runtime-events-sse.test.ts +55 -7
- package/src/__tests__/schedule-store.test.ts +0 -1
- package/src/__tests__/scheduler-recurrence.test.ts +0 -1
- package/src/__tests__/schema-transforms.test.ts +226 -0
- package/src/__tests__/scoped-approval-grants.test.ts +0 -1
- package/src/__tests__/scoped-grant-security-matrix.test.ts +0 -1
- package/src/__tests__/script-proxy-injection-runtime.test.ts +23 -13
- package/src/__tests__/script-proxy-policy-runtime.test.ts +1 -1
- package/src/__tests__/script-proxy-session-manager.test.ts +1 -1
- package/src/__tests__/secret-ingress-handler.test.ts +0 -1
- package/src/__tests__/secret-onetime-send.test.ts +5 -3
- package/src/__tests__/send-endpoint-busy.test.ts +21 -6
- package/src/__tests__/sequence-store.test.ts +0 -1
- package/src/__tests__/session-init.benchmark.test.ts +4 -5
- package/src/__tests__/session-messaging-secret-redirect.test.ts +5 -4
- package/src/__tests__/skill-include-graph.test.ts +66 -0
- package/src/__tests__/skill-load-feature-flag.test.ts +0 -1
- package/src/__tests__/skill-load-tool.test.ts +149 -1
- package/src/__tests__/skill-projection-feature-flag.test.ts +0 -1
- package/src/__tests__/skills-uninstall.test.ts +3 -3
- package/src/__tests__/skills.test.ts +3 -12
- package/src/__tests__/slack-channel-config.test.ts +76 -11
- package/src/__tests__/slack-share-routes.test.ts +17 -14
- package/src/__tests__/system-prompt.test.ts +0 -1
- package/src/__tests__/telegram-bot-username-resolution.test.ts +3 -0
- package/src/__tests__/telegram-invite-adapter.test.ts +18 -22
- package/src/__tests__/terminal-tools.test.ts +4 -3
- package/src/__tests__/test-support/computer-use-skill-harness.ts +3 -2
- package/src/__tests__/tool-approval-handler.test.ts +0 -1
- package/src/__tests__/tool-execution-pipeline.benchmark.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 +0 -1
- package/src/__tests__/tool-grant-request-escalation.test.ts +0 -1
- package/src/__tests__/trust-store-pattern-matches.test.ts +29 -0
- package/src/__tests__/trust-store.test.ts +1 -22
- package/src/__tests__/trusted-contact-approval-notifier.test.ts +0 -1
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +0 -1
- package/src/__tests__/twilio-config.test.ts +2 -1
- package/src/__tests__/twilio-provider.test.ts +4 -2
- package/src/__tests__/twilio-routes.test.ts +5 -20
- package/src/__tests__/verification-control-plane-policy.test.ts +0 -1
- package/src/__tests__/voice-scoped-grant-consumer.test.ts +0 -1
- package/src/agent/ax-tree-compaction.test.ts +235 -0
- package/src/agent/loop.ts +76 -130
- package/src/calls/call-domain.ts +8 -10
- package/src/calls/relay-server.ts +9 -13
- package/src/calls/twilio-config.ts +4 -8
- package/src/calls/twilio-provider.ts +2 -1
- package/src/calls/twilio-rest.ts +2 -1
- package/src/calls/twilio-routes.ts +1 -2
- package/src/calls/voice-ingress-preflight.ts +1 -1
- package/src/cli/commands/browser-relay.ts +46 -15
- package/src/cli/commands/completions.ts +0 -3
- package/src/cli/commands/credentials.ts +110 -23
- package/src/cli/commands/oauth/apps.ts +255 -0
- package/src/cli/commands/oauth/connections.ts +299 -0
- package/src/cli/commands/oauth/index.ts +52 -0
- package/src/cli/commands/oauth/providers.ts +242 -0
- package/src/cli/commands/skills.ts +4 -338
- package/src/cli/program.ts +1 -5
- package/src/cli/reference.ts +1 -3
- package/src/cli.ts +3 -2
- package/src/config/assistant-feature-flags.ts +0 -3
- package/src/config/bundled-skills/_shared/CLI_RETRIEVAL_PATTERN.md +1 -1
- package/src/config/bundled-skills/claude-code/TOOLS.json +0 -4
- package/src/config/bundled-skills/computer-use/SKILL.md +3 -6
- package/src/config/bundled-skills/computer-use/TOOLS.json +22 -4
- package/src/config/bundled-skills/contacts/tools/google-contacts.ts +29 -32
- package/src/config/bundled-skills/gmail/SKILL.md +4 -4
- package/src/config/bundled-skills/gmail/tools/gmail-archive.ts +54 -61
- package/src/config/bundled-skills/gmail/tools/gmail-attachments.ts +25 -28
- package/src/config/bundled-skills/gmail/tools/gmail-draft.ts +14 -17
- package/src/config/bundled-skills/gmail/tools/gmail-filters.ts +39 -44
- package/src/config/bundled-skills/gmail/tools/gmail-follow-up.ts +61 -58
- package/src/config/bundled-skills/gmail/tools/gmail-forward.ts +50 -49
- package/src/config/bundled-skills/gmail/tools/gmail-label.ts +11 -13
- package/src/config/bundled-skills/gmail/tools/gmail-outreach-scan.ts +148 -146
- package/src/config/bundled-skills/gmail/tools/gmail-send-draft.ts +4 -7
- package/src/config/bundled-skills/gmail/tools/gmail-sender-digest.ts +175 -173
- package/src/config/bundled-skills/gmail/tools/gmail-trash.ts +4 -7
- package/src/config/bundled-skills/gmail/tools/gmail-unsubscribe.ts +71 -76
- package/src/config/bundled-skills/gmail/tools/gmail-vacation.ts +32 -38
- package/src/config/bundled-skills/google-calendar/SKILL.md +2 -2
- package/src/config/bundled-skills/google-calendar/calendar-client.ts +90 -44
- package/src/config/bundled-skills/google-calendar/tools/calendar-check-availability.ts +9 -10
- package/src/config/bundled-skills/google-calendar/tools/calendar-create-event.ts +5 -6
- package/src/config/bundled-skills/google-calendar/tools/calendar-get-event.ts +4 -5
- package/src/config/bundled-skills/google-calendar/tools/calendar-list-events.ts +14 -15
- package/src/config/bundled-skills/google-calendar/tools/calendar-rsvp.ts +37 -37
- package/src/config/bundled-skills/google-calendar/tools/shared.ts +4 -9
- package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +24 -3
- package/src/config/bundled-skills/messaging/SKILL.md +6 -6
- package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +62 -63
- package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +15 -16
- package/src/config/bundled-skills/messaging/tools/messaging-auth-test.ts +4 -5
- package/src/config/bundled-skills/messaging/tools/messaging-list-conversations.ts +6 -7
- package/src/config/bundled-skills/messaging/tools/messaging-mark-read.ts +4 -5
- package/src/config/bundled-skills/messaging/tools/messaging-read.ts +14 -15
- package/src/config/bundled-skills/messaging/tools/messaging-search.ts +4 -5
- package/src/config/bundled-skills/messaging/tools/messaging-send.ts +128 -128
- package/src/config/bundled-skills/messaging/tools/messaging-sender-digest.ts +33 -34
- package/src/config/bundled-skills/messaging/tools/shared.ts +12 -15
- package/src/config/bundled-skills/settings/SKILL.md +1 -1
- package/src/config/bundled-skills/settings/TOOLS.json +2 -8
- package/src/config/bundled-skills/settings/tools/voice-config-update.ts +5 -33
- package/src/config/bundled-skills/slack/tools/shared.ts +4 -10
- package/src/config/bundled-skills/slack/tools/slack-add-reaction.ts +4 -5
- package/src/config/bundled-skills/slack/tools/slack-channel-details.ts +15 -16
- package/src/config/bundled-skills/slack/tools/slack-delete-message.ts +4 -5
- package/src/config/bundled-skills/slack/tools/slack-edit-message.ts +4 -5
- package/src/config/bundled-skills/slack/tools/slack-leave-channel.ts +4 -5
- package/src/config/bundled-skills/slack/tools/slack-scan-digest.ts +95 -92
- package/src/config/env-registry.ts +14 -83
- package/src/config/env.ts +11 -50
- package/src/config/feature-flag-registry.json +16 -16
- package/src/config/schema.ts +3 -1
- package/src/config/skills.ts +21 -2
- package/src/context/image-dimensions.ts +229 -0
- package/src/context/token-estimator.ts +75 -12
- package/src/context/window-manager.ts +49 -10
- package/src/daemon/assistant-attachments.ts +1 -13
- package/src/daemon/guardian-action-generators.ts +4 -5
- package/src/daemon/handlers/config-ingress.ts +8 -33
- package/src/daemon/handlers/config-slack-channel.ts +76 -56
- package/src/daemon/handlers/config-telegram.ts +53 -24
- package/src/daemon/handlers/sessions.ts +10 -24
- package/src/daemon/handlers/shared.ts +0 -130
- package/src/daemon/host-cu-proxy.ts +401 -0
- package/src/daemon/lifecycle.ts +39 -63
- package/src/daemon/message-protocol.ts +3 -0
- package/src/daemon/message-types/computer-use.ts +2 -119
- package/src/daemon/message-types/host-cu.ts +19 -0
- package/src/daemon/message-types/integrations.ts +1 -0
- package/src/daemon/message-types/messages.ts +3 -0
- package/src/daemon/server.ts +14 -21
- package/src/daemon/session-agent-loop-handlers.ts +2 -0
- package/src/daemon/session-attachments.ts +1 -2
- package/src/daemon/session-messaging.ts +3 -1
- package/src/daemon/session-slash.ts +1 -1
- package/src/daemon/session-surfaces.ts +40 -28
- package/src/daemon/session-tool-setup.ts +20 -11
- package/src/daemon/session.ts +139 -16
- package/src/daemon/tool-side-effects.ts +2 -8
- package/src/daemon/watch-handler.ts +2 -2
- package/src/email/providers/index.ts +2 -1
- package/src/events/tool-metrics-listener.ts +2 -2
- package/src/hooks/manager.ts +1 -4
- package/src/inbound/public-ingress-urls.ts +7 -7
- package/src/instrument.ts +15 -1
- package/src/logfire.ts +16 -5
- package/src/media/app-icon-generator.ts +30 -4
- package/src/media/avatar-router.ts +26 -3
- package/src/media/gemini-image-service.ts +28 -2
- package/src/memory/conversation-key-store.ts +21 -0
- package/src/memory/db-init.ts +4 -0
- package/src/memory/guardian-action-store.ts +1 -1
- package/src/memory/migrations/149-oauth-tables.ts +60 -0
- package/src/memory/migrations/index.ts +1 -0
- package/src/memory/schema/guardian.ts +1 -1
- package/src/memory/schema/index.ts +1 -0
- package/src/memory/schema/oauth.ts +65 -0
- package/src/messaging/provider.ts +19 -13
- package/src/messaging/providers/gmail/adapter.ts +40 -23
- package/src/messaging/providers/gmail/client.ts +283 -122
- package/src/messaging/providers/gmail/people-client.ts +32 -24
- package/src/messaging/providers/slack/adapter.ts +29 -19
- package/src/messaging/providers/slack/client.ts +265 -78
- package/src/messaging/providers/telegram-bot/adapter.ts +19 -18
- package/src/messaging/providers/whatsapp/adapter.ts +17 -11
- package/src/messaging/registry.ts +2 -31
- package/src/notifications/copy-composer.ts +0 -5
- package/src/notifications/signal.ts +4 -5
- package/src/oauth/byo-connection.test.ts +537 -0
- package/src/oauth/byo-connection.ts +128 -0
- package/src/oauth/connect-orchestrator.ts +139 -56
- package/src/oauth/connect-types.ts +17 -23
- package/src/oauth/connection-resolver.ts +58 -0
- package/src/oauth/connection.ts +38 -0
- package/src/oauth/manual-token-connection.ts +104 -0
- package/src/oauth/oauth-store.ts +496 -0
- package/src/oauth/platform-connection.test.ts +192 -0
- package/src/oauth/platform-connection.ts +111 -0
- package/src/oauth/provider-behaviors.ts +124 -0
- package/src/oauth/scope-policy.ts +9 -2
- package/src/oauth/seed-providers.ts +161 -0
- package/src/oauth/token-persistence.ts +74 -78
- package/src/permissions/checker.ts +8 -4
- package/src/permissions/defaults.ts +0 -1
- package/src/permissions/prompter.ts +10 -1
- package/src/permissions/trust-store.ts +13 -0
- package/src/prompts/__tests__/build-cli-reference-section.test.ts +3 -1
- package/src/prompts/system-prompt.ts +70 -45
- package/src/providers/anthropic/client.ts +133 -24
- package/src/providers/gemini/client.ts +15 -6
- package/src/providers/managed-proxy/constants.ts +2 -2
- package/src/providers/managed-proxy/context.ts +5 -1
- package/src/providers/ratelimit.ts +17 -0
- package/src/providers/registry.ts +2 -2
- package/src/providers/retry.ts +1 -27
- package/src/runtime/AGENTS.md +17 -0
- package/src/runtime/auth/route-policy.ts +0 -3
- package/src/runtime/channel-invite-transports/telegram.ts +2 -1
- package/src/runtime/channel-readiness-service.ts +168 -195
- package/src/runtime/channel-readiness-types.ts +4 -0
- package/src/runtime/channel-reply-delivery.ts +0 -40
- package/src/runtime/gateway-client.ts +0 -7
- package/src/runtime/guardian-action-conversation-turn.ts +1 -3
- package/src/runtime/guardian-action-followup-executor.ts +1 -1
- package/src/runtime/guardian-action-message-composer.ts +3 -23
- package/src/runtime/http-server.ts +17 -10
- package/src/runtime/http-types.ts +2 -3
- package/src/runtime/middleware/rate-limiter.ts +74 -20
- package/src/runtime/middleware/twilio-validation.ts +1 -11
- package/src/runtime/pending-interactions.ts +14 -12
- package/src/runtime/routes/channel-delivery-routes.ts +0 -1
- package/src/runtime/routes/channel-readiness-routes.ts +2 -0
- package/src/runtime/routes/conversation-routes.ts +73 -19
- package/src/runtime/routes/diagnostics-routes.ts +11 -9
- package/src/runtime/routes/events-routes.ts +21 -11
- package/src/runtime/routes/guardian-approval-interception.ts +20 -5
- package/src/runtime/routes/host-cu-routes.ts +97 -0
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +12 -111
- package/src/runtime/routes/integrations/slack/share.ts +6 -6
- package/src/runtime/routes/integrations/twilio.ts +6 -5
- package/src/runtime/routes/log-export-routes.ts +126 -8
- package/src/runtime/routes/secret-routes.ts +3 -2
- package/src/runtime/routes/settings-routes.ts +113 -48
- package/src/runtime/routes/surface-action-routes.ts +1 -1
- package/src/runtime/routes/watch-routes.ts +128 -0
- package/src/schedule/integration-status.ts +10 -8
- package/src/security/credential-key.ts +14 -0
- package/src/security/keychain-broker-client.ts +5 -6
- package/src/security/oauth2.ts +1 -1
- package/src/security/token-manager.ts +145 -43
- package/src/skills/catalog-install.ts +358 -0
- package/src/skills/include-graph.ts +32 -0
- package/src/telegram/bot-username.ts +2 -3
- package/src/tools/apps/definitions.ts +0 -5
- package/src/tools/assets/materialize.ts +0 -5
- package/src/tools/assets/search.ts +0 -5
- package/src/tools/browser/headless-browser.ts +1 -67
- package/src/tools/browser/network-recorder.ts +1 -1
- package/src/tools/browser/network-recording-types.ts +1 -1
- package/src/tools/claude-code/claude-code.ts +0 -5
- package/src/tools/computer-use/definitions.ts +46 -11
- package/src/tools/computer-use/registry.ts +4 -5
- package/src/tools/credentials/broker.ts +5 -4
- package/src/tools/credentials/metadata-store.ts +22 -74
- package/src/tools/credentials/resolve.ts +2 -1
- package/src/tools/credentials/vault.ts +139 -151
- package/src/tools/filesystem/edit.ts +1 -6
- package/src/tools/filesystem/read.ts +0 -5
- package/src/tools/filesystem/write.ts +1 -6
- package/src/tools/host-filesystem/edit.ts +1 -6
- package/src/tools/host-filesystem/read.ts +1 -6
- package/src/tools/host-filesystem/write.ts +1 -6
- package/src/tools/mcp/mcp-tool-factory.ts +18 -1
- package/src/tools/memory/definitions.ts +0 -5
- package/src/tools/network/web-fetch.ts +0 -5
- package/src/tools/network/web-search.ts +0 -5
- package/src/tools/registry.ts +2 -7
- package/src/tools/schema-transforms.ts +99 -0
- package/src/tools/skills/load.ts +62 -8
- package/src/tools/swarm/delegate.ts +0 -5
- package/src/tools/system/avatar-generator.ts +0 -5
- package/src/tools/ui-surface/definitions.ts +0 -15
- package/src/tools/watch/screen-watch.ts +0 -5
- package/src/tools/watch/watch-state.ts +0 -12
- package/src/util/logger.ts +7 -41
- package/src/util/platform.ts +9 -28
- package/src/version.ts +10 -0
- package/src/watcher/providers/github.ts +51 -52
- package/src/watcher/providers/gmail.ts +88 -80
- package/src/watcher/providers/google-calendar.ts +94 -86
- package/src/watcher/providers/linear.ts +87 -93
- package/src/__tests__/computer-use-session-compaction.test.ts +0 -143
- package/src/__tests__/computer-use-session-lifecycle.test.ts +0 -322
- package/src/__tests__/computer-use-session-working-dir.test.ts +0 -166
- package/src/__tests__/computer-use-skill-baseline.test.ts +0 -78
- package/src/__tests__/computer-use-skill-endstate.test.ts +0 -105
- package/src/__tests__/computer-use-skill-lifecycle-cleanup.test.ts +0 -249
- package/src/__tests__/ride-shotgun-handler.test.ts +0 -452
- package/src/cli/commands/dev.ts +0 -129
- package/src/cli/commands/map.ts +0 -391
- package/src/cli/commands/oauth.ts +0 -77
- package/src/config/bundled-skills/computer-use/tools/computer-use-request-control.ts +0 -16
- package/src/daemon/computer-use-session.ts +0 -1020
- package/src/daemon/ride-shotgun-handler.ts +0 -567
- package/src/oauth/provider-profiles.ts +0 -192
- package/src/prompts/computer-use-prompt.ts +0 -98
- package/src/runtime/routes/computer-use-routes.ts +0 -641
- package/src/runtime/telegram-streaming-delivery.test.ts +0 -597
- package/src/runtime/telegram-streaming-delivery.ts +0 -383
- package/src/tools/computer-use/request-computer-control.ts +0 -61
|
@@ -44,10 +44,67 @@ mock.module("../tools/registry.js", () => ({
|
|
|
44
44
|
registerTool: () => {},
|
|
45
45
|
}));
|
|
46
46
|
|
|
47
|
+
// ---------------------------------------------------------------------------
|
|
48
|
+
// Mock oauth-store to avoid SQLite dependency in unit tests
|
|
49
|
+
// ---------------------------------------------------------------------------
|
|
50
|
+
|
|
51
|
+
let mockGetMostRecentAppByProvider: ReturnType<
|
|
52
|
+
typeof mock<(key: string) => unknown>
|
|
53
|
+
>;
|
|
54
|
+
let mockGetAppByProviderAndClientId: ReturnType<
|
|
55
|
+
typeof mock<(key: string, clientId: string) => unknown>
|
|
56
|
+
>;
|
|
57
|
+
let mockGetProvider: ReturnType<typeof mock<(key: string) => unknown>>;
|
|
58
|
+
|
|
59
|
+
mock.module("../oauth/oauth-store.js", () => {
|
|
60
|
+
mockGetMostRecentAppByProvider = mock(() => undefined);
|
|
61
|
+
mockGetAppByProviderAndClientId = mock(() => undefined);
|
|
62
|
+
mockGetProvider = mock(() => undefined);
|
|
63
|
+
return {
|
|
64
|
+
getMostRecentAppByProvider: mockGetMostRecentAppByProvider,
|
|
65
|
+
getAppByProviderAndClientId: mockGetAppByProviderAndClientId,
|
|
66
|
+
getProvider: mockGetProvider,
|
|
67
|
+
listConnections: mock(() => []),
|
|
68
|
+
seedProviders: mock(() => {}),
|
|
69
|
+
disconnectOAuthProvider: mock(async () => "not-found" as const),
|
|
70
|
+
};
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
// ---------------------------------------------------------------------------
|
|
74
|
+
// Mock public ingress URL — not available in unit tests. The connect
|
|
75
|
+
// orchestrator dynamically imports this for non-interactive flows.
|
|
76
|
+
// ---------------------------------------------------------------------------
|
|
77
|
+
|
|
78
|
+
mock.module("../inbound/public-ingress-urls.js", () => ({
|
|
79
|
+
getPublicBaseUrl: () => {
|
|
80
|
+
throw new Error("No public ingress URL configured");
|
|
81
|
+
},
|
|
82
|
+
}));
|
|
83
|
+
|
|
84
|
+
// ---------------------------------------------------------------------------
|
|
85
|
+
// Mock prepareOAuth2Flow — unit tests should not start real loopback HTTP
|
|
86
|
+
// servers. The connect orchestrator still runs its own validation logic
|
|
87
|
+
// (scope policy, non-interactive ingress checks, etc.) but the actual
|
|
88
|
+
// OAuth flow setup is stubbed.
|
|
89
|
+
// ---------------------------------------------------------------------------
|
|
90
|
+
|
|
91
|
+
mock.module("../security/oauth2.js", () => ({
|
|
92
|
+
prepareOAuth2Flow: mock(async () => ({
|
|
93
|
+
authUrl: "https://mock-auth-url.example.com/authorize",
|
|
94
|
+
state: "mock-state",
|
|
95
|
+
completion: new Promise(() => {}),
|
|
96
|
+
})),
|
|
97
|
+
startOAuth2Flow: mock(async () => ({
|
|
98
|
+
grantedScopes: [],
|
|
99
|
+
tokens: { access_token: "mock-token" },
|
|
100
|
+
})),
|
|
101
|
+
}));
|
|
102
|
+
|
|
47
103
|
// ---------------------------------------------------------------------------
|
|
48
104
|
// Imports under test
|
|
49
105
|
// ---------------------------------------------------------------------------
|
|
50
106
|
|
|
107
|
+
import { credentialKey } from "../security/credential-key.js";
|
|
51
108
|
import { getSecureKey, setSecureKey } from "../security/secure-keys.js";
|
|
52
109
|
import { CredentialBroker } from "../tools/credentials/broker.js";
|
|
53
110
|
import {
|
|
@@ -108,7 +165,7 @@ describe("CredentialBroker transient credentials", () => {
|
|
|
108
165
|
const result = broker.consume(auth.token.tokenId);
|
|
109
166
|
expect(result.success).toBe(true);
|
|
110
167
|
expect(result.value).toBe("one-time-secret");
|
|
111
|
-
expect(result.storageKey).toBe("
|
|
168
|
+
expect(result.storageKey).toBe(credentialKey("svc", "key"));
|
|
112
169
|
|
|
113
170
|
// Second authorize + consume should NOT have the transient value
|
|
114
171
|
const auth2 = broker.authorize({
|
|
@@ -148,7 +205,7 @@ describe("CredentialBroker transient credentials", () => {
|
|
|
148
205
|
upsertCredentialMetadata("github", "token", {
|
|
149
206
|
allowedTools: ["browser_fill_credential"],
|
|
150
207
|
});
|
|
151
|
-
setSecureKey("
|
|
208
|
+
setSecureKey(credentialKey("github", "token"), "stored-value");
|
|
152
209
|
broker.injectTransient("github", "token", "transient-value");
|
|
153
210
|
|
|
154
211
|
// First fill uses transient
|
|
@@ -411,7 +468,7 @@ describe("credential_store tool — prompt action", () => {
|
|
|
411
468
|
expect(result.content).not.toContain("prompt-secret-val");
|
|
412
469
|
|
|
413
470
|
// Verify stored
|
|
414
|
-
expect(getSecureKey("
|
|
471
|
+
expect(getSecureKey(credentialKey("test-prompt", "api_key"))).toBe(
|
|
415
472
|
"prompt-secret-val",
|
|
416
473
|
);
|
|
417
474
|
});
|
|
@@ -472,18 +529,50 @@ describe("credential_store tool — prompt action", () => {
|
|
|
472
529
|
// ---------------------------------------------------------------------------
|
|
473
530
|
|
|
474
531
|
describe("credential_store tool — oauth2_connect error paths", () => {
|
|
532
|
+
/** Well-known provider rows returned by the mocked getProvider */
|
|
533
|
+
const wellKnownProviders: Record<string, object> = {
|
|
534
|
+
"integration:gmail": {
|
|
535
|
+
key: "integration:gmail",
|
|
536
|
+
authUrl: "https://accounts.google.com/o/oauth2/v2/auth",
|
|
537
|
+
tokenUrl: "https://oauth2.googleapis.com/token",
|
|
538
|
+
defaultScopes: JSON.stringify(["https://mail.google.com/"]),
|
|
539
|
+
scopePolicy: JSON.stringify({}),
|
|
540
|
+
callbackTransport: "loopback",
|
|
541
|
+
loopbackPort: 8756,
|
|
542
|
+
},
|
|
543
|
+
"integration:slack": {
|
|
544
|
+
key: "integration:slack",
|
|
545
|
+
authUrl: "https://slack.com/oauth/v2/authorize",
|
|
546
|
+
tokenUrl: "https://slack.com/api/oauth.v2.access",
|
|
547
|
+
defaultScopes: JSON.stringify(["channels:read"]),
|
|
548
|
+
scopePolicy: JSON.stringify({}),
|
|
549
|
+
},
|
|
550
|
+
};
|
|
551
|
+
|
|
475
552
|
beforeEach(() => {
|
|
476
553
|
if (existsSync(TEST_DIR)) rmSync(TEST_DIR, { recursive: true });
|
|
477
554
|
mkdirSync(TEST_DIR, { recursive: true });
|
|
478
555
|
_setStorePath(STORE_PATH);
|
|
479
556
|
_resetBackend();
|
|
480
557
|
_setMetadataPath(join(TEST_DIR, "metadata.json"));
|
|
558
|
+
// Return well-known provider rows so vault.ts knows gmail/slack are
|
|
559
|
+
// registered, and custom providers return undefined.
|
|
560
|
+
mockGetProvider.mockImplementation(
|
|
561
|
+
(key: string) => wellKnownProviders[key] ?? undefined,
|
|
562
|
+
);
|
|
563
|
+
mockGetMostRecentAppByProvider.mockClear();
|
|
564
|
+
mockGetMostRecentAppByProvider.mockImplementation(() => undefined);
|
|
565
|
+
mockGetAppByProviderAndClientId.mockClear();
|
|
566
|
+
mockGetAppByProviderAndClientId.mockImplementation(() => undefined);
|
|
481
567
|
});
|
|
482
568
|
|
|
483
569
|
afterEach(() => {
|
|
484
570
|
_setMetadataPath(null);
|
|
485
571
|
_setStorePath(null);
|
|
486
572
|
_resetBackend();
|
|
573
|
+
mockGetProvider.mockImplementation(() => undefined);
|
|
574
|
+
mockGetMostRecentAppByProvider.mockImplementation(() => undefined);
|
|
575
|
+
mockGetAppByProviderAndClientId.mockImplementation(() => undefined);
|
|
487
576
|
});
|
|
488
577
|
|
|
489
578
|
test("requires service parameter", async () => {
|
|
@@ -495,55 +584,38 @@ describe("credential_store tool — oauth2_connect error paths", () => {
|
|
|
495
584
|
expect(result.content).toContain("service is required");
|
|
496
585
|
});
|
|
497
586
|
|
|
498
|
-
test("
|
|
499
|
-
const result = await credentialStoreTool.execute(
|
|
500
|
-
{
|
|
501
|
-
action: "oauth2_connect",
|
|
502
|
-
service: "custom-svc",
|
|
503
|
-
token_url: "https://t",
|
|
504
|
-
scopes: ["read"],
|
|
505
|
-
},
|
|
506
|
-
_ctx,
|
|
507
|
-
);
|
|
508
|
-
expect(result.isError).toBe(true);
|
|
509
|
-
expect(result.content).toContain("auth_url is required");
|
|
510
|
-
});
|
|
511
|
-
|
|
512
|
-
test("requires token_url for unknown service", async () => {
|
|
513
|
-
const result = await credentialStoreTool.execute(
|
|
514
|
-
{
|
|
515
|
-
action: "oauth2_connect",
|
|
516
|
-
service: "custom-svc",
|
|
517
|
-
auth_url: "https://a",
|
|
518
|
-
scopes: ["read"],
|
|
519
|
-
},
|
|
520
|
-
_ctx,
|
|
521
|
-
);
|
|
522
|
-
expect(result.isError).toBe(true);
|
|
523
|
-
expect(result.content).toContain("token_url is required");
|
|
524
|
-
});
|
|
525
|
-
|
|
526
|
-
test("requires scopes for unknown service", async () => {
|
|
587
|
+
test("rejects unknown service without registered provider", async () => {
|
|
527
588
|
const result = await credentialStoreTool.execute(
|
|
528
589
|
{
|
|
529
590
|
action: "oauth2_connect",
|
|
530
591
|
service: "custom-svc",
|
|
531
592
|
auth_url: "https://a",
|
|
532
593
|
token_url: "https://t",
|
|
594
|
+
scopes: ["read"],
|
|
533
595
|
},
|
|
534
596
|
_ctx,
|
|
535
597
|
);
|
|
536
598
|
expect(result.isError).toBe(true);
|
|
537
|
-
expect(result.content).toContain("
|
|
599
|
+
expect(result.content).toContain("no OAuth provider registered");
|
|
538
600
|
});
|
|
539
601
|
|
|
540
602
|
test("requires client_id", async () => {
|
|
603
|
+
mockGetProvider.mockImplementation((key: string) => {
|
|
604
|
+
if (key === "custom-svc") {
|
|
605
|
+
return {
|
|
606
|
+
key: "custom-svc",
|
|
607
|
+
authUrl: "https://auth.example.com",
|
|
608
|
+
tokenUrl: "https://token.example.com",
|
|
609
|
+
defaultScopes: JSON.stringify(["read"]),
|
|
610
|
+
scopePolicy: JSON.stringify({}),
|
|
611
|
+
};
|
|
612
|
+
}
|
|
613
|
+
return wellKnownProviders[key] ?? undefined;
|
|
614
|
+
});
|
|
541
615
|
const result = await credentialStoreTool.execute(
|
|
542
616
|
{
|
|
543
617
|
action: "oauth2_connect",
|
|
544
618
|
service: "custom-svc",
|
|
545
|
-
auth_url: "https://auth.example.com",
|
|
546
|
-
token_url: "https://token.example.com",
|
|
547
619
|
scopes: ["read"],
|
|
548
620
|
},
|
|
549
621
|
_ctx,
|
|
@@ -553,6 +625,21 @@ describe("credential_store tool — oauth2_connect error paths", () => {
|
|
|
553
625
|
});
|
|
554
626
|
|
|
555
627
|
test("requires interactive context", async () => {
|
|
628
|
+
// Register custom-svc as a provider so the orchestrator finds it
|
|
629
|
+
// and reaches the non-interactive check (gateway transport).
|
|
630
|
+
mockGetProvider.mockImplementation((key: string) => {
|
|
631
|
+
if (key === "custom-svc") {
|
|
632
|
+
return {
|
|
633
|
+
key: "custom-svc",
|
|
634
|
+
authUrl: "https://auth.example.com",
|
|
635
|
+
tokenUrl: "https://token.example.com",
|
|
636
|
+
defaultScopes: JSON.stringify(["read"]),
|
|
637
|
+
scopePolicy: JSON.stringify({}),
|
|
638
|
+
};
|
|
639
|
+
}
|
|
640
|
+
return wellKnownProviders[key] ?? undefined;
|
|
641
|
+
});
|
|
642
|
+
|
|
556
643
|
const result = await credentialStoreTool.execute(
|
|
557
644
|
{
|
|
558
645
|
action: "oauth2_connect",
|
|
@@ -595,16 +682,25 @@ describe("credential_store tool — oauth2_connect error paths", () => {
|
|
|
595
682
|
expect(result.content).toContain("client_id is required");
|
|
596
683
|
});
|
|
597
684
|
|
|
598
|
-
test("uses stored client_id from
|
|
599
|
-
//
|
|
600
|
-
//
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
);
|
|
607
|
-
|
|
685
|
+
test("uses stored client_id from oauth-store DB", async () => {
|
|
686
|
+
// Mock getMostRecentAppByProvider to return an app with a client_id
|
|
687
|
+
// and store client_secret in the secure store.
|
|
688
|
+
mockGetMostRecentAppByProvider.mockImplementation(() => ({
|
|
689
|
+
id: "test-app-id",
|
|
690
|
+
providerKey: "integration:gmail",
|
|
691
|
+
clientId: "stored-client-id-123",
|
|
692
|
+
createdAt: Date.now(),
|
|
693
|
+
}));
|
|
694
|
+
mockGetProvider.mockImplementation(() => ({
|
|
695
|
+
key: "integration:gmail",
|
|
696
|
+
authUrl: "https://accounts.google.com/o/oauth2/v2/auth",
|
|
697
|
+
tokenUrl: "https://oauth2.googleapis.com/token",
|
|
698
|
+
defaultScopes: JSON.stringify(["https://mail.google.com/"]),
|
|
699
|
+
scopePolicy: JSON.stringify({}),
|
|
700
|
+
callbackTransport: "loopback",
|
|
701
|
+
loopbackPort: 8756,
|
|
702
|
+
}));
|
|
703
|
+
setSecureKey("oauth_app/test-app-id/client_secret", "test-secret");
|
|
608
704
|
|
|
609
705
|
const result = await credentialStoreTool.execute(
|
|
610
706
|
{
|
|
@@ -621,26 +717,163 @@ describe("credential_store tool — oauth2_connect error paths", () => {
|
|
|
621
717
|
expect(result.content).toContain("To connect gmail, open this link");
|
|
622
718
|
expect(result.content).not.toContain("client_id is required");
|
|
623
719
|
expect(result.content).not.toContain("client_secret is required");
|
|
720
|
+
|
|
721
|
+
// Reset mocks
|
|
722
|
+
mockGetMostRecentAppByProvider.mockImplementation(() => undefined);
|
|
723
|
+
mockGetProvider.mockImplementation(() => undefined);
|
|
624
724
|
});
|
|
625
725
|
|
|
626
|
-
test("
|
|
627
|
-
//
|
|
628
|
-
//
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
726
|
+
test("uses getAppByProviderAndClientId when client_id is provided without client_secret", async () => {
|
|
727
|
+
// When client_id is supplied but client_secret is not, the vault should
|
|
728
|
+
// look up the matching app via getAppByProviderAndClientId (not the
|
|
729
|
+
// most-recent-app heuristic) so the secret comes from the correct app.
|
|
730
|
+
mockGetAppByProviderAndClientId.mockImplementation(
|
|
731
|
+
(providerKey: string, cId: string) => {
|
|
732
|
+
if (
|
|
733
|
+
providerKey === "integration:gmail" &&
|
|
734
|
+
cId === "caller-supplied-client-id"
|
|
735
|
+
) {
|
|
736
|
+
return {
|
|
737
|
+
id: "matched-app-id",
|
|
738
|
+
providerKey: "integration:gmail",
|
|
739
|
+
clientId: "caller-supplied-client-id",
|
|
740
|
+
createdAt: Date.now(),
|
|
741
|
+
};
|
|
742
|
+
}
|
|
743
|
+
return undefined;
|
|
744
|
+
},
|
|
745
|
+
);
|
|
746
|
+
mockGetProvider.mockImplementation(() => ({
|
|
747
|
+
key: "integration:gmail",
|
|
748
|
+
authUrl: "https://accounts.google.com/o/oauth2/v2/auth",
|
|
749
|
+
tokenUrl: "https://oauth2.googleapis.com/token",
|
|
750
|
+
defaultScopes: JSON.stringify(["https://mail.google.com/"]),
|
|
751
|
+
scopePolicy: JSON.stringify({}),
|
|
752
|
+
callbackTransport: "loopback",
|
|
753
|
+
loopbackPort: 8756,
|
|
754
|
+
}));
|
|
755
|
+
setSecureKey("oauth_app/matched-app-id/client_secret", "matched-secret");
|
|
756
|
+
|
|
757
|
+
const result = await credentialStoreTool.execute(
|
|
758
|
+
{
|
|
759
|
+
action: "oauth2_connect",
|
|
760
|
+
service: "gmail",
|
|
761
|
+
client_id: "caller-supplied-client-id",
|
|
762
|
+
},
|
|
763
|
+
{ ..._ctx, isInteractive: false },
|
|
632
764
|
);
|
|
633
765
|
|
|
766
|
+
// Should succeed — client_secret resolved from the matched app
|
|
767
|
+
expect(result.isError).toBe(false);
|
|
768
|
+
expect(result.content).toContain("To connect gmail, open this link");
|
|
769
|
+
// getMostRecentAppByProvider should NOT have been called since client_id was known
|
|
770
|
+
expect(mockGetMostRecentAppByProvider).not.toHaveBeenCalled();
|
|
771
|
+
|
|
772
|
+
// Reset mocks
|
|
773
|
+
mockGetAppByProviderAndClientId.mockImplementation(() => undefined);
|
|
774
|
+
mockGetProvider.mockImplementation(() => undefined);
|
|
775
|
+
});
|
|
776
|
+
|
|
777
|
+
test("falls back to getMostRecentAppByProvider when client_id is not provided", async () => {
|
|
778
|
+
// When neither client_id nor client_secret is provided, the vault should
|
|
779
|
+
// use getMostRecentAppByProvider (the fallback heuristic).
|
|
780
|
+
mockGetMostRecentAppByProvider.mockImplementation(() => ({
|
|
781
|
+
id: "recent-app-id",
|
|
782
|
+
providerKey: "integration:gmail",
|
|
783
|
+
clientId: "recent-client-id",
|
|
784
|
+
createdAt: Date.now(),
|
|
785
|
+
}));
|
|
786
|
+
mockGetProvider.mockImplementation(() => ({
|
|
787
|
+
key: "integration:gmail",
|
|
788
|
+
authUrl: "https://accounts.google.com/o/oauth2/v2/auth",
|
|
789
|
+
tokenUrl: "https://oauth2.googleapis.com/token",
|
|
790
|
+
defaultScopes: JSON.stringify(["https://mail.google.com/"]),
|
|
791
|
+
scopePolicy: JSON.stringify({}),
|
|
792
|
+
callbackTransport: "loopback",
|
|
793
|
+
loopbackPort: 8756,
|
|
794
|
+
}));
|
|
795
|
+
setSecureKey("oauth_app/recent-app-id/client_secret", "recent-secret");
|
|
796
|
+
|
|
634
797
|
const result = await credentialStoreTool.execute(
|
|
635
798
|
{
|
|
636
799
|
action: "oauth2_connect",
|
|
637
800
|
service: "gmail",
|
|
638
801
|
},
|
|
802
|
+
{ ..._ctx, isInteractive: false },
|
|
803
|
+
);
|
|
804
|
+
|
|
805
|
+
expect(result.isError).toBe(false);
|
|
806
|
+
expect(result.content).toContain("To connect gmail, open this link");
|
|
807
|
+
// getAppByProviderAndClientId should NOT have been called since client_id was unknown
|
|
808
|
+
expect(mockGetAppByProviderAndClientId).not.toHaveBeenCalled();
|
|
809
|
+
|
|
810
|
+
// Reset mocks
|
|
811
|
+
mockGetMostRecentAppByProvider.mockImplementation(() => undefined);
|
|
812
|
+
mockGetProvider.mockImplementation(() => undefined);
|
|
813
|
+
});
|
|
814
|
+
|
|
815
|
+
test("getAppByProviderAndClientId returning undefined leaves client_secret unresolved", async () => {
|
|
816
|
+
// When client_id is provided but getAppByProviderAndClientId returns no
|
|
817
|
+
// matching app, client_secret remains unresolved and the vault should
|
|
818
|
+
// report the missing secret error.
|
|
819
|
+
mockGetAppByProviderAndClientId.mockImplementation(() => undefined);
|
|
820
|
+
mockGetProvider.mockImplementation(() => ({
|
|
821
|
+
key: "integration:gmail",
|
|
822
|
+
authUrl: "https://accounts.google.com/o/oauth2/v2/auth",
|
|
823
|
+
tokenUrl: "https://oauth2.googleapis.com/token",
|
|
824
|
+
defaultScopes: JSON.stringify(["https://mail.google.com/"]),
|
|
825
|
+
}));
|
|
826
|
+
|
|
827
|
+
const result = await credentialStoreTool.execute(
|
|
828
|
+
{
|
|
829
|
+
action: "oauth2_connect",
|
|
830
|
+
service: "gmail",
|
|
831
|
+
client_id: "unknown-client-id",
|
|
832
|
+
},
|
|
639
833
|
_ctx,
|
|
640
834
|
);
|
|
641
835
|
|
|
642
836
|
expect(result.isError).toBe(true);
|
|
643
837
|
expect(result.content).toContain("client_secret is required for gmail");
|
|
838
|
+
// getMostRecentAppByProvider should NOT have been called
|
|
839
|
+
expect(mockGetMostRecentAppByProvider).not.toHaveBeenCalled();
|
|
840
|
+
|
|
841
|
+
// Reset mocks
|
|
842
|
+
mockGetAppByProviderAndClientId.mockImplementation(() => undefined);
|
|
843
|
+
mockGetProvider.mockImplementation(() => undefined);
|
|
844
|
+
});
|
|
845
|
+
|
|
846
|
+
test("rejects when client_secret is missing for service that requires it", async () => {
|
|
847
|
+
// Mock getMostRecentAppByProvider to return an app with client_id but
|
|
848
|
+
// no client_secret in secure storage — validates the requiresClientSecret
|
|
849
|
+
// guardrail.
|
|
850
|
+
mockGetMostRecentAppByProvider.mockImplementation(() => ({
|
|
851
|
+
id: "test-app-id-no-secret",
|
|
852
|
+
providerKey: "integration:gmail",
|
|
853
|
+
clientId: "stored-client-id-456",
|
|
854
|
+
createdAt: Date.now(),
|
|
855
|
+
}));
|
|
856
|
+
mockGetProvider.mockImplementation(() => ({
|
|
857
|
+
key: "integration:gmail",
|
|
858
|
+
authUrl: "https://accounts.google.com/o/oauth2/v2/auth",
|
|
859
|
+
tokenUrl: "https://oauth2.googleapis.com/token",
|
|
860
|
+
defaultScopes: JSON.stringify(["https://mail.google.com/"]),
|
|
861
|
+
}));
|
|
862
|
+
|
|
863
|
+
const result = await credentialStoreTool.execute(
|
|
864
|
+
{
|
|
865
|
+
action: "oauth2_connect",
|
|
866
|
+
service: "gmail",
|
|
867
|
+
},
|
|
868
|
+
_ctx,
|
|
869
|
+
);
|
|
870
|
+
|
|
871
|
+
expect(result.isError).toBe(true);
|
|
872
|
+
expect(result.content).toContain("client_secret is required for gmail");
|
|
873
|
+
|
|
874
|
+
// Reset mocks
|
|
875
|
+
mockGetMostRecentAppByProvider.mockImplementation(() => undefined);
|
|
876
|
+
mockGetProvider.mockImplementation(() => undefined);
|
|
644
877
|
});
|
|
645
878
|
});
|
|
646
879
|
|
|
@@ -786,7 +1019,7 @@ describe("credential_store tool — store validation edge cases", () => {
|
|
|
786
1019
|
);
|
|
787
1020
|
|
|
788
1021
|
// Verify stored
|
|
789
|
-
expect(getSecureKey("
|
|
1022
|
+
expect(getSecureKey(credentialKey("del-test", "key"))).toBe("secret");
|
|
790
1023
|
const { getCredentialMetadata } =
|
|
791
1024
|
await import("../tools/credentials/metadata-store.js");
|
|
792
1025
|
expect(getCredentialMetadata("del-test", "key")).toBeDefined();
|
|
@@ -803,7 +1036,7 @@ describe("credential_store tool — store validation edge cases", () => {
|
|
|
803
1036
|
expect(result.isError).toBe(false);
|
|
804
1037
|
|
|
805
1038
|
// Both should be gone
|
|
806
|
-
expect(getSecureKey("
|
|
1039
|
+
expect(getSecureKey(credentialKey("del-test", "key"))).toBeUndefined();
|
|
807
1040
|
expect(getCredentialMetadata("del-test", "key")).toBeUndefined();
|
|
808
1041
|
});
|
|
809
1042
|
});
|
|
@@ -892,7 +1125,7 @@ describe("CredentialBroker — serverUseById edge cases", () => {
|
|
|
892
1125
|
},
|
|
893
1126
|
],
|
|
894
1127
|
});
|
|
895
|
-
setSecureKey("
|
|
1128
|
+
setSecureKey(credentialKey("multi", "api_key"), "multi-secret");
|
|
896
1129
|
|
|
897
1130
|
const result = broker.serverUseById({
|
|
898
1131
|
credentialId: meta.credentialId,
|