@vellumai/assistant 0.5.10 → 0.5.12
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/AGENTS.md +8 -0
- package/ARCHITECTURE.md +43 -43
- package/Dockerfile +3 -0
- package/docs/architecture/integrations.md +37 -42
- package/docs/architecture/memory.md +7 -12
- package/docs/credential-execution-service.md +9 -9
- package/docs/skills.md +1 -1
- package/node_modules/@vellumai/ces-contracts/src/__tests__/grants.test.ts +7 -7
- package/node_modules/@vellumai/ces-contracts/src/handles.ts +5 -4
- package/node_modules/@vellumai/credential-storage/src/index.ts +3 -3
- package/node_modules/@vellumai/credential-storage/src/static-credentials.ts +1 -1
- package/openapi.yaml +7208 -0
- package/package.json +2 -1
- package/scripts/generate-openapi.ts +562 -0
- package/src/__tests__/acp-session.test.ts +239 -44
- package/src/__tests__/assistant-feature-flag-guard.test.ts +8 -8
- package/src/__tests__/assistant-feature-flag-guardrails.test.ts +5 -86
- package/src/__tests__/assistant-feature-flags-integration.test.ts +7 -14
- package/src/__tests__/browser-skill-endstate.test.ts +1 -1
- package/src/__tests__/btw-routes.test.ts +8 -0
- package/src/__tests__/bundled-skill-retrieval-guard.test.ts +10 -10
- package/src/__tests__/catalog-cache.test.ts +164 -0
- package/src/__tests__/catalog-search.test.ts +61 -0
- package/src/__tests__/channel-approvals.test.ts +7 -7
- package/src/__tests__/channel-readiness-service.test.ts +41 -0
- package/src/__tests__/cli-command-risk-guard.test.ts +181 -6
- package/src/__tests__/config-schema.test.ts +10 -2
- package/src/__tests__/context-memory-e2e.test.ts +2 -6
- package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +396 -0
- package/src/__tests__/conversation-error.test.ts +3 -2
- package/src/__tests__/conversation-skill-tools.test.ts +1 -3
- package/src/__tests__/conversation-title-service.test.ts +2 -15
- package/src/__tests__/credential-execution-feature-gates.test.ts +4 -8
- package/src/__tests__/credential-execution-managed-contract.test.ts +8 -8
- package/src/__tests__/credential-security-e2e.test.ts +4 -4
- package/src/__tests__/credential-security-invariants.test.ts +12 -18
- package/src/__tests__/credential-vault-unit.test.ts +32 -34
- package/src/__tests__/credential-vault.test.ts +25 -33
- package/src/__tests__/credentials-cli.test.ts +3 -3
- package/src/__tests__/daemon-credential-client.test.ts +2 -2
- package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +1 -1
- package/src/__tests__/gateway-only-guard.test.ts +3 -0
- package/src/__tests__/heartbeat-service.test.ts +35 -0
- package/src/__tests__/host-bash-proxy.test.ts +79 -0
- package/src/__tests__/host-cu-proxy.test.ts +90 -0
- package/src/__tests__/host-file-proxy.test.ts +89 -0
- package/src/__tests__/host-shell-tool.test.ts +1 -1
- package/src/__tests__/inline-skill-load-permissions.test.ts +3 -3
- package/src/__tests__/integration-status.test.ts +5 -5
- package/src/__tests__/list-messages-attachments.test.ts +171 -0
- package/src/__tests__/llm-request-log-turn-query.test.ts +64 -0
- package/src/__tests__/log-export-workspace.test.ts +1 -1
- package/src/__tests__/mcp-abort-signal.test.ts +205 -0
- package/src/__tests__/mcp-client-auth.test.ts +1 -1
- package/src/__tests__/memory-lifecycle-e2e.test.ts +2 -2
- package/src/__tests__/memory-recall-log-store.test.ts +182 -0
- package/src/__tests__/memory-recall-quality.test.ts +6 -8
- package/src/__tests__/memory-regressions.test.ts +53 -42
- package/src/__tests__/memory-retrieval.benchmark.test.ts +5 -9
- package/src/__tests__/messaging-send-tool.test.ts +5 -5
- package/src/__tests__/messaging-skill-split.test.ts +2 -17
- package/src/__tests__/notification-telegram-adapter.test.ts +125 -0
- package/src/__tests__/oauth-cli.test.ts +203 -649
- package/src/__tests__/oauth-provider-profiles.test.ts +55 -20
- package/src/__tests__/oauth-scope-policy.test.ts +4 -6
- package/src/__tests__/onboarding-template-contract.test.ts +2 -2
- package/src/__tests__/platform-callback-registration.test.ts +119 -0
- package/src/__tests__/secret-ingress-channel.test.ts +261 -0
- package/src/__tests__/secret-ingress-cli.test.ts +201 -0
- package/src/__tests__/secret-ingress-http.test.ts +312 -0
- package/src/__tests__/secret-ingress.test.ts +283 -0
- package/src/__tests__/secret-onetime-send.test.ts +4 -4
- package/src/__tests__/secret-routes-managed-proxy.test.ts +78 -0
- package/src/__tests__/secure-keys-managed-failover.test.ts +73 -0
- package/src/__tests__/skill-feature-flags-integration.test.ts +4 -4
- package/src/__tests__/skill-feature-flags.test.ts +11 -19
- package/src/__tests__/skill-load-feature-flag.test.ts +1 -1
- package/src/__tests__/skill-load-inline-command.test.ts +3 -3
- package/src/__tests__/skill-load-inline-includes.test.ts +2 -2
- package/src/__tests__/skill-memory.test.ts +2 -4
- package/src/__tests__/skill-projection-feature-flag.test.ts +2 -4
- package/src/__tests__/skill-projection.benchmark.test.ts +1 -3
- package/src/__tests__/skills-uninstall.test.ts +2 -2
- package/src/__tests__/skills.test.ts +16 -2
- package/src/__tests__/slack-channel-config.test.ts +1 -1
- package/src/__tests__/slack-messaging-token-resolution.test.ts +22 -24
- package/src/__tests__/slack-share-routes.test.ts +5 -5
- package/src/__tests__/slack-skill.test.ts +5 -69
- package/src/__tests__/system-prompt.test.ts +39 -0
- package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +1 -1
- package/src/__tests__/workspace-migration-018-rekey-compound-credential-keys.test.ts +181 -0
- package/src/__tests__/workspace-migration-backfill-installation-id.test.ts +5 -4
- package/src/acp/client-handler.ts +113 -31
- package/src/acp/session-manager.ts +29 -27
- package/src/approvals/guardian-request-resolvers.ts +1 -1
- package/src/cli/AGENTS.md +113 -0
- package/src/cli/commands/autonomy.ts +3 -5
- package/src/cli/commands/browser-relay.ts +2 -17
- package/src/cli/commands/contacts.ts +6 -4
- package/src/cli/commands/conversations.ts +13 -1
- package/src/cli/commands/credential-execution.ts +17 -3
- package/src/cli/commands/credentials.ts +2 -8
- package/src/cli/commands/memory.ts +2 -3
- package/src/cli/commands/oauth/__tests__/connect.test.ts +706 -0
- package/src/cli/commands/oauth/__tests__/disconnect.test.ts +686 -0
- package/src/cli/commands/oauth/__tests__/mode.test.ts +625 -0
- package/src/cli/commands/oauth/__tests__/ping.test.ts +631 -0
- package/src/cli/commands/oauth/__tests__/providers-delete.test.ts +574 -0
- package/src/cli/commands/oauth/__tests__/providers-update.test.ts +416 -0
- package/src/cli/commands/oauth/__tests__/status.test.ts +551 -0
- package/src/cli/commands/oauth/__tests__/token.test.ts +420 -0
- package/src/cli/commands/oauth/apps.ts +87 -50
- package/src/cli/commands/oauth/connect.ts +405 -0
- package/src/cli/commands/oauth/disconnect.ts +285 -0
- package/src/cli/commands/oauth/index.ts +62 -20
- package/src/cli/commands/oauth/mode.ts +251 -0
- package/src/cli/commands/oauth/ping.ts +196 -0
- package/src/cli/commands/oauth/providers.ts +589 -55
- package/src/cli/commands/oauth/request.ts +564 -0
- package/src/cli/commands/oauth/shared.ts +114 -0
- package/src/cli/commands/oauth/status.ts +191 -0
- package/src/cli/commands/oauth/token.ts +150 -0
- package/src/cli/commands/platform/connect.ts +104 -0
- package/src/cli/commands/platform/disconnect.ts +118 -0
- package/src/cli/commands/platform/index.ts +252 -0
- package/src/cli/commands/sequence.ts +5 -4
- package/src/cli/commands/shotgun.ts +16 -0
- package/src/cli/commands/skills.ts +173 -41
- package/src/cli/commands/usage.ts +5 -11
- package/src/cli/lib/daemon-credential-client.ts +22 -38
- package/src/cli/program.ts +1 -1
- package/src/cli.ts +82 -17
- package/src/config/assistant-feature-flags.ts +77 -18
- package/src/config/bundled-skills/_shared/CLI_RETRIEVAL_PATTERN.md +1 -1
- package/src/config/bundled-skills/app-builder/tools/app-create.ts +1 -1
- package/src/config/bundled-skills/contacts/tools/google-contacts.ts +1 -1
- package/src/config/bundled-skills/conversations/SKILL.md +20 -0
- package/src/config/bundled-skills/conversations/TOOLS.json +23 -0
- package/src/config/bundled-skills/conversations/tools/rename-conversation.ts +66 -0
- package/src/config/bundled-skills/gmail/SKILL.md +13 -13
- package/src/config/bundled-skills/gmail/tools/gmail-archive.ts +3 -3
- package/src/config/bundled-skills/gmail/tools/gmail-attachments.ts +2 -2
- package/src/config/bundled-skills/gmail/tools/gmail-draft.ts +1 -1
- package/src/config/bundled-skills/gmail/tools/gmail-filters.ts +1 -1
- package/src/config/bundled-skills/gmail/tools/gmail-follow-up.ts +1 -1
- package/src/config/bundled-skills/gmail/tools/gmail-forward.ts +1 -1
- package/src/config/bundled-skills/gmail/tools/gmail-label.ts +2 -2
- package/src/config/bundled-skills/gmail/tools/gmail-outreach-scan.ts +1 -1
- package/src/config/bundled-skills/gmail/tools/gmail-send-draft.ts +1 -1
- package/src/config/bundled-skills/gmail/tools/gmail-sender-digest.ts +1 -1
- package/src/config/bundled-skills/gmail/tools/gmail-trash.ts +1 -1
- package/src/config/bundled-skills/gmail/tools/gmail-unsubscribe.ts +1 -1
- package/src/config/bundled-skills/gmail/tools/gmail-vacation.ts +1 -1
- package/src/config/bundled-skills/google-calendar/SKILL.md +10 -4
- package/src/config/bundled-skills/google-calendar/tools/shared.ts +1 -1
- package/src/config/bundled-skills/messaging/SKILL.md +19 -42
- package/src/config/bundled-skills/messaging/TOOLS.json +9 -9
- package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +1 -1
- package/src/config/bundled-skills/messaging/tools/messaging-send.ts +5 -2
- package/src/config/bundled-skills/messaging/tools/shared.ts +5 -6
- package/src/config/bundled-skills/notifications/SKILL.md +1 -1
- package/src/config/bundled-skills/schedule/SKILL.md +2 -2
- package/src/config/bundled-skills/settings/SKILL.md +5 -3
- package/src/config/bundled-skills/settings/TOOLS.json +17 -0
- package/src/config/bundled-skills/settings/tools/avatar-get.ts +50 -0
- package/src/config/bundled-skills/settings/tools/avatar-remove.ts +7 -0
- package/src/config/bundled-skills/settings/tools/avatar-update.ts +6 -1
- package/src/config/bundled-skills/settings/tools/identity-avatar.ts +55 -0
- package/src/config/bundled-skills/skills-catalog/SKILL.md +3 -3
- package/src/config/bundled-skills/slack/SKILL.md +58 -44
- package/src/config/bundled-tool-registry.ts +7 -19
- package/src/config/env.ts +5 -1
- package/src/config/feature-flag-registry.json +58 -42
- package/src/config/loader.ts +4 -0
- package/src/config/schemas/platform.ts +0 -8
- package/src/config/schemas/security.ts +9 -1
- package/src/config/schemas/services.ts +1 -1
- package/src/config/skill-state.ts +1 -3
- package/src/config/skills.ts +2 -4
- package/src/credential-execution/client.ts +1 -1
- package/src/credential-execution/feature-gates.ts +9 -16
- package/src/credential-execution/process-manager.ts +12 -0
- package/src/daemon/config-watcher.ts +4 -0
- package/src/daemon/conversation-agent-loop-handlers.ts +10 -0
- package/src/daemon/conversation-agent-loop.ts +51 -2
- package/src/daemon/conversation-error.ts +36 -6
- package/src/daemon/conversation-memory.ts +0 -1
- package/src/daemon/conversation-messaging.ts +9 -0
- package/src/daemon/conversation-runtime-assembly.ts +33 -0
- package/src/daemon/conversation-surfaces.ts +120 -14
- package/src/daemon/conversation.ts +5 -0
- package/src/daemon/handlers/config-slack-channel.ts +43 -1
- package/src/daemon/handlers/conversations.ts +41 -33
- package/src/daemon/handlers/skills.ts +148 -3
- package/src/daemon/host-bash-proxy.ts +16 -0
- package/src/daemon/host-cu-proxy.ts +16 -0
- package/src/daemon/host-file-proxy.ts +16 -0
- package/src/daemon/lifecycle.ts +73 -3
- package/src/daemon/message-types/acp.ts +0 -15
- package/src/daemon/message-types/conversations.ts +1 -0
- package/src/daemon/message-types/guardian-actions.ts +2 -0
- package/src/daemon/message-types/host-bash.ts +6 -1
- package/src/daemon/message-types/host-cu.ts +6 -1
- package/src/daemon/message-types/host-file.ts +6 -1
- package/src/daemon/message-types/integrations.ts +0 -1
- package/src/daemon/message-types/memory.ts +0 -1
- package/src/daemon/message-types/messages.ts +9 -1
- package/src/daemon/message-types/schedules.ts +9 -0
- package/src/daemon/server.ts +48 -9
- package/src/email/feature-gate.ts +3 -3
- package/src/heartbeat/heartbeat-service.ts +48 -0
- package/src/hooks/cli.ts +74 -0
- package/src/inbound/platform-callback-registration.ts +68 -19
- package/src/mcp/client.ts +6 -1
- package/src/mcp/manager.ts +2 -1
- package/src/mcp/mcp-oauth-provider.ts +3 -3
- package/src/memory/app-store.ts +3 -3
- package/src/memory/conversation-crud.ts +213 -0
- package/src/memory/conversation-key-store.ts +26 -0
- package/src/memory/conversation-title-service.ts +7 -17
- package/src/memory/db-init.ts +24 -0
- package/src/memory/embedding-local.ts +47 -2
- package/src/memory/indexer.ts +13 -10
- package/src/memory/items-extractor.ts +12 -4
- package/src/memory/job-utils.ts +5 -0
- package/src/memory/jobs-store.ts +10 -2
- package/src/memory/journal-memory.ts +6 -2
- package/src/memory/llm-request-log-store.ts +88 -21
- package/src/memory/memory-recall-log-store.ts +128 -0
- package/src/memory/migrations/194-memory-recall-logs.ts +50 -0
- package/src/memory/migrations/195-oauth-providers-ping-config.ts +23 -0
- package/src/memory/migrations/196-messages-conversation-created-at-index.ts +9 -0
- package/src/memory/migrations/196-strip-integration-prefix-from-provider-keys.ts +186 -0
- package/src/memory/migrations/197-oauth-providers-behavior-columns.ts +29 -0
- package/src/memory/migrations/198-drop-setup-skill-id-column.ts +11 -0
- package/src/memory/migrations/index.ts +6 -0
- package/src/memory/migrations/registry.ts +8 -0
- package/src/memory/retriever.test.ts +4 -5
- package/src/memory/schema/infrastructure.ts +31 -0
- package/src/memory/schema/oauth.ts +14 -0
- package/src/messaging/provider.ts +13 -12
- package/src/messaging/providers/gmail/adapter.ts +44 -35
- package/src/messaging/providers/slack/adapter.ts +63 -33
- package/src/messaging/providers/telegram-bot/adapter.ts +7 -9
- package/src/messaging/providers/whatsapp/adapter.ts +6 -8
- package/src/notifications/adapters/telegram.ts +78 -2
- package/src/oauth/__tests__/identity-verifier.test.ts +464 -0
- package/src/oauth/byo-connection.test.ts +22 -24
- package/src/oauth/connect-orchestrator.ts +79 -64
- package/src/oauth/connect-types.ts +7 -65
- package/src/oauth/connection-resolver.test.ts +13 -13
- package/src/oauth/connection-resolver.ts +3 -4
- package/src/oauth/identity-verifier.ts +177 -0
- package/src/oauth/manual-token-connection.ts +5 -5
- package/src/oauth/oauth-store.ts +251 -5
- package/src/oauth/platform-connection.test.ts +56 -6
- package/src/oauth/platform-connection.ts +8 -1
- package/src/oauth/seed-providers.ts +256 -34
- package/src/permissions/checker.ts +129 -3
- package/src/permissions/trust-client.ts +2 -2
- package/src/platform/client.ts +2 -2
- package/src/prompts/journal-context.ts +6 -1
- package/src/prompts/system-prompt.ts +43 -9
- package/src/prompts/templates/BOOTSTRAP.md +16 -5
- package/src/providers/anthropic/client.ts +139 -28
- package/src/runtime/auth/__tests__/middleware.test.ts +19 -0
- package/src/runtime/auth/route-policy.ts +0 -1
- package/src/runtime/btw-sidechain.ts +7 -1
- package/src/runtime/channel-approvals.ts +2 -2
- package/src/runtime/channel-readiness-service.ts +30 -7
- package/src/runtime/guardian-action-service.ts +7 -2
- package/src/runtime/http-router.ts +31 -0
- package/src/runtime/http-server.ts +26 -7
- package/src/runtime/http-types.ts +9 -0
- package/src/runtime/pending-interactions.ts +21 -3
- package/src/runtime/routes/acp-routes.ts +46 -28
- package/src/runtime/routes/app-management-routes.ts +123 -0
- package/src/runtime/routes/app-routes.ts +31 -0
- package/src/runtime/routes/approval-routes.ts +108 -3
- package/src/runtime/routes/attachment-routes.ts +45 -0
- package/src/runtime/routes/avatar-routes.ts +16 -0
- package/src/runtime/routes/brain-graph-routes.ts +18 -0
- package/src/runtime/routes/btw-routes.ts +20 -0
- package/src/runtime/routes/call-routes.ts +81 -0
- package/src/runtime/routes/channel-readiness-routes.ts +48 -7
- package/src/runtime/routes/channel-routes.ts +18 -0
- package/src/runtime/routes/channel-verification-routes.ts +49 -1
- package/src/runtime/routes/contact-routes.ts +77 -0
- package/src/runtime/routes/conversation-attention-routes.ts +37 -0
- package/src/runtime/routes/conversation-management-routes.ts +125 -0
- package/src/runtime/routes/conversation-query-routes.ts +78 -0
- package/src/runtime/routes/conversation-routes.ts +191 -39
- package/src/runtime/routes/conversation-starter-routes.ts +29 -0
- package/src/runtime/routes/debug-routes.ts +23 -0
- package/src/runtime/routes/diagnostics-routes.ts +30 -0
- package/src/runtime/routes/documents-routes.ts +42 -0
- package/src/runtime/routes/events-routes.ts +10 -0
- package/src/runtime/routes/global-search-routes.ts +35 -0
- package/src/runtime/routes/guardian-action-routes.ts +61 -3
- package/src/runtime/routes/guardian-approval-prompt.ts +77 -2
- package/src/runtime/routes/heartbeat-routes.ts +278 -0
- package/src/runtime/routes/host-bash-routes.ts +16 -1
- package/src/runtime/routes/host-cu-routes.ts +23 -1
- package/src/runtime/routes/host-file-routes.ts +18 -1
- package/src/runtime/routes/identity-routes.ts +35 -0
- package/src/runtime/routes/inbound-message-handler.ts +46 -25
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +21 -8
- package/src/runtime/routes/inbound-stages/secret-ingress-check.ts +30 -2
- package/src/runtime/routes/inbound-stages/transcribe-audio.ts +1 -2
- package/src/runtime/routes/integrations/slack/share.ts +1 -1
- package/src/runtime/routes/integrations/twilio.ts +32 -22
- package/src/runtime/routes/invite-routes.ts +83 -0
- package/src/runtime/routes/log-export-routes.ts +14 -0
- package/src/runtime/routes/memory-item-routes.ts +99 -1
- package/src/runtime/routes/migration-rollback-routes.ts +25 -0
- package/src/runtime/routes/migration-routes.ts +40 -0
- package/src/runtime/routes/notification-routes.ts +20 -0
- package/src/runtime/routes/oauth-apps.ts +13 -4
- package/src/runtime/routes/pairing-routes.ts +15 -0
- package/src/runtime/routes/recording-routes.ts +72 -0
- package/src/runtime/routes/schedule-routes.ts +77 -5
- package/src/runtime/routes/secret-routes.ts +99 -14
- package/src/runtime/routes/settings-routes.ts +102 -19
- package/src/runtime/routes/skills-routes.ts +141 -18
- package/src/runtime/routes/subagents-routes.ts +38 -3
- package/src/runtime/routes/surface-action-routes.ts +66 -24
- package/src/runtime/routes/surface-content-routes.ts +20 -0
- package/src/runtime/routes/telemetry-routes.ts +12 -0
- package/src/runtime/routes/trace-event-routes.ts +25 -0
- package/src/runtime/routes/trust-rules-routes.ts +46 -0
- package/src/runtime/routes/tts-routes.ts +15 -4
- package/src/runtime/routes/upgrade-broadcast-routes.ts +38 -0
- package/src/runtime/routes/usage-routes.ts +59 -0
- package/src/runtime/routes/watch-routes.ts +28 -0
- package/src/runtime/routes/work-items-routes.ts +59 -0
- package/src/runtime/routes/workspace-commit-routes.ts +12 -0
- package/src/runtime/routes/workspace-routes.ts +102 -0
- package/src/schedule/integration-status.ts +2 -2
- package/src/schedule/scheduler.ts +7 -1
- package/src/security/AGENTS.md +7 -0
- package/src/security/ces-rpc-credential-backend.ts +19 -16
- package/src/security/credential-backend.ts +1 -1
- package/src/security/encrypted-store.ts +3 -3
- package/src/security/oauth-completion-page.ts +153 -0
- package/src/security/oauth2.ts +58 -17
- package/src/security/secret-ingress.ts +174 -0
- package/src/security/secret-patterns.ts +133 -0
- package/src/security/secret-scanner.ts +28 -117
- package/src/security/secure-keys.ts +207 -7
- package/src/security/token-manager.ts +3 -6
- package/src/signals/bash.ts +6 -1
- package/src/signals/confirm.ts +12 -8
- package/src/signals/user-message.ts +18 -3
- package/src/skills/catalog-cache.ts +44 -0
- package/src/skills/catalog-search.ts +18 -0
- package/src/skills/skill-memory.ts +1 -2
- package/src/tasks/task-runner.ts +7 -1
- package/src/tools/credentials/broker.ts +1 -1
- package/src/tools/credentials/metadata-store.ts +1 -1
- package/src/tools/credentials/post-connect-hooks.ts +1 -1
- package/src/tools/credentials/vault.ts +36 -48
- package/src/tools/host-terminal/host-shell.ts +16 -3
- package/src/tools/mcp/mcp-tool-factory.ts +2 -1
- package/src/tools/memory/definitions.ts +1 -1
- package/src/tools/memory/handlers.test.ts +2 -4
- package/src/tools/skills/load.ts +1 -1
- package/src/tools/skills/sandbox-runner.ts +16 -3
- package/src/tools/terminal/safe-env.ts +7 -0
- package/src/tools/terminal/shell.ts +16 -3
- package/src/tools/tool-manifest.ts +1 -1
- package/src/util/log-redact.ts +9 -34
- package/src/util/logger.ts +11 -1
- package/src/util/sentry-log-stream.ts +51 -0
- package/src/watcher/providers/github.ts +2 -2
- package/src/watcher/providers/gmail.ts +1 -1
- package/src/watcher/providers/google-calendar.ts +1 -1
- package/src/watcher/providers/linear.ts +2 -2
- package/src/workspace/migrations/011-backfill-installation-id.ts +5 -3
- package/src/workspace/migrations/020-rename-oauth-skill-dirs.ts +119 -0
- package/src/workspace/migrations/registry.ts +2 -0
- package/docs/architecture/keychain-broker.md +0 -68
- package/src/cli/commands/oauth/connections.ts +0 -734
- package/src/cli/commands/oauth/platform.ts +0 -525
- package/src/cli/commands/platform.ts +0 -176
- package/src/config/bundled-skills/slack/TOOLS.json +0 -272
- package/src/config/bundled-skills/slack/tools/shared.ts +0 -34
- package/src/config/bundled-skills/slack/tools/slack-add-reaction.ts +0 -27
- package/src/config/bundled-skills/slack/tools/slack-channel-details.ts +0 -38
- package/src/config/bundled-skills/slack/tools/slack-channel-permissions.ts +0 -146
- package/src/config/bundled-skills/slack/tools/slack-configure-channels.ts +0 -105
- package/src/config/bundled-skills/slack/tools/slack-delete-message.ts +0 -26
- package/src/config/bundled-skills/slack/tools/slack-edit-message.ts +0 -27
- package/src/config/bundled-skills/slack/tools/slack-leave-channel.ts +0 -25
- package/src/config/bundled-skills/slack/tools/slack-scan-digest.ts +0 -372
- package/src/oauth/provider-behaviors.ts +0 -634
|
@@ -76,7 +76,7 @@ export async function run(
|
|
|
76
76
|
if (!forwardTo) return err("to is required.");
|
|
77
77
|
|
|
78
78
|
try {
|
|
79
|
-
const connection = await resolveOAuthConnection("
|
|
79
|
+
const connection = await resolveOAuthConnection("google", {
|
|
80
80
|
account,
|
|
81
81
|
});
|
|
82
82
|
const message = await getMessage(connection, messageId, "full");
|
|
@@ -21,7 +21,7 @@ export async function run(
|
|
|
21
21
|
|
|
22
22
|
if (messageIds && messageIds.length > 0) {
|
|
23
23
|
try {
|
|
24
|
-
const connection = await resolveOAuthConnection("
|
|
24
|
+
const connection = await resolveOAuthConnection("google", {
|
|
25
25
|
account,
|
|
26
26
|
});
|
|
27
27
|
await batchModifyMessages(connection, messageIds, {
|
|
@@ -36,7 +36,7 @@ export async function run(
|
|
|
36
36
|
|
|
37
37
|
if (messageId) {
|
|
38
38
|
try {
|
|
39
|
-
const connection = await resolveOAuthConnection("
|
|
39
|
+
const connection = await resolveOAuthConnection("google", {
|
|
40
40
|
account,
|
|
41
41
|
});
|
|
42
42
|
await modifyMessage(connection, messageId, {
|
|
@@ -56,7 +56,7 @@ export async function run(
|
|
|
56
56
|
const query = `in:inbox -has:unsubscribe newer_than:${timeRange}`;
|
|
57
57
|
|
|
58
58
|
try {
|
|
59
|
-
const connection = await resolveOAuthConnection("
|
|
59
|
+
const connection = await resolveOAuthConnection("google", {
|
|
60
60
|
account,
|
|
61
61
|
});
|
|
62
62
|
// Pipeline: fire metadata fetches for each page of IDs as they arrive
|
|
@@ -15,7 +15,7 @@ export async function run(
|
|
|
15
15
|
if (!draftId) return err("draft_id is required.");
|
|
16
16
|
|
|
17
17
|
try {
|
|
18
|
-
const connection = await resolveOAuthConnection("
|
|
18
|
+
const connection = await resolveOAuthConnection("google", {
|
|
19
19
|
account,
|
|
20
20
|
});
|
|
21
21
|
const msg = await sendDraft(connection, draftId);
|
|
@@ -58,7 +58,7 @@ export async function run(
|
|
|
58
58
|
const inputPageToken = input.page_token as string | undefined;
|
|
59
59
|
|
|
60
60
|
try {
|
|
61
|
-
const connection = await resolveOAuthConnection("
|
|
61
|
+
const connection = await resolveOAuthConnection("google", {
|
|
62
62
|
account,
|
|
63
63
|
});
|
|
64
64
|
// Pipeline: fire metadata fetches for each page of IDs as they arrive,
|
|
@@ -32,7 +32,7 @@ export async function run(
|
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
try {
|
|
35
|
-
const connection = await resolveOAuthConnection("
|
|
35
|
+
const connection = await resolveOAuthConnection("google", {
|
|
36
36
|
account,
|
|
37
37
|
});
|
|
38
38
|
const message = await getMessage(connection, messageId, "metadata", [
|
|
@@ -14,10 +14,16 @@ You are a Google Calendar assistant with full access to the user's calendar. Use
|
|
|
14
14
|
|
|
15
15
|
Before using any Calendar tool, verify that Google Calendar is connected by attempting a lightweight call (e.g., `calendar_list_events` with a narrow date range). If the call fails with a token/authorization error:
|
|
16
16
|
|
|
17
|
-
1. **
|
|
18
|
-
2.
|
|
19
|
-
- Call `skill_load` with `skill: "
|
|
20
|
-
|
|
17
|
+
1. **Try connecting directly first.** Run `assistant oauth status google`. This will show whether or not the user had previously connected their google account. If so, they are ready to go.
|
|
18
|
+
2. **If no connections are found:** The user needs to either use Vellum's managed google integration or set up their own google oauth app.
|
|
19
|
+
- Call `skill_load` with `skill: "vellum-oauth-integrations"` with `provider-key: google` throughout.
|
|
20
|
+
- To use `your-own` mode, you will need to call `skill_load` with `skill: google-oauth-app-setup`. In this case:
|
|
21
|
+
- Tell the user Google account 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:
|
|
22
|
+
- **message:** "Ready to set up Google Calendar?"
|
|
23
|
+
- **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.\n\n**Your emails stay under your control** — I only ever create drafts. Nothing gets sent without your explicit say-so."
|
|
24
|
+
- **confirmLabel:** "Get Started"
|
|
25
|
+
- **cancelLabel:** "Not Now"
|
|
26
|
+
- If the user confirms, briefly acknowledge (e.g., "Setting up Google Calendar now...") and proceed with the setup guide. If they decline, acknowledge and let them know they can set it up later.
|
|
21
27
|
|
|
22
28
|
## Capabilities
|
|
23
29
|
|
|
@@ -13,5 +13,5 @@ export function ok(content: string): ToolExecutionResult {
|
|
|
13
13
|
export async function getCalendarConnection(
|
|
14
14
|
account?: string,
|
|
15
15
|
): Promise<OAuthConnection> {
|
|
16
|
-
return resolveOAuthConnection("
|
|
16
|
+
return resolveOAuthConnection("google", { account });
|
|
17
17
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: messaging
|
|
3
|
-
description: Read, search, send, and manage messages across
|
|
3
|
+
description: Read, search, send, and manage messages across Gmail, Telegram, and other platforms
|
|
4
4
|
compatibility: "Designed for Vellum personal assistants"
|
|
5
5
|
metadata:
|
|
6
6
|
emoji: "\U0001F4AC"
|
|
@@ -11,7 +11,9 @@ metadata:
|
|
|
11
11
|
- "Handles credential flows -- do not improvise setup instructions"
|
|
12
12
|
---
|
|
13
13
|
|
|
14
|
-
You are a unified messaging assistant with access to multiple platforms (
|
|
14
|
+
You are a unified messaging assistant with access to multiple platforms (Gmail, Telegram, and more). Use the messaging tools to help users read, search, organize, draft, and send messages across all connected platforms.
|
|
15
|
+
|
|
16
|
+
**Slack is not handled by this skill.** Slack messaging (send, read, search) is handled by the **slack** skill, which uses the Slack Web API directly via CLI. Do not use messaging tools with `platform: "slack"`.
|
|
15
17
|
|
|
16
18
|
## External Identity
|
|
17
19
|
|
|
@@ -28,19 +30,21 @@ Do not offer AgentMail as an option or mention it unless the user specifically a
|
|
|
28
30
|
## Communication Style
|
|
29
31
|
|
|
30
32
|
- **Be action-oriented.** When the user asks to do something ("declutter", "check my email"), start doing it immediately. Don't ask for permission to read their inbox - that's obviously what they want.
|
|
31
|
-
- **Keep it human.** Never mention OAuth, tokens, APIs, sandboxes, credential proxies, or other technical internals. If something isn't working, say "Gmail needs to be reconnected" - not "the OAuth2 access token for
|
|
33
|
+
- **Keep it human.** Never mention OAuth, tokens, APIs, sandboxes, credential proxies, or other technical internals. If something isn't working, say "Gmail needs to be reconnected" - not "the OAuth2 access token for google has expired."
|
|
32
34
|
- **Show progress.** When running a tool that scans many emails, tell the user what you're doing: "Scanning your inbox for clutter..." Don't go silent.
|
|
33
35
|
- **Be brief and warm.** One or two sentences per update is plenty. Don't over-explain what you're about to do - just do it and narrate lightly.
|
|
34
36
|
|
|
35
37
|
When a platform is connected (auth test succeeds), always use the messaging API tools for that platform. Never fall back to browser automation, shell commands (bash, curl), or any other approach for operations that messaging tools can handle. The messaging tools handle authentication internally - never try to access tokens or call APIs directly. Browser automation is only appropriate for initial credential setup (OAuth consent screens), not for day-to-day messaging operations.
|
|
36
38
|
|
|
39
|
+
**Exception: Slack.** Slack messaging should use the Slack Web API directly via CLI, not messaging tools. See the **slack** skill for details.
|
|
40
|
+
|
|
37
41
|
## Connection Setup
|
|
38
42
|
|
|
39
43
|
Before using any messaging tool, verify that the platform is connected by calling `messaging_auth_test` with the appropriate `platform` parameter. If the call fails with a token/authorization error, follow the steps below.
|
|
40
44
|
|
|
41
45
|
### Public Ingress (required for Telegram)
|
|
42
46
|
|
|
43
|
-
Telegram setup requires a
|
|
47
|
+
Telegram setup requires webhook routing, but it does **not** always require ngrok. Before suggesting public ingress for Telegram, check managed callback availability with `assistant platform status --json`. If that reports `containerized: true` with a non-empty `assistantId` and `available: true`, use the platform callback route flow and do not prompt for ngrok. Only use the **public-ingress** skill for local assistants that genuinely need a public gateway URL. Slack uses Socket Mode and does not require public ingress. Gmail on the desktop app uses a loopback callback and does not require public ingress; the channel path (Path B in the google-oauth-app-setup skill) handles public ingress internally when needed.
|
|
44
48
|
|
|
45
49
|
### Email Connection Flow
|
|
46
50
|
|
|
@@ -52,30 +56,26 @@ When the user asks to "connect my email", "set up email", "manage my email", or
|
|
|
52
56
|
|
|
53
57
|
### Gmail
|
|
54
58
|
|
|
55
|
-
1. **Try connecting directly first.** Call `credential_store` with `action: "oauth2_connect"` and `service: "
|
|
56
|
-
2. **If it fails because no client_id is found:** The user needs to create Google Cloud OAuth credentials first. Load the **google-oauth-
|
|
57
|
-
- Call `skill_load` with `skill: "google-oauth-
|
|
59
|
+
1. **Try connecting directly first.** Call `credential_store` with `action: "oauth2_connect"` and `service: "google"`. 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.
|
|
60
|
+
2. **If it fails because no client_id is found:** The user needs to create Google Cloud OAuth credentials first. Load the **google-oauth-app-setup** skill:
|
|
61
|
+
- Call `skill_load` with `skill: "google-oauth-app-setup"` to load the dependency skill.
|
|
58
62
|
- 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:
|
|
59
63
|
- **message:** "Ready to set up Gmail?"
|
|
60
64
|
- **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."
|
|
61
65
|
- **confirmLabel:** "Get Started"
|
|
62
66
|
- **cancelLabel:** "Not Now"
|
|
63
67
|
- 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.
|
|
64
|
-
3. **If the user provides a client_id directly in chat:** Call `credential_store` with `action: "oauth2_connect"`, `service: "
|
|
68
|
+
3. **If the user provides a client_id directly in chat:** Call `credential_store` with `action: "oauth2_connect"`, `service: "google"`, and `client_id: "<their value>"`. Include `client_secret` too if they provide one. Everything else is auto-filled.
|
|
65
69
|
|
|
66
70
|
### Slack
|
|
67
71
|
|
|
68
|
-
Slack
|
|
69
|
-
|
|
70
|
-
- Call `skill_load` with `skill: "slack-app-setup"` to load the dependency skill.
|
|
71
|
-
- Tell the user Slack isn't connected yet and briefly explain what the setup involves, then follow the skill's guided flow.
|
|
72
|
-
|
|
73
|
-
The slack-app-setup skill handles: manifest-driven app creation, app token and bot token collection via secure prompt (never accept tokens pasted in plaintext chat), and Slack connection setup through the same settings handler used by the Settings UI. That handler validates the bot token, stores workspace metadata, and activates Socket Mode. The skill also covers optional identity verification.
|
|
72
|
+
Slack is **not** handled by this skill. For Slack setup, load the **slack-app-setup** skill directly. For Slack messaging, use the **slack** skill which accesses the Slack Web API via CLI.
|
|
74
73
|
|
|
75
74
|
### Telegram
|
|
76
75
|
|
|
77
|
-
Telegram uses a bot token (not OAuth). Load the **telegram-setup** skill
|
|
76
|
+
Telegram uses a bot token (not OAuth). Load the **telegram-setup** skill, which uses a managed platform callback route in containerized deployments and falls back to **public-ingress** locally when needed:
|
|
78
77
|
|
|
78
|
+
- First run `assistant platform status --json`. If it shows managed callback routing is available, tell the user you will use the platform callback route and skip ngrok/public-ingress.
|
|
79
79
|
- Call `skill_load` with `skill: "telegram-setup"` to load the dependency skill.
|
|
80
80
|
- Tell the user: _"I've loaded a setup guide for Telegram. It will walk you through connecting a Telegram bot to your assistant."_
|
|
81
81
|
|
|
@@ -96,7 +96,7 @@ The guardian-verify-setup skill handles the full outbound verification flow for
|
|
|
96
96
|
When a messaging tool fails with a token or authorization error:
|
|
97
97
|
|
|
98
98
|
1. **Try to reconnect silently.** Call `credential_store` with `action: "oauth2_connect"` and the appropriate `service`. This often resolves expired tokens automatically.
|
|
99
|
-
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 that platform (e.g., install and load **google-oauth-
|
|
99
|
+
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 that platform (e.g., install and load **google-oauth-app-setup** for Gmail). The user came to you to get something done, not to troubleshoot OAuth - make it seamless.
|
|
100
100
|
3. **Never try alternative approaches.** Don't use bash, curl, browser automation, or any workaround. If the messaging tools can't do it, the reconnection flow is the answer.
|
|
101
101
|
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.
|
|
102
102
|
|
|
@@ -109,10 +109,10 @@ When a messaging tool fails with a token or authorization error:
|
|
|
109
109
|
|
|
110
110
|
## Capabilities
|
|
111
111
|
|
|
112
|
-
### Universal (
|
|
112
|
+
### Universal (Gmail)
|
|
113
113
|
|
|
114
114
|
- **Auth Test**: Verify connection and show account info
|
|
115
|
-
- **List Conversations**: Show
|
|
115
|
+
- **List Conversations**: Show inboxes, DMs with unread counts
|
|
116
116
|
- **Read Messages**: Read message history from a conversation
|
|
117
117
|
- **Search**: Search messages with platform-appropriate query syntax
|
|
118
118
|
- **Send / Reply**: Send a message or reply in a thread (via `thread_id`). High risk - requires user approval.
|
|
@@ -120,7 +120,7 @@ When a messaging tool fails with a token or authorization error:
|
|
|
120
120
|
|
|
121
121
|
### Telegram
|
|
122
122
|
|
|
123
|
-
Telegram is supported as a messaging provider with limited capabilities compared to
|
|
123
|
+
Telegram is supported as a messaging provider with limited capabilities compared to Gmail due to Bot API constraints:
|
|
124
124
|
|
|
125
125
|
- **Send**: Send a message to a known chat ID (high risk - requires user approval)
|
|
126
126
|
- **Auth Test**: Verify bot token and show bot info
|
|
@@ -136,29 +136,6 @@ Telegram is supported as a messaging provider with limited capabilities compared
|
|
|
136
136
|
- The bot can only message users or groups that have previously interacted with it (sent `/start` or been added to a group). Bots cannot initiate conversations with arbitrary phone numbers.
|
|
137
137
|
- Future support for MTProto user-account sessions may lift some of these restrictions.
|
|
138
138
|
|
|
139
|
-
### Slack-specific
|
|
140
|
-
|
|
141
|
-
- **Add Reaction**: Add an emoji reaction to a message
|
|
142
|
-
- **Leave Channel**: Leave a Slack channel
|
|
143
|
-
- **Edit Message**: `slack_edit_message` - edit a message the assistant previously sent. Requires `channel_id` and the message timestamp (`ts`) from the original send response. High risk - requires confidence score.
|
|
144
|
-
- **Delete Message**: `slack_delete_message` - delete a message the assistant previously sent. Requires `channel_id` and the message timestamp (`ts`). High risk - requires confidence score. This is irreversible.
|
|
145
|
-
|
|
146
|
-
When sending a Slack message, retain the `ts` (message timestamp) from the send response - it is needed to edit or delete that message later. Only messages sent by the assistant's bot can be edited or deleted.
|
|
147
|
-
|
|
148
|
-
## Slack Search Syntax
|
|
149
|
-
|
|
150
|
-
When searching Slack, the query is passed directly to Slack's search API:
|
|
151
|
-
|
|
152
|
-
| Operator | Example | What it finds |
|
|
153
|
-
| -------------- | ------------------- | ------------------------------ |
|
|
154
|
-
| `from:` | `from:@alice` | Messages from a specific user |
|
|
155
|
-
| `in:` | `in:#general` | Messages in a specific channel |
|
|
156
|
-
| `has:` | `has:link` | Messages containing links |
|
|
157
|
-
| `before:` | `before:2024-01-01` | Messages before a date |
|
|
158
|
-
| `after:` | `after:2024-01-01` | Messages after a date |
|
|
159
|
-
| `has:reaction` | `has:reaction` | Messages with reactions |
|
|
160
|
-
| `has:star` | `has:star` | Starred messages |
|
|
161
|
-
|
|
162
139
|
## Notifications vs Messages
|
|
163
140
|
|
|
164
141
|
- `send_notification` is provided by the **notifications** skill (always active) -- use it when the user asks for an alert/notification (for example "send this as a desktop notification").
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"properties": {
|
|
12
12
|
"platform": {
|
|
13
13
|
"type": "string",
|
|
14
|
-
"description": "Platform to test (e.g. \"
|
|
14
|
+
"description": "Platform to test (e.g. \"gmail\"). Auto-detected if only one is connected. Slack is not supported — use the Slack Web API directly."
|
|
15
15
|
},
|
|
16
16
|
"account": {
|
|
17
17
|
"type": "string",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"properties": {
|
|
37
37
|
"platform": {
|
|
38
38
|
"type": "string",
|
|
39
|
-
"description": "Platform (e.g. \"
|
|
39
|
+
"description": "Platform (e.g. \"gmail\"). Auto-detected if only one is connected. Slack is not supported — use the Slack Web API directly."
|
|
40
40
|
},
|
|
41
41
|
"account": {
|
|
42
42
|
"type": "string",
|
|
@@ -73,7 +73,7 @@
|
|
|
73
73
|
"properties": {
|
|
74
74
|
"platform": {
|
|
75
75
|
"type": "string",
|
|
76
|
-
"description": "Platform (e.g. \"
|
|
76
|
+
"description": "Platform (e.g. \"gmail\"). Auto-detected if only one is connected. Slack is not supported — use the Slack Web API directly."
|
|
77
77
|
},
|
|
78
78
|
"account": {
|
|
79
79
|
"type": "string",
|
|
@@ -111,7 +111,7 @@
|
|
|
111
111
|
"properties": {
|
|
112
112
|
"platform": {
|
|
113
113
|
"type": "string",
|
|
114
|
-
"description": "Platform (e.g. \"
|
|
114
|
+
"description": "Platform (e.g. \"gmail\"). Auto-detected if only one is connected. Slack is not supported — use the Slack Web API directly."
|
|
115
115
|
},
|
|
116
116
|
"account": {
|
|
117
117
|
"type": "string",
|
|
@@ -145,7 +145,7 @@
|
|
|
145
145
|
"properties": {
|
|
146
146
|
"platform": {
|
|
147
147
|
"type": "string",
|
|
148
|
-
"description": "Platform (e.g. \"
|
|
148
|
+
"description": "Platform (e.g. \"gmail\"). Auto-detected if only one is connected. Slack is not supported — use the Slack Web API directly."
|
|
149
149
|
},
|
|
150
150
|
"account": {
|
|
151
151
|
"type": "string",
|
|
@@ -202,7 +202,7 @@
|
|
|
202
202
|
"properties": {
|
|
203
203
|
"platform": {
|
|
204
204
|
"type": "string",
|
|
205
|
-
"description": "Platform (e.g. \"
|
|
205
|
+
"description": "Platform (e.g. \"gmail\"). Auto-detected if only one is connected. Slack is not supported — use the Slack Web API directly."
|
|
206
206
|
},
|
|
207
207
|
"account": {
|
|
208
208
|
"type": "string",
|
|
@@ -236,7 +236,7 @@
|
|
|
236
236
|
"properties": {
|
|
237
237
|
"platform": {
|
|
238
238
|
"type": "string",
|
|
239
|
-
"description": "Platform (e.g. \"
|
|
239
|
+
"description": "Platform (e.g. \"gmail\"). Auto-detected if only one is connected. Slack is not supported — use the Slack Web API directly."
|
|
240
240
|
},
|
|
241
241
|
"account": {
|
|
242
242
|
"type": "string",
|
|
@@ -248,7 +248,7 @@
|
|
|
248
248
|
},
|
|
249
249
|
"query_filter": {
|
|
250
250
|
"type": "string",
|
|
251
|
-
"description": "Optional search filter (e.g. 'to:alice@example.com' for Gmail
|
|
251
|
+
"description": "Optional search filter (e.g. 'to:alice@example.com' for Gmail)"
|
|
252
252
|
},
|
|
253
253
|
"activity": {
|
|
254
254
|
"type": "string",
|
|
@@ -274,7 +274,7 @@
|
|
|
274
274
|
},
|
|
275
275
|
"platform": {
|
|
276
276
|
"type": "string",
|
|
277
|
-
"description": "Platform (e.g. \"
|
|
277
|
+
"description": "Platform (e.g. \"gmail\"). Required for create/list. Slack is not supported — use the Slack Web API directly."
|
|
278
278
|
},
|
|
279
279
|
"conversation_id": {
|
|
280
280
|
"type": "string",
|
|
@@ -50,7 +50,7 @@ function upsertMemoryItem(opts: {
|
|
|
50
50
|
Math.max(existing.importance ?? 0, opts.importance),
|
|
51
51
|
),
|
|
52
52
|
lastSeenAt: now,
|
|
53
|
-
sourceType: "extraction",
|
|
53
|
+
sourceType: existing.sourceType === "tool" ? "tool" : "extraction",
|
|
54
54
|
})
|
|
55
55
|
.where(eq(memoryItems.id, existing.id))
|
|
56
56
|
.run();
|
|
@@ -9,7 +9,6 @@ import {
|
|
|
9
9
|
listMessages,
|
|
10
10
|
} from "../../../../messaging/providers/gmail/client.js";
|
|
11
11
|
import { buildMultipartMime } from "../../../../messaging/providers/gmail/mime-builder.js";
|
|
12
|
-
import type { OAuthConnection } from "../../../../oauth/connection.js";
|
|
13
12
|
import type {
|
|
14
13
|
ToolContext,
|
|
15
14
|
ToolExecutionResult,
|
|
@@ -57,7 +56,11 @@ export async function run(
|
|
|
57
56
|
|
|
58
57
|
// Gmail: create a draft instead of sending directly
|
|
59
58
|
if (provider.id === "gmail") {
|
|
60
|
-
|
|
59
|
+
if (!conn)
|
|
60
|
+
return err(
|
|
61
|
+
"Gmail requires an OAuth connection — is the account connected?",
|
|
62
|
+
);
|
|
63
|
+
const gmailConn = conn;
|
|
61
64
|
// Reply mode: thread_id provided - create a threaded draft with reply-all recipients
|
|
62
65
|
if (threadId) {
|
|
63
66
|
// Fetch thread messages to extract recipients and threading headers
|
|
@@ -126,17 +126,16 @@ export async function resolveProvider(
|
|
|
126
126
|
}
|
|
127
127
|
|
|
128
128
|
/**
|
|
129
|
-
* Resolve an OAuthConnection
|
|
130
|
-
* for the given messaging provider.
|
|
129
|
+
* Resolve an OAuthConnection for the given messaging provider.
|
|
131
130
|
*
|
|
132
|
-
*
|
|
133
|
-
*
|
|
131
|
+
* Returns undefined for providers that manage credentials internally
|
|
132
|
+
* (e.g. Telegram bot tokens, Slack Socket Mode bot tokens).
|
|
134
133
|
*/
|
|
135
134
|
export async function getProviderConnection(
|
|
136
135
|
provider: MessagingProvider,
|
|
137
136
|
account?: string,
|
|
138
|
-
): Promise<OAuthConnection |
|
|
137
|
+
): Promise<OAuthConnection | undefined> {
|
|
139
138
|
if (provider.resolveConnection) return provider.resolveConnection(account);
|
|
140
|
-
if (await provider.isConnected?.()) return
|
|
139
|
+
if (await provider.isConnected?.()) return undefined;
|
|
141
140
|
return resolveOAuthConnection(provider.credentialService, { account });
|
|
142
141
|
}
|
|
@@ -37,4 +37,4 @@ Conversation grouping is handled by the LLM-powered decision engine, not by any
|
|
|
37
37
|
## Important
|
|
38
38
|
|
|
39
39
|
- Do **NOT** use AppleScript `display notification` or other OS-level notification commands for assistant-managed alerts. Always use `send_notification`.
|
|
40
|
-
- For sending rich content (digests, summaries, reports) to a specific chat or email destination, use the
|
|
40
|
+
- For sending rich content (digests, summaries, reports) to a specific chat or email destination, use the appropriate platform's API directly. For Gmail, use `messaging_send`. For Slack, use the Slack Web API directly (see the **slack** skill). The decision engine rewrites `send_notification` content into short alerts, which strips rich formatting.
|
|
@@ -163,9 +163,9 @@ Scheduled messages run without user interaction. If the task produces output tha
|
|
|
163
163
|
|
|
164
164
|
Choose the right delivery tool based on the content:
|
|
165
165
|
|
|
166
|
-
- **Rich content** (digests, summaries, reports):
|
|
166
|
+
- **Rich content** (digests, summaries, reports): For Gmail, use `messaging_send` with the target platform and conversation ID. For Slack, use the Slack Web API directly via CLI (`chat.postMessage`). This preserves the full content and posts directly.
|
|
167
167
|
- **Short alerts** (status updates, completion notices): Use `send_notification` to let the notification router pick the best channel. Note: the router's decision engine rewrites content into short alerts, so it is not suitable for rich content.
|
|
168
168
|
|
|
169
169
|
Example schedule message for a Slack digest:
|
|
170
170
|
|
|
171
|
-
> "Scan my Slack channels for the last 24 hours using
|
|
171
|
+
> "Scan my Slack channels for the last 24 hours using the Slack Web API via bash (network_mode: proxied, credential_ids: ['slack_channel/bot_token']), then post the summary to #alex-agent-messages (C0A7STRJ4G5)."
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: settings
|
|
3
|
-
description: Manage assistant voice, avatar, and system settings
|
|
3
|
+
description: Manage assistant voice, avatar (set, remove, view, show), and system settings
|
|
4
4
|
compatibility: "Designed for Vellum personal assistants"
|
|
5
5
|
metadata:
|
|
6
6
|
emoji: "\u2699\uFE0F"
|
|
@@ -8,7 +8,7 @@ metadata:
|
|
|
8
8
|
display-name: "Settings"
|
|
9
9
|
---
|
|
10
10
|
|
|
11
|
-
Tools for managing assistant settings: voice configuration (TTS voice, PTT activation key, conversation timeout), avatar management, system settings navigation, and in-app settings tab navigation.
|
|
11
|
+
Tools for managing assistant settings: voice configuration (TTS voice, PTT activation key, conversation timeout), avatar management (set, remove, view/show current avatar), system settings navigation, and in-app settings tab navigation.
|
|
12
12
|
|
|
13
13
|
## Avatar
|
|
14
14
|
|
|
@@ -21,4 +21,6 @@ The tool copies the image to the canonical location (`data/avatar/avatar-image.p
|
|
|
21
21
|
|
|
22
22
|
When the user asks to remove, clear, or reset their avatar, use the `remove_avatar` tool. It deletes only the custom image and preserves the native character traits so the character avatar is restored automatically.
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
When the user asks to see, view, or show their current avatar, use the `get_avatar` tool. It returns the avatar image inline. If no custom image exists but character traits are set, it regenerates the static PNG from traits and returns that.
|
|
25
|
+
|
|
26
|
+
**Do NOT use `bash`, `cp`, `rm`, or `file_read` for avatar operations** — always use `set_avatar` / `remove_avatar` / `get_avatar` so the app is properly notified and character traits are preserved.
|
|
@@ -124,6 +124,23 @@
|
|
|
124
124
|
},
|
|
125
125
|
"executor": "tools/avatar-remove.ts",
|
|
126
126
|
"execution_target": "sandbox"
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
"name": "get_avatar",
|
|
130
|
+
"description": "Read and return the current avatar image so the user can see it. Use this when the user asks to see, view, or show their avatar. Returns the image inline — do NOT copy the file or use bash commands.",
|
|
131
|
+
"category": "system",
|
|
132
|
+
"risk": "low",
|
|
133
|
+
"input_schema": {
|
|
134
|
+
"type": "object",
|
|
135
|
+
"properties": {
|
|
136
|
+
"activity": {
|
|
137
|
+
"type": "string",
|
|
138
|
+
"description": "Brief non-technical explanation of what you are doing, shown to the user as a status update."
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
},
|
|
142
|
+
"executor": "tools/avatar-get.ts",
|
|
143
|
+
"execution_target": "sandbox"
|
|
127
144
|
}
|
|
128
145
|
]
|
|
129
146
|
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
|
|
4
|
+
import { writeTraitsAndRenderAvatar } from "../../../../avatar/traits-png-sync.js";
|
|
5
|
+
import { readImageFile } from "../../../../tools/shared/filesystem/image-read.js";
|
|
6
|
+
import type {
|
|
7
|
+
ToolContext,
|
|
8
|
+
ToolExecutionResult,
|
|
9
|
+
} from "../../../../tools/types.js";
|
|
10
|
+
import { getWorkspaceDir } from "../../../../util/platform.js";
|
|
11
|
+
|
|
12
|
+
export async function run(
|
|
13
|
+
_input: Record<string, unknown>,
|
|
14
|
+
_context: ToolContext,
|
|
15
|
+
): Promise<ToolExecutionResult> {
|
|
16
|
+
const avatarPath = join(
|
|
17
|
+
getWorkspaceDir(),
|
|
18
|
+
"data",
|
|
19
|
+
"avatar",
|
|
20
|
+
"avatar-image.png",
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
if (!existsSync(avatarPath)) {
|
|
24
|
+
// Check for native character traits and regenerate the static PNG
|
|
25
|
+
const traitsPath = join(
|
|
26
|
+
getWorkspaceDir(),
|
|
27
|
+
"data",
|
|
28
|
+
"avatar",
|
|
29
|
+
"character-traits.json",
|
|
30
|
+
);
|
|
31
|
+
if (existsSync(traitsPath)) {
|
|
32
|
+
try {
|
|
33
|
+
const traits = JSON.parse(readFileSync(traitsPath, "utf-8"));
|
|
34
|
+
const result = writeTraitsAndRenderAvatar(traits);
|
|
35
|
+
if (result.ok && existsSync(avatarPath)) {
|
|
36
|
+
return readImageFile(avatarPath);
|
|
37
|
+
}
|
|
38
|
+
} catch {
|
|
39
|
+
// Fall through to default message
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return {
|
|
43
|
+
content:
|
|
44
|
+
"No avatar is currently set — no custom image and no character traits found.",
|
|
45
|
+
isError: false,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return readImageFile(avatarPath);
|
|
50
|
+
}
|
|
@@ -10,6 +10,7 @@ import type {
|
|
|
10
10
|
} from "../../../../tools/types.js";
|
|
11
11
|
import { getLogger } from "../../../../util/logger.js";
|
|
12
12
|
import { getWorkspaceDir } from "../../../../util/platform.js";
|
|
13
|
+
import { updateIdentityAvatarSection } from "./identity-avatar.js";
|
|
13
14
|
|
|
14
15
|
const log = getLogger("avatar-remove");
|
|
15
16
|
|
|
@@ -50,6 +51,12 @@ export async function run(
|
|
|
50
51
|
log.warn({ err }, "Failed to publish avatar_updated event");
|
|
51
52
|
});
|
|
52
53
|
|
|
54
|
+
// Update IDENTITY.md to reflect the avatar was removed.
|
|
55
|
+
updateIdentityAvatarSection(
|
|
56
|
+
"Default character avatar (no custom image set)",
|
|
57
|
+
log,
|
|
58
|
+
);
|
|
59
|
+
|
|
53
60
|
log.info("Custom avatar removed, reverting to character avatar");
|
|
54
61
|
|
|
55
62
|
return {
|
|
@@ -10,6 +10,7 @@ import type {
|
|
|
10
10
|
} from "../../../../tools/types.js";
|
|
11
11
|
import { getLogger } from "../../../../util/logger.js";
|
|
12
12
|
import { getWorkspaceDir } from "../../../../util/platform.js";
|
|
13
|
+
import { updateIdentityAvatarSection } from "./identity-avatar.js";
|
|
13
14
|
|
|
14
15
|
const log = getLogger("avatar-update");
|
|
15
16
|
|
|
@@ -71,10 +72,14 @@ export async function run(
|
|
|
71
72
|
log.warn({ err }, "Failed to publish avatar_updated event");
|
|
72
73
|
});
|
|
73
74
|
|
|
75
|
+
// Clear any stale avatar description from IDENTITY.md so the assistant
|
|
76
|
+
// is prompted to describe the new image on next read.
|
|
77
|
+
updateIdentityAvatarSection(null, log);
|
|
78
|
+
|
|
74
79
|
log.info({ avatarPath, source: resolvedSource }, "Avatar updated");
|
|
75
80
|
|
|
76
81
|
return {
|
|
77
|
-
content: `Avatar updated from ${sourcePath}. The app will refresh automatically.`,
|
|
82
|
+
content: `Avatar updated from ${sourcePath}. The app will refresh automatically. The avatar description in IDENTITY.md has been cleared — describe what the new avatar looks like by updating the ## Avatar section in IDENTITY.md with a plain-text description (not an image link).`,
|
|
78
83
|
isError: false,
|
|
79
84
|
};
|
|
80
85
|
}
|