@vellumai/assistant 0.5.16 → 0.6.1
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 +4 -0
- package/ARCHITECTURE.md +69 -16
- package/Dockerfile +2 -5
- package/bun.lock +6 -2
- package/docker-entrypoint.sh +32 -1
- package/docs/architecture/integrations.md +1 -1
- package/docs/architecture/memory.md +21 -24
- package/knip.json +2 -1
- package/openapi.yaml +1198 -83
- package/package.json +5 -1
- package/src/__tests__/actor-token-service.test.ts +68 -0
- package/src/__tests__/agent-loop.test.ts +0 -32
- package/src/__tests__/always-loaded-tools-guard.test.ts +2 -2
- package/src/__tests__/anthropic-provider.test.ts +217 -98
- package/src/__tests__/app-compiler.test.ts +120 -0
- package/src/__tests__/app-dir-path-guard.test.ts +1 -0
- package/src/__tests__/app-executors.test.ts +47 -1
- package/src/__tests__/app-source-watcher.test.ts +159 -0
- package/src/__tests__/assistant-feature-flags-integration.test.ts +2 -2
- package/src/__tests__/call-conversation-messages.test.ts +2 -6
- package/src/__tests__/call-domain.test.ts +2 -6
- package/src/__tests__/call-pointer-messages.test.ts +2 -14
- package/src/__tests__/call-recovery.test.ts +2 -6
- package/src/__tests__/call-routes-http.test.ts +2 -6
- package/src/__tests__/call-store.test.ts +2 -6
- package/src/__tests__/cancel-resolves-conversation-key.test.ts +2 -6
- package/src/__tests__/canonical-guardian-store.test.ts +2 -6
- package/src/__tests__/channel-delivery-store.test.ts +2 -6
- package/src/__tests__/channel-retry-sweep.test.ts +2 -6
- package/src/__tests__/checker.test.ts +63 -9
- package/src/__tests__/clawhub.test.ts +54 -24
- package/src/__tests__/cli-command-risk-guard.test.ts +14 -0
- package/src/__tests__/config-schema.test.ts +6 -1
- package/src/__tests__/config-set-platform-guard.test.ts +302 -0
- package/src/__tests__/confirmation-request-guardian-bridge.test.ts +2 -6
- package/src/__tests__/contacts-tools.test.ts +31 -0
- package/src/__tests__/context-overflow-reducer.test.ts +86 -0
- package/src/__tests__/context-token-estimator.test.ts +175 -10
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +13 -6
- package/src/__tests__/conversation-agent-loop.test.ts +13 -51
- package/src/__tests__/conversation-attachments.test.ts +2 -6
- package/src/__tests__/conversation-attention-store.test.ts +2 -6
- package/src/__tests__/conversation-clear-safety.test.ts +2 -6
- package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +4 -10
- package/src/__tests__/conversation-disk-view-integration.test.ts +2 -6
- package/src/__tests__/conversation-disk-view.test.ts +2 -6
- package/src/__tests__/conversation-error.test.ts +33 -2
- package/src/__tests__/conversation-fork-crud.test.ts +2 -6
- package/src/__tests__/conversation-history-web-search.test.ts +6 -1
- package/src/__tests__/conversation-load-history-repair.test.ts +5 -1
- package/src/__tests__/conversation-media-retry.test.ts +91 -0
- package/src/__tests__/conversation-runtime-assembly.test.ts +653 -832
- package/src/__tests__/conversation-runtime-workspace.test.ts +1 -93
- package/src/__tests__/conversation-starter-routes.test.ts +20 -11
- package/src/__tests__/conversation-store.test.ts +2 -6
- package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +17 -4
- package/src/__tests__/conversation-usage.test.ts +2 -6
- package/src/__tests__/conversation-wipe.test.ts +13 -414
- package/src/__tests__/conversation-workspace-cache-state.test.ts +6 -12
- package/src/__tests__/conversation-workspace-injection.test.ts +25 -26
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +1 -1
- package/src/__tests__/copy-composer-tc-templates.test.ts +335 -0
- package/src/__tests__/credential-execution-feature-gates.test.ts +3 -3
- package/src/__tests__/credential-execution-shell-lockdown.test.ts +2 -2
- package/src/__tests__/credential-security-e2e.test.ts +2 -0
- package/src/__tests__/date-context.test.ts +76 -210
- package/src/__tests__/db-schedule-syntax-migration.test.ts +16 -1
- package/src/__tests__/file-list-tool.test.ts +219 -0
- package/src/__tests__/first-greeting.test.ts +1 -1
- package/src/__tests__/followup-tools.test.ts +2 -6
- package/src/__tests__/graph-extraction-event-date.test.ts +186 -0
- package/src/__tests__/guardian-action-conversation-turn.test.ts +2 -6
- package/src/__tests__/guardian-action-followup-executor.test.ts +2 -6
- package/src/__tests__/guardian-action-followup-store.test.ts +2 -6
- package/src/__tests__/guardian-action-grant-mint-consume.test.ts +2 -6
- package/src/__tests__/guardian-action-late-reply.test.ts +2 -6
- package/src/__tests__/guardian-action-store.test.ts +2 -6
- package/src/__tests__/guardian-binding-drift-heal.test.ts +2 -6
- package/src/__tests__/guardian-decision-primitive-canonical.test.ts +8 -8
- package/src/__tests__/guardian-dispatch.test.ts +2 -6
- package/src/__tests__/guardian-grant-minting.test.ts +2 -14
- package/src/__tests__/guardian-principal-id-roundtrip.test.ts +2 -6
- package/src/__tests__/guardian-routing-invariants.test.ts +192 -6
- package/src/__tests__/guardian-routing-state.test.ts +2 -6
- package/src/__tests__/guardian-verification-voice-binding.test.ts +2 -6
- package/src/__tests__/heartbeat-service.test.ts +180 -3
- package/src/__tests__/identity-routes.test.ts +328 -0
- package/src/__tests__/inbound-invite-redemption.test.ts +2 -6
- package/src/__tests__/injection-block.test.ts +178 -0
- package/src/__tests__/install-meta.test.ts +506 -0
- package/src/__tests__/install-skill-routing.test.ts +293 -0
- package/src/__tests__/invite-redemption-service.test.ts +2 -6
- package/src/__tests__/invite-routes-http.test.ts +2 -6
- package/src/__tests__/jobs-store-qdrant-breaker.test.ts +17 -28
- package/src/__tests__/list-messages-attachments.test.ts +2 -6
- package/src/__tests__/list-messages-tool-merge.test.ts +300 -0
- package/src/__tests__/llm-context-normalization.test.ts +18 -18
- package/src/__tests__/llm-context-route-provider.test.ts +103 -6
- package/src/__tests__/llm-request-log-turn-query.test.ts +164 -6
- package/src/__tests__/llm-usage-store.test.ts +2 -6
- package/src/__tests__/log-export-workspace.test.ts +74 -111
- package/src/__tests__/managed-store.test.ts +38 -11
- package/src/__tests__/mcp-abort-signal.test.ts +5 -0
- package/src/__tests__/mcp-client-auth.test.ts +5 -0
- package/src/__tests__/memory-jobs-worker-backoff.test.ts +2 -8
- package/src/__tests__/memory-recall-log-store.test.ts +134 -6
- package/src/__tests__/memory-upsert-concurrency.test.ts +4 -112
- package/src/__tests__/migration-export-streaming.test.ts +304 -0
- package/src/__tests__/migration-import-commit-http.test.ts +11 -10
- package/src/__tests__/mock-fetch.ts +87 -0
- package/src/__tests__/non-member-access-request.test.ts +2 -6
- package/src/__tests__/notification-decision-recipient-context.test.ts +282 -0
- package/src/__tests__/notification-guardian-path.test.ts +2 -6
- package/src/__tests__/oauth-cli.test.ts +364 -2
- package/src/__tests__/oauth2-gateway-transport.test.ts +18 -3
- package/src/__tests__/onboarding-template-contract.test.ts +62 -14
- package/src/__tests__/outlook-attachments.test.ts +301 -0
- package/src/__tests__/outlook-automation-tools.test.ts +425 -0
- package/src/__tests__/outlook-categories.test.ts +212 -0
- package/src/__tests__/outlook-client-automation.test.ts +246 -0
- package/src/__tests__/outlook-compose-tools.test.ts +325 -0
- package/src/__tests__/outlook-declutter-tools.test.ts +585 -0
- package/src/__tests__/outlook-email-watcher.test.ts +322 -0
- package/src/__tests__/outlook-follow-up.test.ts +196 -0
- package/src/__tests__/outlook-messaging-provider.test.ts +498 -3
- package/src/__tests__/outlook-trash.test.ts +77 -0
- package/src/__tests__/outlook-unsubscribe.test.ts +250 -0
- package/src/__tests__/parser.test.ts +32 -0
- package/src/__tests__/permission-checker-host-gate.test.ts +452 -0
- package/src/__tests__/permission-controls-v2-flag.test.ts +55 -0
- package/src/__tests__/permission-mode-sse.test.ts +418 -0
- package/src/__tests__/permission-mode-store.test.ts +277 -0
- package/src/__tests__/permission-mode.test.ts +101 -0
- package/src/__tests__/platform-bash-auto-approve.test.ts +359 -0
- package/src/__tests__/platform-callback-registration.test.ts +4 -4
- package/src/__tests__/playbook-execution.test.ts +76 -80
- package/src/__tests__/playbook-tools.test.ts +5 -7
- package/src/__tests__/profiler-routes.test.ts +502 -0
- package/src/__tests__/profiler-run-store.test.ts +441 -0
- package/src/__tests__/provider-error-scenarios.test.ts +21 -0
- package/src/__tests__/proxy-approval-callback.test.ts +4 -75
- package/src/__tests__/rebuild-index-graph-nodes.test.ts +273 -0
- package/src/__tests__/registry.test.ts +3 -3
- package/src/__tests__/require-fresh-approval.test.ts +64 -2
- package/src/__tests__/runtime-events-sse-parity.test.ts +2 -6
- package/src/__tests__/runtime-events-sse.test.ts +2 -6
- package/src/__tests__/sandbox-host-parity.test.ts +5 -4
- package/src/__tests__/schedule-store.test.ts +2 -6
- package/src/__tests__/schedule-tools.test.ts +2 -6
- package/src/__tests__/scheduler-recurrence.test.ts +1 -5
- package/src/__tests__/scheduler-reuse-conversation.test.ts +368 -0
- package/src/__tests__/scoped-approval-grants.test.ts +2 -6
- package/src/__tests__/scoped-grant-security-matrix.test.ts +2 -6
- package/src/__tests__/scrub-corrupted-image-attachments.test.ts +278 -0
- package/src/__tests__/search-skills-unified.test.ts +422 -0
- package/src/__tests__/secret-onetime-send.test.ts +2 -0
- package/src/__tests__/send-endpoint-busy.test.ts +44 -9
- package/src/__tests__/sequence-store.test.ts +2 -6
- package/src/__tests__/server-history-render.test.ts +2 -6
- package/src/__tests__/set-permission-mode.test.ts +274 -0
- package/src/__tests__/skill-feature-flags-integration.test.ts +38 -31
- package/src/__tests__/skill-feature-flags.test.ts +6 -6
- package/src/__tests__/skill-load-feature-flag.test.ts +23 -11
- package/src/__tests__/skill-memory.test.ts +2 -741
- package/src/__tests__/skills-uninstall.test.ts +2 -2
- package/src/__tests__/skills.test.ts +1 -1
- package/src/__tests__/slack-inbound-verification.test.ts +2 -6
- package/src/__tests__/strip-memory-injections.test.ts +187 -0
- package/src/__tests__/subagent-detail.test.ts +84 -0
- package/src/__tests__/subagent-disposal.test.ts +308 -0
- package/src/__tests__/subagent-manager-notify.test.ts +19 -10
- package/src/__tests__/subagent-notify-parent.test.ts +390 -0
- package/src/__tests__/subagent-role-registry.test.ts +108 -0
- package/src/__tests__/subagent-tool-filtering.test.ts +71 -0
- package/src/__tests__/subagent-tools.test.ts +464 -4
- package/src/__tests__/system-prompt-ask-mode.test.ts +139 -0
- package/src/__tests__/task-compiler.test.ts +2 -6
- package/src/__tests__/task-management-tools.test.ts +2 -6
- package/src/__tests__/task-memory-cleanup.test.ts +185 -241
- package/src/__tests__/task-runner.test.ts +2 -6
- package/src/__tests__/task-scheduler.test.ts +2 -6
- package/src/__tests__/terminal-tools.test.ts +17 -27
- package/src/__tests__/test-preload.ts +7 -0
- package/src/__tests__/tool-approval-handler.test.ts +2 -6
- package/src/__tests__/tool-executor.test.ts +4 -26
- package/src/__tests__/tool-grant-request-escalation.test.ts +2 -6
- package/src/__tests__/tool-side-effects-slack-dm.test.ts +277 -0
- package/src/__tests__/top-level-renderer.test.ts +10 -13
- package/src/__tests__/trust-store.test.ts +1 -1
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +2 -6
- package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +118 -8
- package/src/__tests__/trusted-contact-multichannel.test.ts +2 -6
- package/src/__tests__/trusted-contact-verification.test.ts +2 -6
- package/src/__tests__/turn-boundary-resolution.test.ts +2 -6
- package/src/__tests__/usage-cache-backfill-migration.test.ts +1 -6
- package/src/__tests__/usage-routes.test.ts +2 -6
- package/src/__tests__/verification-control-plane-policy.test.ts +0 -2
- package/src/__tests__/voice-invite-redemption.test.ts +2 -6
- package/src/__tests__/voice-scoped-grant-consumer.test.ts +2 -6
- package/src/__tests__/voice-session-bridge.test.ts +2 -6
- package/src/__tests__/volume-security-guard.test.ts +2 -0
- package/src/__tests__/workspace-lifecycle.test.ts +29 -1
- package/src/__tests__/workspace-migration-009-backfill-conversation-disk-view.test.ts +2 -6
- package/src/__tests__/workspace-migration-013-repair-conversation-disk-view.test.ts +2 -6
- package/src/__tests__/workspace-migration-026-backfill-install-meta.test.ts +558 -0
- package/src/__tests__/workspace-migration-028-recover-conversations-from-disk-view.test.ts +387 -0
- package/src/__tests__/workspace-policy.test.ts +1 -1
- package/src/agent/attachments.ts +7 -2
- package/src/agent/image-optimize.ts +165 -0
- package/src/agent/loop.ts +7 -15
- package/src/approvals/guardian-request-resolvers.ts +24 -0
- package/src/avatar/traits-png-sync.ts +3 -3
- package/src/bundler/app-compiler.ts +179 -2
- package/src/bundler/package-resolver.ts +3 -5
- package/src/cli/__tests__/notifications.test.ts +1 -2
- package/src/cli/__tests__/run-assistant-command.ts +29 -0
- package/src/cli/commands/__tests__/email-download.test.ts +245 -0
- package/src/cli/commands/__tests__/email-list.test.ts +192 -0
- package/src/cli/commands/__tests__/email-register.test.ts +186 -0
- package/src/cli/commands/__tests__/email-send.test.ts +291 -0
- package/src/cli/commands/__tests__/email-status.test.ts +181 -0
- package/src/cli/commands/__tests__/email-unregister.test.ts +139 -0
- package/src/cli/commands/__tests__/routes.test.ts +562 -0
- package/src/cli/commands/avatar.ts +3 -3
- package/src/cli/commands/config.ts +26 -13
- package/src/cli/commands/conversations.ts +1 -8
- package/src/cli/commands/doctor.ts +2 -2
- package/src/cli/commands/email.ts +584 -835
- package/src/cli/commands/memory.ts +37 -84
- package/src/cli/commands/notifications.ts +7 -2
- package/src/cli/commands/oauth/__tests__/connect.test.ts +2 -2
- package/src/cli/commands/oauth/__tests__/disconnect.test.ts +2 -2
- package/src/cli/commands/oauth/__tests__/mode.test.ts +8 -1
- package/src/cli/commands/oauth/__tests__/status.test.ts +2 -2
- package/src/cli/commands/oauth/connect.ts +25 -11
- package/src/cli/commands/oauth/mode.ts +7 -0
- package/src/cli/commands/oauth/shared.ts +39 -3
- package/src/cli/commands/platform/__tests__/connect.test.ts +1 -1
- package/src/cli/commands/platform/__tests__/disconnect.test.ts +1 -1
- package/src/cli/commands/platform/__tests__/status.test.ts +5 -5
- package/src/cli/commands/platform/index.ts +16 -16
- package/src/cli/commands/routes.ts +396 -0
- package/src/cli/commands/skills.ts +218 -36
- package/src/cli/commands/trust.ts +2 -2
- package/src/cli/lib/daemon-credential-client.ts +2 -3
- package/src/cli/program.ts +2 -0
- package/src/cli.ts +1 -120
- package/src/config/bundled-skills/acp/TOOLS.json +1 -1
- package/src/config/bundled-skills/app-builder/SKILL.md +4 -1
- package/src/config/bundled-skills/contacts/SKILL.md +0 -1
- package/src/config/bundled-skills/contacts/TOOLS.json +0 -8
- package/src/config/bundled-skills/contacts/tools/contact-upsert.ts +0 -4
- package/src/config/bundled-skills/gmail/SKILL.md +4 -12
- package/src/config/bundled-skills/google-calendar/SKILL.md +1 -9
- package/src/config/bundled-skills/messaging/SKILL.md +17 -18
- package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +40 -33
- package/src/config/bundled-skills/outlook/SKILL.md +189 -0
- package/src/config/bundled-skills/outlook/TOOLS.json +530 -0
- package/src/config/bundled-skills/outlook/tools/outlook-attachments.ts +85 -0
- package/src/config/bundled-skills/outlook/tools/outlook-categories.ts +77 -0
- package/src/config/bundled-skills/outlook/tools/outlook-draft.ts +84 -0
- package/src/config/bundled-skills/outlook/tools/outlook-follow-up.ts +94 -0
- package/src/config/bundled-skills/outlook/tools/outlook-forward.ts +49 -0
- package/src/config/bundled-skills/outlook/tools/outlook-outreach-scan.ts +237 -0
- package/src/config/bundled-skills/outlook/tools/outlook-rules.ts +161 -0
- package/src/config/bundled-skills/outlook/tools/outlook-send-draft.ts +32 -0
- package/src/config/bundled-skills/outlook/tools/outlook-sender-digest.ts +272 -0
- package/src/config/bundled-skills/outlook/tools/outlook-trash.ts +29 -0
- package/src/config/bundled-skills/outlook/tools/outlook-unsubscribe.ts +129 -0
- package/src/config/bundled-skills/outlook/tools/outlook-vacation.ts +87 -0
- package/src/config/bundled-skills/outlook/tools/shared.ts +20 -0
- package/src/config/bundled-skills/outlook-calendar/SKILL.md +51 -0
- package/src/config/bundled-skills/outlook-calendar/TOOLS.json +221 -0
- package/src/config/bundled-skills/outlook-calendar/calendar-client.ts +252 -0
- package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-check-availability.ts +53 -0
- package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-create-event.ts +74 -0
- package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-get-event.ts +18 -0
- package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-list-events.ts +46 -0
- package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-rsvp.ts +36 -0
- package/src/config/bundled-skills/outlook-calendar/tools/shared.ts +17 -0
- package/src/config/bundled-skills/outlook-calendar/types.ts +120 -0
- package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +47 -40
- package/src/config/bundled-skills/playbooks/tools/playbook-delete.ts +16 -29
- package/src/config/bundled-skills/playbooks/tools/playbook-list.ts +16 -18
- package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +39 -47
- package/src/config/bundled-skills/schedule/SKILL.md +22 -2
- package/src/config/bundled-skills/schedule/TOOLS.json +8 -0
- package/src/config/bundled-skills/settings/tools/avatar-get.ts +3 -13
- package/src/config/bundled-skills/settings/tools/avatar-remove.ts +2 -4
- package/src/config/bundled-skills/settings/tools/avatar-update.ts +5 -2
- package/src/config/bundled-skills/slack/SKILL.md +3 -7
- package/src/config/bundled-skills/subagent/SKILL.md +43 -3
- package/src/config/bundled-skills/subagent/TOOLS.json +29 -4
- package/src/config/bundled-tool-registry.ts +56 -4
- package/src/config/env-registry.ts +78 -8
- package/src/config/feature-flag-registry.json +38 -125
- package/src/config/schema.ts +8 -0
- package/src/config/schemas/filing.ts +51 -0
- package/src/config/schemas/heartbeat.ts +15 -12
- package/src/config/schemas/memory-lifecycle.ts +12 -0
- package/src/config/schemas/platform.ts +8 -0
- package/src/config/schemas/security.ts +14 -0
- package/src/config/schemas/timeouts.ts +1 -1
- package/src/config/skills.ts +18 -7
- package/src/context/token-estimator.ts +25 -18
- package/src/context/window-manager.ts +6 -2
- package/src/credential-execution/process-manager.ts +3 -1
- package/src/daemon/app-source-watcher.ts +93 -0
- package/src/daemon/config-watcher.ts +79 -1
- package/src/daemon/context-overflow-reducer.ts +46 -2
- package/src/daemon/conversation-agent-loop-handlers.ts +143 -82
- package/src/daemon/conversation-agent-loop.ts +236 -108
- package/src/daemon/conversation-error.ts +31 -8
- package/src/daemon/conversation-history.ts +4 -19
- package/src/daemon/conversation-lifecycle.ts +36 -9
- package/src/daemon/conversation-media-retry.ts +85 -7
- package/src/daemon/conversation-notifiers.ts +4 -1
- package/src/daemon/conversation-process.ts +13 -7
- package/src/daemon/conversation-runtime-assembly.ts +305 -306
- package/src/daemon/conversation-tool-setup.ts +44 -14
- package/src/daemon/conversation-workspace.ts +1 -2
- package/src/daemon/conversation.ts +59 -2
- package/src/daemon/daemon-control.ts +8 -2
- package/src/daemon/date-context.ts +26 -53
- package/src/daemon/first-greeting.ts +1 -1
- package/src/daemon/handlers/conversations.ts +4 -7
- package/src/daemon/handlers/shared.test.ts +143 -0
- package/src/daemon/handlers/shared.ts +85 -17
- package/src/daemon/handlers/skills.ts +416 -209
- package/src/daemon/lifecycle.ts +212 -131
- package/src/daemon/main.ts +5 -1
- package/src/daemon/message-types/conversations.ts +29 -7
- package/src/daemon/message-types/messages.ts +12 -2
- package/src/daemon/message-types/schedules.ts +1 -0
- package/src/daemon/message-types/settings.ts +6 -0
- package/src/daemon/message-types/skills.ts +97 -36
- package/src/daemon/profiler-run-store.ts +557 -0
- package/src/daemon/providers-setup.ts +5 -0
- package/src/daemon/server.ts +100 -11
- package/src/daemon/shutdown-handlers.ts +5 -0
- package/src/daemon/tool-side-effects.ts +50 -8
- package/src/export/transcript-formatter.ts +148 -0
- package/src/filing/filing-service.ts +228 -0
- package/src/heartbeat/heartbeat-service.ts +97 -7
- package/src/hooks/cli.ts +2 -2
- package/src/hooks/runner.ts +15 -38
- package/src/inbound/platform-callback-registration.ts +14 -14
- package/src/mcp/client.ts +6 -0
- package/src/mcp/mcp-oauth-provider.ts +149 -27
- package/src/memory/admin.ts +42 -75
- package/src/memory/app-store.ts +69 -0
- package/src/memory/conversation-bootstrap.ts +3 -1
- package/src/memory/conversation-crud.ts +211 -288
- package/src/memory/conversation-group-migration.ts +157 -0
- package/src/memory/conversation-queries.ts +61 -13
- package/src/memory/conversation-title-service.ts +1 -0
- package/src/memory/db-init.ts +194 -361
- package/src/memory/embed.ts +73 -0
- package/src/memory/embedding-backend.ts +8 -14
- package/src/memory/embedding-runtime-manager.ts +12 -114
- package/src/memory/fingerprint.ts +2 -2
- package/src/memory/graph/bootstrap.ts +521 -0
- package/src/memory/graph/capability-seed.ts +449 -0
- package/src/memory/graph/consolidation.ts +725 -0
- package/src/memory/graph/conversation-graph-memory.ts +659 -0
- package/src/memory/graph/decay.test.ts +208 -0
- package/src/memory/graph/decay.ts +195 -0
- package/src/memory/graph/extraction-job.ts +74 -0
- package/src/memory/graph/extraction.test.ts +936 -0
- package/src/memory/graph/extraction.ts +1297 -0
- package/src/memory/graph/graph-memory-state-store.ts +37 -0
- package/src/memory/graph/graph-search.ts +280 -0
- package/src/memory/graph/image-ref-utils.ts +29 -0
- package/src/memory/graph/injection.test.ts +513 -0
- package/src/memory/graph/injection.ts +469 -0
- package/src/memory/graph/inspect.ts +543 -0
- package/src/memory/graph/narrative.ts +267 -0
- package/src/memory/graph/pattern-scan.ts +269 -0
- package/src/memory/graph/retriever.ts +1111 -0
- package/src/memory/graph/scoring.test.ts +548 -0
- package/src/memory/graph/scoring.ts +232 -0
- package/src/memory/graph/serendipity.ts +65 -0
- package/src/memory/graph/store.test.ts +1098 -0
- package/src/memory/graph/store.ts +838 -0
- package/src/memory/graph/tool-handlers.ts +301 -0
- package/src/memory/graph/tools.ts +97 -0
- package/src/memory/graph/triggers.test.ts +487 -0
- package/src/memory/graph/triggers.ts +223 -0
- package/src/memory/graph/types.ts +295 -0
- package/src/memory/group-crud.ts +191 -0
- package/src/memory/indexer.ts +37 -19
- package/src/memory/job-handlers/cleanup.ts +32 -42
- package/src/memory/job-handlers/conversation-starters.ts +91 -53
- package/src/memory/job-handlers/embedding.ts +5 -31
- package/src/memory/job-handlers/index-maintenance.ts +23 -11
- package/src/memory/job-handlers/summarization.ts +32 -17
- package/src/memory/job-utils.ts +1 -1
- package/src/memory/jobs-store.ts +21 -31
- package/src/memory/jobs-worker.ts +180 -129
- package/src/memory/llm-request-log-store.ts +96 -12
- package/src/memory/memory-recall-log-store.ts +49 -5
- package/src/memory/message-content.ts +1 -0
- package/src/memory/migrations/202-memory-graph-tables.ts +130 -0
- package/src/memory/migrations/203-drop-memory-items-tables.ts +55 -0
- package/src/memory/migrations/204-rename-memory-graph-type-values.ts +46 -0
- package/src/memory/migrations/205-memory-graph-image-refs.ts +11 -0
- package/src/memory/migrations/206-memory-graph-node-edits.ts +19 -0
- package/src/memory/migrations/206-scrub-corrupted-image-attachments.ts +131 -0
- package/src/memory/migrations/207-conversation-graph-memory-state.ts +20 -0
- package/src/memory/migrations/208-conversations-last-message-at.ts +35 -0
- package/src/memory/migrations/209-strip-thinking-from-consolidated.ts +85 -0
- package/src/memory/migrations/210-schedule-reuse-conversation.ts +13 -0
- package/src/memory/migrations/211-memory-recall-logs-query-context.ts +21 -0
- package/src/memory/migrations/212-llm-request-logs-created-at-index.ts +19 -0
- package/src/memory/migrations/index.ts +12 -0
- package/src/memory/migrations/registry.ts +16 -0
- package/src/memory/qdrant-client.ts +44 -17
- package/src/memory/schema/conversations.ts +14 -0
- package/src/memory/schema/index.ts +1 -0
- package/src/memory/schema/infrastructure.ts +8 -1
- package/src/memory/schema/memory-core.ts +0 -51
- package/src/memory/schema/memory-graph.ts +154 -0
- package/src/memory/search/semantic.ts +47 -91
- package/src/memory/task-memory-cleanup.ts +58 -61
- package/src/messaging/providers/outlook/adapter.ts +8 -1
- package/src/messaging/providers/outlook/client.ts +299 -0
- package/src/messaging/providers/outlook/types.ts +118 -0
- package/src/notifications/adapters/macos.ts +1 -0
- package/src/notifications/copy-composer.ts +95 -0
- package/src/notifications/decision-engine.ts +35 -0
- package/src/notifications/signal.ts +16 -0
- package/src/oauth/seed-providers.ts +2 -1
- package/src/permissions/checker.ts +36 -4
- package/src/permissions/defaults.ts +4 -4
- package/src/permissions/permission-mode-store.ts +180 -0
- package/src/permissions/permission-mode.ts +31 -0
- package/src/permissions/workspace-policy.ts +10 -1
- package/src/playbooks/playbook-compiler.ts +19 -18
- package/src/playbooks/types.ts +4 -3
- package/src/prompts/system-prompt.ts +62 -36
- package/src/prompts/templates/BOOTSTRAP-REFERENCE.md +100 -0
- package/src/prompts/templates/BOOTSTRAP.md +70 -165
- package/src/prompts/templates/HEARTBEAT.md +3 -1
- package/src/prompts/templates/SOUL.md +25 -4
- package/src/prompts/templates/UPDATES.md +8 -0
- package/src/providers/anthropic/client.ts +136 -220
- package/src/providers/gemini/client.ts +1 -1
- package/src/providers/openai/client.ts +1 -1
- package/src/providers/registry.ts +1 -1
- package/src/providers/retry.ts +19 -3
- package/src/runtime/actor-trust-resolver.ts +5 -1
- package/src/runtime/auth/route-policy.ts +30 -0
- package/src/runtime/guardian-reply-router.ts +5 -1
- package/src/runtime/http-server.ts +55 -5
- package/src/runtime/http-types.ts +12 -1
- package/src/runtime/middleware/auth.ts +20 -0
- package/src/runtime/migrations/vbundle-builder.ts +389 -3
- package/src/runtime/migrations/vbundle-importer.ts +8 -6
- package/src/runtime/routes/__tests__/user-route-dispatcher.test.ts +378 -0
- package/src/runtime/routes/app-management-routes.ts +1 -11
- package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +26 -0
- package/src/runtime/routes/archive-utils.ts +29 -0
- package/src/runtime/routes/attachment-routes.test.ts +106 -0
- package/src/runtime/routes/attachment-routes.ts +106 -16
- package/src/runtime/routes/avatar-routes.ts +2 -9
- package/src/runtime/routes/brain-graph-routes.ts +21 -22
- package/src/runtime/routes/btw-routes.ts +22 -1
- package/src/runtime/routes/conversation-analysis-routes.ts +173 -0
- package/src/runtime/routes/conversation-management-routes.ts +3 -14
- package/src/runtime/routes/conversation-query-routes.ts +49 -3
- package/src/runtime/routes/conversation-routes.ts +264 -44
- package/src/runtime/routes/conversation-starter-routes.ts +2 -2
- package/src/runtime/routes/debug-routes.ts +1 -1
- package/src/runtime/routes/global-search-routes.ts +21 -19
- package/src/runtime/routes/group-routes.ts +207 -0
- package/src/runtime/routes/guardian-action-routes.ts +21 -10
- package/src/runtime/routes/guardian-bootstrap-routes.ts +23 -19
- package/src/runtime/routes/heartbeat-routes.ts +4 -10
- package/src/runtime/routes/identity-routes.ts +53 -18
- package/src/runtime/routes/inbound-message-handler.ts +19 -0
- package/src/runtime/routes/inbound-stages/guardian-activation-intercept.test.ts +292 -0
- package/src/runtime/routes/inbound-stages/guardian-activation-intercept.ts +207 -0
- package/src/runtime/routes/llm-context-normalization.ts +14 -10
- package/src/runtime/routes/log-export-routes.ts +23 -275
- package/src/runtime/routes/memory-item-routes.test.ts +170 -247
- package/src/runtime/routes/memory-item-routes.ts +341 -388
- package/src/runtime/routes/migration-routes.ts +18 -7
- package/src/runtime/routes/profiler-routes.ts +350 -0
- package/src/runtime/routes/schedule-routes.ts +28 -11
- package/src/runtime/routes/settings-routes.ts +95 -8
- package/src/runtime/routes/skills-routes.ts +103 -37
- package/src/runtime/routes/subagents-routes.ts +28 -7
- package/src/runtime/routes/user-route-dispatcher.ts +223 -0
- package/src/runtime/routes/user-routes.ts +41 -0
- package/src/runtime/routes/work-items-routes.test.ts +2 -6
- package/src/runtime/routes/workspace-routes.ts +0 -1
- package/src/schedule/schedule-store.ts +30 -0
- package/src/schedule/scheduler.ts +52 -18
- package/src/security/oauth2.ts +1 -1
- package/src/security/secure-keys.ts +4 -8
- package/src/shared/provider-env-vars.ts +19 -0
- package/src/skills/catalog-cache.ts +5 -0
- package/src/skills/catalog-install.ts +25 -16
- package/src/skills/clawhub.ts +134 -154
- package/src/skills/install-meta.ts +208 -0
- package/src/skills/managed-store.ts +29 -18
- package/src/skills/skill-memory.ts +12 -229
- package/src/skills/skillssh-registry.ts +19 -17
- package/src/subagent/index.ts +13 -3
- package/src/subagent/manager.ts +308 -29
- package/src/subagent/types.ts +68 -0
- package/src/tasks/task-runner.ts +7 -5
- package/src/telemetry/usage-telemetry-reporter.test.ts +3 -5
- package/src/tools/apps/executors.ts +29 -4
- package/src/tools/browser/runtime-check.ts +3 -1
- package/src/tools/filesystem/list.ts +93 -0
- package/src/tools/memory/register.ts +63 -46
- package/src/tools/permission-checker.ts +85 -1
- package/src/tools/registry.ts +4 -0
- package/src/tools/schedule/create.ts +3 -0
- package/src/tools/schedule/list.ts +1 -0
- package/src/tools/schedule/update.ts +6 -0
- package/src/tools/shared/filesystem/errors.ts +5 -0
- package/src/tools/shared/filesystem/file-ops-service.ts +90 -2
- package/src/tools/shared/filesystem/image-read.ts +22 -85
- package/src/tools/shared/filesystem/types.ts +17 -0
- package/src/tools/shared/shell-output.ts +31 -2
- package/src/tools/subagent/abort.ts +12 -2
- package/src/tools/subagent/message.ts +9 -2
- package/src/tools/subagent/notify-parent.ts +79 -0
- package/src/tools/subagent/read.ts +29 -8
- package/src/tools/subagent/resolve.ts +21 -0
- package/src/tools/subagent/spawn.ts +2 -0
- package/src/tools/subagent/status.ts +11 -1
- package/src/tools/system/avatar-generator.ts +3 -3
- package/src/tools/system/register.ts +23 -0
- package/src/tools/system/set-permission-mode.ts +103 -0
- package/src/tools/terminal/parser.ts +30 -5
- package/src/tools/terminal/safe-env.ts +17 -1
- package/src/tools/tool-manifest.ts +9 -3
- package/src/tools/types.ts +2 -0
- package/src/util/browser.ts +25 -10
- package/src/util/bun-runtime.ts +172 -0
- package/src/util/logger.ts +1 -1
- package/src/util/platform.ts +50 -17
- package/src/watcher/providers/outlook-calendar.ts +343 -0
- package/src/watcher/providers/outlook.ts +198 -0
- package/src/workspace/migrations/023-move-config-files-to-workspace.ts +2 -2
- package/src/workspace/migrations/024-move-runtime-files-to-workspace.ts +2 -2
- package/src/workspace/migrations/025-remove-oauth-app-setup-skills.ts +76 -0
- package/src/workspace/migrations/026-backfill-install-meta.ts +325 -0
- package/src/workspace/migrations/027-remove-orphaned-optimized-images-cache.ts +42 -0
- package/src/workspace/migrations/028-recover-conversations-from-disk-view.ts +270 -0
- package/src/workspace/migrations/029-seed-pkb.ts +84 -0
- package/src/workspace/migrations/registry.ts +10 -0
- package/src/workspace/top-level-renderer.ts +5 -9
- package/src/__tests__/cli-memory.test.ts +0 -372
- package/src/__tests__/clipboard.test.ts +0 -88
- package/src/__tests__/context-memory-e2e.test.ts +0 -415
- package/src/__tests__/journal-context.test.ts +0 -268
- package/src/__tests__/memory-context-benchmark.benchmark.test.ts +0 -297
- package/src/__tests__/memory-lifecycle-e2e.test.ts +0 -459
- package/src/__tests__/memory-query-builder.test.ts +0 -59
- package/src/__tests__/memory-recall-quality.test.ts +0 -1046
- package/src/__tests__/memory-regressions.experimental.test.ts +0 -629
- package/src/__tests__/memory-regressions.test.ts +0 -3696
- package/src/__tests__/memory-retrieval.benchmark.test.ts +0 -295
- package/src/cli/cli-memory.ts +0 -176
- package/src/daemon/conversation-memory.ts +0 -207
- package/src/memory/conversation-starters-cadence.ts +0 -74
- package/src/memory/items-extractor.ts +0 -860
- package/src/memory/job-handlers/batch-extraction.ts +0 -753
- package/src/memory/job-handlers/extraction.ts +0 -40
- package/src/memory/job-handlers/journal-carry-forward.test.ts +0 -355
- package/src/memory/job-handlers/journal-carry-forward.ts +0 -255
- package/src/memory/journal-memory.ts +0 -224
- package/src/memory/query-builder.ts +0 -47
- package/src/memory/query-expansion.ts +0 -83
- package/src/memory/retriever.test.ts +0 -1592
- package/src/memory/retriever.ts +0 -1331
- package/src/memory/search/formatting.test.ts +0 -140
- package/src/memory/search/formatting.ts +0 -262
- package/src/memory/search/mmr.ts +0 -139
- package/src/memory/search/ranking.ts +0 -15
- package/src/memory/search/staleness.ts +0 -40
- package/src/memory/search/tier-classifier.ts +0 -18
- package/src/memory/search/types.ts +0 -121
- package/src/prompts/journal-context.ts +0 -154
- package/src/tools/memory/definitions.ts +0 -69
- package/src/tools/memory/handlers.test.ts +0 -562
- package/src/tools/memory/handlers.ts +0 -434
- package/src/util/clipboard.ts +0 -34
|
@@ -238,7 +238,7 @@ export const Header: FunctionComponent<HeaderProps> = ({ title, count }) => (
|
|
|
238
238
|
|
|
239
239
|
file_write("{workspaceDir}/data/apps/project-tracker/src/styles.css", `.app { padding: var(--v-spacing-lg); }
|
|
240
240
|
.header { display: flex; justify-content: space-between; align-items: center; }
|
|
241
|
-
.badge { background: var(--v-accent); color: white; padding: var(--v-spacing-xs) var(--v-spacing-sm); border-radius: var(--v-radius-pill); }`)
|
|
241
|
+
.badge { background: var(--v-accent); color: var(--v-aux-white); padding: var(--v-spacing-xs) var(--v-spacing-sm); border-radius: var(--v-radius-pill); }`)
|
|
242
242
|
|
|
243
243
|
# After all files are written, compile and refresh:
|
|
244
244
|
app_refresh(app_id)
|
|
@@ -290,9 +290,12 @@ Available design tokens:
|
|
|
290
290
|
| **Typography** | `--v-font-family`, `--v-font-mono`, `--v-font-size-xs` (10px) / `-sm` (11px) / `-base` (14px) / `-lg` (17px) / `-xl` (22px) / `-2xl` (26px), `--v-line-height` |
|
|
291
291
|
| **Animation** | `--v-duration-fast` (0.15s) / `-standard` (0.25s) / `-slow` (0.4s) |
|
|
292
292
|
| **Palettes** | `--v-slate-{950..50}`, `--v-emerald-*`, `--v-violet-*`, `--v-indigo-*`, `--v-rose-*`, `--v-amber-*` |
|
|
293
|
+
| **Constant** | `--v-aux-white` (always `#FFFFFF` in both modes — use for text on filled/accent backgrounds) |
|
|
293
294
|
|
|
294
295
|
Utility classes: `.v-button` (`.secondary`/`.danger`/`.ghost`), `.v-card`, `.v-list`/`.v-list-item`, `.v-badge` (`.success`/`.warning`/`.danger`), `.v-input-row`, `.v-empty-state`, `.v-toggle`.
|
|
295
296
|
|
|
297
|
+
**Never hardcode `color: white` or `color: #fff`.** Use `var(--v-aux-white)` for text on filled/accent backgrounds, or `var(--v-text)` / `var(--v-text-secondary)` for text on surface backgrounds. Hardcoded white causes invisible text on light surfaces.
|
|
298
|
+
|
|
296
299
|
**Custom themes:** When the user wants a specific branded look, write complete CSS with hardcoded colors and `@media (prefers-color-scheme: dark)` for dark variants. Don't mix `--v-*` auto-switching variables with hardcoded colors in the same element.
|
|
297
300
|
|
|
298
301
|
**Theme detection in JavaScript:**
|
|
@@ -6,7 +6,6 @@ metadata:
|
|
|
6
6
|
emoji: "👥"
|
|
7
7
|
vellum:
|
|
8
8
|
display-name: "Contacts"
|
|
9
|
-
feature-flag: "contacts"
|
|
10
9
|
---
|
|
11
10
|
|
|
12
11
|
Manage the user's contacts, relationship graph, access control (trusted contacts), and invite links. This skill covers contact CRUD with multi-channel tracking, controlling who can message the assistant through external channels (Telegram, phone), and creating/managing invite links that grant access.
|
|
@@ -47,14 +47,6 @@
|
|
|
47
47
|
"is_primary": {
|
|
48
48
|
"type": "boolean",
|
|
49
49
|
"description": "Whether this is the primary channel for this type"
|
|
50
|
-
},
|
|
51
|
-
"external_user_id": {
|
|
52
|
-
"type": "string",
|
|
53
|
-
"description": "Platform-native user ID (e.g. Slack user ID like U12345). Used to cache user lookups."
|
|
54
|
-
},
|
|
55
|
-
"external_chat_id": {
|
|
56
|
-
"type": "string",
|
|
57
|
-
"description": "Platform-native chat/DM channel ID (e.g. Slack DM channel like D12345). Used to cache DM channel lookups."
|
|
58
50
|
}
|
|
59
51
|
},
|
|
60
52
|
"required": ["type", "address"]
|
|
@@ -63,16 +63,12 @@ export async function executeContactUpsert(
|
|
|
63
63
|
type: string;
|
|
64
64
|
address: string;
|
|
65
65
|
is_primary?: boolean;
|
|
66
|
-
external_user_id?: string;
|
|
67
|
-
external_chat_id?: string;
|
|
68
66
|
}>
|
|
69
67
|
| undefined;
|
|
70
68
|
const channels = rawChannels?.map((ch) => ({
|
|
71
69
|
type: ch.type,
|
|
72
70
|
address: ch.address,
|
|
73
71
|
isPrimary: ch.is_primary,
|
|
74
|
-
externalUserId: ch.external_user_id,
|
|
75
|
-
externalChatId: ch.external_chat_id,
|
|
76
72
|
}));
|
|
77
73
|
|
|
78
74
|
try {
|
|
@@ -28,22 +28,14 @@ Do not offer AgentMail as an option or mention it unless the user specifically a
|
|
|
28
28
|
### Gmail
|
|
29
29
|
|
|
30
30
|
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.
|
|
31
|
-
2. **If no connections are found:**
|
|
32
|
-
- Call `skill_load` with `skill: "vellum-oauth-integrations"` with `provider-key: google` throughout.
|
|
33
|
-
- To use `your-own` mode, you will need to call `skill_load` with `skill: google-oauth-app-setup`. In this case:
|
|
34
|
-
- 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:
|
|
35
|
-
- **message:** "Ready to set up Gmail?"
|
|
36
|
-
- **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."
|
|
37
|
-
- **confirmLabel:** "Get Started"
|
|
38
|
-
- **cancelLabel:** "Not Now"
|
|
39
|
-
- 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.
|
|
31
|
+
2. **If no connections are found:** Call `skill_load` with `skill: "vellum-oauth-integrations"`. The skill will evaluate whether managed or your-own mode is appropriate and guide the user accordingly.
|
|
40
32
|
|
|
41
33
|
## Error Recovery
|
|
42
34
|
|
|
43
35
|
When a Gmail tool fails with a token or authorization error:
|
|
44
36
|
|
|
45
37
|
1. **Try to reconnect silently.** Call `assistant oauth ping google`. This often resolves expired tokens automatically.
|
|
46
|
-
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
|
|
38
|
+
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 load **vellum-oauth-integrations**. The user came to you to get something done, not to troubleshoot OAuth - make it seamless.
|
|
47
39
|
3. **Never try alternative approaches.** Don't use bash, curl, browser automation, or any workaround. If the Gmail tools can't do it, the reconnection flow is the answer.
|
|
48
40
|
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.
|
|
49
41
|
|
|
@@ -164,9 +156,9 @@ Scan tools (`gmail_sender_digest`, `gmail_outreach_scan`) return a `scan_id` tha
|
|
|
164
156
|
|
|
165
157
|
Before composing any email that references a date or time:
|
|
166
158
|
|
|
167
|
-
1. Check the
|
|
159
|
+
1. Check the `timestamp:` field in the `<turn_context>` block for today's date and timezone
|
|
168
160
|
2. Verify that "tomorrow" means the day after today's date, "next week" means the upcoming Monday–Friday, etc.
|
|
169
|
-
3. If the email references a date from another message, cross-check it against the
|
|
161
|
+
3. If the email references a date from another message, cross-check it against the turn context to ensure it's in the future
|
|
170
162
|
|
|
171
163
|
## Confidence Scores
|
|
172
164
|
|
|
@@ -15,15 +15,7 @@ You are a Google Calendar assistant with full access to the user's calendar. Use
|
|
|
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
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:**
|
|
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.
|
|
18
|
+
2. **If no connections are found:** Call `skill_load` with `skill: "vellum-oauth-integrations"`. The skill will evaluate whether managed or your-own mode is appropriate and guide the user accordingly.
|
|
27
19
|
|
|
28
20
|
## Capabilities
|
|
29
21
|
|
|
@@ -19,13 +19,13 @@ You are a unified messaging assistant with access to multiple platforms (Gmail,
|
|
|
19
19
|
|
|
20
20
|
When composing messages on behalf of your user to external recipients, refer to yourself as an "assistant" (not "AI assistant"). Use your user's name and pronouns from USER.md. Don't volunteer that you are an AI unless directly asked.
|
|
21
21
|
|
|
22
|
-
For
|
|
22
|
+
For Email management (archive, label, triage, declutter), load the **gmail** or **outlook** skill. For email sequences, load the **sequences** skill.
|
|
23
23
|
|
|
24
24
|
## Email Routing Priority
|
|
25
25
|
|
|
26
|
-
When the user mentions "email" - sending, reading, checking, decluttering, drafting, or anything else - **always default to the user's own email
|
|
26
|
+
When the user mentions "email" - sending, reading, checking, decluttering, drafting, or anything else - **always default to the user's own email** unless they explicitly ask about the assistant's own email address (e.g., "set up your email", "send from your address", "check your inbox"). The vast majority of email requests are about the user's Gmail or Outlook, not the assistant's AgentMail address.
|
|
27
27
|
|
|
28
|
-
Do not offer AgentMail as an option or mention it unless the user specifically asks. If Gmail
|
|
28
|
+
Do not offer AgentMail as an option or mention it unless the user specifically asks. If Gmail and Outlookk are not connected, guide them through setup - do not suggest AgentMail as an alternative.
|
|
29
29
|
|
|
30
30
|
## Communication Style
|
|
31
31
|
|
|
@@ -44,33 +44,25 @@ Before using any messaging tool, verify that the platform is connected by callin
|
|
|
44
44
|
|
|
45
45
|
### Public Ingress (required for Telegram)
|
|
46
46
|
|
|
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 `
|
|
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 `isPlatform: 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/Outlook on the desktop app uses a loopback callback and does not require public ingress; the channel path (Path B in the vellum-oauth-integrations skill) handles public ingress internally when needed.
|
|
48
48
|
|
|
49
49
|
### Email Connection Flow
|
|
50
50
|
|
|
51
51
|
When the user asks to "connect my email", "set up email", "manage my email", or similar - and has not named a specific provider:
|
|
52
52
|
|
|
53
|
-
1. **Discover what's connected.** Call `messaging_auth_test` for `gmail` (and any other email-capable platforms). If one succeeds, tell the user it's already connected and proceed with their request.
|
|
53
|
+
1. **Discover what's connected.** Call `messaging_auth_test` for `gmail`or `outlook` (and any other email-capable platforms). If one succeeds, tell the user it's already connected and proceed with their request.
|
|
54
54
|
2. **If nothing is connected**, ask which provider they use - but keep it brief and conversational (e.g., "Which email do you use - Gmail, Outlook, etc.?"), not a numbered list of options with descriptions.
|
|
55
|
-
3. **Once the provider is known, act immediately.** Don't present setup options or explain OAuth. If it's Gmail, follow the
|
|
55
|
+
3. **Once the provider is known, act immediately.** Don't present setup options or explain OAuth. If it's Gmail or Outlook, follow the sections below. For any other provider, let the user know that only Gmail and Outlook are fully supported right now, and offer to set up Gmail/Outlook instead.
|
|
56
56
|
|
|
57
57
|
### Gmail
|
|
58
58
|
|
|
59
59
|
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.
|
|
60
|
-
2. **If no connections are found:**
|
|
61
|
-
- Call `skill_load` with `skill: "vellum-oauth-integrations"` with `provider-key: google` throughout.
|
|
62
|
-
- To use `your-own` mode, you will need to call `skill_load` with `skill: google-oauth-app-setup`. In this case:
|
|
63
|
-
- 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:
|
|
64
|
-
- **message:** "Ready to set up Gmail?"
|
|
65
|
-
- **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."
|
|
66
|
-
- **confirmLabel:** "Get Started"
|
|
67
|
-
- **cancelLabel:** "Not Now"
|
|
68
|
-
- 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.
|
|
60
|
+
2. **If no connections are found:** Call `skill_load` with `skill: "vellum-oauth-integrations"`. The skill will evaluate whether managed or your-own mode is appropriate and guide the user accordingly.
|
|
69
61
|
|
|
70
62
|
### Outlook
|
|
71
63
|
|
|
72
64
|
1. **Try connecting directly first.** Run `assistant oauth status outlook`. This will show whether the user has previously connected their Outlook account.
|
|
73
|
-
2. **If no connections are found:**
|
|
65
|
+
2. **If no connections are found:** Call `skill_load` with `skill: "vellum-oauth-integrations"`. The skill will evaluate whether managed or your-own mode is appropriate and guide the user accordingly.
|
|
74
66
|
|
|
75
67
|
### Slack
|
|
76
68
|
|
|
@@ -101,7 +93,7 @@ The guardian-verify-setup skill handles the full outbound verification flow for
|
|
|
101
93
|
When a messaging tool fails with a token or authorization error:
|
|
102
94
|
|
|
103
95
|
1. **Try to reconnect silently.** Run `assistant oauth ping <provider>`. This often resolves expired tokens automatically.
|
|
104
|
-
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
|
|
96
|
+
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 load **vellum-oauth-integrations**. The user came to you to get something done, not to troubleshoot OAuth - make it seamless.
|
|
105
97
|
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.
|
|
106
98
|
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.
|
|
107
99
|
|
|
@@ -114,7 +106,7 @@ When a messaging tool fails with a token or authorization error:
|
|
|
114
106
|
|
|
115
107
|
## Capabilities
|
|
116
108
|
|
|
117
|
-
###
|
|
109
|
+
### Gmail
|
|
118
110
|
|
|
119
111
|
- **Auth Test**: Verify connection and show account info
|
|
120
112
|
- **List Conversations**: Show inboxes, DMs with unread counts
|
|
@@ -156,6 +148,7 @@ Telegram is supported as a messaging provider with limited capabilities compared
|
|
|
156
148
|
- `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").
|
|
157
149
|
- Use `messaging_send` when the user asks to send a message into a specific chat/email destination.
|
|
158
150
|
- `send_notification` channel routing is LLM-driven; `preferred_channels` are hints, not hard channel forcing.
|
|
151
|
+
- Before using `messaging_send` or `send_notification`, look up the recipient's contact record with `contact_search` to inform tone and content (see **Recipient Context** below).
|
|
159
152
|
|
|
160
153
|
## Personalized Drafting
|
|
161
154
|
|
|
@@ -165,6 +158,12 @@ If no style items exist and the user asks you to draft a message, suggest runnin
|
|
|
165
158
|
|
|
166
159
|
> "I can analyze your sent messages to learn your writing style so drafts sound like you. Want me to do that?"
|
|
167
160
|
|
|
161
|
+
## Recipient Context
|
|
162
|
+
|
|
163
|
+
Before composing or sending a message to someone, look up their contact record with `contact_search` using their name or channel address. If the contact has notes (e.g. relationship context, communication preferences, response expectations), use that context to inform the message's tone, level of detail, and content. This ensures outbound messages are personalized to the recipient — not just the sender's style.
|
|
164
|
+
|
|
165
|
+
If no contact record exists, proceed without recipient context.
|
|
166
|
+
|
|
168
167
|
## Confidence Scores
|
|
169
168
|
|
|
170
169
|
Medium and high risk tools require a confidence score between 0 and 1:
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import { and, eq } from "drizzle-orm";
|
|
1
|
+
import { and, eq, sql } from "drizzle-orm";
|
|
2
2
|
import { v4 as uuid } from "uuid";
|
|
3
3
|
|
|
4
4
|
import { getDb } from "../../../../memory/db.js";
|
|
5
|
-
import { computeMemoryFingerprint } from "../../../../memory/fingerprint.js";
|
|
6
5
|
import { enqueueMemoryJob } from "../../../../memory/jobs-store.js";
|
|
7
|
-
import {
|
|
6
|
+
import { memoryGraphNodes } from "../../../../memory/schema.js";
|
|
8
7
|
import { clampUnitInterval } from "../../../../memory/validation.js";
|
|
9
8
|
import { extractStylePatterns } from "../../../../messaging/style-analyzer.js";
|
|
10
9
|
import type {
|
|
@@ -14,6 +13,12 @@ import type {
|
|
|
14
13
|
import { truncate } from "../../../../util/truncate.js";
|
|
15
14
|
import { err, getProviderConnection, ok, resolveProvider } from "./shared.js";
|
|
16
15
|
|
|
16
|
+
/** Map legacy caller kinds to valid MemoryType values. */
|
|
17
|
+
const KIND_TO_MEMORY_TYPE: Record<string, string> = {
|
|
18
|
+
style: "behavioral",
|
|
19
|
+
relationship: "semantic",
|
|
20
|
+
};
|
|
21
|
+
|
|
17
22
|
function upsertMemoryItem(opts: {
|
|
18
23
|
kind: string;
|
|
19
24
|
subject: string;
|
|
@@ -23,58 +28,60 @@ function upsertMemoryItem(opts: {
|
|
|
23
28
|
}): void {
|
|
24
29
|
const db = getDb();
|
|
25
30
|
const now = Date.now();
|
|
26
|
-
const
|
|
27
|
-
opts.scopeId,
|
|
28
|
-
opts.kind,
|
|
29
|
-
opts.subject,
|
|
30
|
-
opts.statement,
|
|
31
|
-
);
|
|
31
|
+
const content = `${opts.subject}\n${opts.statement}`;
|
|
32
32
|
|
|
33
33
|
const existing = db
|
|
34
34
|
.select()
|
|
35
|
-
.from(
|
|
35
|
+
.from(memoryGraphNodes)
|
|
36
36
|
.where(
|
|
37
37
|
and(
|
|
38
|
-
eq(
|
|
39
|
-
eq(
|
|
38
|
+
eq(memoryGraphNodes.content, content),
|
|
39
|
+
eq(memoryGraphNodes.scopeId, opts.scopeId),
|
|
40
|
+
sql`${memoryGraphNodes.fidelity} != 'gone'`,
|
|
40
41
|
),
|
|
41
42
|
)
|
|
42
43
|
.get();
|
|
43
44
|
|
|
44
45
|
if (existing) {
|
|
45
|
-
db.update(
|
|
46
|
+
db.update(memoryGraphNodes)
|
|
46
47
|
.set({
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
48
|
+
content,
|
|
49
|
+
type: KIND_TO_MEMORY_TYPE[opts.kind] ?? opts.kind,
|
|
50
|
+
fidelity: "vivid",
|
|
51
|
+
significance: clampUnitInterval(
|
|
52
|
+
Math.max(existing.significance ?? 0, opts.importance),
|
|
51
53
|
),
|
|
52
|
-
|
|
53
|
-
sourceType: existing.sourceType === "
|
|
54
|
+
lastAccessed: now,
|
|
55
|
+
sourceType: existing.sourceType === "direct" ? "direct" : "inferred",
|
|
54
56
|
})
|
|
55
|
-
.where(eq(
|
|
57
|
+
.where(eq(memoryGraphNodes.id, existing.id))
|
|
56
58
|
.run();
|
|
57
|
-
enqueueMemoryJob("
|
|
59
|
+
enqueueMemoryJob("embed_graph_node", { nodeId: existing.id });
|
|
58
60
|
} else {
|
|
59
61
|
const id = uuid();
|
|
60
|
-
db.insert(
|
|
62
|
+
db.insert(memoryGraphNodes)
|
|
61
63
|
.values({
|
|
62
64
|
id,
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
65
|
+
content,
|
|
66
|
+
type: KIND_TO_MEMORY_TYPE[opts.kind] ?? opts.kind,
|
|
67
|
+
created: now,
|
|
68
|
+
lastAccessed: now,
|
|
69
|
+
lastConsolidated: now,
|
|
70
|
+
emotionalCharge: '{"valence":0,"intensity":0.1,"decayCurve":"linear","decayRate":0.05,"originalIntensity":0.1}',
|
|
71
|
+
fidelity: "vivid",
|
|
67
72
|
confidence: 0.8,
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
73
|
+
significance: clampUnitInterval(opts.importance),
|
|
74
|
+
stability: 14,
|
|
75
|
+
reinforcementCount: 0,
|
|
76
|
+
lastReinforced: now,
|
|
77
|
+
sourceConversations: "[]",
|
|
78
|
+
sourceType: "inferred",
|
|
79
|
+
narrativeRole: null,
|
|
80
|
+
partOfStory: null,
|
|
71
81
|
scopeId: opts.scopeId,
|
|
72
|
-
firstSeenAt: now,
|
|
73
|
-
lastSeenAt: now,
|
|
74
|
-
lastUsedAt: null,
|
|
75
82
|
})
|
|
76
83
|
.run();
|
|
77
|
-
enqueueMemoryJob("
|
|
84
|
+
enqueueMemoryJob("embed_graph_node", { nodeId: id });
|
|
78
85
|
}
|
|
79
86
|
}
|
|
80
87
|
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: outlook
|
|
3
|
+
description: Archive, categorize, draft, unsubscribe, and manage Outlook email
|
|
4
|
+
compatibility: "Designed for Vellum personal assistants"
|
|
5
|
+
metadata:
|
|
6
|
+
emoji: "\U0001F4E7"
|
|
7
|
+
vellum:
|
|
8
|
+
display-name: "Outlook"
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
This skill provides Outlook-specific tools beyond the shared **messaging** skill. For cross-platform messaging (send, read, search, reply), use the messaging skill. Outlook tools depend on the messaging skill's provider infrastructure - load messaging first if Outlook is not yet connected.
|
|
12
|
+
|
|
13
|
+
## Tool Reference
|
|
14
|
+
|
|
15
|
+
| Tool | Description |
|
|
16
|
+
| --- | --- |
|
|
17
|
+
| `outlook_attachments` | List and download email attachments |
|
|
18
|
+
| `outlook_trash` | Move messages to Deleted Items |
|
|
19
|
+
| `outlook_categories` | Manage message categories (add, remove, list available) |
|
|
20
|
+
| `outlook_follow_up` | Track messages with Outlook's native flag system |
|
|
21
|
+
| `outlook_draft` | Create email drafts in the Drafts folder (including reply drafts) |
|
|
22
|
+
| `outlook_send_draft` | Send an existing draft (high-risk - requires explicit user confirmation) |
|
|
23
|
+
| `outlook_forward` | Create forward drafts, preserving attachments |
|
|
24
|
+
| `outlook_unsubscribe` | Unsubscribe from mailing lists via List-Unsubscribe header |
|
|
25
|
+
| `outlook_sender_digest` | Scan inbox and group messages by sender for declutter workflows |
|
|
26
|
+
| `outlook_outreach_scan` | Identify cold outreach senders (no List-Unsubscribe header) |
|
|
27
|
+
| `outlook_rules` | Create, list, and delete server-side inbox message rules |
|
|
28
|
+
| `outlook_vacation` | Get, enable, or disable auto-reply (out-of-office) settings |
|
|
29
|
+
|
|
30
|
+
All tools above are Outlook-specific. For shared operations (send, read, search, reply, archive), use `messaging_send`, `messaging_search`, etc. from the messaging skill.
|
|
31
|
+
|
|
32
|
+
## Email Routing Priority
|
|
33
|
+
|
|
34
|
+
When the user mentions "email" - sending, reading, checking, decluttering, drafting, or anything else - **always default to the user's own email (Outlook)** unless they explicitly ask about the assistant's own email address (e.g., "set up your email", "send from your address", "check your inbox"). The vast majority of email requests are about the user's Outlook, not the assistant's AgentMail address.
|
|
35
|
+
|
|
36
|
+
Do not offer AgentMail as an option or mention it unless the user specifically asks. If Outlook is not connected, guide them through Outlook setup - do not suggest AgentMail as an alternative.
|
|
37
|
+
|
|
38
|
+
## Communication Style
|
|
39
|
+
|
|
40
|
+
- **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.
|
|
41
|
+
- **Keep it human.** Never mention OAuth, tokens, APIs, sandboxes, credential proxies, or other technical internals. If something isn't working, say "Outlook needs to be reconnected" - not "the OAuth2 access token for outlook has expired."
|
|
42
|
+
- **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.
|
|
43
|
+
- **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.
|
|
44
|
+
|
|
45
|
+
## Error Recovery
|
|
46
|
+
|
|
47
|
+
When an Outlook tool fails with a token or authorization error:
|
|
48
|
+
|
|
49
|
+
1. **Try to reconnect silently.** Call `assistant oauth ping outlook`. This often resolves expired tokens automatically.
|
|
50
|
+
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., "Outlook needs to be reconnected - let me set that up") and immediately follow the connection setup flow for Outlook. The user came to you to get something done, not to troubleshoot OAuth - make it seamless.
|
|
51
|
+
3. **Never try alternative approaches.** Don't use bash, curl, browser automation, or any workaround. If the Outlook tools can't do it, the reconnection flow is the answer.
|
|
52
|
+
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.
|
|
53
|
+
|
|
54
|
+
## Drafting vs Sending (Outlook)
|
|
55
|
+
|
|
56
|
+
Outlook uses a **draft-first workflow** where appropriate:
|
|
57
|
+
|
|
58
|
+
- `messaging_send` (Outlook) sends messages directly via the Graph API.
|
|
59
|
+
- `outlook_draft` creates a draft in the Outlook Drafts folder for user review before sending.
|
|
60
|
+
- `outlook_forward` creates a forward draft, preserving attachments.
|
|
61
|
+
|
|
62
|
+
When the user asks to "draft" or "compose" an email, use `outlook_draft`. When they say "send", use `messaging_send`. If ambiguous, prefer drafting so the user can review first.
|
|
63
|
+
|
|
64
|
+
## Differences from Gmail
|
|
65
|
+
|
|
66
|
+
Outlook and Gmail have different organizational models. Keep these distinctions in mind:
|
|
67
|
+
|
|
68
|
+
| Concept | Gmail | Outlook |
|
|
69
|
+
| --- | --- | --- |
|
|
70
|
+
| **Organization** | Labels (multiple per message) | Folders (one per message) + Categories (multiple per message) |
|
|
71
|
+
| **Categorization** | Labels serve dual purpose | Categories are color-coded tags independent of folder location |
|
|
72
|
+
| **Follow-up** | Label-based tracking | Native flag system (`flagged`, `complete`, `notFlagged`) |
|
|
73
|
+
| **Inbox rules** | Gmail filters | Outlook inbox rules (server-side) |
|
|
74
|
+
| **Archive** | Remove INBOX label | Move to Archive folder |
|
|
75
|
+
|
|
76
|
+
### Categories
|
|
77
|
+
|
|
78
|
+
Categories are Outlook's tagging system for organizing messages. Unlike Gmail labels, categories are independent of folder structure - a message can be in any folder and have multiple categories. Categories are color-coded (Blue, Green, Orange, Purple, Red, Yellow, or custom names). Use categories to tag and organize messages without moving them between folders.
|
|
79
|
+
|
|
80
|
+
### Follow-up Flags
|
|
81
|
+
|
|
82
|
+
Outlook uses a native flag system for follow-up tracking:
|
|
83
|
+
|
|
84
|
+
- `flagged` - message is marked for follow-up
|
|
85
|
+
- `complete` - follow-up is done
|
|
86
|
+
- `notFlagged` - no follow-up tracking
|
|
87
|
+
|
|
88
|
+
This replaces Gmail's label-based follow-up approach. Use the Outlook flag system directly rather than creating custom folder-based workarounds.
|
|
89
|
+
|
|
90
|
+
### Inbox Rules vs Gmail Filters
|
|
91
|
+
|
|
92
|
+
Outlook inbox rules (`outlook_rules`) run server-side and support conditions like sender, subject, body keywords, and importance level. Actions include moving to folders, categorizing, flagging, forwarding, and deleting. Gmail filters (`gmail_filters`) are similar but use Gmail's query syntax and label-based actions. When a user asks to "filter" or "auto-sort" email, use `outlook_rules` - do not try to replicate Gmail's label-based filtering with Outlook folders.
|
|
93
|
+
|
|
94
|
+
### Folders vs Labels
|
|
95
|
+
|
|
96
|
+
Gmail uses labels - a message can have multiple labels and removing the INBOX label archives it. Outlook uses folders - a message lives in exactly one folder at a time. Moving a message to Archive removes it from Inbox. To tag a message with multiple categories without moving it, use `outlook_categories`. Do not create folder hierarchies to simulate Gmail's multi-label system.
|
|
97
|
+
|
|
98
|
+
## Email Decluttering
|
|
99
|
+
|
|
100
|
+
When a user asks to declutter, clean up, or organize their email - start scanning immediately. Don't ask what kind of cleanup they want or request permission to read their inbox. Go straight to scanning - but once results are ready, always show them via `ui_show` and let the user choose actions before archiving or unsubscribing.
|
|
101
|
+
|
|
102
|
+
**CRITICAL**: Never call `messaging_archive_by_sender`, `outlook_unsubscribe`, or similar bulk actions unless the user has clicked an action button on the table for that specific batch. Each batch of results requires its own explicit user confirmation via the table UI. If the user says "keep going" or "keep decluttering," that means scan and present a new table - NOT auto-archive. Previous batch approvals do not carry forward, but **deselections DO carry forward**: when the user deselects senders from a cleanup table, the system records those deselections as user preferences. Before building the next cleanup table, check `<dynamic-user-profile>` for previously deselected senders and exclude them from future cleanup tables - the user already indicated they want to keep those.
|
|
103
|
+
|
|
104
|
+
### Workflow
|
|
105
|
+
|
|
106
|
+
1. **Scan**: Call `outlook_sender_digest`. Default query targets promotional messages from the last 90 days.
|
|
107
|
+
2. **Present**: Show results as a `ui_show` table with `selectionMode: "multiple"`:
|
|
108
|
+
- **Columns (exactly 3)**: Sender, Emails Found, Unsub?
|
|
109
|
+
- **Unsub? cell values**: Use rich cell format: `{ "text": "Yes", "icon": "checkmark.circle.fill", "iconColor": "success" }` when `has_unsubscribe` is true, `{ "text": "No", "icon": "minus.circle", "iconColor": "muted" }` when false.
|
|
110
|
+
- **Pre-select all rows** (`selected: true`) - users deselect what they want to keep
|
|
111
|
+
- **Caption**: Include two parts separated by a newline: (1) data scope, e.g. "Newsletters, notifications, and outreach from last 90 days. Deselect anything you want to keep." (adjusted to match the query used), and (2) the Unsub? column legend: "Unsub? - \"Yes\" means these emails contain an unsubscribe link, so I can opt you out automatically. \"No\" means no unsubscribe link was found - these will be archived but you may continue receiving them."
|
|
112
|
+
- **Action buttons (exactly 2)**: "Archive & Unsubscribe" (primary), "Archive Only" (secondary). **NEVER offer Delete, Trash, or any destructive action.**
|
|
113
|
+
3. **Wait for user action**: Stop and wait. Do NOT proceed to archiving or unsubscribing until the user clicks one of the action buttons on the table. When the user clicks an action button:
|
|
114
|
+
- **Dismiss the table immediately** with `ui_dismiss` - it collapses to a completion chip
|
|
115
|
+
- **Show a `task_progress` card** with steps for each phase (e.g., "Archiving 89 senders (2,400 emails)", "Unsubscribing from 72 senders"). Update each step from `in_progress` to `completed` as each phase finishes.
|
|
116
|
+
- When all senders are processed, set the progress card's `status: "completed"`.
|
|
117
|
+
4. **Act on selection** - batch, don't loop:
|
|
118
|
+
- **Archive all at once**: Call `messaging_archive_by_sender` **once** with `scan_id` + **all** selected senders' `id` values in the `sender_ids` array. The tool resolves message IDs server-side and batches the API calls internally - never loop sender-by-sender.
|
|
119
|
+
- **Unsubscribe in bulk**: If the action is "Archive & Unsubscribe", call `outlook_unsubscribe` for each sender that has `has_unsubscribe: true` - but emit **all** unsubscribe tool calls in a **single assistant response** (parallel tool use) rather than one-at-a-time across separate turns.
|
|
120
|
+
5. **Accurate summary**: The scan counts are exact - the `message_count` shown in the table matches the number of messages archived. Format: "Cleaned up [total_archived] emails from [sender_count] senders. Unsubscribed from [unsub_count]."
|
|
121
|
+
6. **Ongoing protection offer**: After reporting results, offer inbox rules:
|
|
122
|
+
- "Want me to set up inbox rules so future emails from these senders skip your inbox?"
|
|
123
|
+
- If yes, call `outlook_rules` with `action: "create"` for each sender.
|
|
124
|
+
- Then offer a recurring declutter schedule: "Want me to scan for new clutter monthly?" If yes, use `schedule_create` to set up a monthly declutter check.
|
|
125
|
+
|
|
126
|
+
### Edge Cases
|
|
127
|
+
|
|
128
|
+
- **Zero results**: Tell the user "No newsletter emails found" and suggest broadening the query (e.g. extending the date range)
|
|
129
|
+
- **Unsubscribe failures**: Report per-sender success/failure; the `outlook_unsubscribe` tool handles edge cases
|
|
130
|
+
- **Truncation handling**: If `truncated` is true, the top senders are still captured - don't offer to scan more. Tell the user: "Scanned [N] messages - here are your top senders."
|
|
131
|
+
- **Time budget exceeded**: If the scan returns `time_budget_exceeded: true`, present whatever results were collected. Do not retry or continue - the partial results are useful as-is.
|
|
132
|
+
|
|
133
|
+
## Scan ID
|
|
134
|
+
|
|
135
|
+
Scan tools (`outlook_sender_digest`, `outlook_outreach_scan`) return a `scan_id` that references message IDs stored server-side. This keeps thousands of message IDs out of the conversation context.
|
|
136
|
+
|
|
137
|
+
- Pass `scan_id` + `sender_ids` to `messaging_archive_by_sender` instead of `message_ids`
|
|
138
|
+
- Scan results expire after **30 minutes** - if archiving fails with an expiration error, re-run the scan
|
|
139
|
+
- Raw `message_ids` still work as a fallback for non-scan workflows
|
|
140
|
+
|
|
141
|
+
## Batch Operations
|
|
142
|
+
|
|
143
|
+
- `messaging_archive_by_sender` supports `scan_id` + `sender_ids` (preferred for declutter workflows) or raw `message_ids`.
|
|
144
|
+
- First scan to get a `scan_id`, then use `messaging_archive_by_sender` to batch-archive by sender.
|
|
145
|
+
- Always confirm with the user before batch operations on large numbers of messages.
|
|
146
|
+
|
|
147
|
+
## Common Workflows
|
|
148
|
+
|
|
149
|
+
### Declutter Inbox
|
|
150
|
+
|
|
151
|
+
1. Call `outlook_sender_digest` to scan for newsletters and promotions
|
|
152
|
+
2. Present results via `ui_show` table (see Email Decluttering section for full workflow)
|
|
153
|
+
3. Wait for user to select senders and click an action button
|
|
154
|
+
4. Call `messaging_archive_by_sender` with `scan_id` + selected `sender_ids`
|
|
155
|
+
5. If "Archive & Unsubscribe", also call `outlook_unsubscribe` for senders with `has_unsubscribe: true`
|
|
156
|
+
6. Offer to create inbox rules for ongoing protection
|
|
157
|
+
|
|
158
|
+
### Create a Mail Rule
|
|
159
|
+
|
|
160
|
+
1. User says "auto-archive emails from newsletters@example.com"
|
|
161
|
+
2. Call `outlook_rules` with `action: "create"`, specifying the sender condition and the move-to-folder action
|
|
162
|
+
3. Confirm the rule was created and explain what it does
|
|
163
|
+
|
|
164
|
+
### Set Vacation Auto-Reply
|
|
165
|
+
|
|
166
|
+
1. User says "set my out-of-office for next week"
|
|
167
|
+
2. Call `outlook_vacation` with `action: "enable"`, the date range, and the auto-reply message
|
|
168
|
+
3. Confirm the auto-reply is active and when it expires
|
|
169
|
+
|
|
170
|
+
### Manage Follow-ups
|
|
171
|
+
|
|
172
|
+
1. User says "flag this email for follow-up" - call `outlook_follow_up` with `action: "track"` and the message ID
|
|
173
|
+
2. User says "what emails am I tracking?" - call `outlook_follow_up` with `action: "list"` to show all flagged messages
|
|
174
|
+
3. User says "mark that as done" - call `outlook_follow_up` with `action: "complete"` to clear the flag
|
|
175
|
+
|
|
176
|
+
### Identify Cold Outreach
|
|
177
|
+
|
|
178
|
+
1. Call `outlook_outreach_scan` to find senders without unsubscribe headers
|
|
179
|
+
2. Present results for review - these are likely cold outreach or unsolicited emails
|
|
180
|
+
3. User can choose to archive, create rules to block, or ignore
|
|
181
|
+
|
|
182
|
+
## Confidence Scores
|
|
183
|
+
|
|
184
|
+
Medium and high risk tools require a confidence score between 0 and 1:
|
|
185
|
+
|
|
186
|
+
- **0.9-1.0**: User explicitly requested this exact action
|
|
187
|
+
- **0.7-0.8**: Action is strongly implied by context
|
|
188
|
+
- **0.5-0.6**: Reasonable inference but some ambiguity
|
|
189
|
+
- **Below 0.5**: Ask the user to confirm before proceeding
|