@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
package/ARCHITECTURE.md
CHANGED
|
@@ -347,8 +347,8 @@ Both tokens are stored in the secure key store (macOS Keychain with encrypted fi
|
|
|
347
347
|
|
|
348
348
|
| Secure key | Content |
|
|
349
349
|
| ------------------------------------ | -------------------------------------------------------------------------- |
|
|
350
|
-
| `credential
|
|
351
|
-
| `credential
|
|
350
|
+
| `credential/slack_channel/bot_token` | Slack bot token (used for `chat.postMessage` and `auth.test`) |
|
|
351
|
+
| `credential/slack_channel/app_token` | Slack app token (`xapp-...`, used for Socket Mode `apps.connections.open`) |
|
|
352
352
|
|
|
353
353
|
Workspace metadata (team ID, team name, bot user ID, bot username) is stored as JSON in the credential metadata store under `('slack_channel', 'bot_token')`.
|
|
354
354
|
|
|
@@ -468,7 +468,7 @@ A complementary access-granting flow where the guardian proactively creates a sh
|
|
|
468
468
|
|
|
469
469
|
| Channel | Status | Prerequisites |
|
|
470
470
|
| -------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
471
|
-
| Telegram | Shipped | Bot username resolved from credential metadata or
|
|
471
|
+
| Telegram | Shipped | Bot username resolved from credential metadata or config |
|
|
472
472
|
| Voice | Shipped | Identity-bound voice code redemption via DTMF/speech in the relay state machine. Always-on canonical behavior with personalized friend/guardian name prompts. |
|
|
473
473
|
| Slack | Deferred | Needs DM-safe ingress — Socket Mode handles channel messages but DM-initiated invite flows need routing |
|
|
474
474
|
|
|
@@ -641,7 +641,7 @@ The assistant feature-flag resolver (`src/config/assistant-feature-flags.ts`) is
|
|
|
641
641
|
| **3. `skill_load` tool** | `executeSkillLoad()` in `tools/skills/load.ts` | If the model attempts to load a flagged-off skill by name, the tool returns an error: `"skill is currently unavailable (disabled by feature flag)"`. |
|
|
642
642
|
| **4. Runtime tool projection** | `projectSkillTools()` in `daemon/session-skill-tools.ts` | Even if a skill was previously active in a session (has `<loaded_skill>` markers in history), the per-turn projection drops it when the flag is OFF. Already-registered tools are unregistered. |
|
|
643
643
|
| **5. Included child skills** | `executeSkillLoad()` in `tools/skills/load.ts` | When a parent skill includes children via the `includes` directive, each child is independently checked against its feature flag. Flagged-off children are silently excluded from the loaded skill content. |
|
|
644
|
-
| **6. Skill install gate** | `
|
|
644
|
+
| **6. Skill install gate** | `handleSkillsInstall()` in `daemon/handlers/skills.ts` | When a client requests skill installation, the handler checks the skill's feature flag before proceeding. If the flag is OFF, the install is rejected with an error. |
|
|
645
645
|
|
|
646
646
|
All six enforcement points derive the flag key via `skillFlagKey(skill)` — which returns `undefined` for ungated skills, short-circuiting the check — and then call `isAssistantFeatureFlagEnabled(flagKey, config)` for consistency.
|
|
647
647
|
|
|
@@ -657,7 +657,7 @@ All six enforcement points derive the flag key via `skillFlagKey(skill)` — whi
|
|
|
657
657
|
| `src/tools/skills/load.ts` | `executeSkillLoad()` — enforcement points 3 and 5 |
|
|
658
658
|
| `src/daemon/session-skill-tools.ts` | `projectSkillTools()` — enforcement point 4 |
|
|
659
659
|
| `src/config/schema.ts` | `assistantFeatureFlagValues` field definition in `AssistantConfig` (Zod schema) |
|
|
660
|
-
| `src/daemon/handlers/skills.ts` | `handleSkillsList()` — uses `resolveSkillStates()` for client responses; `
|
|
660
|
+
| `src/daemon/handlers/skills.ts` | `handleSkillsList()` — uses `resolveSkillStates()` for client responses; `handleSkillsInstall()` — enforcement point 6 |
|
|
661
661
|
| `meta/feature-flags/feature-flag-registry.json` | Unified feature flag registry (repo root) — all declared flags with scope, label, default values, and descriptions |
|
|
662
662
|
| `src/config/feature-flag-registry.json` | Bundled copy of the unified registry for compiled binary resolution |
|
|
663
663
|
|
|
@@ -669,7 +669,7 @@ All six enforcement points derive the flag key via `skillFlagKey(skill)` — whi
|
|
|
669
669
|
graph LR
|
|
670
670
|
subgraph "macOS Keychain"
|
|
671
671
|
K1["API Key<br/>service: vellum-assistant<br/>account: anthropic<br/>stored via /usr/bin/security CLI"]
|
|
672
|
-
K2["Credential Secrets<br/>key: credential
|
|
672
|
+
K2["Credential Secrets<br/>key: credential/{service}/{field}<br/>stored via secure-keys.ts<br/>(encrypted file fallback if Keychain unavailable)"]
|
|
673
673
|
end
|
|
674
674
|
|
|
675
675
|
subgraph "UserDefaults (plist)"
|
|
@@ -1709,7 +1709,7 @@ graph TB
|
|
|
1709
1709
|
end
|
|
1710
1710
|
|
|
1711
1711
|
subgraph "SSE Transport"
|
|
1712
|
-
SSE_ROUTE["SSE Route<br/>GET /v1/events?conversationKey
|
|
1712
|
+
SSE_ROUTE["SSE Route<br/>GET /v1/events[?conversationKey=...]<br/>(events-routes.ts)<br/>──────────────────────<br/>ReadableStream + CountQueuingStrategy(16)<br/>Heartbeat every 30 s<br/>Slow-consumer shed"]
|
|
1713
1713
|
end
|
|
1714
1714
|
|
|
1715
1715
|
subgraph "Clients"
|
package/README.md
CHANGED
|
@@ -73,7 +73,6 @@ For low-level development (e.g., working on the assistant runtime itself):
|
|
|
73
73
|
```bash
|
|
74
74
|
bun run src/index.ts daemon start # start daemon only
|
|
75
75
|
bun run src/index.ts # interactive CLI session
|
|
76
|
-
bun run src/index.ts dev # dev mode (auto-restart on file changes)
|
|
77
76
|
```
|
|
78
77
|
|
|
79
78
|
### CLI commands
|
|
@@ -84,7 +83,6 @@ bun run src/index.ts dev # dev mode (auto-restart on file changes)
|
|
|
84
83
|
| `vellum sleep` | Stop assistant + gateway processes |
|
|
85
84
|
| `vellum ps` | List assistants and per-assistant process status |
|
|
86
85
|
| `assistant` | Launch interactive CLI session |
|
|
87
|
-
| `assistant dev` | Run assistant with auto-restart on file changes |
|
|
88
86
|
| `assistant sessions list\|new\|export\|clear` | Manage conversation sessions |
|
|
89
87
|
| `assistant config set\|get\|list` | Manage configuration |
|
|
90
88
|
| `assistant keys set\|list\|delete` | Manage API keys in secure storage |
|
|
@@ -241,12 +239,9 @@ The per-assistant mapping is propagated to the gateway via the config file watch
|
|
|
241
239
|
|
|
242
240
|
### Phone Number Resolution Order
|
|
243
241
|
|
|
244
|
-
At runtime, `getTwilioConfig()` resolves the phone number
|
|
242
|
+
At runtime, `getTwilioConfig()` resolves the phone number from **`twilio.phoneNumber` in config** — the primary source of truth, written by `provision_number` and `assign_number`.
|
|
245
243
|
|
|
246
|
-
|
|
247
|
-
2. **`twilio.phoneNumber` in config** — the primary source of truth, written by `provision_number` and `assign_number`.
|
|
248
|
-
|
|
249
|
-
If no number is found after both sources, an error is thrown.
|
|
244
|
+
If no number is found, an error is thrown.
|
|
250
245
|
|
|
251
246
|
### Assistant-Scoped Guardian State
|
|
252
247
|
|
|
@@ -476,22 +471,6 @@ docker run --rm -p 3001:3001 \
|
|
|
476
471
|
|
|
477
472
|
The image exposes port `3001` and bundles the `assistant` CLI binary.
|
|
478
473
|
|
|
479
|
-
## Ride Shotgun
|
|
480
|
-
|
|
481
|
-
Ride Shotgun is a background screen-watching feature that observes user workflows. It has two modes:
|
|
482
|
-
|
|
483
|
-
- **Observe mode** — captures periodic screenshots and generates a workflow summary via the LLM.
|
|
484
|
-
- **Learn mode** — records browser network traffic alongside screenshots to capture API patterns. The assistant owns CDP browser lifecycle: `ride-shotgun-handler.ts` calls `ensureChromeWithCdp()` to launch or connect to Chrome with remote debugging, so clients do not need to pre-launch Chrome with `--remote-debugging-port`.
|
|
485
|
-
|
|
486
|
-
Key modules:
|
|
487
|
-
|
|
488
|
-
| File | Purpose |
|
|
489
|
-
| --------------------------------------- | ------------------------------------------------------- |
|
|
490
|
-
| `src/daemon/ride-shotgun-handler.ts` | Session orchestration, CDP bootstrap, network recording |
|
|
491
|
-
| `src/tools/browser/chrome-cdp.ts` | Reusable Chrome CDP launcher (`ensureChromeWithCdp`) |
|
|
492
|
-
| `src/tools/browser/network-recorder.ts` | CDP-based network traffic capture |
|
|
493
|
-
| `src/tools/browser/recording-store.ts` | Session recording persistence |
|
|
494
|
-
|
|
495
474
|
## Troubleshooting
|
|
496
475
|
|
|
497
476
|
### Guardian and gateway-origin issues
|
|
@@ -28,7 +28,7 @@ graph TB
|
|
|
28
28
|
DRAFT["messaging_draft"]
|
|
29
29
|
SENDER_DIGEST["messaging_sender_digest"]
|
|
30
30
|
ARCHIVE_BY_SENDER["messaging_archive_by_sender"]
|
|
31
|
-
SHARED["shared.ts<br/>resolveProvider +
|
|
31
|
+
SHARED["shared.ts<br/>resolveProvider + getProviderConnection"]
|
|
32
32
|
end
|
|
33
33
|
|
|
34
34
|
subgraph "Gmail Skill (bundled-skills/gmail/)"
|
|
@@ -121,7 +121,8 @@ sequenceDiagram
|
|
|
121
121
|
participant OAuth as OAuth2 PKCE Flow
|
|
122
122
|
participant Browser as System Browser
|
|
123
123
|
participant Google as Google OAuth Server
|
|
124
|
-
participant
|
|
124
|
+
participant Store as SQLite OAuth Store
|
|
125
|
+
participant Vault as Secure Keychain
|
|
125
126
|
participant TokenMgr as TokenManager
|
|
126
127
|
participant Tool as Gmail Tool Executor
|
|
127
128
|
participant API as Gmail REST API
|
|
@@ -140,20 +141,25 @@ sequenceDiagram
|
|
|
140
141
|
Google->>OAuth: callback with auth code
|
|
141
142
|
OAuth->>Google: exchange code + code_verifier for tokens
|
|
142
143
|
Google-->>OAuth: access + refresh tokens
|
|
143
|
-
OAuth->>
|
|
144
|
-
|
|
144
|
+
OAuth->>Store: storeOAuth2Tokens() → upsert oauth_app + oauth_connection rows
|
|
145
|
+
Store->>Vault: setSecureKeyAsync("oauth_connection/{id}/access_token")
|
|
146
|
+
Store->>Vault: setSecureKeyAsync("oauth_connection/{id}/refresh_token")
|
|
147
|
+
Store->>Store: write expiresAt, grantedScopes to oauth_connections
|
|
145
148
|
OAuth-->>Handler: success + account email
|
|
146
149
|
Handler->>HTTP: integration_connect_result {success, accountInfo}
|
|
147
150
|
HTTP->>UI: show connected state
|
|
148
151
|
|
|
149
152
|
Note over UI,API: Tool Execution Flow
|
|
150
153
|
Tool->>TokenMgr: withValidToken("gmail", callback)
|
|
151
|
-
TokenMgr->>
|
|
152
|
-
TokenMgr->>Vault:
|
|
154
|
+
TokenMgr->>Store: getConnectionByProvider("integration:gmail")
|
|
155
|
+
TokenMgr->>Vault: getSecureKey("oauth_connection/{conn.id}/access_token")
|
|
156
|
+
TokenMgr->>Store: check oauth_connections.expires_at
|
|
153
157
|
alt Token expired
|
|
158
|
+
TokenMgr->>Store: resolveRefreshConfig() → tokenUrl, clientId from provider/app rows
|
|
154
159
|
TokenMgr->>Google: refresh with refresh_token
|
|
155
160
|
Google-->>TokenMgr: new access token
|
|
156
|
-
TokenMgr->>Vault:
|
|
161
|
+
TokenMgr->>Vault: setSecureKeyAsync("oauth_connection/{id}/access_token")
|
|
162
|
+
TokenMgr->>Store: updateConnection(expiresAt)
|
|
157
163
|
end
|
|
158
164
|
TokenMgr->>Tool: callback(validToken)
|
|
159
165
|
Tool->>API: Gmail REST API call with Bearer token
|
|
@@ -167,13 +173,13 @@ sequenceDiagram
|
|
|
167
173
|
|
|
168
174
|
| Decision | Rationale |
|
|
169
175
|
| ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
170
|
-
| PKCE by default, optional client_secret | Desktop apps prefer PKCE; some providers (Slack) require a secret, which is stored in
|
|
176
|
+
| PKCE by default, optional client_secret | Desktop apps prefer PKCE; some providers (Slack) require a secret, which is stored in the secure keychain (`oauth_app/{id}/client_secret`) for autonomous refresh |
|
|
171
177
|
| Shared connect orchestrator | All OAuth providers route through `orchestrateOAuthConnect()`, which resolves profiles, enforces scope policy, runs the flow, stores tokens, and verifies identity. Adding a provider is a declarative profile entry, not new orchestration code |
|
|
172
178
|
| Canonical credential naming | All reads and writes use `client_id`/`client_secret` as canonical field names |
|
|
173
179
|
| Gateway callback transport | OAuth callbacks are now routed through the gateway at `${ingress.publicBaseUrl}/webhooks/oauth/callback` instead of a loopback redirect URI. This enables OAuth flows to work in remote and tunneled deployments. |
|
|
174
180
|
| Unified `MessagingProvider` interface | All platforms implement the same contract; generic tools work immediately for new providers |
|
|
175
181
|
| Provider auto-selection | If only one provider is connected, tools skip the `platform` parameter — seamless single-platform UX |
|
|
176
|
-
| Token expiry in
|
|
182
|
+
| Token expiry in SQLite oauth-store | `oauth_connections.expires_at` column tracks token expiry; `TokenManager` reads it for proactive refresh with 5min buffer. No separate metadata store needed |
|
|
177
183
|
| Confidence scores on medium-risk tools | LLM self-reports confidence (0-1); enables future trust calibration without blocking execution |
|
|
178
184
|
| Platform-specific extension tools | Operations unique to one platform (e.g. Gmail labels, Slack reactions) are separate tools, not forced into the generic interface |
|
|
179
185
|
| Identity verification before token storage | OAuth2 tokens are only persisted after a successful identity verification call, preventing storage of invalid or mismatched credentials |
|
|
@@ -197,34 +203,32 @@ sequenceDiagram
|
|
|
197
203
|
| `assistant/src/watcher/providers/gmail.ts` | Gmail watcher using History API |
|
|
198
204
|
| `assistant/src/watcher/providers/github.ts` | GitHub watcher for PRs, issues, review requests, and mentions |
|
|
199
205
|
| `assistant/src/watcher/providers/linear.ts` | Linear watcher for assigned issues, status changes, and @mentions |
|
|
200
|
-
| `assistant/src/oauth/provider-
|
|
206
|
+
| `assistant/src/oauth/provider-behaviors.ts` | Provider behavior registry: identity verifiers, setup metadata, injection templates |
|
|
201
207
|
| `assistant/src/oauth/connect-orchestrator.ts` | Shared OAuth connect orchestrator: profile resolution, scope policy, flow execution, token storage |
|
|
202
208
|
| `assistant/src/oauth/scope-policy.ts` | Deterministic scope resolution and policy enforcement |
|
|
203
|
-
| `assistant/src/oauth/connect-types.ts` | Shared types: `
|
|
209
|
+
| `assistant/src/oauth/connect-types.ts` | Shared types: `OAuthProviderBehavior`, `OAuthScopePolicy`, `OAuthConnectResult` |
|
|
204
210
|
| `assistant/src/oauth/token-persistence.ts` | Token storage helper: persists tokens, metadata, and runs post-connect hooks |
|
|
205
211
|
| `assistant/src/daemon/handlers/oauth-connect.ts` | Generic OAuth connect handler (`oauth_connect_start` / `oauth_connect_result`) |
|
|
206
212
|
|
|
207
213
|
---
|
|
208
214
|
|
|
209
|
-
## OAuth Extensibility — Provider
|
|
215
|
+
## OAuth Extensibility — Provider Behaviors, Scope Policy, and Connect Orchestrator
|
|
210
216
|
|
|
211
|
-
The OAuth extensibility layer makes adding a new OAuth provider a declarative operation.
|
|
217
|
+
The OAuth extensibility layer makes adding a new OAuth provider a declarative operation. Protocol fields (auth URLs, token URLs, scopes, scope policy) are stored in the `oauth_providers` database table, while behavioral fields (identity verifiers, setup metadata, injection templates) live in the **provider behavior registry**. The shared **connect orchestrator** handles the full flow from provider resolution through token storage.
|
|
212
218
|
|
|
213
|
-
### Provider
|
|
219
|
+
### Provider Behavior Registry
|
|
214
220
|
|
|
215
|
-
`assistant/src/oauth/provider-
|
|
221
|
+
`assistant/src/oauth/provider-behaviors.ts` contains the `PROVIDER_BEHAVIORS` map — a registry of behavioral aspects for well-known OAuth providers. Each behavior (`OAuthProviderBehavior`) declares:
|
|
216
222
|
|
|
217
|
-
| Field
|
|
218
|
-
|
|
|
219
|
-
| `
|
|
220
|
-
| `
|
|
221
|
-
| `
|
|
222
|
-
| `callbackTransport` | `'loopback'` (local redirect) or `'gateway'` (public ingress) |
|
|
223
|
-
| `identityVerifier` | Async function that fetches human-readable account info (e.g. `@username`, email) after token exchange |
|
|
224
|
-
| `setup` | Optional metadata for the generic OAuth setup skill (display name, dashboard URL, app type) |
|
|
225
|
-
| `injectionTemplates` | Auto-applied credential injection rules for the script proxy |
|
|
223
|
+
| Field | Purpose |
|
|
224
|
+
| -------------------- | ------------------------------------------------------------------------------------------------------ |
|
|
225
|
+
| `identityVerifier` | Async function that fetches human-readable account info (e.g. `@username`, email) after token exchange |
|
|
226
|
+
| `setup` | Optional metadata for the generic OAuth setup skill (display name, dashboard URL, app type) |
|
|
227
|
+
| `injectionTemplates` | Auto-applied credential injection rules for the script proxy |
|
|
226
228
|
|
|
227
|
-
|
|
229
|
+
Protocol fields (`authUrl`, `tokenUrl`, `defaultScopes`, `scopePolicy`, `callbackTransport`) are stored in the `oauth_providers` database table rather than in code.
|
|
230
|
+
|
|
231
|
+
Registered providers: `integration:gmail`, `integration:slack`, `integration:notion`. Short aliases (e.g. `gmail`, `slack`) are resolved via `resolveService()`.
|
|
228
232
|
|
|
229
233
|
### Scope Policy Engine
|
|
230
234
|
|
|
@@ -244,9 +248,9 @@ Returns `{ ok: true, scopes }` or `{ ok: false, error, allowedScopes }`.
|
|
|
244
248
|
`assistant/src/oauth/connect-orchestrator.ts` exports `orchestrateOAuthConnect(options)`, which runs the full OAuth2 flow:
|
|
245
249
|
|
|
246
250
|
1. **Resolve service** — alias expansion via `resolveService()`.
|
|
247
|
-
2. **Load
|
|
251
|
+
2. **Load behavior** — `getProviderBehavior()` from the registry; load protocol fields from the `oauth_providers` DB table.
|
|
248
252
|
3. **Compute scopes** — `resolveScopes()` with scope policy enforcement.
|
|
249
|
-
4. **Build OAuth config** —
|
|
253
|
+
4. **Build OAuth config** — assemble protocol-level config from the DB provider row.
|
|
250
254
|
5. **Run flow** — interactive (opens browser, blocks until completion) or deferred (returns auth URL for the caller to deliver).
|
|
251
255
|
6. **Verify identity** — runs the profile's `identityVerifier` if defined.
|
|
252
256
|
7. **Store tokens** — `storeOAuth2Tokens()` persists access/refresh tokens, client credentials, and metadata.
|
|
@@ -266,24 +270,24 @@ This replaces provider-specific handlers — any provider in the registry can be
|
|
|
266
270
|
|
|
267
271
|
### Adding a New OAuth Provider
|
|
268
272
|
|
|
269
|
-
1. **
|
|
273
|
+
1. **Register protocol fields** in the `oauth_providers` database table (via CLI or migration):
|
|
270
274
|
- Set `authUrl`, `tokenUrl`, `defaultScopes`, `scopePolicy`, and `callbackTransport`.
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
275
|
+
2. **Optional: declare behavioral fields** in `PROVIDER_BEHAVIORS` (`oauth/provider-behaviors.ts`):
|
|
276
|
+
- Add an `identityVerifier` — an async function that fetches the user's account info from the provider's API.
|
|
277
|
+
- Add `setup` metadata — `displayName`, `dashboardUrl`, `appType` enable the generic OAuth setup skill to guide users through app creation.
|
|
278
|
+
- Add `injectionTemplates` — for providers whose tokens should be auto-injected by the script proxy.
|
|
279
|
+
3. **No handler code needed** — the generic `oauth_connect_start` handler and the connect orchestrator handle the flow automatically.
|
|
276
280
|
|
|
277
281
|
### Key Source Files
|
|
278
282
|
|
|
279
|
-
| File | Role
|
|
280
|
-
| ------------------------------------------------ |
|
|
281
|
-
| `assistant/src/oauth/provider-
|
|
282
|
-
| `assistant/src/oauth/scope-policy.ts` | Scope resolution and policy enforcement (pure, no I/O)
|
|
283
|
-
| `assistant/src/oauth/connect-orchestrator.ts` | Shared connect orchestrator (profile → scopes → flow → tokens)
|
|
284
|
-
| `assistant/src/oauth/connect-types.ts` | Shared types (`
|
|
285
|
-
| `assistant/src/oauth/token-persistence.ts` | Token storage: keychain writes, metadata upsert, post-connect hooks
|
|
286
|
-
| `assistant/src/daemon/handlers/oauth-connect.ts` | Generic `oauth_connect_start` / `oauth_connect_result` handler
|
|
283
|
+
| File | Role |
|
|
284
|
+
| ------------------------------------------------ | -------------------------------------------------------------------------------- |
|
|
285
|
+
| `assistant/src/oauth/provider-behaviors.ts` | Provider behavior registry and alias resolution |
|
|
286
|
+
| `assistant/src/oauth/scope-policy.ts` | Scope resolution and policy enforcement (pure, no I/O) |
|
|
287
|
+
| `assistant/src/oauth/connect-orchestrator.ts` | Shared connect orchestrator (profile → scopes → flow → tokens) |
|
|
288
|
+
| `assistant/src/oauth/connect-types.ts` | Shared types (`OAuthProviderBehavior`, `OAuthScopePolicy`, `OAuthConnectResult`) |
|
|
289
|
+
| `assistant/src/oauth/token-persistence.ts` | Token storage: keychain writes, metadata upsert, post-connect hooks |
|
|
290
|
+
| `assistant/src/daemon/handlers/oauth-connect.ts` | Generic `oauth_connect_start` / `oauth_connect_result` handler |
|
|
287
291
|
|
|
288
292
|
---
|
|
289
293
|
|
|
@@ -66,7 +66,7 @@ graph LR
|
|
|
66
66
|
### Transport
|
|
67
67
|
|
|
68
68
|
- Unix domain socket: `~/.vellum/keychain-broker.sock`
|
|
69
|
-
- Socket path is
|
|
69
|
+
- Socket path is derived from the data directory (e.g., `join(getRootDir(), "keychain-broker.sock")`)
|
|
70
70
|
- Newline-delimited JSON (`\n` as message boundary)
|
|
71
71
|
|
|
72
72
|
### Request envelope
|
|
@@ -157,8 +157,8 @@ XPC provides stronger caller identity guarantees via audit tokens and code requi
|
|
|
157
157
|
|
|
158
158
|
## Developer Experience
|
|
159
159
|
|
|
160
|
-
- **Debug builds:** The `#if !DEBUG` guard compiles out the entire `KeychainBrokerServer`. The
|
|
161
|
-
- **Release builds:** The broker starts automatically with the app. The daemon discovers
|
|
160
|
+
- **Debug builds:** The `#if !DEBUG` guard compiles out the entire `KeychainBrokerServer`. The broker socket is not created, so clients see the broker as unavailable and use the encrypted store. Developers never encounter keychain prompts during the edit-build-run cycle.
|
|
161
|
+
- **Release builds:** The broker starts automatically with the app. The daemon discovers the broker via the derived socket path (`join(getRootDir(), "keychain-broker.sock")`) and token file. No configuration needed.
|
|
162
162
|
- **CLI-only / headless:** No macOS app means no broker socket. All storage uses the encrypted file store. This is the expected path for CI, servers, and non-macOS platforms.
|
|
163
163
|
|
|
164
164
|
## Callsite Policy
|
|
@@ -179,7 +179,7 @@ File tool candidates include canonical (symlink-resolved) absolute paths via `no
|
|
|
179
179
|
| `assistant/src/permissions/checker.ts` | `classifyRisk()`, `check()`, `buildCommandCandidates()`, allowlist/scope generation |
|
|
180
180
|
| `assistant/src/permissions/shell-identity.ts` | `analyzeShellCommand()`, `deriveShellActionKeys()`, `buildShellCommandCandidates()`, `buildShellAllowlistOptions()` — parser-based shell command identity and action key derivation |
|
|
181
181
|
| `assistant/src/permissions/trust-store.ts` | Rule persistence, `findHighestPriorityRule()`, execution-target matching, starter bundle |
|
|
182
|
-
| `assistant/src/permissions/prompter.ts` | HTTP prompt flow: `confirmation_request` → `confirmation_response`
|
|
182
|
+
| `assistant/src/permissions/prompter.ts` | HTTP prompt flow: `confirmation_request` → `confirmation_response` |
|
|
183
183
|
| `assistant/src/permissions/defaults.ts` | Default rule templates (system ask rules for host tools, CU, etc.) |
|
|
184
184
|
| `assistant/src/skills/version-hash.ts` | `computeSkillVersionHash()` — deterministic SHA-256 of skill source files |
|
|
185
185
|
| `assistant/src/skills/path-classifier.ts` | `isSkillSourcePath()`, `normalizeFilePath()`, skill root detection |
|
|
@@ -233,7 +233,7 @@ sequenceDiagram
|
|
|
233
233
|
UI->>HTTP: secret_response {requestId, value, delivery: "store"}
|
|
234
234
|
HTTP->>Prompter: resolve(value, "store")
|
|
235
235
|
Prompter->>Vault: {value, delivery: "store"}
|
|
236
|
-
Vault->>Keychain: setSecureKey("credential
|
|
236
|
+
Vault->>Keychain: setSecureKey("credential/svc/field", value)
|
|
237
237
|
Vault->>Model: "Credential stored securely" (no value in output)
|
|
238
238
|
else One-Time Send (if enabled)
|
|
239
239
|
UI->>HTTP: secret_response {requestId, value, delivery: "transient_send"}
|
|
@@ -272,7 +272,7 @@ graph TB
|
|
|
272
272
|
TOOL["Tool (e.g. browser_fill_credential)"] --> BROKER["CredentialBroker.use(service, field, tool, domain)"]
|
|
273
273
|
BROKER --> POLICY{"Check policy:<br/>allowedTools + allowedDomains"}
|
|
274
274
|
POLICY -->|denied| REJECT["PolicyDenied error"]
|
|
275
|
-
POLICY -->|allowed| FETCH["getSecureKey(credential
|
|
275
|
+
POLICY -->|allowed| FETCH["getSecureKey(credential/svc/field)"]
|
|
276
276
|
FETCH --> INJECT["Inject value into tool execution<br/>(never returned to model)"]
|
|
277
277
|
```
|
|
278
278
|
|
|
@@ -290,7 +290,7 @@ The `allowOneTimeSend` config gate (default: `false`) enables a secondary "Send
|
|
|
290
290
|
|
|
291
291
|
| Component | Location | What it stores |
|
|
292
292
|
| ------------------- | ---------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
293
|
-
| Secret values | macOS Keychain (primary) or encrypted file fallback | Encrypted credential values keyed as `credential
|
|
293
|
+
| Secret values | macOS Keychain (primary) or encrypted file fallback | Encrypted credential values keyed as `credential/{service}/{field}`. Falls back to encrypted file backend on Linux/headless or when Keychain is unavailable. |
|
|
294
294
|
| Credential metadata | `~/.vellum/workspace/data/credentials/metadata.json` | Service, field, label, policy (allowedTools, allowedDomains), timestamps |
|
|
295
295
|
| Config | `~/.vellum/workspace/config.*` | `secretDetection` settings: enabled, action, entropyThreshold, allowOneTimeSend |
|
|
296
296
|
|
|
@@ -303,7 +303,7 @@ The `allowOneTimeSend` config gate (default: `false`) enables a secondary "Send
|
|
|
303
303
|
| `assistant/src/tools/credentials/metadata-store.ts` | JSON file metadata CRUD for credential records |
|
|
304
304
|
| `assistant/src/tools/credentials/broker.ts` | Brokered credential access with policy enforcement and transient send |
|
|
305
305
|
| `assistant/src/tools/credentials/policy-validate.ts` | Policy input validation (allowedTools, allowedDomains) |
|
|
306
|
-
| `assistant/src/permissions/secret-prompter.ts` | HTTP secret_request/secret_response flow
|
|
306
|
+
| `assistant/src/permissions/secret-prompter.ts` | HTTP secret_request/secret_response flow |
|
|
307
307
|
| `assistant/src/security/secret-scanner.ts` | Regex + entropy-based secret detection |
|
|
308
308
|
| `assistant/src/security/secret-ingress.ts` | Inbound message secret blocking |
|
|
309
309
|
| `clients/macos/.../SecretPromptManager.swift` | Floating panel UI for secure credential entry |
|
|
@@ -1,17 +1,12 @@
|
|
|
1
1
|
# Trusted Contacts — Operator Runbook
|
|
2
2
|
|
|
3
|
-
Operational procedures for inspecting, managing, and debugging the trusted contact access flow. HTTP commands use the
|
|
4
|
-
|
|
5
|
-
> **Note:** The `/v1/contacts` endpoints are served by the assistant runtime, not
|
|
6
|
-
> the gateway. If you prefer to route through the gateway (`localhost:7830`), set
|
|
7
|
-
> `GATEWAY_RUNTIME_PROXY_ENABLED=true` in the gateway environment — the proxy is
|
|
8
|
-
> disabled by default and these routes will 404 without it.
|
|
3
|
+
Operational procedures for inspecting, managing, and debugging the trusted contact access flow. HTTP commands use the gateway API (default `http://localhost:7830`) with bearer authentication.
|
|
9
4
|
|
|
10
5
|
## Prerequisites
|
|
11
6
|
|
|
12
7
|
```bash
|
|
13
|
-
# Base URL —
|
|
14
|
-
BASE=http://localhost:
|
|
8
|
+
# Base URL — gateway (adjust if using a non-default port)
|
|
9
|
+
BASE=http://localhost:7830
|
|
15
10
|
|
|
16
11
|
# Bearer token: for operator use, retrieve from the daemon process environment
|
|
17
12
|
# or use `assistant` CLI commands which handle auth automatically.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "debug-prompt-logger",
|
|
3
|
-
"description": "Logs system prompt and conversation history to stderr
|
|
3
|
+
"description": "Logs system prompt and conversation history to stderr before each LLM call",
|
|
4
4
|
"version": "1.0.0",
|
|
5
5
|
"events": ["pre-llm-call"],
|
|
6
6
|
"script": "run.sh"
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
# Debug Prompt Logger — prints the system prompt and conversation
|
|
3
|
-
# history before each LLM call.
|
|
4
|
-
|
|
5
|
-
[ "$VELLUM_DEBUG" != "1" ] && exit 0
|
|
3
|
+
# history before each LLM call. Runs whenever the hook is installed.
|
|
6
4
|
|
|
7
5
|
data=$(cat)
|
|
8
6
|
|
package/package.json
CHANGED
|
@@ -41,7 +41,6 @@ mock.module("../config/env.js", () => ({
|
|
|
41
41
|
getGatewayBaseUrl: () => "http://localhost:7822",
|
|
42
42
|
getRuntimeGatewayOriginSecret: () => undefined,
|
|
43
43
|
isHttpAuthDisabledWithoutSafetyGate: () => false,
|
|
44
|
-
getEnableMonitoring: () => false,
|
|
45
44
|
checkUnrecognizedEnvVars: () => {},
|
|
46
45
|
getBaseDataDir: () => testDir,
|
|
47
46
|
}));
|
|
@@ -666,6 +666,162 @@ describe("AnthropicProvider — Cache-Control Characterization", () => {
|
|
|
666
666
|
).toBe(true);
|
|
667
667
|
});
|
|
668
668
|
|
|
669
|
+
// -----------------------------------------------------------------------
|
|
670
|
+
// ensureToolPairing — server_tool_use / web_search_tool_result pairing
|
|
671
|
+
// -----------------------------------------------------------------------
|
|
672
|
+
|
|
673
|
+
test("server_tool_use with missing web_search_tool_result gets synthetic result injected", async () => {
|
|
674
|
+
const messages: Message[] = [
|
|
675
|
+
userMsg("Search for something"),
|
|
676
|
+
{
|
|
677
|
+
role: "assistant",
|
|
678
|
+
content: [
|
|
679
|
+
{
|
|
680
|
+
type: "server_tool_use",
|
|
681
|
+
id: "srvtoolu_abc123",
|
|
682
|
+
name: "web_search",
|
|
683
|
+
input: { query: "test" },
|
|
684
|
+
},
|
|
685
|
+
],
|
|
686
|
+
},
|
|
687
|
+
userMsg("Thanks"), // user text but no web_search_tool_result
|
|
688
|
+
];
|
|
689
|
+
await provider.sendMessage(messages);
|
|
690
|
+
|
|
691
|
+
const sent = lastStreamParams!.messages as Array<{
|
|
692
|
+
role: string;
|
|
693
|
+
content: Array<{
|
|
694
|
+
type: string;
|
|
695
|
+
tool_use_id?: string;
|
|
696
|
+
content?: unknown;
|
|
697
|
+
}>;
|
|
698
|
+
}>;
|
|
699
|
+
|
|
700
|
+
// The user message after assistant should contain a synthetic web_search_tool_result
|
|
701
|
+
const userAfterAssistant = sent[2];
|
|
702
|
+
expect(userAfterAssistant.role).toBe("user");
|
|
703
|
+
expect(userAfterAssistant.content[0].type).toBe("web_search_tool_result");
|
|
704
|
+
expect(userAfterAssistant.content[0].tool_use_id).toBe("srvtoolu_abc123");
|
|
705
|
+
});
|
|
706
|
+
|
|
707
|
+
test("server_tool_use at end of messages gets synthetic web_search_tool_result appended", async () => {
|
|
708
|
+
const messages: Message[] = [
|
|
709
|
+
userMsg("Search something"),
|
|
710
|
+
{
|
|
711
|
+
role: "assistant",
|
|
712
|
+
content: [
|
|
713
|
+
{
|
|
714
|
+
type: "server_tool_use",
|
|
715
|
+
id: "srvtoolu_end",
|
|
716
|
+
name: "web_search",
|
|
717
|
+
input: { query: "test" },
|
|
718
|
+
},
|
|
719
|
+
],
|
|
720
|
+
},
|
|
721
|
+
];
|
|
722
|
+
await provider.sendMessage(messages);
|
|
723
|
+
|
|
724
|
+
const sent = lastStreamParams!.messages as Array<{
|
|
725
|
+
role: string;
|
|
726
|
+
content: Array<{ type: string; tool_use_id?: string }>;
|
|
727
|
+
}>;
|
|
728
|
+
|
|
729
|
+
// A synthetic user message should have been appended
|
|
730
|
+
expect(sent).toHaveLength(3);
|
|
731
|
+
expect(sent[2].role).toBe("user");
|
|
732
|
+
expect(sent[2].content[0].type).toBe("web_search_tool_result");
|
|
733
|
+
expect(sent[2].content[0].tool_use_id).toBe("srvtoolu_end");
|
|
734
|
+
});
|
|
735
|
+
|
|
736
|
+
test("server_tool_use with matching web_search_tool_result passes through unchanged", async () => {
|
|
737
|
+
const messages: Message[] = [
|
|
738
|
+
userMsg("Search something"),
|
|
739
|
+
{
|
|
740
|
+
role: "assistant",
|
|
741
|
+
content: [
|
|
742
|
+
{
|
|
743
|
+
type: "server_tool_use",
|
|
744
|
+
id: "srvtoolu_ok",
|
|
745
|
+
name: "web_search",
|
|
746
|
+
input: { query: "test" },
|
|
747
|
+
},
|
|
748
|
+
],
|
|
749
|
+
},
|
|
750
|
+
{
|
|
751
|
+
role: "user",
|
|
752
|
+
content: [
|
|
753
|
+
{
|
|
754
|
+
type: "web_search_tool_result",
|
|
755
|
+
tool_use_id: "srvtoolu_ok",
|
|
756
|
+
content: [
|
|
757
|
+
{
|
|
758
|
+
type: "web_search_result",
|
|
759
|
+
url: "https://example.com",
|
|
760
|
+
title: "Example",
|
|
761
|
+
encrypted_content: "enc_abc",
|
|
762
|
+
},
|
|
763
|
+
],
|
|
764
|
+
},
|
|
765
|
+
],
|
|
766
|
+
},
|
|
767
|
+
];
|
|
768
|
+
await provider.sendMessage(messages);
|
|
769
|
+
|
|
770
|
+
const sent = lastStreamParams!.messages as Array<{
|
|
771
|
+
role: string;
|
|
772
|
+
content: Array<{ type: string; tool_use_id?: string }>;
|
|
773
|
+
}>;
|
|
774
|
+
|
|
775
|
+
// No synthetic messages or blocks added
|
|
776
|
+
expect(sent).toHaveLength(3);
|
|
777
|
+
const resultBlocks = sent[2].content.filter(
|
|
778
|
+
(b) => b.type === "web_search_tool_result",
|
|
779
|
+
);
|
|
780
|
+
expect(resultBlocks).toHaveLength(1);
|
|
781
|
+
expect(resultBlocks[0].tool_use_id).toBe("srvtoolu_ok");
|
|
782
|
+
});
|
|
783
|
+
|
|
784
|
+
test("mixed tool_use and server_tool_use with partial results gets missing ones filled", async () => {
|
|
785
|
+
const messages: Message[] = [
|
|
786
|
+
userMsg("Do things"),
|
|
787
|
+
{
|
|
788
|
+
role: "assistant",
|
|
789
|
+
content: [
|
|
790
|
+
{ type: "tool_use", id: "tu_a", name: "file_read", input: {} },
|
|
791
|
+
{
|
|
792
|
+
type: "server_tool_use",
|
|
793
|
+
id: "srvtoolu_b",
|
|
794
|
+
name: "web_search",
|
|
795
|
+
input: { query: "test" },
|
|
796
|
+
},
|
|
797
|
+
],
|
|
798
|
+
},
|
|
799
|
+
// Only tu_a has a result
|
|
800
|
+
toolResultMsg("tu_a", "result A"),
|
|
801
|
+
];
|
|
802
|
+
await provider.sendMessage(messages);
|
|
803
|
+
|
|
804
|
+
const sent = lastStreamParams!.messages as Array<{
|
|
805
|
+
role: string;
|
|
806
|
+
content: Array<{
|
|
807
|
+
type: string;
|
|
808
|
+
tool_use_id?: string;
|
|
809
|
+
}>;
|
|
810
|
+
}>;
|
|
811
|
+
|
|
812
|
+
const userAfterAssistant = sent[2];
|
|
813
|
+
// Should have tool_result for tu_a and synthetic web_search_tool_result for srvtoolu_b
|
|
814
|
+
expect(userAfterAssistant.content).toHaveLength(2);
|
|
815
|
+
expect(userAfterAssistant.content[0]).toMatchObject({
|
|
816
|
+
type: "tool_result",
|
|
817
|
+
tool_use_id: "tu_a",
|
|
818
|
+
});
|
|
819
|
+
expect(userAfterAssistant.content[1]).toMatchObject({
|
|
820
|
+
type: "web_search_tool_result",
|
|
821
|
+
tool_use_id: "srvtoolu_b",
|
|
822
|
+
});
|
|
823
|
+
});
|
|
824
|
+
|
|
669
825
|
test("assistant message with only unknown blocks gets placeholder text", async () => {
|
|
670
826
|
const messages: Message[] = [
|
|
671
827
|
userMsg("Start"),
|