@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
|
@@ -1,169 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Background-job → home feed event helper.
|
|
3
|
-
*
|
|
4
|
-
* The "force-write, not taught-write" entry point for the activity
|
|
5
|
-
* log. Every background job that wants to surface something on the
|
|
6
|
-
* Home page calls `emitFeedEvent({ source, title, summary, ... })`
|
|
7
|
-
* at the end of its completion path — no LLM involved, no prompt
|
|
8
|
-
* instruction, just a deterministic side effect. This keeps the
|
|
9
|
-
* "what got surfaced" question grep-able to a single symbol.
|
|
10
|
-
*
|
|
11
|
-
* Opinionated defaults for action items:
|
|
12
|
-
*
|
|
13
|
-
* - `type` is hard-coded to `"action"` — this helper is specifically
|
|
14
|
-
* for the activity log. Nudges / digests / threads continue to
|
|
15
|
-
* go through `writeAssistantFeedItem` or platform baseline
|
|
16
|
-
* generators.
|
|
17
|
-
* - `author` is hard-coded to `"assistant"` so hybrid authoring
|
|
18
|
-
* resolution treats these as assistant-produced (platform
|
|
19
|
-
* defaults can never overwrite them).
|
|
20
|
-
* - `source` is REQUIRED — actions always have an origin (gmail,
|
|
21
|
-
* slack, calendar, assistant). The per-source volume cap in
|
|
22
|
-
* `feed-writer.ts` depends on this.
|
|
23
|
-
* - No default `expiresAt`. Action items persist until the user
|
|
24
|
-
* dismisses them. Callers that want auto-expiry pass `expiresAt`
|
|
25
|
-
* explicitly.
|
|
26
|
-
* - Optional `dedupKey` — when set, the helper derives a
|
|
27
|
-
* deterministic id so a second emit for the same logical event
|
|
28
|
-
* (e.g. the same background job running twice on the same
|
|
29
|
-
* signal) updates the existing entry in place instead of
|
|
30
|
-
* appending a duplicate. When absent, a fresh `randomUUID` is
|
|
31
|
-
* used and every call produces a new entry.
|
|
32
|
-
*
|
|
33
|
-
* Persistence goes through `appendFeedItem`, inheriting its
|
|
34
|
-
* warn-log-on-failure contract — callers never need a try/catch.
|
|
35
|
-
* Schema validation runs at build time so a malformed call throws
|
|
36
|
-
* loudly at the source rather than silently corrupting the file.
|
|
37
|
-
*/
|
|
38
|
-
|
|
39
|
-
import { randomUUID } from "node:crypto";
|
|
40
|
-
|
|
41
|
-
import {
|
|
42
|
-
type FeedAction,
|
|
43
|
-
type FeedItem,
|
|
44
|
-
type FeedItemDetailPanel,
|
|
45
|
-
feedItemSchema,
|
|
46
|
-
type FeedItemSource,
|
|
47
|
-
type FeedItemUrgency,
|
|
48
|
-
} from "./feed-types.js";
|
|
49
|
-
import { appendFeedItem } from "./feed-writer.js";
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Default priority for background-job action items. Sits below the
|
|
53
|
-
* assistant nudge default (60) so an explicit nudge from
|
|
54
|
-
* `writeAssistantFeedItem` surfaces above routine activity log
|
|
55
|
-
* entries, but above the platform baseline (40) so background job
|
|
56
|
-
* traces outrank same-source platform defaults.
|
|
57
|
-
*/
|
|
58
|
-
const DEFAULT_EMIT_PRIORITY = 50;
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Parameters accepted by {@link emitFeedEvent}.
|
|
62
|
-
*
|
|
63
|
-
* All action items emitted by background jobs have an origin, so
|
|
64
|
-
* `source` is required. Everything else is optional — callers supply
|
|
65
|
-
* only the fields that describe the specific event.
|
|
66
|
-
*/
|
|
67
|
-
export interface EmitFeedEventParams {
|
|
68
|
-
/** Origin of the underlying event (gmail, slack, calendar, assistant). */
|
|
69
|
-
source: FeedItemSource;
|
|
70
|
-
/** Short headline rendered in the feed row. */
|
|
71
|
-
title: string;
|
|
72
|
-
/** Body copy rendered below the title. */
|
|
73
|
-
summary: string;
|
|
74
|
-
/**
|
|
75
|
-
* Stable key used to derive a deterministic id so a second emit
|
|
76
|
-
* for the same logical event updates the existing feed entry in
|
|
77
|
-
* place. Should include enough structure to identify the event
|
|
78
|
-
* uniquely (e.g. `"gmail-unread:msg-<messageId>"`,
|
|
79
|
-
* `"task-runner:<taskId>"`). When omitted, every call produces a
|
|
80
|
-
* fresh id and appends a new entry.
|
|
81
|
-
*/
|
|
82
|
-
dedupKey?: string;
|
|
83
|
-
/**
|
|
84
|
-
* Priority in [0, 100]. Defaults to {@link DEFAULT_EMIT_PRIORITY}
|
|
85
|
-
* (50) — above the platform baseline of 40, below the assistant
|
|
86
|
-
* nudge default of 60.
|
|
87
|
-
*/
|
|
88
|
-
priority?: number;
|
|
89
|
-
/** Action buttons surfaced on the feed row. */
|
|
90
|
-
actions?: FeedAction[];
|
|
91
|
-
/** Minimum seconds the user must be away before the item is shown. */
|
|
92
|
-
minTimeAway?: number;
|
|
93
|
-
/**
|
|
94
|
-
* Absolute ISO-8601 expiry timestamp. Omit to let the item persist
|
|
95
|
-
* until the user dismisses it (default for activity-log actions).
|
|
96
|
-
*/
|
|
97
|
-
expiresAt?: string;
|
|
98
|
-
/** Visual urgency treatment — controls badge color independently of sort priority. */
|
|
99
|
-
urgency?: FeedItemUrgency;
|
|
100
|
-
/** Optional conversation this feed item is associated with. */
|
|
101
|
-
conversationId?: string;
|
|
102
|
-
/** Server-driven detail panel descriptor; when present, the client opens this panel kind. */
|
|
103
|
-
detailPanel?: FeedItemDetailPanel;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
/**
|
|
107
|
-
* Build a deterministic feed item id from a source + dedup key.
|
|
108
|
-
*
|
|
109
|
-
* The id is intentionally human-readable: `emit:<source>:<dedupKey>`.
|
|
110
|
-
* This makes debugging easier than a hash (you can eyeball the file
|
|
111
|
-
* and immediately see which background job produced which entry)
|
|
112
|
-
* and `FeedItem.id` is a free-form string so there is no length or
|
|
113
|
-
* charset constraint to worry about.
|
|
114
|
-
*/
|
|
115
|
-
function deterministicId(source: FeedItemSource, dedupKey: string): string {
|
|
116
|
-
return `emit:${source}:${dedupKey}`;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
/**
|
|
120
|
-
* Emit a background-job activity-log entry onto the home feed.
|
|
121
|
-
*
|
|
122
|
-
* Builds a fully-formed assistant-authored `action` {@link FeedItem},
|
|
123
|
-
* validates it against the canonical schema, and persists it via
|
|
124
|
-
* {@link appendFeedItem}. Returns the constructed item so the caller
|
|
125
|
-
* can log / reference it downstream.
|
|
126
|
-
*
|
|
127
|
-
* Throws a `ZodError` if the constructed item fails validation
|
|
128
|
-
* (e.g. a `priority` outside `[0, 100]`) — a programming error in
|
|
129
|
-
* the caller that must not be silently swallowed. Persistence-layer
|
|
130
|
-
* failures are absorbed by `appendFeedItem` per its warn-log
|
|
131
|
-
* contract.
|
|
132
|
-
*/
|
|
133
|
-
export async function emitFeedEvent(
|
|
134
|
-
params: EmitFeedEventParams,
|
|
135
|
-
): Promise<FeedItem> {
|
|
136
|
-
const now = new Date().toISOString();
|
|
137
|
-
|
|
138
|
-
const id =
|
|
139
|
-
params.dedupKey !== undefined
|
|
140
|
-
? deterministicId(params.source, params.dedupKey)
|
|
141
|
-
: randomUUID();
|
|
142
|
-
|
|
143
|
-
const item: FeedItem = {
|
|
144
|
-
id,
|
|
145
|
-
type: "action",
|
|
146
|
-
source: params.source,
|
|
147
|
-
title: params.title,
|
|
148
|
-
summary: params.summary,
|
|
149
|
-
priority: params.priority ?? DEFAULT_EMIT_PRIORITY,
|
|
150
|
-
status: "new",
|
|
151
|
-
author: "assistant",
|
|
152
|
-
timestamp: now,
|
|
153
|
-
createdAt: now,
|
|
154
|
-
actions: params.actions,
|
|
155
|
-
urgency: params.urgency,
|
|
156
|
-
conversationId: params.conversationId,
|
|
157
|
-
detailPanel: params.detailPanel,
|
|
158
|
-
minTimeAway: params.minTimeAway,
|
|
159
|
-
expiresAt: params.expiresAt,
|
|
160
|
-
};
|
|
161
|
-
|
|
162
|
-
// Programming-error guardrail: invalid input throws at the source
|
|
163
|
-
// instead of corrupting the on-disk snapshot via the writer.
|
|
164
|
-
feedItemSchema.parse(item);
|
|
165
|
-
|
|
166
|
-
await appendFeedItem(item);
|
|
167
|
-
|
|
168
|
-
return item;
|
|
169
|
-
}
|
|
@@ -1,281 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Home activity feed scheduler.
|
|
3
|
-
*
|
|
4
|
-
* Periodic tick loop that drives the feed producers — the assistant
|
|
5
|
-
* roll-up loop and the platform-baseline Gmail digest generator. This
|
|
6
|
-
* is the layer that turns the Phase-5 scaffolding into a live feed: the
|
|
7
|
-
* producers exist as standalone functions, the writer knows how to
|
|
8
|
-
* persist their output, and the HTTP route + SSE pipeline surface it
|
|
9
|
-
* to the macOS client; this scheduler is what actually calls them.
|
|
10
|
-
*
|
|
11
|
-
* Design notes:
|
|
12
|
-
*
|
|
13
|
-
* - Mirrors `schedule/scheduler.ts`: `setInterval` + coalescing flag
|
|
14
|
-
* so two ticks never run in parallel, `timer.unref()` so the timer
|
|
15
|
-
* never blocks daemon exit, stop() clears the interval on shutdown.
|
|
16
|
-
*
|
|
17
|
-
* - Each producer tracks its own "last ran at" timestamp and decides
|
|
18
|
-
* whether to run on each tick. This keeps the tick cadence short
|
|
19
|
-
* (so cheap producers refresh often) while expensive producers
|
|
20
|
-
* (LLM roll-up) self-throttle independently.
|
|
21
|
-
*
|
|
22
|
-
* - Fire-and-forget: every producer failure is logged and swallowed.
|
|
23
|
-
* A broken producer must never break the tick loop or the daemon.
|
|
24
|
-
*
|
|
25
|
-
* - `writeAssistantFeedItem` / `generateGmailDigest` both invoke the
|
|
26
|
-
* feed writer directly, which publishes `home_feed_updated` on every
|
|
27
|
-
* successful write, so the macOS store auto-refreshes without this
|
|
28
|
-
* scheduler needing to touch the event hub.
|
|
29
|
-
*/
|
|
30
|
-
|
|
31
|
-
import {
|
|
32
|
-
checkDiskPressureBackgroundGate,
|
|
33
|
-
diskPressureBackgroundSkipLogFields,
|
|
34
|
-
shouldLogDiskPressureBackgroundSkip,
|
|
35
|
-
} from "../daemon/disk-pressure-background-gate.js";
|
|
36
|
-
import { getLogger } from "../util/logger.js";
|
|
37
|
-
import type { FeedItem } from "./feed-types.js";
|
|
38
|
-
import {
|
|
39
|
-
generateGmailDigest,
|
|
40
|
-
type GmailCountSource,
|
|
41
|
-
} from "./platform-gmail-digest.js";
|
|
42
|
-
import { type RollupResult, runRollupProducer } from "./rollup-producer.js";
|
|
43
|
-
|
|
44
|
-
const log = getLogger("home-feed-scheduler");
|
|
45
|
-
|
|
46
|
-
/** Tick cadence — fast enough for a Gmail digest to feel fresh. */
|
|
47
|
-
const TICK_INTERVAL_MS = 5 * 60 * 1000;
|
|
48
|
-
|
|
49
|
-
/** Per-producer minimum gap between runs. */
|
|
50
|
-
const GMAIL_DIGEST_INTERVAL_MS = 5 * 60 * 1000;
|
|
51
|
-
/**
|
|
52
|
-
* Roll-up cadence is deliberately long — 120 minutes — because the
|
|
53
|
-
* scheduler is the *safety net*, not the primary trigger. Opening the
|
|
54
|
-
* Home page fires a debounced on-visit refresh in the HTTP route (see
|
|
55
|
-
* `runtime/routes/home-feed-routes.ts`), which is the path most users
|
|
56
|
-
* actually hit. The scheduler exists so the feed still stays fresh
|
|
57
|
-
* for long idle stretches where nobody opens the Home page.
|
|
58
|
-
*/
|
|
59
|
-
const ROLLUP_INTERVAL_MS = 2 * 60 * 60 * 1000;
|
|
60
|
-
|
|
61
|
-
export interface FeedSchedulerHandle {
|
|
62
|
-
/** Stops the interval. Safe to call multiple times. */
|
|
63
|
-
stop(): void;
|
|
64
|
-
/**
|
|
65
|
-
* Run a single tick synchronously for tests. Returns a summary of
|
|
66
|
-
* which producers ran during this tick.
|
|
67
|
-
*/
|
|
68
|
-
runOnce(now?: Date): Promise<FeedTickSummary>;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
export interface FeedTickSummary {
|
|
72
|
-
gmailDigestRan: boolean;
|
|
73
|
-
rollupRan: boolean;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
export interface FeedSchedulerOptions {
|
|
77
|
-
/**
|
|
78
|
-
* Optional count source for the Gmail digest. Defaults to
|
|
79
|
-
* {@link defaultGmailCountSource}, which reads the active OAuth
|
|
80
|
-
* connection and issues one `messages.list?q=is:unread&maxResults=1`
|
|
81
|
-
* call to read the `resultSizeEstimate` field (no body fetches).
|
|
82
|
-
*/
|
|
83
|
-
gmailCountSource?: GmailCountSource;
|
|
84
|
-
/**
|
|
85
|
-
* When true (the default), the scheduler fires one tick synchronously
|
|
86
|
-
* after startup so the feed is populated on the first app open after
|
|
87
|
-
* daemon boot. Set to false in tests so the only ticks that run are
|
|
88
|
-
* the ones the test drives via `runOnce()`.
|
|
89
|
-
*/
|
|
90
|
-
runOnStart?: boolean;
|
|
91
|
-
/**
|
|
92
|
-
* Dependency seams for tests. Production callers pass `undefined` so
|
|
93
|
-
* the scheduler uses the real producer implementations. Tests pass
|
|
94
|
-
* spies to avoid `mock.module`, which leaks across files in Bun's
|
|
95
|
-
* test runner.
|
|
96
|
-
*/
|
|
97
|
-
gmailDigestRunner?: (
|
|
98
|
-
now: Date,
|
|
99
|
-
countSource: GmailCountSource,
|
|
100
|
-
) => Promise<FeedItem | null>;
|
|
101
|
-
rollupRunner?: (now: Date) => Promise<RollupResult>;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
/**
|
|
105
|
-
* Start the home feed scheduler. Returns a handle whose `stop()` is
|
|
106
|
-
* wired into the daemon shutdown sequence via `ShutdownDeps`.
|
|
107
|
-
*/
|
|
108
|
-
export function startFeedScheduler(
|
|
109
|
-
options: FeedSchedulerOptions = {},
|
|
110
|
-
): FeedSchedulerHandle {
|
|
111
|
-
let stopped = false;
|
|
112
|
-
let tickRunning = false;
|
|
113
|
-
let lastGmailDigestAt = 0;
|
|
114
|
-
let lastRollupAt = 0;
|
|
115
|
-
|
|
116
|
-
const gmailCountSource = options.gmailCountSource ?? defaultGmailCountSource;
|
|
117
|
-
const gmailDigestRunner = options.gmailDigestRunner ?? generateGmailDigest;
|
|
118
|
-
const rollupRunner =
|
|
119
|
-
options.rollupRunner ?? ((now: Date) => runRollupProducer(now));
|
|
120
|
-
|
|
121
|
-
const tick = async (now: Date = new Date()): Promise<FeedTickSummary> => {
|
|
122
|
-
const summary: FeedTickSummary = {
|
|
123
|
-
gmailDigestRan: false,
|
|
124
|
-
rollupRan: false,
|
|
125
|
-
};
|
|
126
|
-
if (stopped || tickRunning) return summary;
|
|
127
|
-
const diskPressureGate = checkDiskPressureBackgroundGate("background-work");
|
|
128
|
-
if (diskPressureGate.action === "skip") {
|
|
129
|
-
if (shouldLogDiskPressureBackgroundSkip("home-feed-scheduler")) {
|
|
130
|
-
log.warn(
|
|
131
|
-
{
|
|
132
|
-
source: "feed-scheduler",
|
|
133
|
-
...diskPressureBackgroundSkipLogFields(diskPressureGate),
|
|
134
|
-
},
|
|
135
|
-
"Home feed scheduler skipped during disk pressure cleanup mode",
|
|
136
|
-
);
|
|
137
|
-
}
|
|
138
|
-
return summary;
|
|
139
|
-
}
|
|
140
|
-
tickRunning = true;
|
|
141
|
-
const nowMs = now.getTime();
|
|
142
|
-
try {
|
|
143
|
-
if (nowMs - lastGmailDigestAt >= GMAIL_DIGEST_INTERVAL_MS) {
|
|
144
|
-
lastGmailDigestAt = nowMs;
|
|
145
|
-
summary.gmailDigestRan = true;
|
|
146
|
-
const startedAt = Date.now();
|
|
147
|
-
try {
|
|
148
|
-
const item = await gmailDigestRunner(now, gmailCountSource);
|
|
149
|
-
log.info(
|
|
150
|
-
{ wroteItem: item !== null, durationMs: Date.now() - startedAt },
|
|
151
|
-
"Gmail digest producer ran",
|
|
152
|
-
);
|
|
153
|
-
} catch (err) {
|
|
154
|
-
log.warn(
|
|
155
|
-
{ err, durationMs: Date.now() - startedAt },
|
|
156
|
-
"Gmail digest producer threw",
|
|
157
|
-
);
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
if (nowMs - lastRollupAt >= ROLLUP_INTERVAL_MS) {
|
|
162
|
-
summary.rollupRan = true;
|
|
163
|
-
const startedAt = Date.now();
|
|
164
|
-
try {
|
|
165
|
-
const result = await rollupRunner(now);
|
|
166
|
-
log.info(
|
|
167
|
-
{
|
|
168
|
-
wroteCount: result.wroteCount,
|
|
169
|
-
skippedReason: result.skippedReason,
|
|
170
|
-
durationMs: Date.now() - startedAt,
|
|
171
|
-
},
|
|
172
|
-
"Rollup producer ran",
|
|
173
|
-
);
|
|
174
|
-
// Only advance the cooldown gate when the producer actually
|
|
175
|
-
// had a chance to run the LLM. Three skip reasons short-
|
|
176
|
-
// circuit before any provider call and should NOT burn the
|
|
177
|
-
// window:
|
|
178
|
-
// - `no_provider`: the provider registry wasn't ready yet
|
|
179
|
-
// (happens on the startup tick because the feed scheduler
|
|
180
|
-
// boots before the provider init pass in
|
|
181
|
-
// `daemon/lifecycle.ts`).
|
|
182
|
-
// - `no_actions`: there was nothing to roll up. A subsequent
|
|
183
|
-
// tick should retry as soon as new actions land, not wait
|
|
184
|
-
// the full window.
|
|
185
|
-
// - `in_flight`: another caller (usually the on-visit
|
|
186
|
-
// refresh trigger in `home-feed-routes.ts`) is already
|
|
187
|
-
// running the rollup. That caller's result effectively
|
|
188
|
-
// counts as this scheduler tick's real run; bumping the
|
|
189
|
-
// gate here would force the NEXT tick to also wait out
|
|
190
|
-
// the full window even though nothing broken happened.
|
|
191
|
-
// Every other outcome — success, empty items, malformed
|
|
192
|
-
// output, provider error — is a real LLM attempt and does
|
|
193
|
-
// advance the gate so a broken producer doesn't hammer us.
|
|
194
|
-
if (
|
|
195
|
-
result.skippedReason !== "no_provider" &&
|
|
196
|
-
result.skippedReason !== "no_actions" &&
|
|
197
|
-
result.skippedReason !== "in_flight"
|
|
198
|
-
) {
|
|
199
|
-
lastRollupAt = nowMs;
|
|
200
|
-
}
|
|
201
|
-
} catch (err) {
|
|
202
|
-
lastRollupAt = nowMs;
|
|
203
|
-
log.warn(
|
|
204
|
-
{ err, durationMs: Date.now() - startedAt },
|
|
205
|
-
"Rollup producer threw",
|
|
206
|
-
);
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
} finally {
|
|
210
|
-
tickRunning = false;
|
|
211
|
-
}
|
|
212
|
-
return summary;
|
|
213
|
-
};
|
|
214
|
-
|
|
215
|
-
const timer = setInterval(() => {
|
|
216
|
-
void tick();
|
|
217
|
-
}, TICK_INTERVAL_MS);
|
|
218
|
-
timer.unref();
|
|
219
|
-
if (options.runOnStart !== false) {
|
|
220
|
-
// Fire once on startup so the feed is populated on the first app
|
|
221
|
-
// open after daemon boot. Runs in the background — startup does
|
|
222
|
-
// not await it.
|
|
223
|
-
void tick();
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
log.info(
|
|
227
|
-
{
|
|
228
|
-
tickIntervalMs: TICK_INTERVAL_MS,
|
|
229
|
-
gmailDigestIntervalMs: GMAIL_DIGEST_INTERVAL_MS,
|
|
230
|
-
rollupIntervalMs: ROLLUP_INTERVAL_MS,
|
|
231
|
-
},
|
|
232
|
-
"Home feed scheduler started",
|
|
233
|
-
);
|
|
234
|
-
|
|
235
|
-
return {
|
|
236
|
-
stop(): void {
|
|
237
|
-
if (stopped) return;
|
|
238
|
-
stopped = true;
|
|
239
|
-
clearInterval(timer);
|
|
240
|
-
log.info("Home feed scheduler stopped");
|
|
241
|
-
},
|
|
242
|
-
runOnce: tick,
|
|
243
|
-
};
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
/**
|
|
247
|
-
* Default Gmail count source — resolves the active `google` OAuth
|
|
248
|
-
* connection via {@link resolveOAuthConnection}, issues one cheap
|
|
249
|
-
* `messages.list` call with `q=is:unread&maxResults=1`, and returns
|
|
250
|
-
* the `resultSizeEstimate` field. Returns 0 when no Gmail connection
|
|
251
|
-
* exists or the call fails so the digest generator no-ops without
|
|
252
|
-
* throwing.
|
|
253
|
-
*
|
|
254
|
-
* Deliberately does NOT pre-check `isProviderConnected("google")` —
|
|
255
|
-
* that helper only reports local oauth-store rows, which are absent
|
|
256
|
-
* in managed-OAuth mode even when `resolveOAuthConnection("google")`
|
|
257
|
-
* would still resolve via the platform path. Letting the resolver
|
|
258
|
-
* make the decision is the only way to cover both modes.
|
|
259
|
-
*/
|
|
260
|
-
async function defaultGmailCountSource(): Promise<number> {
|
|
261
|
-
// Lazy import — the oauth resolver + gmail client drag in a fair
|
|
262
|
-
// bit of transitive state, and we only want to pay that cost when a
|
|
263
|
-
// tick actually runs (not at module load time).
|
|
264
|
-
const [{ resolveOAuthConnection }, { listMessages }] = await Promise.all([
|
|
265
|
-
import("../oauth/connection-resolver.js"),
|
|
266
|
-
import("../messaging/providers/gmail/client.js"),
|
|
267
|
-
]);
|
|
268
|
-
|
|
269
|
-
try {
|
|
270
|
-
const connection = await resolveOAuthConnection("google");
|
|
271
|
-
const response = await listMessages(connection, "is:unread", 1);
|
|
272
|
-
const estimate = response.resultSizeEstimate;
|
|
273
|
-
return typeof estimate === "number" && estimate >= 0 ? estimate : 0;
|
|
274
|
-
} catch (err) {
|
|
275
|
-
// Either no Gmail connection exists (managed or direct) or the
|
|
276
|
-
// API call itself failed. Both paths degrade to zero so the
|
|
277
|
-
// digest generator no-ops without writing a stale item.
|
|
278
|
-
log.warn({ err }, "Gmail count source failed; treating as zero");
|
|
279
|
-
return 0;
|
|
280
|
-
}
|
|
281
|
-
}
|
|
@@ -1,163 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Platform-baseline Gmail digest generator.
|
|
3
|
-
*
|
|
4
|
-
* Produces a mechanical "N new emails" digest FeedItem for the home
|
|
5
|
-
* activity feed. This is the first platform-authored feed source —
|
|
6
|
-
* it writes a digest item via the feed writer. Scheduling/invocation
|
|
7
|
-
* wiring lands in a follow-up PR when the end-to-end feed flow is
|
|
8
|
-
* turned on.
|
|
9
|
-
*
|
|
10
|
-
* Design notes:
|
|
11
|
-
*
|
|
12
|
-
* - No LLM calls. Title and summary are purely mechanical so this
|
|
13
|
-
* path stays cheap and deterministic. Assistant-authored nudges
|
|
14
|
-
* can override a platform digest for the same `(type, source)`
|
|
15
|
-
* pair via the feed writer's hybrid-authoring resolver (see
|
|
16
|
-
* `feed-writer.ts`).
|
|
17
|
-
* - No direct Gmail API fetches. The count is read from whatever
|
|
18
|
-
* integration cache already exists. A dependency-injected count
|
|
19
|
-
* source keeps the function testable and leaves room for the real
|
|
20
|
-
* integration wiring to land in a follow-up PR.
|
|
21
|
-
* - One-per-source replacement is handled by the writer — a fresh
|
|
22
|
-
* digest automatically replaces any prior Gmail digest in place
|
|
23
|
-
* on each call.
|
|
24
|
-
* - `minTimeAway: 3600` (1 hour) avoids showing the digest to users
|
|
25
|
-
* who've only briefly stepped away. Priority `40` is mid-tier so
|
|
26
|
-
* assistant-authored items naturally win on the sort.
|
|
27
|
-
*/
|
|
28
|
-
|
|
29
|
-
import { randomUUID } from "node:crypto";
|
|
30
|
-
|
|
31
|
-
import { getLogger } from "../util/logger.js";
|
|
32
|
-
import type { FeedItem } from "./feed-types.js";
|
|
33
|
-
import { appendFeedItem, readHomeFeed } from "./feed-writer.js";
|
|
34
|
-
|
|
35
|
-
const log = getLogger("platform-gmail-digest");
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Count source for pending Gmail emails. Kept as an injectable
|
|
39
|
-
* dependency so tests can supply a deterministic number and so the
|
|
40
|
-
* real wiring (an integration cache / event bus) can be swapped in
|
|
41
|
-
* without touching this module.
|
|
42
|
-
*
|
|
43
|
-
* The default source returns 0 — there is no persistent, platform-
|
|
44
|
-
* wide Gmail inbox count tracked in the daemon today, so the default
|
|
45
|
-
* path is a no-op until a real count source is wired in.
|
|
46
|
-
*/
|
|
47
|
-
export type GmailCountSource = () => Promise<number>;
|
|
48
|
-
|
|
49
|
-
async function defaultGmailCountSource(): Promise<number> {
|
|
50
|
-
// No platform-wide Gmail inbox count exists in the daemon yet.
|
|
51
|
-
// Callers pass an explicit `countSource` from whatever integration
|
|
52
|
-
// state is appropriate for their context (tests, watcher store,
|
|
53
|
-
// future integration event bus, etc.).
|
|
54
|
-
return 0;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Build and append a platform-baseline Gmail digest feed item.
|
|
59
|
-
*
|
|
60
|
-
* Returns `null` when the count is 0 (no-op; we do not write an
|
|
61
|
-
* empty digest). Otherwise returns the constructed `FeedItem` after
|
|
62
|
-
* successfully enqueueing it via `appendFeedItem`.
|
|
63
|
-
*
|
|
64
|
-
* Never throws — all failures degrade to a warn-log so the caller
|
|
65
|
-
* (a scheduler tick) can fire-and-forget without a try/catch.
|
|
66
|
-
*/
|
|
67
|
-
export async function generateGmailDigest(
|
|
68
|
-
now: Date,
|
|
69
|
-
countSource: GmailCountSource = defaultGmailCountSource,
|
|
70
|
-
): Promise<FeedItem | null> {
|
|
71
|
-
let count: number;
|
|
72
|
-
try {
|
|
73
|
-
count = await countSource();
|
|
74
|
-
} catch (err) {
|
|
75
|
-
log.warn({ err }, "Gmail count source threw; skipping digest");
|
|
76
|
-
return null;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
if (!Number.isFinite(count) || count <= 0) {
|
|
80
|
-
return null;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
const flooredCount = Math.floor(count);
|
|
84
|
-
const timestamp = now.toISOString();
|
|
85
|
-
const summary = buildDigestSummary(now);
|
|
86
|
-
|
|
87
|
-
const item: FeedItem = {
|
|
88
|
-
id: randomUUID(),
|
|
89
|
-
type: "digest",
|
|
90
|
-
source: "gmail",
|
|
91
|
-
author: "platform",
|
|
92
|
-
title: `${flooredCount} new email${flooredCount === 1 ? "" : "s"}`,
|
|
93
|
-
summary,
|
|
94
|
-
priority: 40,
|
|
95
|
-
minTimeAway: 3600,
|
|
96
|
-
timestamp,
|
|
97
|
-
createdAt: timestamp,
|
|
98
|
-
status: "new",
|
|
99
|
-
};
|
|
100
|
-
|
|
101
|
-
try {
|
|
102
|
-
await appendFeedItem(item);
|
|
103
|
-
} catch (err) {
|
|
104
|
-
log.warn({ err }, "Failed to append Gmail digest to feed");
|
|
105
|
-
return null;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
return item;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
/**
|
|
112
|
-
* Builds the digest summary line. Reads the prior Gmail digest's
|
|
113
|
-
* timestamp from the feed and formats it as `"Since <short time>"`
|
|
114
|
-
* so users can anchor "new emails" to a specific moment. Falls back
|
|
115
|
-
* to a generic string on first-ever digest or on any read failure
|
|
116
|
-
* (the writer is authoritative; we never throw out of the generator).
|
|
117
|
-
*/
|
|
118
|
-
function buildDigestSummary(now: Date): string {
|
|
119
|
-
const priorTimestamp = readPriorGmailDigestTimestamp();
|
|
120
|
-
if (priorTimestamp == null) {
|
|
121
|
-
return "Since your last check-in";
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
const priorDate = new Date(priorTimestamp);
|
|
125
|
-
if (Number.isNaN(priorDate.getTime())) {
|
|
126
|
-
return "Since your last check-in";
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
return `Since ${formatShortTime(priorDate, now)}`;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
function readPriorGmailDigestTimestamp(): string | null {
|
|
133
|
-
try {
|
|
134
|
-
const feed = readHomeFeed();
|
|
135
|
-
const prior = feed.items.find(
|
|
136
|
-
(item) => item.type === "digest" && item.source === "gmail",
|
|
137
|
-
);
|
|
138
|
-
return prior?.timestamp ?? null;
|
|
139
|
-
} catch (err) {
|
|
140
|
-
log.warn({ err }, "Failed to read prior Gmail digest timestamp");
|
|
141
|
-
return null;
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
/**
|
|
146
|
-
* Same-day prior → "10:32 AM". Cross-day prior → "Mon 10:32 AM".
|
|
147
|
-
* Plain `toLocaleTimeString` would conflate yesterday and today.
|
|
148
|
-
*/
|
|
149
|
-
function formatShortTime(prior: Date, now: Date): string {
|
|
150
|
-
const time = prior.toLocaleTimeString("en-US", {
|
|
151
|
-
hour: "numeric",
|
|
152
|
-
minute: "2-digit",
|
|
153
|
-
});
|
|
154
|
-
const sameDay =
|
|
155
|
-
prior.getFullYear() === now.getFullYear() &&
|
|
156
|
-
prior.getMonth() === now.getMonth() &&
|
|
157
|
-
prior.getDate() === now.getDate();
|
|
158
|
-
if (sameDay) {
|
|
159
|
-
return time;
|
|
160
|
-
}
|
|
161
|
-
const weekday = prior.toLocaleDateString("en-US", { weekday: "short" });
|
|
162
|
-
return `${weekday} ${time}`;
|
|
163
|
-
}
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
import { getConfiguredProvider } from "../providers/provider-send-message.js";
|
|
2
|
-
import { getLogger } from "../util/logger.js";
|
|
3
|
-
|
|
4
|
-
const log = getLogger("command-preview-rewriter");
|
|
5
|
-
const REWRITE_TIMEOUT_MS = 3000;
|
|
6
|
-
const REWRITE_MAX_TOKENS = 100;
|
|
7
|
-
|
|
8
|
-
const SYSTEM_PROMPT = `You rewrite technical computer commands into simple, human-readable descriptions.
|
|
9
|
-
Output ONLY the rewritten description — no quotes, no explanation, no preamble.
|
|
10
|
-
Keep it under 15 words. Use plain language a non-technical person would understand.
|
|
11
|
-
Examples:
|
|
12
|
-
- "ls -la ~/Desktop" → "View files on the desktop"
|
|
13
|
-
- "cat ~/.bashrc" → "Read shell configuration file"
|
|
14
|
-
- "rm -rf /tmp/cache" → "Delete temporary cache files"
|
|
15
|
-
- "grep -r 'password' ." → "Search files for the word 'password'"
|
|
16
|
-
- "curl https://api.example.com/users" → "Fetch user data from an API"`;
|
|
17
|
-
|
|
18
|
-
export async function rewriteCommandPreview(
|
|
19
|
-
toolName: string,
|
|
20
|
-
commandPreview: string,
|
|
21
|
-
): Promise<string | null> {
|
|
22
|
-
try {
|
|
23
|
-
const provider = await getConfiguredProvider("feedEventCopy");
|
|
24
|
-
if (!provider) return null;
|
|
25
|
-
|
|
26
|
-
const response = await provider.sendMessage(
|
|
27
|
-
[
|
|
28
|
-
{
|
|
29
|
-
role: "user",
|
|
30
|
-
content: [
|
|
31
|
-
{
|
|
32
|
-
type: "text",
|
|
33
|
-
text: `Tool: ${toolName}\nCommand: ${commandPreview}`,
|
|
34
|
-
},
|
|
35
|
-
],
|
|
36
|
-
},
|
|
37
|
-
],
|
|
38
|
-
[],
|
|
39
|
-
SYSTEM_PROMPT,
|
|
40
|
-
{
|
|
41
|
-
config: {
|
|
42
|
-
max_tokens: REWRITE_MAX_TOKENS,
|
|
43
|
-
callSite: "feedEventCopy",
|
|
44
|
-
},
|
|
45
|
-
signal: AbortSignal.timeout(REWRITE_TIMEOUT_MS),
|
|
46
|
-
},
|
|
47
|
-
);
|
|
48
|
-
|
|
49
|
-
const block = response.content.find((entry) => entry.type === "text");
|
|
50
|
-
const text =
|
|
51
|
-
block && "text" in block ? (block as { text: string }).text.trim() : "";
|
|
52
|
-
if (!text) return null;
|
|
53
|
-
return (
|
|
54
|
-
text
|
|
55
|
-
.replace(/^["'`]+/, "")
|
|
56
|
-
.replace(/["'`]+$/, "")
|
|
57
|
-
.trim() || null
|
|
58
|
-
);
|
|
59
|
-
} catch (err) {
|
|
60
|
-
log.warn(
|
|
61
|
-
{ err, toolName, commandPreview },
|
|
62
|
-
"Command preview rewrite failed",
|
|
63
|
-
);
|
|
64
|
-
return null;
|
|
65
|
-
}
|
|
66
|
-
}
|