@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
|
@@ -1,13 +1,22 @@
|
|
|
1
1
|
import { getConfig } from "../../config/loader.js";
|
|
2
2
|
import { orchestrateOAuthConnect } from "../../oauth/connect-orchestrator.js";
|
|
3
3
|
import {
|
|
4
|
-
|
|
4
|
+
disconnectOAuthProvider,
|
|
5
|
+
getAppByProviderAndClientId,
|
|
6
|
+
getMostRecentAppByProvider,
|
|
7
|
+
getProvider,
|
|
8
|
+
} from "../../oauth/oauth-store.js";
|
|
9
|
+
import {
|
|
10
|
+
getProviderBehavior,
|
|
5
11
|
resolveService,
|
|
6
12
|
SERVICE_ALIASES,
|
|
7
|
-
} from "../../oauth/provider-
|
|
13
|
+
} from "../../oauth/provider-behaviors.js";
|
|
8
14
|
import { RiskLevel } from "../../permissions/types.js";
|
|
9
15
|
import type { ToolDefinition } from "../../providers/types.js";
|
|
10
|
-
import
|
|
16
|
+
import { buildAssistantEvent } from "../../runtime/assistant-event.js";
|
|
17
|
+
import { assistantEventHub } from "../../runtime/assistant-event-hub.js";
|
|
18
|
+
import { DAEMON_INTERNAL_ASSISTANT_ID } from "../../runtime/assistant-scope.js";
|
|
19
|
+
import { credentialKey } from "../../security/credential-key.js";
|
|
11
20
|
import {
|
|
12
21
|
deleteSecureKeyAsync,
|
|
13
22
|
getSecureKey,
|
|
@@ -32,27 +41,6 @@ import { toPolicyFromInput, validatePolicyInput } from "./policy-validate.js";
|
|
|
32
41
|
|
|
33
42
|
const log = getLogger("credential-vault");
|
|
34
43
|
|
|
35
|
-
/**
|
|
36
|
-
* Look up a stored OAuth field (e.g. client_id or client_secret) for a service.
|
|
37
|
-
* Checks both the canonical and alias service names.
|
|
38
|
-
*/
|
|
39
|
-
function findStoredOAuthField(
|
|
40
|
-
service: string,
|
|
41
|
-
field: string,
|
|
42
|
-
): string | undefined {
|
|
43
|
-
const servicesToCheck = [service];
|
|
44
|
-
// Also check the alias if the input is the canonical name, or vice versa
|
|
45
|
-
for (const [alias, canonical] of Object.entries(SERVICE_ALIASES)) {
|
|
46
|
-
if (canonical === service) servicesToCheck.push(alias);
|
|
47
|
-
if (alias === service) servicesToCheck.push(canonical);
|
|
48
|
-
}
|
|
49
|
-
for (const svc of servicesToCheck) {
|
|
50
|
-
const value = getSecureKey(`credential:${svc}:${field}`);
|
|
51
|
-
if (value) return value;
|
|
52
|
-
}
|
|
53
|
-
return undefined;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
44
|
class CredentialStoreTool implements Tool {
|
|
57
45
|
name = "credential_store";
|
|
58
46
|
description =
|
|
@@ -124,16 +112,6 @@ class CredentialStoreTool implements Tool {
|
|
|
124
112
|
description:
|
|
125
113
|
'Human-readable description of intended usage (for store/prompt actions), e.g. "GitHub login for pushing changes"',
|
|
126
114
|
},
|
|
127
|
-
auth_url: {
|
|
128
|
-
type: "string",
|
|
129
|
-
description:
|
|
130
|
-
"OAuth2 authorization endpoint (only for oauth2_connect action). Auto-filled for well-known services (gmail, slack).",
|
|
131
|
-
},
|
|
132
|
-
token_url: {
|
|
133
|
-
type: "string",
|
|
134
|
-
description:
|
|
135
|
-
"OAuth2 token endpoint (only for oauth2_connect action). Auto-filled for well-known services (gmail, slack).",
|
|
136
|
-
},
|
|
137
115
|
scopes: {
|
|
138
116
|
type: "array",
|
|
139
117
|
items: { type: "string" },
|
|
@@ -145,27 +123,11 @@ class CredentialStoreTool implements Tool {
|
|
|
145
123
|
description:
|
|
146
124
|
"OAuth2 client ID (only for oauth2_connect action). If omitted, looked up from previously stored credentials.",
|
|
147
125
|
},
|
|
148
|
-
extra_params: {
|
|
149
|
-
type: "object",
|
|
150
|
-
description:
|
|
151
|
-
"Extra query params for OAuth2 auth URL (only for oauth2_connect action)",
|
|
152
|
-
},
|
|
153
|
-
userinfo_url: {
|
|
154
|
-
type: "string",
|
|
155
|
-
description:
|
|
156
|
-
"Endpoint to fetch account info after OAuth2 auth (only for oauth2_connect action)",
|
|
157
|
-
},
|
|
158
126
|
client_secret: {
|
|
159
127
|
type: "string",
|
|
160
128
|
description:
|
|
161
129
|
"OAuth2 client secret for providers that require it (e.g. Google, Slack). If omitted, looked up from previously stored credentials; if still absent, PKCE-only is used (only for oauth2_connect action)",
|
|
162
130
|
},
|
|
163
|
-
token_endpoint_auth_method: {
|
|
164
|
-
type: "string",
|
|
165
|
-
enum: ["client_secret_basic", "client_secret_post"],
|
|
166
|
-
description:
|
|
167
|
-
'How to send client credentials at the token endpoint: "client_secret_post" (default, in POST body) or "client_secret_basic" (HTTP Basic Auth header). Only for oauth2_connect action.',
|
|
168
|
-
},
|
|
169
131
|
alias: {
|
|
170
132
|
type: "string",
|
|
171
133
|
description:
|
|
@@ -206,11 +168,6 @@ class CredentialStoreTool implements Tool {
|
|
|
206
168
|
description:
|
|
207
169
|
"Templates describing how to inject this credential into proxied requests (for store and prompt actions)",
|
|
208
170
|
},
|
|
209
|
-
reason: {
|
|
210
|
-
type: "string",
|
|
211
|
-
description:
|
|
212
|
-
"Brief non-technical explanation of what you are doing and why, shown to the user as a status update. Use simple language a non-technical person would understand.",
|
|
213
|
-
},
|
|
214
171
|
},
|
|
215
172
|
required: ["action"],
|
|
216
173
|
},
|
|
@@ -359,7 +316,7 @@ class CredentialStoreTool implements Tool {
|
|
|
359
316
|
};
|
|
360
317
|
}
|
|
361
318
|
|
|
362
|
-
const key =
|
|
319
|
+
const key = credentialKey(service, field);
|
|
363
320
|
const ok = await setSecureKeyAsync(key, value);
|
|
364
321
|
if (!ok) {
|
|
365
322
|
return {
|
|
@@ -422,7 +379,7 @@ class CredentialStoreTool implements Tool {
|
|
|
422
379
|
const entries = allMetadata
|
|
423
380
|
.filter((m) => {
|
|
424
381
|
if (secureKeySet)
|
|
425
|
-
return secureKeySet.has(
|
|
382
|
+
return secureKeySet.has(credentialKey(m.service, m.field));
|
|
426
383
|
return true;
|
|
427
384
|
})
|
|
428
385
|
.map((m) => {
|
|
@@ -472,7 +429,7 @@ class CredentialStoreTool implements Tool {
|
|
|
472
429
|
};
|
|
473
430
|
}
|
|
474
431
|
|
|
475
|
-
const key =
|
|
432
|
+
const key = credentialKey(service, field);
|
|
476
433
|
const result = await deleteSecureKeyAsync(key);
|
|
477
434
|
if (result === "error") {
|
|
478
435
|
return {
|
|
@@ -494,6 +451,21 @@ class CredentialStoreTool implements Tool {
|
|
|
494
451
|
"metadata delete failed after removing credential",
|
|
495
452
|
);
|
|
496
453
|
}
|
|
454
|
+
// Also clean up any OAuth connection for this service (best-effort)
|
|
455
|
+
try {
|
|
456
|
+
const oauthResult = await disconnectOAuthProvider(service);
|
|
457
|
+
if (oauthResult === "error") {
|
|
458
|
+
log.warn(
|
|
459
|
+
{ service },
|
|
460
|
+
"OAuth disconnect failed after removing credential — secure key deletion error",
|
|
461
|
+
);
|
|
462
|
+
}
|
|
463
|
+
} catch (err) {
|
|
464
|
+
log.warn(
|
|
465
|
+
{ service, err },
|
|
466
|
+
"OAuth disconnect failed after removing credential",
|
|
467
|
+
);
|
|
468
|
+
}
|
|
497
469
|
return {
|
|
498
470
|
content: `Deleted credential for ${service}/${field}.`,
|
|
499
471
|
isError: false,
|
|
@@ -712,7 +684,7 @@ class CredentialStoreTool implements Tool {
|
|
|
712
684
|
}
|
|
713
685
|
|
|
714
686
|
// Default: persist to keychain
|
|
715
|
-
const key =
|
|
687
|
+
const key = credentialKey(service, field);
|
|
716
688
|
const ok = await setSecureKeyAsync(key, result.value);
|
|
717
689
|
if (!ok) {
|
|
718
690
|
return {
|
|
@@ -754,51 +726,44 @@ class CredentialStoreTool implements Tool {
|
|
|
754
726
|
// Resolve aliases (e.g. "gmail" → "integration:gmail")
|
|
755
727
|
const service = resolveService(rawService);
|
|
756
728
|
|
|
757
|
-
//
|
|
758
|
-
const
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
729
|
+
// Code-side behavioral fields (identityVerifier, setup, etc.)
|
|
730
|
+
const behavior = getProviderBehavior(service);
|
|
731
|
+
// Protocol-level config from the DB (authUrl, tokenUrl, scopes, etc.)
|
|
732
|
+
const providerRow = getProvider(service);
|
|
733
|
+
|
|
734
|
+
// Resolve client_id and client_secret.
|
|
735
|
+
// Priority:
|
|
736
|
+
// 1. Explicit input from the caller
|
|
737
|
+
// 2. oauth-store DB — when clientId is already known, look up the
|
|
738
|
+
// matching app so the secret comes from the same app. Only fall
|
|
739
|
+
// back to the most-recent-app heuristic when clientId is unknown.
|
|
740
|
+
let clientId = input.client_id as string | undefined;
|
|
741
|
+
let clientSecret = input.client_secret as string | undefined;
|
|
742
|
+
|
|
743
|
+
if (!clientId || !clientSecret) {
|
|
744
|
+
const dbApp = clientId
|
|
745
|
+
? getAppByProviderAndClientId(service, clientId)
|
|
746
|
+
: getMostRecentAppByProvider(service);
|
|
747
|
+
if (dbApp) {
|
|
748
|
+
if (!clientId) clientId = dbApp.clientId;
|
|
749
|
+
if (!clientSecret) {
|
|
750
|
+
clientSecret = getSecureKey(
|
|
751
|
+
`oauth_app/${dbApp.id}/client_secret`,
|
|
752
|
+
);
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
}
|
|
767
756
|
|
|
768
757
|
// Early guardrails that stay in vault.ts (credential resolution is vault-specific)
|
|
769
758
|
const inputScopes = input.scopes as string[] | undefined;
|
|
770
759
|
|
|
771
|
-
if (
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
} else {
|
|
777
|
-
// Custom/unknown provider: require authUrl, tokenUrl, scopes from input
|
|
778
|
-
if (!input.auth_url)
|
|
779
|
-
return {
|
|
780
|
-
content:
|
|
781
|
-
"Error: auth_url is required for oauth2_connect action (no well-known config for this service)",
|
|
782
|
-
isError: true,
|
|
783
|
-
};
|
|
784
|
-
if (!input.token_url)
|
|
785
|
-
return {
|
|
786
|
-
content:
|
|
787
|
-
"Error: token_url is required for oauth2_connect action (no well-known config for this service)",
|
|
788
|
-
isError: true,
|
|
789
|
-
};
|
|
790
|
-
if (!inputScopes)
|
|
791
|
-
return {
|
|
792
|
-
content:
|
|
793
|
-
"Error: scopes is required for oauth2_connect action (no well-known config for this service)",
|
|
794
|
-
isError: true,
|
|
795
|
-
};
|
|
760
|
+
if (!providerRow) {
|
|
761
|
+
return {
|
|
762
|
+
content: `Error: no OAuth provider registered for "${service}". Ensure the provider is seeded in the database.`,
|
|
763
|
+
isError: true,
|
|
764
|
+
};
|
|
796
765
|
}
|
|
797
766
|
|
|
798
|
-
const authUrl =
|
|
799
|
-
(input.auth_url as string | undefined) ?? profile?.authUrl;
|
|
800
|
-
const tokenUrl =
|
|
801
|
-
(input.token_url as string | undefined) ?? profile?.tokenUrl;
|
|
802
767
|
if (!clientId)
|
|
803
768
|
return {
|
|
804
769
|
content:
|
|
@@ -810,10 +775,10 @@ class CredentialStoreTool implements Tool {
|
|
|
810
775
|
// agent to collect it from the user rather than letting it improvise
|
|
811
776
|
// browser-automation workarounds that inevitably fail.
|
|
812
777
|
const requiresSecret =
|
|
813
|
-
|
|
814
|
-
!!(
|
|
778
|
+
behavior?.setup?.requiresClientSecret ??
|
|
779
|
+
!!(providerRow.tokenEndpointAuthMethod || providerRow.extraParams);
|
|
815
780
|
if (requiresSecret && !clientSecret) {
|
|
816
|
-
const skillId =
|
|
781
|
+
const skillId = behavior?.setupSkillId;
|
|
817
782
|
const skillHint = skillId
|
|
818
783
|
? `\n\nLoad the "${skillId}" skill for provider-specific instructions on obtaining the client secret.`
|
|
819
784
|
: '\n\nUse credential_store with action "prompt" to securely collect the client_secret from the user before calling oauth2_connect again.';
|
|
@@ -823,25 +788,8 @@ class CredentialStoreTool implements Tool {
|
|
|
823
788
|
};
|
|
824
789
|
}
|
|
825
790
|
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
} catch {
|
|
829
|
-
return {
|
|
830
|
-
content:
|
|
831
|
-
"Error: credential metadata file has an unrecognized version; cannot store credentials",
|
|
832
|
-
isError: true,
|
|
833
|
-
};
|
|
834
|
-
}
|
|
835
|
-
|
|
836
|
-
const tokenEndpointAuthMethod =
|
|
837
|
-
(input.token_endpoint_auth_method as
|
|
838
|
-
| TokenEndpointAuthMethod
|
|
839
|
-
| undefined) ?? profile?.tokenEndpointAuthMethod;
|
|
840
|
-
|
|
841
|
-
// Delegate to the shared orchestrator.
|
|
842
|
-
// For profile-based providers, pass user scopes as requestedScopes so the
|
|
843
|
-
// scope policy engine (resolveScopes) is invoked. For custom providers,
|
|
844
|
-
// pass scopes directly as an explicit override.
|
|
791
|
+
// Delegate to the shared orchestrator — it resolves authUrl, tokenUrl,
|
|
792
|
+
// extraParams, userinfoUrl, and tokenEndpointAuthMethod from the DB.
|
|
845
793
|
const result = await orchestrateOAuthConnect({
|
|
846
794
|
service: rawService,
|
|
847
795
|
clientId,
|
|
@@ -849,24 +797,45 @@ class CredentialStoreTool implements Tool {
|
|
|
849
797
|
isInteractive: !!context.isInteractive,
|
|
850
798
|
sendToClient: context.sendToClient,
|
|
851
799
|
allowedTools: input.allowed_tools as string[] | undefined,
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
800
|
+
...(inputScopes ? { requestedScopes: inputScopes } : {}),
|
|
801
|
+
onDeferredComplete: (deferredResult) => {
|
|
802
|
+
// Emit oauth_connect_result to all connected SSE clients so the
|
|
803
|
+
// UI can update immediately when the deferred browser flow completes.
|
|
804
|
+
assistantEventHub
|
|
805
|
+
.publish(
|
|
806
|
+
buildAssistantEvent(DAEMON_INTERNAL_ASSISTANT_ID, {
|
|
807
|
+
type: "oauth_connect_result",
|
|
808
|
+
success: deferredResult.success,
|
|
809
|
+
service: deferredResult.service,
|
|
810
|
+
accountInfo: deferredResult.accountInfo,
|
|
811
|
+
error: deferredResult.error,
|
|
812
|
+
}),
|
|
813
|
+
)
|
|
814
|
+
.catch((err) => {
|
|
815
|
+
log.warn(
|
|
816
|
+
{ err, service: deferredResult.service },
|
|
817
|
+
"Failed to publish oauth_connect_result event",
|
|
818
|
+
);
|
|
819
|
+
});
|
|
820
|
+
|
|
821
|
+
if (deferredResult.success) {
|
|
822
|
+
log.info(
|
|
823
|
+
{
|
|
824
|
+
service: deferredResult.service,
|
|
825
|
+
accountInfo: deferredResult.accountInfo,
|
|
826
|
+
},
|
|
827
|
+
"Deferred OAuth connect completed successfully",
|
|
828
|
+
);
|
|
829
|
+
} else {
|
|
830
|
+
log.warn(
|
|
831
|
+
{
|
|
832
|
+
service: deferredResult.service,
|
|
833
|
+
err: deferredResult.error,
|
|
834
|
+
},
|
|
835
|
+
"Deferred OAuth connect failed",
|
|
836
|
+
);
|
|
837
|
+
}
|
|
838
|
+
},
|
|
870
839
|
});
|
|
871
840
|
|
|
872
841
|
if (!result.success) {
|
|
@@ -897,8 +866,8 @@ class CredentialStoreTool implements Tool {
|
|
|
897
866
|
};
|
|
898
867
|
}
|
|
899
868
|
const resolvedService = resolveService(rawService);
|
|
900
|
-
const
|
|
901
|
-
if (!
|
|
869
|
+
const descProviderRow = getProvider(resolvedService);
|
|
870
|
+
if (!descProviderRow) {
|
|
902
871
|
return {
|
|
903
872
|
content: `No well-known OAuth config found for "${rawService}". Available services: ${Object.keys(
|
|
904
873
|
SERVICE_ALIASES,
|
|
@@ -907,11 +876,17 @@ class CredentialStoreTool implements Tool {
|
|
|
907
876
|
};
|
|
908
877
|
}
|
|
909
878
|
|
|
879
|
+
const descBehavior = getProviderBehavior(resolvedService);
|
|
880
|
+
|
|
910
881
|
// Compute the redirect URI based on callback transport
|
|
911
882
|
let redirectUri: string;
|
|
912
|
-
const transport =
|
|
913
|
-
|
|
914
|
-
|
|
883
|
+
const transport =
|
|
884
|
+
(descProviderRow.callbackTransport as
|
|
885
|
+
| "loopback"
|
|
886
|
+
| "gateway"
|
|
887
|
+
| null) ?? "gateway";
|
|
888
|
+
if (transport === "loopback" && descProviderRow.loopbackPort) {
|
|
889
|
+
redirectUri = `http://127.0.0.1:${descProviderRow.loopbackPort}/oauth/callback`;
|
|
915
890
|
} else if (transport === "loopback") {
|
|
916
891
|
redirectUri =
|
|
917
892
|
"(automatic — no redirect URI needed, uses random localhost port)";
|
|
@@ -925,26 +900,39 @@ class CredentialStoreTool implements Tool {
|
|
|
925
900
|
redirectUri = `${baseUrl}/webhooks/oauth/callback`;
|
|
926
901
|
} catch {
|
|
927
902
|
redirectUri =
|
|
928
|
-
"(requires
|
|
903
|
+
"(requires ingress.publicBaseUrl — not currently configured)";
|
|
929
904
|
}
|
|
930
905
|
}
|
|
931
906
|
|
|
932
907
|
// Prefer explicit setup metadata, fall back to heuristic
|
|
933
908
|
const requiresClientSecret =
|
|
934
|
-
|
|
935
|
-
!!(
|
|
909
|
+
descBehavior?.setup?.requiresClientSecret ??
|
|
910
|
+
!!(
|
|
911
|
+
descProviderRow.tokenEndpointAuthMethod ||
|
|
912
|
+
descProviderRow.extraParams
|
|
913
|
+
);
|
|
914
|
+
|
|
915
|
+
const descDefaultScopes: string[] = descProviderRow.defaultScopes
|
|
916
|
+
? JSON.parse(descProviderRow.defaultScopes)
|
|
917
|
+
: [];
|
|
936
918
|
|
|
937
919
|
const info: Record<string, unknown> = {
|
|
938
920
|
service: resolvedService,
|
|
939
|
-
authUrl:
|
|
940
|
-
tokenUrl:
|
|
941
|
-
scopes:
|
|
921
|
+
authUrl: descProviderRow.authUrl,
|
|
922
|
+
tokenUrl: descProviderRow.tokenUrl,
|
|
923
|
+
scopes: descDefaultScopes,
|
|
942
924
|
callbackTransport: transport,
|
|
943
925
|
redirectUri,
|
|
944
926
|
requiresClientSecret,
|
|
945
927
|
};
|
|
946
|
-
if (
|
|
947
|
-
if (
|
|
928
|
+
if (descBehavior?.setup) info.setup = descBehavior.setup;
|
|
929
|
+
if (descProviderRow.extraParams) {
|
|
930
|
+
try {
|
|
931
|
+
info.extraParams = JSON.parse(descProviderRow.extraParams);
|
|
932
|
+
} catch {
|
|
933
|
+
// Non-fatal
|
|
934
|
+
}
|
|
935
|
+
}
|
|
948
936
|
|
|
949
937
|
return { content: JSON.stringify(info, null, 2), isError: false };
|
|
950
938
|
}
|
|
@@ -38,13 +38,8 @@ class FileEditTool implements Tool {
|
|
|
38
38
|
description:
|
|
39
39
|
"Replace all occurrences of old_string instead of requiring a unique match (default: false)",
|
|
40
40
|
},
|
|
41
|
-
reason: {
|
|
42
|
-
type: "string",
|
|
43
|
-
description:
|
|
44
|
-
"Brief non-technical explanation of why this file is being edited, shown to the user as a status update. Use simple language a non-technical person would understand.",
|
|
45
|
-
},
|
|
46
41
|
},
|
|
47
|
-
required: ["path", "old_string", "new_string"
|
|
42
|
+
required: ["path", "old_string", "new_string"],
|
|
48
43
|
},
|
|
49
44
|
};
|
|
50
45
|
}
|
|
@@ -38,11 +38,6 @@ class FileReadTool implements Tool {
|
|
|
38
38
|
type: "number",
|
|
39
39
|
description: "Maximum number of lines to read",
|
|
40
40
|
},
|
|
41
|
-
reason: {
|
|
42
|
-
type: "string",
|
|
43
|
-
description:
|
|
44
|
-
"Brief non-technical explanation of what you are reading and why, shown to the user as a status update. Use simple language a non-technical person would understand.",
|
|
45
|
-
},
|
|
46
41
|
},
|
|
47
42
|
required: ["path"],
|
|
48
43
|
},
|
|
@@ -28,13 +28,8 @@ class FileWriteTool implements Tool {
|
|
|
28
28
|
type: "string",
|
|
29
29
|
description: "The content to write to the file",
|
|
30
30
|
},
|
|
31
|
-
reason: {
|
|
32
|
-
type: "string",
|
|
33
|
-
description:
|
|
34
|
-
"Brief non-technical explanation of why this file is being written, shown to the user as a status update. Use simple language a non-technical person would understand.",
|
|
35
|
-
},
|
|
36
31
|
},
|
|
37
|
-
required: ["path", "content"
|
|
32
|
+
required: ["path", "content"],
|
|
38
33
|
},
|
|
39
34
|
};
|
|
40
35
|
}
|
|
@@ -35,13 +35,8 @@ class HostFileEditTool implements Tool {
|
|
|
35
35
|
description:
|
|
36
36
|
"Replace all occurrences instead of requiring a unique match (default: false)",
|
|
37
37
|
},
|
|
38
|
-
reason: {
|
|
39
|
-
type: "string",
|
|
40
|
-
description:
|
|
41
|
-
"Brief non-technical explanation of why this file is being edited, shown to the user as a status update. Use simple language a non-technical person would understand.",
|
|
42
|
-
},
|
|
43
38
|
},
|
|
44
|
-
required: ["path", "old_string", "new_string"
|
|
39
|
+
required: ["path", "old_string", "new_string"],
|
|
45
40
|
},
|
|
46
41
|
};
|
|
47
42
|
}
|
|
@@ -29,13 +29,8 @@ class HostFileReadTool implements Tool {
|
|
|
29
29
|
type: "number",
|
|
30
30
|
description: "Maximum number of lines to read",
|
|
31
31
|
},
|
|
32
|
-
reason: {
|
|
33
|
-
type: "string",
|
|
34
|
-
description:
|
|
35
|
-
"Brief non-technical explanation of why this file is being read, shown to the user as a status update. Use simple language a non-technical person would understand.",
|
|
36
|
-
},
|
|
37
32
|
},
|
|
38
|
-
required: ["path"
|
|
33
|
+
required: ["path"],
|
|
39
34
|
},
|
|
40
35
|
};
|
|
41
36
|
}
|
|
@@ -27,13 +27,8 @@ class HostFileWriteTool implements Tool {
|
|
|
27
27
|
type: "string",
|
|
28
28
|
description: "The content to write to the file",
|
|
29
29
|
},
|
|
30
|
-
reason: {
|
|
31
|
-
type: "string",
|
|
32
|
-
description:
|
|
33
|
-
"Brief non-technical explanation of why this file is being written, shown to the user as a status update. Use simple language a non-technical person would understand.",
|
|
34
|
-
},
|
|
35
30
|
},
|
|
36
|
-
required: ["path", "content"
|
|
31
|
+
required: ["path", "content"],
|
|
37
32
|
},
|
|
38
33
|
};
|
|
39
34
|
}
|
|
@@ -2,6 +2,7 @@ import type { McpServerConfig } from "../../config/schemas/mcp.js";
|
|
|
2
2
|
import type { McpServerManager } from "../../mcp/manager.js";
|
|
3
3
|
import { RiskLevel } from "../../permissions/types.js";
|
|
4
4
|
import type { ToolDefinition } from "../../providers/types.js";
|
|
5
|
+
import { schemaDefinesProperty } from "../schema-transforms.js";
|
|
5
6
|
import type { Tool, ToolContext, ToolExecutionResult } from "../types.js";
|
|
6
7
|
|
|
7
8
|
const riskMap: Record<string, RiskLevel> = {
|
|
@@ -36,6 +37,10 @@ export function createMcpTool(
|
|
|
36
37
|
): Tool {
|
|
37
38
|
const namespacedName = mcpToolName(serverId, metadata.name);
|
|
38
39
|
const riskLevel = riskMap[serverConfig.defaultRiskLevel] ?? RiskLevel.High;
|
|
40
|
+
const serverDefinesReason = schemaDefinesProperty(
|
|
41
|
+
metadata.inputSchema,
|
|
42
|
+
"reason",
|
|
43
|
+
);
|
|
39
44
|
|
|
40
45
|
return {
|
|
41
46
|
name: namespacedName,
|
|
@@ -59,7 +64,19 @@ export function createMcpTool(
|
|
|
59
64
|
_context: ToolContext,
|
|
60
65
|
): Promise<ToolExecutionResult> {
|
|
61
66
|
try {
|
|
62
|
-
|
|
67
|
+
// Strip injected reason before sending to MCP server
|
|
68
|
+
const { reason: _reason, ...mcpInput } = input as Record<
|
|
69
|
+
string,
|
|
70
|
+
unknown
|
|
71
|
+
> & {
|
|
72
|
+
reason?: unknown;
|
|
73
|
+
};
|
|
74
|
+
const forwardInput = serverDefinesReason ? input : mcpInput;
|
|
75
|
+
const result = await manager.callTool(
|
|
76
|
+
serverId,
|
|
77
|
+
metadata.name,
|
|
78
|
+
forwardInput,
|
|
79
|
+
);
|
|
63
80
|
return {
|
|
64
81
|
content: result.content,
|
|
65
82
|
isError: result.isError,
|
|
@@ -62,11 +62,6 @@ const memoryManageProperties = {
|
|
|
62
62
|
type: "string" as const,
|
|
63
63
|
description: "Short subject/topic label, 2-8 words (optional, save only)",
|
|
64
64
|
},
|
|
65
|
-
reason: {
|
|
66
|
-
type: "string" as const,
|
|
67
|
-
description:
|
|
68
|
-
"Brief non-technical explanation shown to the user as a status update",
|
|
69
|
-
},
|
|
70
65
|
};
|
|
71
66
|
|
|
72
67
|
export const memoryManageDefinition: ToolDefinition = {
|
|
@@ -863,11 +863,6 @@ class WebFetchTool implements Tool {
|
|
|
863
863
|
description:
|
|
864
864
|
"If true, allows requests to localhost/private-network hosts. Disabled by default for SSRF safety.",
|
|
865
865
|
},
|
|
866
|
-
reason: {
|
|
867
|
-
type: "string",
|
|
868
|
-
description:
|
|
869
|
-
"Brief non-technical explanation of what you are fetching and why, shown to the user as a status update. Use simple language a non-technical person would understand.",
|
|
870
|
-
},
|
|
871
866
|
},
|
|
872
867
|
required: ["url"],
|
|
873
868
|
},
|
|
@@ -302,11 +302,6 @@ class WebSearchTool implements Tool {
|
|
|
302
302
|
description:
|
|
303
303
|
'Filter by recency: "pd" (past day), "pw" (past week), "pm" (past month), "py" (past year). Only used with Brave provider.',
|
|
304
304
|
},
|
|
305
|
-
reason: {
|
|
306
|
-
type: "string",
|
|
307
|
-
description:
|
|
308
|
-
"Brief non-technical explanation of what you are searching for and why, shown to the user as a status update. Use simple language a non-technical person would understand.",
|
|
309
|
-
},
|
|
310
305
|
},
|
|
311
306
|
required: ["query"],
|
|
312
307
|
},
|
package/src/tools/registry.ts
CHANGED
|
@@ -4,7 +4,6 @@ import { getLogger } from "../util/logger.js";
|
|
|
4
4
|
import { coreAppProxyTools } from "./apps/definitions.js";
|
|
5
5
|
import { registerAppTools } from "./apps/registry.js";
|
|
6
6
|
import { allComputerUseTools } from "./computer-use/definitions.js";
|
|
7
|
-
import { requestComputerControlTool } from "./computer-use/request-computer-control.js";
|
|
8
7
|
import { hostFileEditTool } from "./host-filesystem/edit.js";
|
|
9
8
|
import { hostFileReadTool } from "./host-filesystem/read.js";
|
|
10
9
|
import { hostFileWriteTool } from "./host-filesystem/write.js";
|
|
@@ -300,8 +299,8 @@ export function getSkillRefCount(skillId: string): number {
|
|
|
300
299
|
}
|
|
301
300
|
|
|
302
301
|
export function getAllToolDefinitions(): ToolDefinition[] {
|
|
303
|
-
// Exclude proxy tools (e.g. computer_use_* tools) — they are
|
|
304
|
-
// by
|
|
302
|
+
// Exclude proxy tools (e.g. computer_use_* tools) — they are projected
|
|
303
|
+
// into sessions by the skill system, not via the global tool list.
|
|
305
304
|
// Exclude skill-origin tools — they are managed by the session-level
|
|
306
305
|
// skill projection system (projectSkillTools) and must not leak into
|
|
307
306
|
// the base tool list, which is shared across sessions via the global
|
|
@@ -341,9 +340,6 @@ export async function initializeTools(): Promise<void> {
|
|
|
341
340
|
registerTool(tool);
|
|
342
341
|
}
|
|
343
342
|
|
|
344
|
-
// The escalation tool is registered in core so text_qa sessions can execute it.
|
|
345
|
-
// The 12 action tools are provided by the bundled computer-use skill.
|
|
346
|
-
registerTool(requestComputerControlTool);
|
|
347
343
|
registerUiSurfaceTools();
|
|
348
344
|
registerAppTools();
|
|
349
345
|
|
|
@@ -367,7 +363,6 @@ export async function initializeTools(): Promise<void> {
|
|
|
367
363
|
...lazyTools.map((t: LazyToolDescriptor) => t.name),
|
|
368
364
|
...hostTools.map((t: Tool) => t.name),
|
|
369
365
|
...allComputerUseTools.map((t: Tool) => t.name),
|
|
370
|
-
requestComputerControlTool.name,
|
|
371
366
|
...allUiSurfaceTools.map((t: Tool) => t.name),
|
|
372
367
|
...coreAppProxyTools.map((t: Tool) => t.name),
|
|
373
368
|
]);
|