@vellumai/assistant 0.7.3 → 0.8.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 +11 -0
- package/ARCHITECTURE.md +29 -28
- package/Dockerfile +6 -4
- package/README.md +2 -2
- package/__tests__/permissions/gateway-threshold-reader.test.ts +236 -9
- package/bun.lock +3 -0
- package/docker-entrypoint.sh +16 -0
- package/eslint-rules/__tests__/cli-no-daemon-internals.test.ts +420 -0
- package/eslint-rules/cli-no-daemon-internals.js +283 -0
- package/eslint.config.mjs +12 -0
- package/knip.json +3 -1
- package/node_modules/@vellumai/ipc-server-utils/bun.lock +24 -0
- package/node_modules/@vellumai/ipc-server-utils/package.json +18 -0
- package/node_modules/@vellumai/ipc-server-utils/src/index.ts +6 -0
- package/node_modules/@vellumai/ipc-server-utils/src/socket-watchdog.test.ts +430 -0
- package/node_modules/@vellumai/ipc-server-utils/src/socket-watchdog.ts +221 -0
- package/node_modules/@vellumai/ipc-server-utils/tsconfig.json +20 -0
- package/node_modules/@vellumai/skill-host-contracts/src/client.ts +10 -1
- package/openapi.yaml +4126 -959
- package/package.json +5 -1
- package/scripts/generate-openapi.ts +52 -4
- package/scripts/sync-llm-catalog.ts +165 -0
- package/scripts/sync-web-search-catalog.ts +107 -0
- package/src/__tests__/actor-trust-resolver-address-fallback.test.ts +169 -0
- package/src/__tests__/agent-loop-override-profile.test.ts +26 -1
- package/src/__tests__/annotate-risk-options.test.ts +291 -0
- package/src/__tests__/anthropic-provider.test.ts +92 -2
- package/src/__tests__/app-control-flow.test.ts +7 -0
- package/src/__tests__/approval-cascade.test.ts +8 -16
- package/src/__tests__/approval-routes-http.test.ts +6 -0
- package/src/__tests__/assistant-events-sse-shed.test.ts +232 -0
- package/src/__tests__/auto-analysis-end-to-end.test.ts +12 -25
- package/src/__tests__/avatar-identity-sync.test.ts +87 -0
- package/src/__tests__/background-workers-disk-pressure.test.ts +11 -22
- package/src/__tests__/btw-routes.test.ts +1 -0
- package/src/__tests__/call-constants.test.ts +10 -1
- package/src/__tests__/call-controller.test.ts +127 -0
- package/src/__tests__/call-site-routing-provider.test.ts +172 -45
- package/src/__tests__/cancel-resolves-conversation-key.test.ts +44 -3
- package/src/__tests__/channel-policy.test.ts +12 -0
- package/src/__tests__/checker.test.ts +89 -0
- package/src/__tests__/cli-memory-v2-reembed-skills.test.ts +88 -30
- package/src/__tests__/compact-event-conversation-id-guard.test.ts +33 -5
- package/src/__tests__/compaction-strip-metadata-clear.test.ts +26 -1
- package/src/__tests__/config-loader-backfill.test.ts +526 -102
- package/src/__tests__/config-loader-corrupt.test.ts +68 -0
- package/src/__tests__/config-loader-platform-defaults.test.ts +345 -8
- package/src/__tests__/config-schema-cmd.test.ts +63 -29
- package/src/__tests__/config-schema.test.ts +14 -3
- package/src/__tests__/config-set-platform-guard.test.ts +75 -152
- package/src/__tests__/config-set-route.test.ts +198 -0
- package/src/__tests__/config-watcher.test.ts +6 -0
- package/src/__tests__/contacts-tools.test.ts +51 -199
- package/src/__tests__/context-search-agent-protocol.test.ts +21 -2
- package/src/__tests__/context-search-agent-runner.test.ts +22 -138
- package/src/__tests__/context-search-conversations-source.test.ts +42 -16
- package/src/__tests__/context-search-fanout.test.ts +20 -157
- package/src/__tests__/context-search-memory-source.test.ts +3 -26
- package/src/__tests__/context-search-memory-v2-source.test.ts +3 -3
- package/src/__tests__/context-search-types.test.ts +7 -2
- package/src/__tests__/context-window-manager.test.ts +389 -1
- package/src/__tests__/conversation-abort-tool-results.test.ts +1 -6
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +1 -1
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +2 -1
- package/src/__tests__/conversation-agent-loop.test.ts +3 -3
- package/src/__tests__/conversation-confirmation-signals.test.ts +5 -13
- package/src/__tests__/conversation-crud-inference-profile.test.ts +100 -0
- package/src/__tests__/conversation-error.test.ts +38 -0
- package/src/__tests__/conversation-fork-crud.test.ts +241 -1
- package/src/__tests__/conversation-inference-profile-route.test.ts +14 -14
- package/src/__tests__/conversation-init.benchmark.test.ts +2 -1
- package/src/__tests__/conversation-lifecycle.test.ts +124 -0
- package/src/__tests__/conversation-process-app-control-preactivation.test.ts +100 -1
- package/src/__tests__/conversation-process-callsite.test.ts +22 -7
- package/src/__tests__/conversation-provider-retry-repair.test.ts +1 -6
- package/src/__tests__/conversation-runtime-assembly.test.ts +19 -10
- package/src/__tests__/conversation-slash-commands.test.ts +194 -2
- package/src/__tests__/conversation-slash-unknown.test.ts +1 -6
- package/src/__tests__/conversation-surfaces-action-delivery.test.ts +170 -9
- package/src/__tests__/conversation-surfaces-app-control.test.ts +323 -3
- package/src/__tests__/conversation-surfaces-data-persist.test.ts +73 -1
- package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +59 -0
- package/src/__tests__/conversation-workspace-injection.test.ts +1 -7
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +1 -7
- package/src/__tests__/credential-security-invariants.test.ts +5 -6
- package/src/__tests__/daemon-credential-client.test.ts +56 -1
- package/src/__tests__/db-activation-state-fk-cascade.test.ts +132 -0
- package/src/__tests__/db-conversation-inference-profile-migration.test.ts +37 -0
- package/src/__tests__/db-memory-graph-event-date-repair.test.ts +43 -20
- package/src/__tests__/db-proxy-transaction.test.ts +206 -0
- package/src/__tests__/external-plugin-loader.test.ts +458 -0
- package/src/__tests__/filing-service.test.ts +25 -22
- package/src/__tests__/fixtures/mock-chrome-extension.ts +5 -0
- package/src/__tests__/gateway-only-guard.test.ts +0 -1
- package/src/__tests__/graph-extraction-event-date.test.ts +34 -0
- package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +10 -34
- package/src/__tests__/heartbeat-disk-pressure.test.ts +21 -8
- package/src/__tests__/heartbeat-service.test.ts +50 -233
- package/src/__tests__/history-repair.test.ts +89 -0
- package/src/__tests__/host-app-control-proxy.test.ts +109 -1
- package/src/__tests__/host-app-control-routes.test.ts +247 -1
- package/src/__tests__/host-browser-proxy.test.ts +416 -20
- package/src/__tests__/host-browser-routes.test.ts +325 -33
- package/src/__tests__/host-proxy-preactivation.test.ts +211 -0
- package/src/__tests__/inference-no-mode-boot-e2e.test.ts +246 -0
- package/src/__tests__/inference-profile-reaper.test.ts +154 -0
- package/src/__tests__/inference-profile-session-handler.test.ts +398 -0
- package/src/__tests__/inference-profile-session-ipc.test.ts +236 -0
- package/src/__tests__/injector-chain.test.ts +24 -16
- package/src/__tests__/injector-pkb-v2-silenced.test.ts +10 -7
- package/src/__tests__/inline-skill-load-permissions.test.ts +6 -1
- package/src/__tests__/install-skill-routing.test.ts +2 -2
- package/src/__tests__/lifecycle-memory-v2-seed.test.ts +169 -67
- package/src/__tests__/llm-callsite-catalog.test.ts +20 -1
- package/src/__tests__/llm-catalog-parity.test.ts +146 -0
- package/src/__tests__/llm-request-log-source-clickhouse.test.ts +188 -0
- package/src/__tests__/llm-request-log-source-factory.test.ts +124 -0
- package/src/__tests__/llm-resolver.test.ts +46 -0
- package/src/__tests__/managed-profile-guard.test.ts +131 -2
- package/src/__tests__/mcp-auth-routes.test.ts +1 -0
- package/src/__tests__/mcp-cli.test.ts +182 -220
- package/src/__tests__/mcp-health-check.test.ts +56 -27
- package/src/__tests__/memory-jobs-worker-lanes.test.ts +18 -11
- package/src/__tests__/message-complete-display-id.test.ts +175 -0
- package/src/__tests__/notification-decision-fallback.test.ts +91 -0
- package/src/__tests__/notification-decision-strategy.test.ts +22 -0
- package/src/__tests__/notification-platform-adapter.test.ts +229 -0
- package/src/__tests__/oauth-cli.test.ts +38 -1888
- package/src/__tests__/oauth-commands-routes.test.ts +711 -0
- package/src/__tests__/oauth-connect-routes.test.ts +174 -11
- package/src/__tests__/oauth-providers-routes.test.ts +14 -10
- package/src/__tests__/openai-responses-cutover-guard.test.ts +33 -12
- package/src/__tests__/openai-responses-provider.test.ts +17 -0
- package/src/__tests__/plugin-bootstrap.test.ts +31 -2
- package/src/__tests__/plugin-route-contribution.test.ts +31 -3
- package/src/__tests__/plugin-tool-contribution.test.ts +31 -3
- package/src/__tests__/plugin-types.test.ts +13 -11
- package/src/__tests__/process-message-background-slack.test.ts +46 -0
- package/src/__tests__/profile-entry-status.test.ts +43 -0
- package/src/__tests__/provider-managed-proxy-integration.test.ts +12 -4
- package/src/__tests__/provider-registry-ollama.test.ts +12 -4
- package/src/__tests__/provider-send-message-override-profile.test.ts +10 -4
- package/src/__tests__/relay-server.test.ts +164 -2
- package/src/__tests__/retry-thinking-tool-choice.test.ts +15 -0
- package/src/__tests__/schedule-retry.test.ts +56 -4
- package/src/__tests__/schedule-routes.test.ts +104 -0
- package/src/__tests__/scheduler-disk-pressure.test.ts +0 -4
- package/src/__tests__/scheduler-recurrence.test.ts +87 -34
- package/src/__tests__/scheduler-reuse-conversation.test.ts +161 -5
- package/src/__tests__/scheduler-wake.test.ts +0 -63
- package/src/__tests__/secret-allowlist.test.ts +1 -0
- package/src/__tests__/secret-prompt-log-hygiene.test.ts +7 -5
- package/src/__tests__/secret-prompter-channel-fallback.test.ts +7 -5
- package/src/__tests__/secret-response-routing.test.ts +7 -5
- package/src/__tests__/secret-routes-managed-proxy.test.ts +12 -4
- package/src/__tests__/server-history-render.test.ts +82 -0
- package/src/__tests__/shell-credential-ref.test.ts +95 -3
- package/src/__tests__/shell-tool-proxy-mode.test.ts +14 -0
- package/src/__tests__/skill-include-graph.test.ts +31 -0
- package/src/__tests__/skill-load-feature-flag.test.ts +1 -0
- package/src/__tests__/skill-load-tool.test.ts +42 -16
- package/src/__tests__/skills.test.ts +39 -0
- package/src/__tests__/subagent-call-site-routing.test.ts +78 -16
- package/src/__tests__/suggestion-routes.test.ts +3 -3
- package/src/__tests__/sync-message-contract.test.ts +63 -0
- package/src/__tests__/task-scheduler.test.ts +88 -23
- package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +0 -42
- package/src/__tests__/tool-executor.test.ts +155 -0
- package/src/__tests__/update-bulletin-job.test.ts +96 -193
- package/src/__tests__/usage-cli.test.ts +11 -73
- package/src/__tests__/user-plugin-loader.test.ts +145 -0
- package/src/__tests__/vercel-config.test.ts +168 -0
- package/src/__tests__/voice-session-bridge.test.ts +3 -0
- package/src/__tests__/web-search-catalog-parity.test.ts +86 -0
- package/src/__tests__/web-search.test.ts +303 -2
- package/src/__tests__/workspace-migration-039-drop-legacy-llm-keys.test.ts +1 -21
- package/src/__tests__/workspace-migration-057-repair-stale-gemini-model-ids.test.ts +58 -0
- package/src/__tests__/workspace-migration-069-seed-onboarding-threads.test.ts +153 -0
- package/src/__tests__/workspace-migration-071-remove-safe-storage-release-note.test.ts +206 -0
- package/src/__tests__/workspace-migration-072-seed-reply-suggestion-callsite.test.ts +191 -0
- package/src/__tests__/workspace-migration-076-drop-services-inference-mode.test.ts +211 -0
- package/src/__tests__/workspace-migration-077-seed-memory-router-callsite.test.ts +174 -0
- package/src/__tests__/workspace-migration-079-home-feed-notification-only.test.ts +323 -0
- package/src/__tests__/workspace-migration-080-restrict-vercel-api-token-metadata.test.ts +299 -0
- package/src/__tests__/workspace-migration-081-backfill-bash-allowed-tools.test.ts +410 -0
- package/src/__tests__/workspace-migration-082-backfill-managed-profile-labels.test.ts +268 -0
- package/src/__tests__/workspace-migration-safe-storage-limits-release.test.ts +15 -27
- package/src/__tests__/workspace-migration-unify-llm-callsite-configs.test.ts +3 -3
- package/src/__tests__/workspace-release-notes-feature-flag-guard.test.ts +115 -0
- package/src/acp/__tests__/helpers/which-stub.ts +4 -2
- package/src/acp/resolve-agent.test.ts +25 -0
- package/src/acp/resolve-agent.ts +13 -2
- package/src/acp/session-manager.ts +14 -0
- package/src/agent/loop.ts +11 -0
- package/src/approvals/guardian-decision-primitive.ts +0 -13
- package/src/approvals/guardian-request-resolvers.ts +19 -102
- package/src/calls/call-constants.ts +5 -8
- package/src/calls/call-controller.ts +130 -67
- package/src/calls/relay-server.ts +42 -1
- package/src/calls/relay-setup-router.ts +36 -0
- package/src/calls/types.ts +1 -0
- package/src/calls/voice-session-bridge.ts +24 -5
- package/src/channels/config.ts +14 -1
- package/src/channels/types.ts +1 -0
- package/src/cli/AGENTS.md +164 -4
- package/src/cli/__tests__/notifications.test.ts +54 -0
- package/src/cli/commands/__tests__/avatar.test.ts +540 -0
- package/src/cli/commands/__tests__/backup.test.ts +236 -776
- package/src/cli/commands/__tests__/cache.test.ts +1 -1
- package/src/cli/commands/__tests__/changelog.test.ts +593 -0
- package/src/cli/commands/__tests__/channel-verification-sessions.test.ts +503 -0
- package/src/cli/commands/__tests__/conversations-import.test.ts +515 -0
- package/src/cli/commands/__tests__/domain-register.test.ts +140 -167
- package/src/cli/commands/__tests__/domain-status.test.ts +137 -76
- package/src/cli/commands/__tests__/email-attachment.test.ts +314 -337
- package/src/cli/commands/__tests__/email-core.test.ts +579 -0
- package/src/cli/commands/__tests__/image-generation.test.ts +87 -824
- package/src/cli/commands/__tests__/inference-send.test.ts +30 -266
- package/src/cli/commands/__tests__/inference-session.test.ts +423 -0
- package/src/cli/commands/__tests__/memory-v2.test.ts +81 -110
- package/src/cli/commands/__tests__/skills.test.ts +563 -0
- package/src/cli/commands/__tests__/status.test.ts +249 -0
- package/src/cli/commands/__tests__/stt.test.ts +320 -0
- package/src/cli/commands/__tests__/tts-synthesize.test.ts +4 -603
- package/src/cli/commands/__tests__/tts.test.ts +321 -0
- package/src/cli/commands/__tests__/webhooks.test.ts +86 -511
- package/src/cli/commands/attachment.ts +8 -3
- package/src/cli/commands/audit.ts +95 -64
- package/src/cli/commands/auth.ts +61 -58
- package/src/cli/commands/avatar.ts +276 -390
- package/src/cli/commands/backup.ts +409 -505
- package/src/cli/commands/bash.ts +9 -5
- package/src/cli/commands/browser.ts +28 -9
- package/src/cli/commands/cache.ts +9 -4
- package/src/cli/commands/changelog.ts +414 -0
- package/src/cli/commands/channel-verification-sessions.ts +238 -317
- package/src/cli/commands/clients.ts +8 -3
- package/src/cli/commands/completions.ts +9 -9
- package/src/cli/commands/config.ts +102 -72
- package/src/cli/commands/contacts.ts +575 -696
- package/src/cli/commands/conversations-defer.ts +17 -69
- package/src/cli/commands/conversations-import.ts +90 -253
- package/src/cli/commands/conversations.ts +346 -436
- package/src/cli/commands/credential-execution.ts +9 -6
- package/src/cli/commands/credentials.ts +456 -736
- package/src/cli/commands/domain.ts +128 -206
- package/src/cli/commands/email.ts +606 -794
- package/src/cli/commands/gateway.ts +8 -1
- package/src/cli/commands/image-generation.ts +157 -205
- package/src/cli/commands/inference-providers.ts +352 -0
- package/src/cli/commands/inference-session.ts +415 -0
- package/src/cli/commands/inference.ts +87 -65
- package/src/cli/commands/keys.ts +8 -3
- package/src/cli/commands/mcp.ts +103 -287
- package/src/cli/commands/memory-v2.ts +163 -517
- package/src/cli/commands/notifications.ts +33 -7
- package/src/cli/commands/oauth/apps.ts +292 -261
- package/src/cli/commands/oauth/connect.ts +182 -345
- package/src/cli/commands/oauth/disconnect.ts +16 -215
- package/src/cli/commands/oauth/index.ts +49 -45
- package/src/cli/commands/oauth/mode.ts +43 -199
- package/src/cli/commands/oauth/ping.ts +17 -125
- package/src/cli/commands/oauth/providers.ts +732 -921
- package/src/cli/commands/oauth/request.ts +60 -350
- package/src/cli/commands/oauth/shared.ts +11 -121
- package/src/cli/commands/oauth/status.ts +31 -121
- package/src/cli/commands/oauth/token.ts +13 -55
- package/src/cli/commands/pending.ts +19 -10
- package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +133 -183
- package/src/cli/commands/platform/__tests__/connect.test.ts +66 -181
- package/src/cli/commands/platform/__tests__/disconnect.test.ts +71 -227
- package/src/cli/commands/platform/__tests__/status.test.ts +169 -287
- package/src/cli/commands/platform/connect.ts +16 -80
- package/src/cli/commands/platform/disconnect.ts +14 -112
- package/src/cli/commands/platform/index.ts +177 -246
- package/src/cli/commands/routes.ts +153 -336
- package/src/cli/commands/sequence.ts +316 -360
- package/src/cli/commands/skills.ts +449 -671
- package/src/cli/commands/status.ts +58 -37
- package/src/cli/commands/stt.ts +94 -262
- package/src/cli/commands/task.ts +14 -40
- package/src/cli/commands/trust.ts +8 -3
- package/src/cli/commands/tts.ts +162 -167
- package/src/cli/commands/ui.ts +35 -42
- package/src/cli/commands/usage.ts +188 -126
- package/src/cli/commands/watchers.ts +8 -3
- package/src/cli/commands/webhooks.ts +99 -193
- package/src/cli/lib/__tests__/register-command.test.ts +85 -0
- package/src/cli/lib/daemon-credential-client.ts +4 -5
- package/src/cli/lib/nested-value.ts +44 -0
- package/src/cli/lib/open-browser.ts +36 -0
- package/src/cli/lib/register-command.ts +19 -0
- package/src/cli/lib/time-ago.ts +34 -0
- package/src/cli/program.ts +2 -4
- package/src/cli/utils/__tests__/conversation-id.test.ts +66 -0
- package/src/cli/utils/__tests__/parse-duration.test.ts +49 -0
- package/src/cli/utils/conversation-id.ts +30 -0
- package/src/cli/utils/parse-duration.ts +41 -0
- package/src/config/acp-defaults.test.ts +5 -1
- package/src/config/acp-defaults.ts +11 -4
- package/src/config/bundled-skills/acp/TOOLS.json +2 -2
- package/src/config/bundled-skills/app-builder/SKILL.md +1 -3
- package/src/config/bundled-skills/app-control/TOOLS.json +32 -0
- package/src/config/bundled-skills/contacts/SKILL.md +12 -45
- package/src/config/bundled-skills/contacts/TOOLS.json +0 -57
- package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +0 -12
- package/src/config/bundled-skills/messaging/tools/messaging-send.ts +0 -58
- package/src/config/bundled-tool-registry.ts +0 -2
- package/src/config/feature-flag-registry.json +17 -17
- package/src/config/llm-resolver.ts +16 -1
- package/src/config/loader.ts +148 -33
- package/src/config/raw-config-utils.ts +2 -30
- package/src/config/schema.ts +4 -0
- package/src/config/schemas/__tests__/memory-v2.test.ts +49 -0
- package/src/config/schemas/call-site-catalog.ts +29 -7
- package/src/config/schemas/llm-request-logs.ts +57 -0
- package/src/config/schemas/llm.ts +52 -2
- package/src/config/schemas/memory-retrospective.ts +48 -0
- package/src/config/schemas/memory-v2.ts +33 -2
- package/src/config/schemas/memory.ts +4 -0
- package/src/config/schemas/services.ts +15 -12
- package/src/config/seed-inference-profiles.ts +195 -134
- package/src/contacts/contact-store.ts +0 -61
- package/src/context/window-manager.ts +191 -5
- package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +111 -0
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +109 -4
- package/src/daemon/__tests__/daemon-skill-host.test.ts +10 -4
- package/src/daemon/approval-generators.ts +23 -29
- package/src/daemon/config-watcher.ts +2 -0
- package/src/daemon/conversation-agent-loop-handlers.ts +56 -0
- package/src/daemon/conversation-agent-loop.ts +140 -107
- package/src/daemon/conversation-error.ts +21 -0
- package/src/daemon/conversation-lifecycle.ts +68 -13
- package/src/daemon/conversation-process.ts +36 -19
- package/src/daemon/conversation-runtime-assembly.ts +14 -5
- package/src/daemon/conversation-slash.ts +175 -23
- package/src/daemon/conversation-store.ts +17 -10
- package/src/daemon/conversation-surfaces.ts +92 -26
- package/src/daemon/conversation-tool-setup.ts +33 -19
- package/src/daemon/conversation.ts +49 -10
- package/src/daemon/external-plugins-bootstrap.ts +18 -8
- package/src/daemon/guardian-action-generators.ts +7 -22
- package/src/daemon/handlers/config-model.ts +8 -126
- package/src/daemon/handlers/config-slack-channel.ts +10 -7
- package/src/daemon/handlers/config-vercel.ts +3 -1
- package/src/daemon/handlers/shared.ts +26 -0
- package/src/daemon/handlers/skills.ts +84 -5
- package/src/daemon/history-repair.ts +33 -6
- package/src/daemon/host-app-control-proxy.ts +44 -19
- package/src/daemon/host-bash-proxy.ts +85 -158
- package/src/daemon/host-browser-proxy.ts +97 -36
- package/src/daemon/host-cu-proxy.ts +1 -1
- package/src/daemon/host-file-proxy.ts +1 -1
- package/src/daemon/host-proxy-base.ts +13 -1
- package/src/daemon/host-proxy-preactivation.ts +25 -1
- package/src/daemon/host-transfer-proxy.ts +2 -2
- package/src/daemon/identity-helpers.ts +19 -0
- package/src/daemon/lifecycle.ts +128 -114
- package/src/daemon/meet-host-supervisor.ts +15 -15
- package/src/daemon/memory-v2-startup.ts +62 -14
- package/src/daemon/message-protocol.ts +6 -0
- package/src/daemon/message-types/bookmarks.ts +18 -0
- package/src/daemon/message-types/conversations.ts +12 -9
- package/src/daemon/message-types/messages.ts +28 -2
- package/src/daemon/message-types/sync.ts +60 -0
- package/src/daemon/pkb-reminder-builder.test.ts +54 -13
- package/src/daemon/pkb-reminder-builder.ts +21 -7
- package/src/daemon/process-message.ts +56 -23
- package/src/daemon/server.ts +23 -18
- package/src/daemon/shutdown-handlers.ts +0 -2
- package/src/daemon/tool-setup-types.ts +9 -0
- package/src/daemon/tool-side-effects.ts +6 -4
- package/src/daemon/wake-target-adapter.ts +11 -0
- package/src/documents/document-store.ts +35 -1
- package/src/export/transcript-formatter.ts +61 -2
- package/src/filing/filing-service.ts +42 -56
- package/src/heartbeat/__tests__/heartbeat-service.test.ts +359 -0
- package/src/heartbeat/heartbeat-run-store.ts +2 -1
- package/src/heartbeat/heartbeat-service.ts +149 -128
- package/src/home/__tests__/feed-types.test.ts +63 -131
- package/src/home/__tests__/feed-writer.test.ts +77 -278
- package/src/home/__tests__/post-connect-feed.test.ts +9 -12
- package/src/home/feed-types.ts +19 -73
- package/src/home/feed-writer.ts +25 -156
- package/src/home/post-connect-feed.ts +1 -3
- package/src/ipc/__tests__/cli-ipc.test.ts +2 -0
- package/src/ipc/__tests__/email-ipc.test.ts +506 -0
- package/src/ipc/__tests__/exit-helper.test.ts +104 -0
- package/src/ipc/__tests__/streaming-client.test.ts +237 -0
- package/src/ipc/__tests__/streaming-framing.test.ts +142 -0
- package/src/ipc/assistant-server.ts +148 -42
- package/src/ipc/cli-client.ts +370 -50
- package/src/ipc/routes/db-proxy-transaction.ts +151 -0
- package/src/ipc/skill-routes/__tests__/events-ipc.test.ts +60 -0
- package/src/ipc/skill-routes/events.ts +30 -3
- package/src/ipc/skill-server.ts +99 -42
- package/src/live-voice/__tests__/live-voice-session-manager.test.ts +46 -0
- package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +1 -0
- package/src/live-voice/live-voice-session-manager.ts +11 -4
- package/src/live-voice/live-voice-session.ts +14 -6
- package/src/memory/__tests__/bookmark-crud.test.ts +258 -0
- package/src/memory/__tests__/bookmark-schema.test.ts +181 -0
- package/src/memory/__tests__/conversation-types.test.ts +36 -0
- package/src/memory/__tests__/find-most-recent-retrospective-for.test.ts +130 -0
- package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +10 -57
- package/src/memory/__tests__/memory-retrospective-enqueue.test.ts +177 -0
- package/src/memory/__tests__/memory-retrospective-job.test.ts +328 -0
- package/src/memory/__tests__/memory-retrospective-startup-cleanup.test.ts +213 -0
- package/src/memory/__tests__/memory-retrospective-trigger-check.test.ts +90 -0
- package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +69 -0
- package/src/memory/__tests__/memory-v2-concept-frequency.test.ts +3 -0
- package/src/memory/bookmark-crud.ts +179 -0
- package/src/memory/context-search/__tests__/agent-runner-redaction.test.ts +31 -9
- package/src/memory/context-search/agent-protocol.ts +5 -1
- package/src/memory/context-search/agent-runner.ts +60 -85
- package/src/memory/context-search/limits.ts +1 -4
- package/src/memory/context-search/search.ts +23 -113
- package/src/memory/context-search/sources/conversations.ts +18 -6
- package/src/memory/context-search/sources/memory-v2.ts +40 -31
- package/src/memory/context-search/sources/memory.ts +9 -2
- package/src/memory/context-search/sources/workspace.ts +13 -10
- package/src/memory/context-search/types.ts +1 -1
- package/src/memory/conversation-bootstrap.ts +11 -0
- package/src/memory/conversation-crud.ts +312 -10
- package/src/memory/conversation-queries.ts +9 -5
- package/src/memory/conversation-title-service.ts +1 -0
- package/src/memory/conversation-types.ts +16 -0
- package/src/memory/db-init.ts +14 -0
- package/src/memory/embedding-backend.ts +2 -1
- package/src/memory/embedding-runtime-manager.ts +1 -2
- package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +104 -61
- package/src/memory/graph/__tests__/handle-remember-v2.test.ts +11 -26
- package/src/memory/graph/__tests__/remember-description.test.ts +55 -0
- package/src/memory/graph/conversation-graph-memory.ts +108 -14
- package/src/memory/graph/extraction.ts +4 -0
- package/src/memory/graph/graph-memory-state-store.ts +16 -3
- package/src/memory/graph/graph-search.test.ts +6 -5
- package/src/memory/graph/graph-search.ts +3 -4
- package/src/memory/graph/retriever.test.ts +12 -7
- package/src/memory/graph/retriever.ts +4 -5
- package/src/memory/graph/tool-handlers.ts +20 -11
- package/src/memory/graph/tools.ts +48 -9
- package/src/memory/indexer.ts +18 -2
- package/src/memory/jobs/__tests__/embed-concept-page.test.ts +120 -6
- package/src/memory/jobs/embed-concept-page.ts +261 -89
- package/src/memory/jobs-store.ts +51 -1
- package/src/memory/jobs-worker.ts +60 -7
- package/src/memory/llm-request-log-source-clickhouse.ts +317 -0
- package/src/memory/llm-request-log-source-local.ts +26 -0
- package/src/memory/llm-request-log-source.ts +97 -0
- package/src/memory/llm-request-log-store.ts +1 -1
- package/src/memory/memory-retrospective-constants.ts +13 -0
- package/src/memory/memory-retrospective-enqueue.ts +114 -0
- package/src/memory/memory-retrospective-job.ts +351 -0
- package/src/memory/memory-retrospective-startup-cleanup.ts +108 -0
- package/src/memory/memory-retrospective-state.ts +162 -0
- package/src/memory/memory-retrospective-trigger-check.ts +91 -0
- package/src/memory/memory-v2-activation-log-store.ts +49 -5
- package/src/memory/memory-v2-concept-frequency.ts +4 -0
- package/src/memory/message-content.ts +38 -1
- package/src/memory/migrations/227-add-conversation-inference-profile.ts +6 -1
- package/src/memory/migrations/228-rename-inference-profile-snake-case.ts +20 -7
- package/src/memory/migrations/229-delete-private-conversations.test.ts +70 -1
- package/src/memory/migrations/229-delete-private-conversations.ts +12 -0
- package/src/memory/migrations/231-repair-memory-graph-event-dates.ts +16 -2
- package/src/memory/migrations/240-conversation-inference-profile-session.ts +25 -0
- package/src/memory/migrations/241-activation-state-fk-cascade.ts +50 -0
- package/src/memory/migrations/242-message-bookmarks.ts +38 -0
- package/src/memory/migrations/243-provider-connections.ts +68 -0
- package/src/memory/migrations/244-provider-connection-status-label.ts +23 -0
- package/src/memory/migrations/245-memory-retrospective-state.ts +36 -0
- package/src/memory/migrations/246-backfill-provider-connection-label.ts +81 -0
- package/src/memory/migrations/__tests__/244-provider-connection-status-label.test.ts +84 -0
- package/src/memory/migrations/__tests__/245-memory-retrospective-state.test.ts +125 -0
- package/src/memory/migrations/__tests__/246-backfill-provider-connection-label.test.ts +192 -0
- package/src/memory/migrations/index.ts +7 -0
- package/src/memory/pkb/pkb-search.test.ts +6 -5
- package/src/memory/pkb/pkb-search.ts +4 -5
- package/src/memory/published-pages-store.ts +16 -0
- package/src/memory/qdrant-client.ts +3 -0
- package/src/memory/schema/bookmarks.ts +38 -0
- package/src/memory/schema/conversations.ts +2 -0
- package/src/memory/schema/index.ts +2 -0
- package/src/memory/schema/inference.ts +29 -0
- package/src/memory/schema/memory-core.ts +9 -0
- package/src/memory/search/semantic.ts +5 -9
- package/src/memory/v2/__tests__/__snapshots__/prompts-router.test.ts.snap +27 -0
- package/src/memory/v2/__tests__/activation-store.test.ts +5 -5
- package/src/memory/v2/__tests__/activation.test.ts +46 -9
- package/src/memory/v2/__tests__/backfill-jobs.test.ts +38 -21
- package/src/memory/v2/__tests__/consolidation-job.test.ts +140 -163
- package/src/memory/v2/__tests__/edge-index.test.ts +1 -1
- package/src/memory/v2/__tests__/frontmatter-sweep.test.ts +111 -0
- package/src/memory/v2/__tests__/injection.test.ts +768 -33
- package/src/memory/v2/__tests__/migration.test.ts +7 -3
- package/src/memory/v2/__tests__/page-index.test.ts +277 -0
- package/src/memory/v2/__tests__/page-store.test.ts +14 -1
- package/src/memory/v2/__tests__/prompts-router.test.ts +257 -0
- package/src/memory/v2/__tests__/qdrant.test.ts +382 -9
- package/src/memory/v2/__tests__/reranker.test.ts +4 -4
- package/src/memory/v2/__tests__/router.test.ts +516 -0
- package/src/memory/v2/__tests__/sim.test.ts +163 -8
- package/src/memory/v2/__tests__/skill-store.test.ts +58 -3
- package/src/memory/v2/__tests__/static-context.test.ts +8 -35
- package/src/memory/v2/__tests__/sweep-job.test.ts +114 -33
- package/src/memory/v2/activation-store.ts +34 -5
- package/src/memory/v2/activation.ts +40 -27
- package/src/memory/v2/backfill-jobs.ts +17 -84
- package/src/memory/v2/consolidation-job.ts +92 -86
- package/src/memory/v2/frontmatter-sweep.ts +91 -0
- package/src/memory/v2/injection.ts +466 -115
- package/src/memory/v2/migration.ts +117 -20
- package/src/memory/v2/page-index.ts +191 -0
- package/src/memory/v2/page-store.ts +42 -0
- package/src/memory/v2/prompts/consolidation.ts +14 -7
- package/src/memory/v2/prompts/router.ts +192 -0
- package/src/memory/v2/qdrant.ts +307 -133
- package/src/memory/v2/reranker.ts +14 -7
- package/src/memory/v2/router.ts +322 -0
- package/src/memory/v2/sim.ts +88 -34
- package/src/memory/v2/skill-store.ts +118 -29
- package/src/memory/v2/static-context.ts +20 -17
- package/src/memory/v2/sweep-job.ts +127 -102
- package/src/memory/v2/types.ts +16 -5
- package/src/memory/validation.ts +13 -0
- package/src/notifications/__tests__/emit-signal-home-feed.test.ts +182 -0
- package/src/notifications/__tests__/home-feed-side-effect.test.ts +199 -0
- package/src/notifications/__tests__/signal-registry.test.ts +17 -0
- package/src/notifications/adapters/platform.ts +171 -0
- package/src/notifications/conversation-pairing.ts +2 -2
- package/src/notifications/copy-composer.ts +61 -12
- package/src/notifications/decision-engine.ts +46 -0
- package/src/notifications/destination-resolver.ts +21 -0
- package/src/notifications/emit-signal.ts +28 -1
- package/src/notifications/home-feed-side-effect.ts +111 -0
- package/src/notifications/signal.ts +5 -0
- package/src/permissions/checker.ts +12 -0
- package/src/permissions/gateway-threshold-reader.ts +116 -8
- package/src/permissions/ipc-risk-types.ts +2 -0
- package/src/permissions/prompter.ts +86 -96
- package/src/permissions/secret-prompter.ts +31 -31
- package/src/plugin-api/index.ts +13 -0
- package/src/plugin-api/package.json +12 -0
- package/src/plugin-api/types.ts +62 -0
- package/src/plugins/defaults/injectors.ts +20 -5
- package/src/plugins/external-plugin-loader.ts +294 -0
- package/src/plugins/types.ts +46 -30
- package/src/plugins/user-loader.ts +64 -41
- package/src/proactive-artifact/job.test.ts +63 -8
- package/src/proactive-artifact/job.ts +20 -2
- package/src/proactive-artifact/message-copy.ts +18 -1
- package/src/proactive-artifact/trigger-state.test.ts +9 -0
- package/src/proactive-artifact/trigger-state.ts +4 -0
- package/src/prompts/__tests__/system-prompt.test.ts +105 -0
- package/src/prompts/system-prompt.ts +22 -1
- package/src/prompts/templates/SOUL.md +13 -28
- package/src/prompts/update-bulletin-job.ts +61 -73
- package/src/providers/__tests__/dispatch-connection-routing.test.ts +279 -0
- package/src/providers/__tests__/inference.test.ts +288 -0
- package/src/providers/__tests__/provider-env-vars.test.ts +6 -0
- package/src/providers/__tests__/provider-secret-catalog.test.ts +6 -0
- package/src/providers/__tests__/retry-callsite.test.ts +14 -32
- package/src/providers/__tests__/satellite-connection-routing.test.ts +510 -0
- package/src/providers/__tests__/search-provider-catalog.test.ts +80 -0
- package/src/providers/anthropic/client.ts +95 -26
- package/src/providers/call-site-routing.ts +94 -16
- package/src/providers/connection-resolution.ts +163 -0
- package/src/providers/inference/__tests__/connections-status-label.test.ts +250 -0
- package/src/providers/inference/adapter-factory.ts +173 -0
- package/src/providers/inference/auth.ts +112 -0
- package/src/providers/inference/backfill.ts +196 -0
- package/src/providers/inference/connections.ts +356 -0
- package/src/providers/inference/resolve-auth.ts +65 -0
- package/src/providers/model-catalog.ts +104 -6
- package/src/providers/openai/responses-provider.ts +4 -2
- package/src/providers/provider-env-vars.ts +17 -7
- package/src/providers/provider-secret-catalog.ts +49 -30
- package/src/providers/provider-send-message.ts +41 -20
- package/src/providers/registry.ts +143 -159
- package/src/providers/retry.ts +18 -10
- package/src/providers/search-provider-catalog.ts +121 -0
- package/src/runtime/AGENTS.md +18 -5
- package/src/runtime/__tests__/background-job-runner.test.ts +357 -0
- package/src/runtime/__tests__/pre-first-message-gate.test.ts +82 -0
- package/src/runtime/actor-trust-resolver.ts +32 -10
- package/src/runtime/agent-wake.ts +35 -6
- package/src/runtime/assistant-event-hub.ts +3 -85
- package/src/runtime/auth/route-policy.ts +304 -8
- package/src/runtime/auth/same-actor.ts +2 -0
- package/src/runtime/background-job-runner.ts +339 -0
- package/src/runtime/btw-sidechain.ts +1 -0
- package/src/runtime/channel-approvals.ts +3 -2
- package/src/runtime/guardian-reply-router.ts +0 -10
- package/src/runtime/http-router.ts +36 -1
- package/src/runtime/http-server.ts +31 -5
- package/src/runtime/http-types.ts +2 -0
- package/src/runtime/middleware/__tests__/request-logger.test.ts +162 -0
- package/src/runtime/middleware/request-logger.ts +62 -1
- package/src/runtime/pending-interactions.ts +19 -15
- package/src/runtime/pre-first-message-gate.ts +83 -0
- package/src/runtime/routes/__tests__/backup-routes.test.ts +8 -1
- package/src/runtime/routes/__tests__/bookmark-routes.test.ts +251 -0
- package/src/runtime/routes/__tests__/connection-routes-vs-cli-parity.test.ts +142 -0
- package/src/runtime/routes/__tests__/conversation-management-routes.test.ts +315 -0
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +189 -0
- package/src/runtime/routes/__tests__/home-feed-routes.test.ts +15 -136
- package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +736 -0
- package/src/runtime/routes/__tests__/memory-v2-routes.test.ts +147 -0
- package/src/runtime/routes/__tests__/stt-routes.test.ts +5 -1
- package/src/runtime/routes/__tests__/surface-action-routes.test.ts +384 -0
- package/src/runtime/routes/__tests__/tts-routes.test.ts +6 -2
- package/src/runtime/routes/acp-routes.ts +10 -8
- package/src/runtime/routes/app-management-routes.ts +228 -3
- package/src/runtime/routes/approval-routes.ts +7 -21
- package/src/runtime/routes/audit-routes.ts +43 -0
- package/src/runtime/routes/auth-routes.ts +72 -0
- package/src/runtime/routes/avatar-routes.ts +273 -20
- package/src/runtime/routes/backup-routes.ts +406 -2
- package/src/runtime/routes/bookmark-routes.ts +154 -0
- package/src/runtime/routes/channel-verification-routes.ts +2 -1
- package/src/runtime/routes/consolidation-routes.ts +8 -9
- package/src/runtime/routes/contact-routes.ts +0 -160
- package/src/runtime/routes/conversation-cli-routes.ts +192 -0
- package/src/runtime/routes/conversation-management-routes.ts +30 -43
- package/src/runtime/routes/conversation-query-routes.ts +373 -82
- package/src/runtime/routes/conversation-routes.ts +31 -10
- package/src/runtime/routes/conversations-import-routes.ts +229 -0
- package/src/runtime/routes/credential-routes.ts +540 -0
- package/src/runtime/routes/debug-bash-routes.ts +2 -0
- package/src/runtime/routes/debug-routes.ts +2 -2
- package/src/runtime/routes/document-pdf-renderer.ts +5 -1
- package/src/runtime/routes/domain-routes.ts +167 -0
- package/src/runtime/routes/email-routes.ts +603 -0
- package/src/runtime/routes/errors.ts +2 -2
- package/src/runtime/routes/events-routes.ts +192 -0
- package/src/runtime/routes/filing-routes.ts +2 -3
- package/src/runtime/routes/home-feed-routes.ts +6 -78
- package/src/runtime/routes/host-app-control-routes.ts +44 -2
- package/src/runtime/routes/host-browser-routes.ts +103 -22
- package/src/runtime/routes/http-adapter.ts +2 -0
- package/src/runtime/routes/identity-routes.ts +5 -0
- package/src/runtime/routes/image-generation-routes.ts +99 -0
- package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +137 -1
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +87 -7
- package/src/runtime/routes/inbound-stages/guardian-reply-intercept.test.ts +156 -0
- package/src/runtime/routes/inbound-stages/guardian-reply-intercept.ts +22 -7
- package/src/runtime/routes/index.ts +36 -0
- package/src/runtime/routes/inference-profile-session-handler.ts +312 -0
- package/src/runtime/routes/inference-profile-session-reaper.ts +98 -0
- package/src/runtime/routes/inference-profile-session-routes.ts +146 -0
- package/src/runtime/routes/inference-provider-connection-routes.ts +317 -0
- package/src/runtime/routes/inference-send-routes.ts +115 -0
- package/src/runtime/routes/integrations/twilio.ts +1 -0
- package/src/runtime/routes/mcp-auth-routes.ts +283 -9
- package/src/runtime/routes/memory-item-routes.test.ts +3 -9
- package/src/runtime/routes/memory-item-routes.ts +5 -6
- package/src/runtime/routes/memory-v2-routes.ts +105 -404
- package/src/runtime/routes/notification-routes.ts +2 -0
- package/src/runtime/routes/oauth-apps.ts +112 -7
- package/src/runtime/routes/oauth-commands-routes.ts +1007 -0
- package/src/runtime/routes/oauth-connect-routes.ts +67 -5
- package/src/runtime/routes/oauth-providers.ts +298 -8
- package/src/runtime/routes/platform-routes.ts +336 -0
- package/src/runtime/routes/playground/inject-failures.ts +2 -1
- package/src/runtime/routes/playground/reset-circuit.ts +2 -1
- package/src/runtime/routes/playground/state.ts +2 -1
- package/src/runtime/routes/publish-routes.ts +221 -0
- package/src/runtime/routes/schedule-routes.ts +82 -0
- package/src/runtime/routes/sequence-routes.ts +291 -0
- package/src/runtime/routes/settings-routes.ts +2 -10
- package/src/runtime/routes/skills-routes.ts +31 -1
- package/src/runtime/routes/stt-routes.ts +240 -3
- package/src/runtime/routes/surface-action-routes.ts +43 -7
- package/src/runtime/routes/tts-routes.ts +67 -0
- package/src/runtime/routes/types.ts +32 -0
- package/src/runtime/routes/user-routes-cli.ts +243 -0
- package/src/runtime/routes/webhook-routes.ts +165 -0
- package/src/runtime/sync/resource-sync-events.ts +25 -0
- package/src/runtime/sync/sync-publisher.test.ts +105 -0
- package/src/runtime/sync/sync-publisher.ts +21 -0
- package/src/schedule/scheduler.ts +200 -123
- package/src/security/__tests__/provider-key-env-fallback.test.ts +12 -6
- package/src/security/secret-patterns.ts +3 -0
- package/src/sequence/engine.ts +38 -40
- package/src/skills/include-graph.ts +35 -13
- package/src/subagent/manager.ts +20 -15
- package/src/tools/browser/__tests__/browser-execution-acquire.test.ts +206 -0
- package/src/tools/browser/browser-execution.ts +15 -4
- package/src/tools/browser/cdp-client/__tests__/factory.test.ts +174 -0
- package/src/tools/browser/cdp-client/cdp-inspect/__tests__/ws-transport.test.ts +16 -13
- package/src/tools/browser/cdp-client/extension-cdp-client.ts +24 -1
- package/src/tools/browser/cdp-client/factory.ts +66 -5
- package/src/tools/browser/runtime-check.ts +77 -0
- package/src/tools/document/document-tool.ts +20 -0
- package/src/tools/executor.ts +18 -2
- package/src/tools/memory/register.test.ts +10 -8
- package/src/tools/memory/register.ts +9 -1
- package/src/tools/network/__tests__/web-search.test.ts +156 -0
- package/src/tools/network/web-search.ts +280 -37
- package/src/tools/permission-checker.ts +28 -5
- package/src/tools/skills/load.ts +24 -20
- package/src/tools/subagent/spawn.ts +3 -3
- package/src/tools/terminal/shell.ts +44 -0
- package/src/tools/tool-name-aliases.ts +19 -0
- package/src/tools/types.ts +19 -1
- package/src/usage/attribution.ts +3 -2
- package/src/util/pricing.ts +86 -160
- package/src/watcher/__tests__/engine.test.ts +301 -0
- package/src/watcher/constants.ts +7 -0
- package/src/watcher/engine.ts +90 -90
- package/src/workspace/migrations/046-seed-conversation-starters-callsite.ts +6 -9
- package/src/workspace/migrations/054-seed-recall-callsite.ts +10 -1
- package/src/workspace/migrations/057-repair-stale-gemini-model-ids.ts +28 -4
- package/src/workspace/migrations/067-release-notes-safe-storage-limits.ts +4 -62
- package/src/workspace/migrations/069-seed-onboarding-threads.ts +34 -0
- package/src/workspace/migrations/070-memory-v2-summary-schema-rebuild.ts +31 -0
- package/src/workspace/migrations/071-remove-safe-storage-release-note.ts +111 -0
- package/src/workspace/migrations/072-seed-reply-suggestion-callsite.ts +104 -0
- package/src/workspace/migrations/073-repair-recall-callsite-empty-profile.ts +93 -0
- package/src/workspace/migrations/074-drop-deprecated-secret-detection-keys.ts +117 -0
- package/src/workspace/migrations/075-memory-v2-bm25-b-default-reembed.ts +61 -0
- package/src/workspace/migrations/076-drop-services-inference-mode.ts +62 -0
- package/src/workspace/migrations/077-seed-memory-router-callsite.ts +89 -0
- package/src/workspace/migrations/078-release-notes-tavily-web-search.ts +66 -0
- package/src/workspace/migrations/079-home-feed-notification-only.ts +197 -0
- package/src/workspace/migrations/080-restrict-vercel-api-token-metadata.ts +182 -0
- package/src/workspace/migrations/081-backfill-bash-allowed-tools-for-injection-credentials.ts +160 -0
- package/src/workspace/migrations/082-backfill-managed-profile-labels.ts +154 -0
- package/src/workspace/migrations/registry.ts +28 -0
- package/src/workspace/migrations/runner.ts +13 -2
- package/src/workspace/migrations/types.ts +13 -3
- package/src/workspace/provider-commit-message-generator.ts +3 -2
- package/src/__tests__/context-search-pkb-source.test.ts +0 -492
- package/src/__tests__/credentials-cli.test.ts +0 -1225
- package/src/__tests__/memory-admin-recall.test.ts +0 -213
- package/src/approvals/__tests__/guardian-feed-event.test.ts +0 -303
- package/src/cli/commands/__tests__/email-download.test.ts +0 -260
- package/src/cli/commands/__tests__/email-list.test.ts +0 -216
- package/src/cli/commands/__tests__/email-register.test.ts +0 -186
- package/src/cli/commands/__tests__/email-send.test.ts +0 -416
- package/src/cli/commands/__tests__/email-status.test.ts +0 -185
- package/src/cli/commands/__tests__/email-unregister.test.ts +0 -168
- package/src/cli/commands/__tests__/routes.test.ts +0 -562
- package/src/cli/commands/__tests__/stt-transcribe.test.ts +0 -454
- package/src/cli/commands/autonomy.ts +0 -365
- package/src/cli/commands/memory.ts +0 -424
- package/src/cli/commands/oauth/__tests__/connect.test.ts +0 -1201
- package/src/cli/commands/oauth/__tests__/disconnect.test.ts +0 -686
- package/src/cli/commands/oauth/__tests__/mode.test.ts +0 -632
- package/src/cli/commands/oauth/__tests__/ping.test.ts +0 -631
- package/src/cli/commands/oauth/__tests__/providers-delete.test.ts +0 -573
- package/src/cli/commands/oauth/__tests__/providers-register.test.ts +0 -330
- package/src/cli/commands/oauth/__tests__/providers-update.test.ts +0 -521
- package/src/cli/commands/oauth/__tests__/status.test.ts +0 -551
- package/src/cli/commands/oauth/__tests__/token.test.ts +0 -420
- package/src/cli/lib/daemon-avatar-client.ts +0 -37
- package/src/config/bundled-skills/contacts/tools/contact-upsert.ts +0 -87
- package/src/config/bundled-skills/messaging/tools/__tests__/messaging-feed-events.test.ts +0 -207
- package/src/daemon/__tests__/conversation-feed-event.test.ts +0 -304
- package/src/heartbeat/__tests__/heartbeat-feed-event.test.ts +0 -233
- package/src/home/__tests__/assistant-feed-authoring.test.ts +0 -156
- package/src/home/__tests__/emit-feed-event.test.ts +0 -169
- package/src/home/__tests__/feed-population-integration.test.ts +0 -312
- package/src/home/__tests__/feed-scheduler.test.ts +0 -222
- package/src/home/__tests__/phase5-exit-criteria.test.ts +0 -229
- package/src/home/__tests__/platform-gmail-digest.test.ts +0 -222
- package/src/home/__tests__/rollup-producer.test.ts +0 -507
- package/src/home/assistant-feed-authoring.ts +0 -135
- package/src/home/emit-feed-event.ts +0 -169
- package/src/home/feed-scheduler.ts +0 -281
- package/src/home/platform-gmail-digest.ts +0 -163
- package/src/home/rewrite-command-preview.ts +0 -66
- package/src/home/rewrite-feed-title.ts +0 -58
- package/src/home/rollup-producer.ts +0 -426
- package/src/memory/admin.ts +0 -326
- package/src/memory/context-search/sources/pkb.ts +0 -477
- package/src/memory/graph/compaction.ts +0 -299
- /package/src/cli/{commands → lib}/cache-fs.ts +0 -0
|
@@ -3,18 +3,15 @@ import {
|
|
|
3
3
|
diskPressureBackgroundSkipLogFields,
|
|
4
4
|
shouldLogDiskPressureBackgroundSkip,
|
|
5
5
|
} from "../daemon/disk-pressure-background-gate.js";
|
|
6
|
-
import { emitFeedEvent } from "../home/emit-feed-event.js";
|
|
7
6
|
import { bootstrapConversation } from "../memory/conversation-bootstrap.js";
|
|
8
7
|
import { getConversation } from "../memory/conversation-crud.js";
|
|
9
8
|
import { invalidateAssistantInferredItemsForConversation } from "../memory/task-memory-cleanup.js";
|
|
9
|
+
import { emitNotificationSignal } from "../notifications/emit-signal.js";
|
|
10
10
|
import { wakeAgentForOpportunity } from "../runtime/agent-wake.js";
|
|
11
|
+
import { runBackgroundJob } from "../runtime/background-job-runner.js";
|
|
11
12
|
import { runSequencesOnce } from "../sequence/engine.js";
|
|
12
13
|
import { getLogger } from "../util/logger.js";
|
|
13
|
-
import {
|
|
14
|
-
runWatchersOnce,
|
|
15
|
-
type WatcherEscalator,
|
|
16
|
-
type WatcherNotifier,
|
|
17
|
-
} from "../watcher/engine.js";
|
|
14
|
+
import { runWatchersOnce, type WatcherNotifier } from "../watcher/engine.js";
|
|
18
15
|
import { hasSetConstructs } from "./recurrence-engine.js";
|
|
19
16
|
import { applyRetryDecision, decideRetry } from "./retry-policy.js";
|
|
20
17
|
import { runScript, type ScriptResult } from "./run-script.js";
|
|
@@ -63,6 +60,20 @@ const TICK_INTERVAL_MS = 15_000;
|
|
|
63
60
|
*/
|
|
64
61
|
const WAKE_MAX_RETRIES = 20;
|
|
65
62
|
|
|
63
|
+
/**
|
|
64
|
+
* Hard timeout for `talk`-mode scheduled jobs. Schedules can do
|
|
65
|
+
* non-trivial work (research, summarize the day, etc.), so the cap is
|
|
66
|
+
* generous; it exists primarily so a wedged turn cannot block the next
|
|
67
|
+
* scheduler tick indefinitely. Mirrors the heartbeat/filing budgets.
|
|
68
|
+
*/
|
|
69
|
+
const SCHEDULE_TALK_TIMEOUT_MS = 30 * 60 * 1000;
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Apply retry policy on schedule-execution failure. Retries are scheduled by
|
|
73
|
+
* `applyRetryDecision`; once retries are exhausted, the `emitAlert` callback
|
|
74
|
+
* fires an `activity.failed` notification so the user sees that a job
|
|
75
|
+
* permanently failed rather than just silently disappearing.
|
|
76
|
+
*/
|
|
66
77
|
function handleExecutionFailure(params: {
|
|
67
78
|
job: ScheduleJob;
|
|
68
79
|
errorMsg: string;
|
|
@@ -77,8 +88,13 @@ function handleExecutionFailure(params: {
|
|
|
77
88
|
scheduleRetry,
|
|
78
89
|
failOneShotPermanently,
|
|
79
90
|
resetRetryCount,
|
|
80
|
-
emitAlert: (
|
|
81
|
-
|
|
91
|
+
emitAlert: (_title, _summary, dedupKey) =>
|
|
92
|
+
emitScheduleActivityFailed({
|
|
93
|
+
jobId: params.job.id,
|
|
94
|
+
jobName: params.job.name,
|
|
95
|
+
errorMessage: params.errorMsg,
|
|
96
|
+
dedupKey,
|
|
97
|
+
}),
|
|
82
98
|
log,
|
|
83
99
|
});
|
|
84
100
|
}
|
|
@@ -87,7 +103,6 @@ export function startScheduler(
|
|
|
87
103
|
processMessage: ScheduleMessageProcessor,
|
|
88
104
|
notifyScheduleOneShot: ScheduleNotifyModeNotifier,
|
|
89
105
|
watcherNotifier?: WatcherNotifier,
|
|
90
|
-
watcherEscalator?: WatcherEscalator,
|
|
91
106
|
onScheduleConversationCreated?: ScheduleConversationCreatedNotifier,
|
|
92
107
|
): SchedulerHandle {
|
|
93
108
|
let stopped = false;
|
|
@@ -101,7 +116,6 @@ export function startScheduler(
|
|
|
101
116
|
processMessage,
|
|
102
117
|
notifyScheduleOneShot,
|
|
103
118
|
watcherNotifier,
|
|
104
|
-
watcherEscalator,
|
|
105
119
|
onScheduleConversationCreated,
|
|
106
120
|
);
|
|
107
121
|
} catch (err) {
|
|
@@ -123,7 +137,6 @@ export function startScheduler(
|
|
|
123
137
|
processMessage,
|
|
124
138
|
notifyScheduleOneShot,
|
|
125
139
|
watcherNotifier,
|
|
126
|
-
watcherEscalator,
|
|
127
140
|
onScheduleConversationCreated,
|
|
128
141
|
);
|
|
129
142
|
},
|
|
@@ -138,7 +151,6 @@ export async function runScheduleOnce(
|
|
|
138
151
|
processMessage: ScheduleMessageProcessor,
|
|
139
152
|
notifyScheduleOneShot: ScheduleNotifyModeNotifier,
|
|
140
153
|
watcherNotifier?: WatcherNotifier,
|
|
141
|
-
watcherEscalator?: WatcherEscalator,
|
|
142
154
|
onScheduleConversationCreated?: ScheduleConversationCreatedNotifier,
|
|
143
155
|
): Promise<number> {
|
|
144
156
|
const now = Date.now();
|
|
@@ -181,21 +193,11 @@ export async function runScheduleOnce(
|
|
|
181
193
|
const successRunId = createScheduleRun(job.id, `notify-ok:${job.id}`);
|
|
182
194
|
completeScheduleRun(successRunId, { status: "ok" });
|
|
183
195
|
completeOneShot(job.id);
|
|
184
|
-
emitScheduleFeedEvent({
|
|
185
|
-
title: job.name,
|
|
186
|
-
summary: "Reminder fired.",
|
|
187
|
-
dedupKey: `schedule-notify-oneshot:${job.id}`,
|
|
188
|
-
});
|
|
189
196
|
} else {
|
|
190
197
|
// Track recurring notify-mode success so lastStatus resets to ok
|
|
191
198
|
// and retryCount clears after a transient failure.
|
|
192
199
|
const runId = createScheduleRun(job.id, `notify-ok:${job.id}`);
|
|
193
200
|
completeScheduleRun(runId, { status: "ok" });
|
|
194
|
-
emitScheduleFeedEvent({
|
|
195
|
-
title: job.name,
|
|
196
|
-
summary: "Scheduled notification fired.",
|
|
197
|
-
dedupKey: `schedule-run:${runId}`,
|
|
198
|
-
});
|
|
199
201
|
}
|
|
200
202
|
} catch (err) {
|
|
201
203
|
log.warn(
|
|
@@ -234,13 +236,6 @@ export async function runScheduleOnce(
|
|
|
234
236
|
error: result.stderr || undefined,
|
|
235
237
|
});
|
|
236
238
|
if (result.exitCode === 0) {
|
|
237
|
-
if (!job.quiet) {
|
|
238
|
-
emitScheduleFeedEvent({
|
|
239
|
-
title: job.name,
|
|
240
|
-
summary: "Script ran.",
|
|
241
|
-
dedupKey: `schedule-run:${runId}`,
|
|
242
|
-
});
|
|
243
|
-
}
|
|
244
239
|
if (isOneShot) completeOneShot(job.id);
|
|
245
240
|
} else {
|
|
246
241
|
const errorMsg =
|
|
@@ -337,13 +332,6 @@ export async function runScheduleOnce(
|
|
|
337
332
|
completeScheduleRun(successRunId, { status: "ok" });
|
|
338
333
|
completeOneShot(job.id);
|
|
339
334
|
}
|
|
340
|
-
if (!job.quiet) {
|
|
341
|
-
emitScheduleFeedEvent({
|
|
342
|
-
title: job.name,
|
|
343
|
-
summary: "Deferred wake fired.",
|
|
344
|
-
dedupKey: `schedule-wake:${job.id}`,
|
|
345
|
-
});
|
|
346
|
-
}
|
|
347
335
|
} catch (err) {
|
|
348
336
|
log.warn(
|
|
349
337
|
{ err, jobId: job.id, name: job.name, wakeConversationId, isOneShot },
|
|
@@ -412,24 +400,23 @@ export async function runScheduleOnce(
|
|
|
412
400
|
// Track the schedule run using the task's conversation
|
|
413
401
|
const runId = createScheduleRun(job.id, result.conversationId);
|
|
414
402
|
if (result.status === "failed") {
|
|
403
|
+
const errorMessage = result.error ?? "Task run failed";
|
|
415
404
|
completeScheduleRun(runId, {
|
|
416
405
|
status: "error",
|
|
417
|
-
error:
|
|
406
|
+
error: errorMessage,
|
|
407
|
+
});
|
|
408
|
+
emitTaskActivityFailed({
|
|
409
|
+
taskId,
|
|
410
|
+
conversationId: result.conversationId,
|
|
411
|
+
errorMessage,
|
|
418
412
|
});
|
|
419
413
|
handleExecutionFailure({
|
|
420
414
|
job,
|
|
421
|
-
errorMsg:
|
|
415
|
+
errorMsg: errorMessage,
|
|
422
416
|
isOneShot,
|
|
423
417
|
});
|
|
424
418
|
} else {
|
|
425
419
|
completeScheduleRun(runId, { status: "ok" });
|
|
426
|
-
if (!job.quiet) {
|
|
427
|
-
emitScheduleFeedEvent({
|
|
428
|
-
title: job.name,
|
|
429
|
-
summary: "Scheduled task ran.",
|
|
430
|
-
dedupKey: `schedule-run:${runId}`,
|
|
431
|
-
});
|
|
432
|
-
}
|
|
433
420
|
if (isOneShot) completeOneShot(job.id);
|
|
434
421
|
}
|
|
435
422
|
processed += 1;
|
|
@@ -464,6 +451,11 @@ export async function runScheduleOnce(
|
|
|
464
451
|
});
|
|
465
452
|
const runId = createScheduleRun(job.id, fallbackConversation.id);
|
|
466
453
|
completeScheduleRun(runId, { status: "error", error: message });
|
|
454
|
+
emitTaskActivityFailed({
|
|
455
|
+
taskId,
|
|
456
|
+
conversationId: fallbackConversation.id,
|
|
457
|
+
errorMessage: message,
|
|
458
|
+
});
|
|
467
459
|
handleExecutionFailure({
|
|
468
460
|
job,
|
|
469
461
|
errorMsg: message,
|
|
@@ -474,71 +466,104 @@ export async function runScheduleOnce(
|
|
|
474
466
|
}
|
|
475
467
|
|
|
476
468
|
// Reuse the conversation from the last successful run when the flag is set
|
|
477
|
-
// and a prior conversation still exists; otherwise
|
|
478
|
-
|
|
479
|
-
|
|
469
|
+
// and a prior conversation still exists; otherwise route through the
|
|
470
|
+
// shared `runBackgroundJob` runner (which bootstraps fresh, applies the
|
|
471
|
+
// standard timeout, and emits `activity.failed` on any failure).
|
|
472
|
+
const isRruleSetMsg =
|
|
473
|
+
job.syntax === "rrule" &&
|
|
474
|
+
job.expression != null &&
|
|
475
|
+
hasSetConstructs(job.expression);
|
|
476
|
+
|
|
477
|
+
let reusedConversationId: string | null = null;
|
|
480
478
|
if (job.reuseConversation && !isOneShot) {
|
|
481
479
|
const lastId = getLastScheduleConversationId(job.id);
|
|
482
480
|
if (lastId && getConversation(lastId)) {
|
|
483
|
-
|
|
484
|
-
conversationReused = true;
|
|
481
|
+
reusedConversationId = lastId;
|
|
485
482
|
}
|
|
486
483
|
}
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
484
|
+
|
|
485
|
+
log.info(
|
|
486
|
+
{
|
|
487
|
+
jobId: job.id,
|
|
488
|
+
name: job.name,
|
|
489
|
+
syntax: job.syntax,
|
|
490
|
+
expression: job.expression,
|
|
491
|
+
isRruleSet: isRruleSetMsg,
|
|
492
|
+
isOneShot,
|
|
493
|
+
...(reusedConversationId
|
|
494
|
+
? { conversationId: reusedConversationId }
|
|
495
|
+
: {}),
|
|
496
|
+
},
|
|
497
|
+
isOneShot ? "Executing one-shot schedule" : "Executing schedule",
|
|
498
|
+
);
|
|
499
|
+
|
|
500
|
+
let conversationId: string;
|
|
501
|
+
let ok: boolean;
|
|
502
|
+
let errorMsg: string | undefined;
|
|
503
|
+
const conversationReused = reusedConversationId != null;
|
|
504
|
+
|
|
505
|
+
if (reusedConversationId) {
|
|
506
|
+
// Reuse path: keep using the injected `processMessage` callback so the
|
|
507
|
+
// existing conversation is continued in place. `runBackgroundJob`
|
|
508
|
+
// unconditionally bootstraps a new conversation and is therefore not a
|
|
509
|
+
// drop-in replacement for the reuse semantics.
|
|
510
|
+
conversationId = reusedConversationId;
|
|
511
|
+
onScheduleConversationCreated?.({
|
|
512
|
+
conversationId,
|
|
491
513
|
scheduleJobId: job.id,
|
|
492
|
-
|
|
514
|
+
title: job.name,
|
|
515
|
+
});
|
|
516
|
+
try {
|
|
517
|
+
await processMessage(conversationId, job.message, {
|
|
518
|
+
trustClass: "guardian",
|
|
519
|
+
});
|
|
520
|
+
ok = true;
|
|
521
|
+
} catch (err) {
|
|
522
|
+
ok = false;
|
|
523
|
+
errorMsg = err instanceof Error ? err.message : String(err);
|
|
524
|
+
}
|
|
525
|
+
} else {
|
|
526
|
+
// Fresh-bootstrap path: route through the shared runner so failures
|
|
527
|
+
// surface via `activity.failed` and we get the standard timeout +
|
|
528
|
+
// error-classification policy applied to every background producer.
|
|
529
|
+
// The runner fires `onConversationCreated` synchronously after bootstrap
|
|
530
|
+
// (before `processMessage` starts) so the macOS sidebar gets the new
|
|
531
|
+
// conversation immediately rather than after the up-to-30-min job ends.
|
|
532
|
+
const result = await runBackgroundJob({
|
|
533
|
+
jobName: `schedule:${job.id}`,
|
|
534
|
+
source: "schedule",
|
|
535
|
+
prompt: job.message,
|
|
536
|
+
trustContext: { sourceChannel: "vellum", trustClass: "guardian" },
|
|
537
|
+
callSite: "mainAgent",
|
|
538
|
+
timeoutMs: SCHEDULE_TALK_TIMEOUT_MS,
|
|
493
539
|
origin: "schedule",
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
540
|
+
groupId: "system:scheduled",
|
|
541
|
+
conversationType: "scheduled",
|
|
542
|
+
scheduleJobId: job.id,
|
|
543
|
+
suppressFailureNotifications: job.quiet === true,
|
|
544
|
+
onConversationCreated: (newConversationId) => {
|
|
545
|
+
onScheduleConversationCreated?.({
|
|
546
|
+
conversationId: newConversationId,
|
|
547
|
+
scheduleJobId: job.id,
|
|
548
|
+
title: job.name,
|
|
549
|
+
});
|
|
550
|
+
},
|
|
497
551
|
});
|
|
498
|
-
conversationId =
|
|
552
|
+
conversationId = result.conversationId;
|
|
553
|
+
ok = result.ok;
|
|
554
|
+
errorMsg = result.error?.message;
|
|
499
555
|
}
|
|
500
|
-
|
|
501
|
-
conversationId,
|
|
502
|
-
scheduleJobId: job.id,
|
|
503
|
-
title: job.name,
|
|
504
|
-
});
|
|
556
|
+
|
|
505
557
|
const runId = createScheduleRun(job.id, conversationId);
|
|
506
|
-
const isRruleSetMsg =
|
|
507
|
-
job.syntax === "rrule" &&
|
|
508
|
-
job.expression != null &&
|
|
509
|
-
hasSetConstructs(job.expression);
|
|
510
558
|
|
|
511
|
-
|
|
512
|
-
log.info(
|
|
513
|
-
{
|
|
514
|
-
jobId: job.id,
|
|
515
|
-
name: job.name,
|
|
516
|
-
syntax: job.syntax,
|
|
517
|
-
expression: job.expression,
|
|
518
|
-
isRruleSet: isRruleSetMsg,
|
|
519
|
-
isOneShot,
|
|
520
|
-
conversationId,
|
|
521
|
-
},
|
|
522
|
-
isOneShot ? "Executing one-shot schedule" : "Executing schedule",
|
|
523
|
-
);
|
|
524
|
-
await processMessage(conversationId, job.message, {
|
|
525
|
-
trustClass: "guardian",
|
|
526
|
-
});
|
|
559
|
+
if (ok) {
|
|
527
560
|
completeScheduleRun(runId, { status: "ok" });
|
|
528
|
-
if (!job.quiet) {
|
|
529
|
-
emitScheduleFeedEvent({
|
|
530
|
-
title: job.name,
|
|
531
|
-
summary: isOneShot ? "One-shot reminder ran." : "Scheduled job ran.",
|
|
532
|
-
dedupKey: `schedule-run:${runId}`,
|
|
533
|
-
});
|
|
534
|
-
}
|
|
535
561
|
if (isOneShot) completeOneShot(job.id);
|
|
536
562
|
processed += 1;
|
|
537
|
-
}
|
|
538
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
563
|
+
} else {
|
|
539
564
|
log.warn(
|
|
540
565
|
{
|
|
541
|
-
err,
|
|
566
|
+
err: errorMsg,
|
|
542
567
|
jobId: job.id,
|
|
543
568
|
name: job.name,
|
|
544
569
|
syntax: job.syntax,
|
|
@@ -550,8 +575,12 @@ export async function runScheduleOnce(
|
|
|
550
575
|
? "One-shot schedule execution failed"
|
|
551
576
|
: "Schedule execution failed",
|
|
552
577
|
);
|
|
553
|
-
completeScheduleRun(runId, { status: "error", error:
|
|
554
|
-
handleExecutionFailure({
|
|
578
|
+
completeScheduleRun(runId, { status: "error", error: errorMsg });
|
|
579
|
+
handleExecutionFailure({
|
|
580
|
+
job,
|
|
581
|
+
errorMsg: errorMsg ?? "Schedule run failed",
|
|
582
|
+
isOneShot,
|
|
583
|
+
});
|
|
555
584
|
|
|
556
585
|
// Only skip invalidation when the conversation was *actually* reused,
|
|
557
586
|
// i.e. it contains prior successful context worth preserving. When
|
|
@@ -572,13 +601,9 @@ export async function runScheduleOnce(
|
|
|
572
601
|
}
|
|
573
602
|
|
|
574
603
|
// ── Watchers (event-driven polling) ────────────────────────────────
|
|
575
|
-
if (watcherNotifier
|
|
604
|
+
if (watcherNotifier) {
|
|
576
605
|
try {
|
|
577
|
-
const watcherProcessed = await runWatchersOnce(
|
|
578
|
-
processMessage,
|
|
579
|
-
watcherNotifier,
|
|
580
|
-
watcherEscalator,
|
|
581
|
-
);
|
|
606
|
+
const watcherProcessed = await runWatchersOnce(watcherNotifier);
|
|
582
607
|
processed += watcherProcessed;
|
|
583
608
|
} catch (err) {
|
|
584
609
|
log.error({ err }, "Watcher tick failed");
|
|
@@ -587,7 +612,7 @@ export async function runScheduleOnce(
|
|
|
587
612
|
|
|
588
613
|
// ── Sequences (multi-step outreach) ──────────────────────────────
|
|
589
614
|
try {
|
|
590
|
-
const sequenceProcessed = await runSequencesOnce(
|
|
615
|
+
const sequenceProcessed = await runSequencesOnce();
|
|
591
616
|
processed += sequenceProcessed;
|
|
592
617
|
} catch (err) {
|
|
593
618
|
log.error({ err }, "Sequence engine tick failed");
|
|
@@ -600,30 +625,82 @@ export async function runScheduleOnce(
|
|
|
600
625
|
}
|
|
601
626
|
|
|
602
627
|
/**
|
|
603
|
-
*
|
|
604
|
-
*
|
|
605
|
-
*
|
|
606
|
-
*
|
|
607
|
-
*
|
|
608
|
-
* the job id, for one-shot notify-mode which fires before a run
|
|
609
|
-
* record is created) so each run lands as its own entry in the
|
|
610
|
-
* activity log — the writer's per-source cap keeps total volume
|
|
611
|
-
* bounded.
|
|
628
|
+
* Emit an `activity.failed` notification for a failed scheduled task run.
|
|
629
|
+
* Mirrors the shape `runBackgroundJob` produces for its own failures so the
|
|
630
|
+
* home feed and native notifications stay consistent regardless of which
|
|
631
|
+
* code path executed the work. Fire-and-forget — a notification failure
|
|
632
|
+
* must never break scheduler operation.
|
|
612
633
|
*/
|
|
613
|
-
function
|
|
614
|
-
|
|
615
|
-
|
|
634
|
+
function emitTaskActivityFailed(args: {
|
|
635
|
+
taskId: string;
|
|
636
|
+
conversationId: string;
|
|
637
|
+
errorMessage: string;
|
|
638
|
+
}): void {
|
|
639
|
+
const day = new Date().toISOString().slice(0, 10);
|
|
640
|
+
emitNotificationSignal({
|
|
641
|
+
sourceChannel: "scheduler",
|
|
642
|
+
sourceContextId: args.conversationId,
|
|
643
|
+
sourceEventName: "activity.failed",
|
|
644
|
+
dedupeKey: `activity-failed:task:${args.taskId}:${day}`,
|
|
645
|
+
contextPayload: {
|
|
646
|
+
jobName: `task:${args.taskId}`,
|
|
647
|
+
errorMessage: args.errorMessage,
|
|
648
|
+
errorKind: "exception",
|
|
649
|
+
},
|
|
650
|
+
attentionHints: {
|
|
651
|
+
requiresAction: false,
|
|
652
|
+
urgency: "medium",
|
|
653
|
+
isAsyncBackground: true,
|
|
654
|
+
visibleInSourceNow: false,
|
|
655
|
+
},
|
|
656
|
+
}).catch((emitErr) => {
|
|
657
|
+
log.warn(
|
|
658
|
+
{
|
|
659
|
+
err: emitErr instanceof Error ? emitErr.message : String(emitErr),
|
|
660
|
+
taskId: args.taskId,
|
|
661
|
+
conversationId: args.conversationId,
|
|
662
|
+
},
|
|
663
|
+
"Failed to emit activity.failed notification for scheduled task",
|
|
664
|
+
);
|
|
665
|
+
});
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
/**
|
|
669
|
+
* Emit an `activity.failed` notification for a schedule whose retries have
|
|
670
|
+
* been exhausted. Distinct from `emitTaskActivityFailed` (which fires per
|
|
671
|
+
* failed task run) — this one fires once when the retry policy has given
|
|
672
|
+
* up, so the dedupeKey caller is the per-attempt key passed in by
|
|
673
|
+
* `applyRetryDecision` (already includes the job id and a timestamp).
|
|
674
|
+
*/
|
|
675
|
+
function emitScheduleActivityFailed(args: {
|
|
676
|
+
jobId: string;
|
|
677
|
+
jobName: string;
|
|
678
|
+
errorMessage: string;
|
|
616
679
|
dedupKey: string;
|
|
617
680
|
}): void {
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
681
|
+
emitNotificationSignal({
|
|
682
|
+
sourceChannel: "scheduler",
|
|
683
|
+
sourceContextId: args.jobId,
|
|
684
|
+
sourceEventName: "activity.failed",
|
|
685
|
+
dedupeKey: args.dedupKey,
|
|
686
|
+
contextPayload: {
|
|
687
|
+
jobName: `schedule:${args.jobName}`,
|
|
688
|
+
errorMessage: args.errorMessage,
|
|
689
|
+
errorKind: "exception",
|
|
690
|
+
},
|
|
691
|
+
attentionHints: {
|
|
692
|
+
requiresAction: false,
|
|
693
|
+
urgency: "medium",
|
|
694
|
+
isAsyncBackground: true,
|
|
695
|
+
visibleInSourceNow: false,
|
|
696
|
+
},
|
|
697
|
+
}).catch((emitErr) => {
|
|
624
698
|
log.warn(
|
|
625
|
-
{
|
|
626
|
-
|
|
699
|
+
{
|
|
700
|
+
err: emitErr instanceof Error ? emitErr.message : String(emitErr),
|
|
701
|
+
jobId: args.jobId,
|
|
702
|
+
},
|
|
703
|
+
"Failed to emit activity.failed notification for exhausted schedule",
|
|
627
704
|
);
|
|
628
705
|
});
|
|
629
706
|
}
|
|
@@ -40,18 +40,19 @@ const STORE_PATH = join(TEST_DIR, "keys.enc");
|
|
|
40
40
|
* Regression test for the env-var fallback in `getProviderKeyAsync`.
|
|
41
41
|
*
|
|
42
42
|
* PR #27126 introduced `getLlmProviderEnvVar` which is LLM-scoped only.
|
|
43
|
-
* After that PR, calls like `getProviderKeyAsync("brave")
|
|
44
|
-
* `getProviderKeyAsync("perplexity")
|
|
45
|
-
* the secure store was empty, breaking web-search
|
|
46
|
-
* env-var-sourced
|
|
47
|
-
*
|
|
48
|
-
*
|
|
43
|
+
* After that PR, calls like `getProviderKeyAsync("brave")`,
|
|
44
|
+
* `getProviderKeyAsync("perplexity")`, and other search-provider keys stopped
|
|
45
|
+
* resolving the env var when the secure store was empty, breaking web-search
|
|
46
|
+
* for users with env-var-sourced search keys. The fix routes the fallback
|
|
47
|
+
* through `getAnyProviderEnvVar` which consults both the LLM catalog and the
|
|
48
|
+
* search-provider map.
|
|
49
49
|
*/
|
|
50
50
|
describe("getProviderKeyAsync env-var fallback (regression #27126)", () => {
|
|
51
51
|
const SAVED_ENV: Record<string, string | undefined> = {};
|
|
52
52
|
const MANAGED_VARS = [
|
|
53
53
|
"BRAVE_API_KEY",
|
|
54
54
|
"PERPLEXITY_API_KEY",
|
|
55
|
+
"TAVILY_API_KEY",
|
|
55
56
|
"ANTHROPIC_API_KEY",
|
|
56
57
|
"OPENAI_API_KEY",
|
|
57
58
|
];
|
|
@@ -97,6 +98,11 @@ describe("getProviderKeyAsync env-var fallback (regression #27126)", () => {
|
|
|
97
98
|
expect(await getProviderKeyAsync("perplexity")).toBe("pplx-env-test");
|
|
98
99
|
});
|
|
99
100
|
|
|
101
|
+
test("returns TAVILY_API_KEY from process.env when secure store is empty", async () => {
|
|
102
|
+
process.env.TAVILY_API_KEY = "tavily-env-test";
|
|
103
|
+
expect(await getProviderKeyAsync("tavily")).toBe("tavily-env-test");
|
|
104
|
+
});
|
|
105
|
+
|
|
100
106
|
test("returns ANTHROPIC_API_KEY from process.env when secure store is empty (LLM regression)", async () => {
|
|
101
107
|
process.env.ANTHROPIC_API_KEY = "anthropic-env-test";
|
|
102
108
|
expect(await getProviderKeyAsync("anthropic")).toBe("anthropic-env-test");
|
package/src/sequence/engine.ts
CHANGED
|
@@ -6,10 +6,8 @@
|
|
|
6
6
|
* sends through the messaging layer.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import { emitFeedEvent } from "../home/emit-feed-event.js";
|
|
10
|
-
import { bootstrapConversation } from "../memory/conversation-bootstrap.js";
|
|
11
9
|
import { getMessages } from "../memory/conversation-crud.js";
|
|
12
|
-
import
|
|
10
|
+
import { runBackgroundJob } from "../runtime/background-job-runner.js";
|
|
13
11
|
import { getLogger } from "../util/logger.js";
|
|
14
12
|
import { recordEvent } from "./analytics.js";
|
|
15
13
|
import { checkAllPreSend, recordSend } from "./guardrails.js";
|
|
@@ -28,14 +26,13 @@ const log = getLogger("sequence-engine");
|
|
|
28
26
|
|
|
29
27
|
const BATCH_SIZE = 10;
|
|
30
28
|
const ERROR_RETRY_DELAY_MS = 60_000;
|
|
29
|
+
const STEP_TIMEOUT_MS = 10 * 60 * 1000; // 10 minutes per step
|
|
31
30
|
|
|
32
31
|
/**
|
|
33
32
|
* Process due sequence enrollments. Called by the scheduler on each tick.
|
|
34
33
|
* Returns the number of enrollments processed.
|
|
35
34
|
*/
|
|
36
|
-
export async function runSequencesOnce(
|
|
37
|
-
processMessage: ScheduleMessageProcessor,
|
|
38
|
-
): Promise<number> {
|
|
35
|
+
export async function runSequencesOnce(): Promise<number> {
|
|
39
36
|
const now = Date.now();
|
|
40
37
|
const claimed = claimDueEnrollments(now, BATCH_SIZE);
|
|
41
38
|
if (claimed.length === 0) return 0;
|
|
@@ -43,7 +40,7 @@ export async function runSequencesOnce(
|
|
|
43
40
|
let processed = 0;
|
|
44
41
|
for (const enrollment of claimed) {
|
|
45
42
|
try {
|
|
46
|
-
await processEnrollment(enrollment
|
|
43
|
+
await processEnrollment(enrollment);
|
|
47
44
|
processed += 1;
|
|
48
45
|
} catch (err) {
|
|
49
46
|
log.error(
|
|
@@ -83,7 +80,6 @@ export async function runSequencesOnce(
|
|
|
83
80
|
|
|
84
81
|
async function processEnrollment(
|
|
85
82
|
enrollment: SequenceEnrollment,
|
|
86
|
-
processMessage: ScheduleMessageProcessor,
|
|
87
83
|
): Promise<void> {
|
|
88
84
|
const sequence = getSequence(enrollment.sequenceId);
|
|
89
85
|
if (!sequence) {
|
|
@@ -146,30 +142,54 @@ async function processEnrollment(
|
|
|
146
142
|
// Build the prompt for the assistant to generate and send the email
|
|
147
143
|
const prompt = buildStepPrompt(enrollment, sequence, step);
|
|
148
144
|
|
|
149
|
-
// Create a conversation for this step execution
|
|
150
|
-
const conversation = bootstrapConversation({
|
|
151
|
-
source: "sequence",
|
|
152
|
-
origin: "sequence",
|
|
153
|
-
systemHint: `Sequence: ${sequence.name} — Step ${step.index + 1}`,
|
|
154
|
-
});
|
|
155
|
-
|
|
156
145
|
log.info(
|
|
157
146
|
{
|
|
158
147
|
enrollmentId: enrollment.id,
|
|
159
148
|
sequenceId: sequence.id,
|
|
160
149
|
step: step.index,
|
|
161
150
|
contactEmail: enrollment.contactEmail,
|
|
162
|
-
conversationId: conversation.id,
|
|
163
151
|
},
|
|
164
152
|
"Processing sequence step",
|
|
165
153
|
);
|
|
166
154
|
|
|
167
|
-
await
|
|
155
|
+
const result = await runBackgroundJob({
|
|
156
|
+
jobName: "sequence-step",
|
|
157
|
+
source: "sequence",
|
|
158
|
+
prompt,
|
|
159
|
+
systemHint: `Sequence: ${sequence.name} — Step ${step.index + 1}`,
|
|
160
|
+
trustContext: { sourceChannel: "vellum", trustClass: "guardian" },
|
|
161
|
+
callSite: "mainAgent",
|
|
162
|
+
timeoutMs: STEP_TIMEOUT_MS,
|
|
163
|
+
origin: "sequence",
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
if (!result.ok) {
|
|
167
|
+
// Timeouts do not cancel the in-flight `processMessage`, so retrying
|
|
168
|
+
// could double-send. Exit the enrollment instead of rescheduling.
|
|
169
|
+
if (result.errorKind === "timeout") {
|
|
170
|
+
log.error(
|
|
171
|
+
{
|
|
172
|
+
enrollmentId: enrollment.id,
|
|
173
|
+
sequenceId: sequence.id,
|
|
174
|
+
step: step.index,
|
|
175
|
+
},
|
|
176
|
+
"Sequence step timed out — exiting enrollment to prevent duplicate outreach",
|
|
177
|
+
);
|
|
178
|
+
recordEvent(sequence.id, enrollment.id, "fail", step.index, {
|
|
179
|
+
reason: "step_timeout",
|
|
180
|
+
});
|
|
181
|
+
exitEnrollment(enrollment.id, "failed");
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
throw (
|
|
185
|
+
result.error ?? new Error(`Background job failed: ${result.errorKind}`)
|
|
186
|
+
);
|
|
187
|
+
}
|
|
168
188
|
|
|
169
189
|
// Try to extract the email thread ID from conversation tool results so
|
|
170
190
|
// subsequent steps can reply in the same conversation.
|
|
171
191
|
const extractedConversationId =
|
|
172
|
-
extractThreadIdFromConversation(
|
|
192
|
+
extractThreadIdFromConversation(result.conversationId) ?? undefined;
|
|
173
193
|
if (extractedConversationId) {
|
|
174
194
|
log.info(
|
|
175
195
|
{ enrollmentId: enrollment.id, conversationId: extractedConversationId },
|
|
@@ -201,28 +221,6 @@ async function processEnrollment(
|
|
|
201
221
|
recordSend(sequence.id);
|
|
202
222
|
recordEvent(sequence.id, enrollment.id, "send", step.index);
|
|
203
223
|
|
|
204
|
-
// Fire-and-forget home-feed activity log entry. Each (enrollment,
|
|
205
|
-
// step) pair is a distinct real signal (an email actually went
|
|
206
|
-
// out), so the dedupKey embeds both — repeat emits for the same
|
|
207
|
-
// step are impossible because the enrollment advances after this
|
|
208
|
-
// line, but if they did occur they'd land on the same entry.
|
|
209
|
-
void emitFeedEvent({
|
|
210
|
-
source: "assistant",
|
|
211
|
-
title: sequence.name,
|
|
212
|
-
summary: `Sent step ${step.index + 1} of ${sequence.steps.length} to ${enrollment.contactEmail}.`,
|
|
213
|
-
dedupKey: `sequence-step:${enrollment.id}:${step.index}`,
|
|
214
|
-
}).catch((err) => {
|
|
215
|
-
log.warn(
|
|
216
|
-
{
|
|
217
|
-
err,
|
|
218
|
-
sequenceId: sequence.id,
|
|
219
|
-
enrollmentId: enrollment.id,
|
|
220
|
-
step: step.index,
|
|
221
|
-
},
|
|
222
|
-
"Failed to emit sequence step feed event",
|
|
223
|
-
);
|
|
224
|
-
});
|
|
225
|
-
|
|
226
224
|
// Advance to the next step
|
|
227
225
|
const nextStepIndex = enrollment.currentStep + 1;
|
|
228
226
|
if (nextStepIndex >= sequence.steps.length) {
|