@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
|
@@ -37,10 +37,6 @@
|
|
|
37
37
|
"type": "string",
|
|
38
38
|
"enum": ["general", "researcher", "coder", "reviewer"],
|
|
39
39
|
"description": "Worker profile that scopes tool access. Defaults to general (backward compatible)."
|
|
40
|
-
},
|
|
41
|
-
"reason": {
|
|
42
|
-
"type": "string",
|
|
43
|
-
"description": "Brief non-technical explanation of what you are delegating and why, shown to the user as a status update. Use simple language a non-technical person would understand."
|
|
44
40
|
}
|
|
45
41
|
}
|
|
46
42
|
},
|
|
@@ -10,13 +10,10 @@ metadata:
|
|
|
10
10
|
disable-model-invocation: true
|
|
11
11
|
---
|
|
12
12
|
|
|
13
|
-
This skill provides the
|
|
14
|
-
the macOS desktop
|
|
13
|
+
This skill provides the computer_use_* action tools for controlling
|
|
14
|
+
the macOS desktop. CU tools run through the main agent loop via HostCuProxy.
|
|
15
15
|
|
|
16
|
-
The
|
|
17
|
-
registry (not this skill) so text_qa sessions can execute it directly.
|
|
18
|
-
|
|
19
|
-
The skill is internally preactivated for computer-use sessions.
|
|
16
|
+
The skill is internally preactivated for sessions with a connected desktop client.
|
|
20
17
|
|
|
21
18
|
Tools in this skill are proxy tools — execution is forwarded to the connected
|
|
22
19
|
macOS client, never handled locally by the assistant.
|
|
@@ -1,9 +1,27 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 1,
|
|
3
3
|
"tools": [
|
|
4
|
+
{
|
|
5
|
+
"name": "computer_use_observe",
|
|
6
|
+
"description": "Capture the current screen state. Returns the accessibility tree with [ID] element references and optionally a screenshot.\n\nThe accessibility tree shows interactive elements like [3] AXButton 'Save' or [17] AXTextField 'Search'. Use element_id to target these elements in subsequent actions — this is much more reliable than pixel coordinates.\n\nCall this before your first computer use action, or to check screen state without acting.",
|
|
7
|
+
"category": "computer-use",
|
|
8
|
+
"risk": "low",
|
|
9
|
+
"input_schema": {
|
|
10
|
+
"type": "object",
|
|
11
|
+
"properties": {
|
|
12
|
+
"reason": {
|
|
13
|
+
"type": "string",
|
|
14
|
+
"description": "Brief non-technical explanation of why this tool is being called"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"required": ["reason"]
|
|
18
|
+
},
|
|
19
|
+
"executor": "tools/computer-use-observe.ts",
|
|
20
|
+
"execution_target": "host"
|
|
21
|
+
},
|
|
4
22
|
{
|
|
5
23
|
"name": "computer_use_click",
|
|
6
|
-
"description": "Click
|
|
24
|
+
"description": "Click an element on screen. Prefer element_id (from the accessibility tree) over x/y coordinates.",
|
|
7
25
|
"category": "computer-use",
|
|
8
26
|
"risk": "low",
|
|
9
27
|
"input_schema": {
|
|
@@ -42,7 +60,7 @@
|
|
|
42
60
|
},
|
|
43
61
|
{
|
|
44
62
|
"name": "computer_use_type_text",
|
|
45
|
-
"description": "Type text at the current cursor position.
|
|
63
|
+
"description": "Type text at the current cursor position. First click a text field (by element_id) to focus it, then call this tool. If a field shows 'FOCUSED', skip the click.",
|
|
46
64
|
"category": "computer-use",
|
|
47
65
|
"risk": "low",
|
|
48
66
|
"input_schema": {
|
|
@@ -235,7 +253,7 @@
|
|
|
235
253
|
},
|
|
236
254
|
{
|
|
237
255
|
"name": "computer_use_run_applescript",
|
|
238
|
-
"description": "
|
|
256
|
+
"description": "Run an AppleScript command. Prefer this over click/type when possible \u2014 it doesn't move the cursor or interrupt the user. Never use 'do shell script' inside AppleScript (blocked for security).",
|
|
239
257
|
"category": "computer-use",
|
|
240
258
|
"risk": "low",
|
|
241
259
|
"input_schema": {
|
|
@@ -261,7 +279,7 @@
|
|
|
261
279
|
},
|
|
262
280
|
{
|
|
263
281
|
"name": "computer_use_done",
|
|
264
|
-
"description": "
|
|
282
|
+
"description": "Signal that the computer use task is complete. Provide a summary of what was accomplished. This ends the computer use session.",
|
|
265
283
|
"category": "computer-use",
|
|
266
284
|
"risk": "low",
|
|
267
285
|
"input_schema": {
|
|
@@ -3,8 +3,7 @@ import {
|
|
|
3
3
|
searchContacts,
|
|
4
4
|
} from "../../../../messaging/providers/gmail/people-client.js";
|
|
5
5
|
import type { Person } from "../../../../messaging/providers/gmail/people-types.js";
|
|
6
|
-
import {
|
|
7
|
-
import { withValidToken } from "../../../../security/token-manager.js";
|
|
6
|
+
import { resolveOAuthConnection } from "../../../../oauth/connection-resolver.js";
|
|
8
7
|
import type {
|
|
9
8
|
ToolContext,
|
|
10
9
|
ToolExecutionResult,
|
|
@@ -44,43 +43,41 @@ export async function run(
|
|
|
44
43
|
}
|
|
45
44
|
|
|
46
45
|
try {
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
const pageToken = input.page_token as string | undefined;
|
|
46
|
+
const connection = resolveOAuthConnection("integration:gmail");
|
|
47
|
+
switch (action) {
|
|
48
|
+
case "list": {
|
|
49
|
+
const pageSize = (input.page_size as number) ?? 50;
|
|
50
|
+
const pageToken = input.page_token as string | undefined;
|
|
53
51
|
|
|
54
|
-
|
|
55
|
-
|
|
52
|
+
const resp = await listContacts(connection, pageSize, pageToken);
|
|
53
|
+
const contacts = (resp.connections ?? []).map(formatContact);
|
|
56
54
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
55
|
+
const result: Record<string, unknown> = {
|
|
56
|
+
contacts,
|
|
57
|
+
total: resp.totalPeople ?? contacts.length,
|
|
58
|
+
};
|
|
59
|
+
if (resp.nextPageToken) result.nextPageToken = resp.nextPageToken;
|
|
62
60
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
case "search": {
|
|
67
|
-
const query = input.query as string;
|
|
68
|
-
if (!query) return err("query is required for search action.");
|
|
61
|
+
return ok(JSON.stringify(result, null, 2));
|
|
62
|
+
}
|
|
69
63
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
);
|
|
64
|
+
case "search": {
|
|
65
|
+
const query = input.query as string;
|
|
66
|
+
if (!query) return err("query is required for search action.");
|
|
74
67
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
)
|
|
78
|
-
|
|
68
|
+
const resp = await searchContacts(connection, query);
|
|
69
|
+
const contacts = (resp.results ?? []).map((r) =>
|
|
70
|
+
formatContact(r.person),
|
|
71
|
+
);
|
|
79
72
|
|
|
80
|
-
|
|
81
|
-
|
|
73
|
+
return ok(
|
|
74
|
+
JSON.stringify({ contacts, total: contacts.length }, null, 2),
|
|
75
|
+
);
|
|
82
76
|
}
|
|
83
|
-
|
|
77
|
+
|
|
78
|
+
default:
|
|
79
|
+
return err(`Unknown action "${action}". Use list or search.`);
|
|
80
|
+
}
|
|
84
81
|
} catch (e) {
|
|
85
82
|
return err(e instanceof Error ? e.message : String(e));
|
|
86
83
|
}
|
|
@@ -30,11 +30,11 @@ Do not offer AgentMail as an option or mention it unless the user specifically a
|
|
|
30
30
|
### Gmail
|
|
31
31
|
|
|
32
32
|
1. **Try connecting directly first.** Call `credential_store` with `action: "oauth2_connect"` and `service: "gmail"`. The tool auto-fills Google's OAuth endpoints and looks up any previously stored client credentials — so this single call may be all that's needed.
|
|
33
|
-
2. **If it fails because no client_id is found:** The user needs to create Google Cloud OAuth credentials first. Load the **google-oauth-
|
|
34
|
-
- Call `skill_load` with `skill: "google-oauth-
|
|
33
|
+
2. **If it fails because no client_id is found:** The user needs to create Google Cloud OAuth credentials first. Load the **google-oauth-applescript** skill:
|
|
34
|
+
- Call `skill_load` with `skill: "google-oauth-applescript"` to load the dependency skill.
|
|
35
35
|
- Tell the user Gmail isn't connected yet and briefly explain what the setup involves, then use `ui_show` with `surface_type: "confirmation"` to ask for permission to start:
|
|
36
36
|
- **message:** "Ready to set up Gmail?"
|
|
37
|
-
- **detail:** "I'll open a browser
|
|
37
|
+
- **detail:** "I'll open a few pages in your browser and walk you through setting up Google Cloud credentials — creating a project, enabling APIs, and connecting your account. Takes about 5 minutes."
|
|
38
38
|
- **confirmLabel:** "Get Started"
|
|
39
39
|
- **cancelLabel:** "Not Now"
|
|
40
40
|
- If the user confirms, briefly acknowledge (e.g., "Setting up Gmail now...") and proceed with the setup guide. If they decline, acknowledge and let them know they can set it up later.
|
|
@@ -45,7 +45,7 @@ Do not offer AgentMail as an option or mention it unless the user specifically a
|
|
|
45
45
|
When a Gmail tool fails with a token or authorization error:
|
|
46
46
|
|
|
47
47
|
1. **Try to reconnect silently.** Call `credential_store` with `action: "oauth2_connect"` and `service: "gmail"`. This often resolves expired tokens automatically.
|
|
48
|
-
2. **If reconnection fails, go straight to setup.** Don't present options, ask which route the user prefers, or explain what went wrong technically. Just tell the user briefly (e.g., "Gmail needs to be reconnected — let me set that up") and immediately follow the connection setup flow for Gmail (e.g., install and load **google-oauth-
|
|
48
|
+
2. **If reconnection fails, go straight to setup.** Don't present options, ask which route the user prefers, or explain what went wrong technically. Just tell the user briefly (e.g., "Gmail needs to be reconnected — let me set that up") and immediately follow the connection setup flow for Gmail (e.g., install and load **google-oauth-applescript**). The user came to you to get something done, not to troubleshoot OAuth — make it seamless.
|
|
49
49
|
3. **Never try alternative approaches.** Don't use bash, curl, browser automation, or any workaround. If the Gmail tools can't do it, the reconnection flow is the answer.
|
|
50
50
|
4. **Never expose error details.** The user doesn't need to see error messages about tokens, OAuth, or API failures. Translate errors into plain language.
|
|
51
51
|
|
|
@@ -3,8 +3,7 @@ import {
|
|
|
3
3
|
listMessages,
|
|
4
4
|
modifyMessage,
|
|
5
5
|
} from "../../../../messaging/providers/gmail/client.js";
|
|
6
|
-
import {
|
|
7
|
-
import { withValidToken } from "../../../../security/token-manager.js";
|
|
6
|
+
import { resolveOAuthConnection } from "../../../../oauth/connection-resolver.js";
|
|
8
7
|
import type {
|
|
9
8
|
ToolContext,
|
|
10
9
|
ToolExecutionResult,
|
|
@@ -35,49 +34,47 @@ export async function run(
|
|
|
35
34
|
}
|
|
36
35
|
|
|
37
36
|
try {
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
let truncated = false;
|
|
37
|
+
const connection = resolveOAuthConnection("integration:gmail");
|
|
38
|
+
const allMessageIds: string[] = [];
|
|
39
|
+
let pageToken: string | undefined;
|
|
40
|
+
let truncated = false;
|
|
43
41
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
42
|
+
while (allMessageIds.length < MAX_MESSAGES) {
|
|
43
|
+
const listResp = await listMessages(
|
|
44
|
+
connection,
|
|
45
|
+
query,
|
|
46
|
+
Math.min(500, MAX_MESSAGES - allMessageIds.length),
|
|
47
|
+
pageToken,
|
|
48
|
+
);
|
|
49
|
+
const ids = (listResp.messages ?? []).map((m) => m.id);
|
|
50
|
+
if (ids.length === 0) break;
|
|
51
|
+
allMessageIds.push(...ids);
|
|
52
|
+
pageToken = listResp.nextPageToken ?? undefined;
|
|
53
|
+
if (!pageToken) break;
|
|
54
|
+
}
|
|
57
55
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
56
|
+
if (allMessageIds.length >= MAX_MESSAGES && pageToken) {
|
|
57
|
+
truncated = true;
|
|
58
|
+
}
|
|
61
59
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
60
|
+
if (allMessageIds.length === 0) {
|
|
61
|
+
return ok("No messages matched the query. Nothing archived.");
|
|
62
|
+
}
|
|
65
63
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
64
|
+
for (let i = 0; i < allMessageIds.length; i += BATCH_MODIFY_LIMIT) {
|
|
65
|
+
const chunk = allMessageIds.slice(i, i + BATCH_MODIFY_LIMIT);
|
|
66
|
+
await batchModifyMessages(connection, chunk, {
|
|
67
|
+
removeLabelIds: ["INBOX"],
|
|
68
|
+
});
|
|
69
|
+
}
|
|
72
70
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
});
|
|
71
|
+
const summary = `Archived ${allMessageIds.length} message(s) matching query: ${query}`;
|
|
72
|
+
if (truncated) {
|
|
73
|
+
return ok(
|
|
74
|
+
`${summary}\n\nNote: this operation was capped at ${MAX_MESSAGES} messages. Additional messages matching the query may remain in the inbox. Run the command again to archive more.`,
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
return ok(summary);
|
|
81
78
|
} catch (e) {
|
|
82
79
|
return err(e instanceof Error ? e.message : String(e));
|
|
83
80
|
}
|
|
@@ -106,11 +103,9 @@ export async function run(
|
|
|
106
103
|
} else if (messageId) {
|
|
107
104
|
// Single message path
|
|
108
105
|
try {
|
|
109
|
-
const
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
return ok("Message archived.");
|
|
113
|
-
});
|
|
106
|
+
const connection = resolveOAuthConnection("integration:gmail");
|
|
107
|
+
await modifyMessage(connection, messageId, { removeLabelIds: ["INBOX"] });
|
|
108
|
+
return ok("Message archived.");
|
|
114
109
|
} catch (e) {
|
|
115
110
|
return err(e instanceof Error ? e.message : String(e));
|
|
116
111
|
}
|
|
@@ -126,23 +121,21 @@ export async function run(
|
|
|
126
121
|
}
|
|
127
122
|
|
|
128
123
|
try {
|
|
129
|
-
const
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
}
|
|
124
|
+
const connection = resolveOAuthConnection("integration:gmail");
|
|
125
|
+
if (messageIds.length === 1) {
|
|
126
|
+
await modifyMessage(connection, messageIds[0], {
|
|
127
|
+
removeLabelIds: ["INBOX"],
|
|
128
|
+
});
|
|
129
|
+
return ok("Message archived.");
|
|
130
|
+
}
|
|
137
131
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
});
|
|
132
|
+
for (let i = 0; i < messageIds.length; i += BATCH_MODIFY_LIMIT) {
|
|
133
|
+
const chunk = messageIds.slice(i, i + BATCH_MODIFY_LIMIT);
|
|
134
|
+
await batchModifyMessages(connection, chunk, {
|
|
135
|
+
removeLabelIds: ["INBOX"],
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
return ok(`Archived ${messageIds.length} message(s).`);
|
|
146
139
|
} catch (e) {
|
|
147
140
|
return err(e instanceof Error ? e.message : String(e));
|
|
148
141
|
}
|
|
@@ -6,8 +6,7 @@ import {
|
|
|
6
6
|
getMessage,
|
|
7
7
|
} from "../../../../messaging/providers/gmail/client.js";
|
|
8
8
|
import type { GmailMessagePart } from "../../../../messaging/providers/gmail/types.js";
|
|
9
|
-
import {
|
|
10
|
-
import { withValidToken } from "../../../../security/token-manager.js";
|
|
9
|
+
import { resolveOAuthConnection } from "../../../../oauth/connection-resolver.js";
|
|
11
10
|
import type {
|
|
12
11
|
ToolContext,
|
|
13
12
|
ToolExecutionResult,
|
|
@@ -57,17 +56,15 @@ export async function run(
|
|
|
57
56
|
|
|
58
57
|
if (action === "list") {
|
|
59
58
|
try {
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
const attachments = collectAttachments(message.payload?.parts);
|
|
59
|
+
const connection = resolveOAuthConnection("integration:gmail");
|
|
60
|
+
const message = await getMessage(connection, messageId, "full");
|
|
61
|
+
const attachments = collectAttachments(message.payload?.parts);
|
|
64
62
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
63
|
+
if (attachments.length === 0) {
|
|
64
|
+
return ok("No attachments found on this message.");
|
|
65
|
+
}
|
|
68
66
|
|
|
69
|
-
|
|
70
|
-
});
|
|
67
|
+
return ok(JSON.stringify(attachments, null, 2));
|
|
71
68
|
} catch (e) {
|
|
72
69
|
return err(e instanceof Error ? e.message : String(e));
|
|
73
70
|
}
|
|
@@ -81,26 +78,26 @@ export async function run(
|
|
|
81
78
|
if (!filename) return err("filename is required for download.");
|
|
82
79
|
|
|
83
80
|
try {
|
|
84
|
-
const
|
|
85
|
-
|
|
86
|
-
|
|
81
|
+
const connection = resolveOAuthConnection("integration:gmail");
|
|
82
|
+
const attachment = await getAttachment(
|
|
83
|
+
connection,
|
|
84
|
+
messageId,
|
|
85
|
+
attachmentId,
|
|
86
|
+
);
|
|
87
87
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
88
|
+
// Gmail returns base64url; convert to standard base64 then to Buffer
|
|
89
|
+
const base64 = attachment.data.replace(/-/g, "+").replace(/_/g, "/");
|
|
90
|
+
const buffer = Buffer.from(base64, "base64");
|
|
91
91
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
92
|
+
const outputDir = context.workingDir ?? process.cwd();
|
|
93
|
+
// Sanitize filename: strip path separators to prevent traversal attacks from crafted MIME filenames
|
|
94
|
+
const safeName = basename(filename).replace(/\.\./g, "_");
|
|
95
|
+
const outputPath = resolve(outputDir, safeName);
|
|
96
|
+
if (!outputPath.startsWith(outputDir))
|
|
97
|
+
return err("Invalid filename: path traversal detected.");
|
|
98
|
+
await writeFile(outputPath, buffer);
|
|
99
99
|
|
|
100
|
-
|
|
101
|
-
`Attachment saved to ${outputPath} (${buffer.length} bytes).`,
|
|
102
|
-
);
|
|
103
|
-
});
|
|
100
|
+
return ok(`Attachment saved to ${outputPath} (${buffer.length} bytes).`);
|
|
104
101
|
} catch (e) {
|
|
105
102
|
return err(e instanceof Error ? e.message : String(e));
|
|
106
103
|
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { createDraft } from "../../../../messaging/providers/gmail/client.js";
|
|
2
|
-
import {
|
|
3
|
-
import { withValidToken } from "../../../../security/token-manager.js";
|
|
2
|
+
import { resolveOAuthConnection } from "../../../../oauth/connection-resolver.js";
|
|
4
3
|
import type {
|
|
5
4
|
ToolContext,
|
|
6
5
|
ToolExecutionResult,
|
|
@@ -23,21 +22,19 @@ export async function run(
|
|
|
23
22
|
if (!body) return err("body is required.");
|
|
24
23
|
|
|
25
24
|
try {
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
);
|
|
40
|
-
});
|
|
25
|
+
const connection = resolveOAuthConnection("integration:gmail");
|
|
26
|
+
const draft = await createDraft(
|
|
27
|
+
connection,
|
|
28
|
+
to,
|
|
29
|
+
subject,
|
|
30
|
+
body,
|
|
31
|
+
inReplyTo,
|
|
32
|
+
cc,
|
|
33
|
+
bcc,
|
|
34
|
+
);
|
|
35
|
+
return ok(
|
|
36
|
+
`Draft created (ID: ${draft.id}). It will appear in your Gmail Drafts.`,
|
|
37
|
+
);
|
|
41
38
|
} catch (e) {
|
|
42
39
|
return err(e instanceof Error ? e.message : String(e));
|
|
43
40
|
}
|
|
@@ -7,8 +7,7 @@ import type {
|
|
|
7
7
|
GmailFilterAction,
|
|
8
8
|
GmailFilterCriteria,
|
|
9
9
|
} from "../../../../messaging/providers/gmail/types.js";
|
|
10
|
-
import {
|
|
11
|
-
import { withValidToken } from "../../../../security/token-manager.js";
|
|
10
|
+
import { resolveOAuthConnection } from "../../../../oauth/connection-resolver.js";
|
|
12
11
|
import type {
|
|
13
12
|
ToolContext,
|
|
14
13
|
ToolExecutionResult,
|
|
@@ -26,57 +25,53 @@ export async function run(
|
|
|
26
25
|
}
|
|
27
26
|
|
|
28
27
|
try {
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
return ok("No filters configured.");
|
|
36
|
-
}
|
|
37
|
-
return ok(JSON.stringify(filters, null, 2));
|
|
28
|
+
const connection = resolveOAuthConnection("integration:gmail");
|
|
29
|
+
switch (action) {
|
|
30
|
+
case "list": {
|
|
31
|
+
const filters = await listFilters(connection);
|
|
32
|
+
if (filters.length === 0) {
|
|
33
|
+
return ok("No filters configured.");
|
|
38
34
|
}
|
|
35
|
+
return ok(JSON.stringify(filters, null, 2));
|
|
36
|
+
}
|
|
39
37
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
const filterAction: GmailFilterAction = {};
|
|
50
|
-
if (input.add_label_ids)
|
|
51
|
-
filterAction.addLabelIds = input.add_label_ids as string[];
|
|
52
|
-
if (input.remove_label_ids)
|
|
53
|
-
filterAction.removeLabelIds = input.remove_label_ids as string[];
|
|
54
|
-
if (input.forward) filterAction.forward = input.forward as string;
|
|
38
|
+
case "create": {
|
|
39
|
+
const criteria: GmailFilterCriteria = {};
|
|
40
|
+
if (input.from) criteria.from = input.from as string;
|
|
41
|
+
if (input.to) criteria.to = input.to as string;
|
|
42
|
+
if (input.subject) criteria.subject = input.subject as string;
|
|
43
|
+
if (input.query) criteria.query = input.query as string;
|
|
44
|
+
if (input.has_attachment !== undefined)
|
|
45
|
+
criteria.hasAttachment = input.has_attachment as boolean;
|
|
55
46
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
47
|
+
const filterAction: GmailFilterAction = {};
|
|
48
|
+
if (input.add_label_ids)
|
|
49
|
+
filterAction.addLabelIds = input.add_label_ids as string[];
|
|
50
|
+
if (input.remove_label_ids)
|
|
51
|
+
filterAction.removeLabelIds = input.remove_label_ids as string[];
|
|
52
|
+
if (input.forward) filterAction.forward = input.forward as string;
|
|
61
53
|
|
|
62
|
-
|
|
63
|
-
return
|
|
54
|
+
if (Object.keys(criteria).length === 0) {
|
|
55
|
+
return err(
|
|
56
|
+
"At least one filter criteria is required (from, to, subject, query, or has_attachment).",
|
|
57
|
+
);
|
|
64
58
|
}
|
|
65
59
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
60
|
+
const filter = await createFilter(connection, criteria, filterAction);
|
|
61
|
+
return ok(`Filter created (ID: ${filter.id}).`);
|
|
62
|
+
}
|
|
69
63
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
64
|
+
case "delete": {
|
|
65
|
+
const filterId = input.filter_id as string;
|
|
66
|
+
if (!filterId) return err("filter_id is required for delete action.");
|
|
73
67
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
`Unknown action "${action}". Use list, create, or delete.`,
|
|
77
|
-
);
|
|
68
|
+
await deleteFilter(connection, filterId);
|
|
69
|
+
return ok("Filter deleted.");
|
|
78
70
|
}
|
|
79
|
-
|
|
71
|
+
|
|
72
|
+
default:
|
|
73
|
+
return err(`Unknown action "${action}". Use list, create, or delete.`);
|
|
74
|
+
}
|
|
80
75
|
} catch (e) {
|
|
81
76
|
return err(e instanceof Error ? e.message : String(e));
|
|
82
77
|
}
|