@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
|
@@ -18,6 +18,9 @@
|
|
|
18
18
|
* handles registration, touch (heartbeat), and unregistration (dispose).
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
|
+
import { type IntervalHistogram, monitorEventLoopDelay } from "node:perf_hooks";
|
|
22
|
+
|
|
23
|
+
import * as Sentry from "@sentry/node";
|
|
21
24
|
import { z } from "zod";
|
|
22
25
|
|
|
23
26
|
import type { HostProxyCapability } from "../../channels/types.js";
|
|
@@ -44,6 +47,175 @@ const log = getLogger("events-routes");
|
|
|
44
47
|
/** Keep-alive comment sent to idle clients every 7 s by default. */
|
|
45
48
|
const DEFAULT_HEARTBEAT_INTERVAL_MS = 7_000;
|
|
46
49
|
|
|
50
|
+
/**
|
|
51
|
+
* Resolution of the event-loop delay histogram, per
|
|
52
|
+
* https://nodejs.org/api/perf_hooks.html#perf_hooksmonitoreventloopdelayoptions.
|
|
53
|
+
* A 20 ms resolution gives sub-tick visibility while keeping overhead near zero.
|
|
54
|
+
*/
|
|
55
|
+
const EVENT_LOOP_DELAY_RESOLUTION_MS = 20;
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* How often we reset the cumulative event-loop delay histogram so subsequent
|
|
59
|
+
* percentile snapshots reflect recent behavior rather than the entire process
|
|
60
|
+
* lifetime. Matches the default window used by `@fastify/under-pressure` and
|
|
61
|
+
* `prom-client` for runtime-pressure metrics.
|
|
62
|
+
*/
|
|
63
|
+
const EVENT_LOOP_DELAY_RESET_INTERVAL_MS = 60_000;
|
|
64
|
+
|
|
65
|
+
let eventLoopDelay: IntervalHistogram | null = null;
|
|
66
|
+
let eventLoopResetTimer: ReturnType<typeof setInterval> | null = null;
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Lazily start a cumulative event-loop delay histogram on the first SSE
|
|
70
|
+
* subscriber, and schedule a periodic reset so percentile readings stay
|
|
71
|
+
* meaningful across long-lived daemon processes.
|
|
72
|
+
*
|
|
73
|
+
* Guarded with try/catch because `node:perf_hooks.monitorEventLoopDelay`
|
|
74
|
+
* was a stub in some older Bun versions; if the runtime ever regresses,
|
|
75
|
+
* we still emit the shed log + Sentry capture without lag stats rather
|
|
76
|
+
* than crashing the SSE handler.
|
|
77
|
+
*/
|
|
78
|
+
function ensureEventLoopDelayMonitorStarted(): void {
|
|
79
|
+
if (eventLoopDelay !== null) return;
|
|
80
|
+
try {
|
|
81
|
+
const histogram = monitorEventLoopDelay({
|
|
82
|
+
resolution: EVENT_LOOP_DELAY_RESOLUTION_MS,
|
|
83
|
+
});
|
|
84
|
+
histogram.enable();
|
|
85
|
+
eventLoopDelay = histogram;
|
|
86
|
+
eventLoopResetTimer = setInterval(() => {
|
|
87
|
+
try {
|
|
88
|
+
histogram.reset();
|
|
89
|
+
} catch {
|
|
90
|
+
if (eventLoopResetTimer) {
|
|
91
|
+
clearInterval(eventLoopResetTimer);
|
|
92
|
+
eventLoopResetTimer = null;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}, EVENT_LOOP_DELAY_RESET_INTERVAL_MS);
|
|
96
|
+
eventLoopResetTimer.unref?.();
|
|
97
|
+
} catch (err) {
|
|
98
|
+
log.warn({ err }, "failed to start event-loop delay monitor");
|
|
99
|
+
eventLoopDelay = null;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export interface EventLoopDelaySnapshot {
|
|
104
|
+
mean_ms: number | null;
|
|
105
|
+
p99_ms: number | null;
|
|
106
|
+
max_ms: number | null;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function nsToMs(ns: number): number | null {
|
|
110
|
+
if (!Number.isFinite(ns)) return null;
|
|
111
|
+
// Round to the nearest microsecond, then express in ms (3 decimal places).
|
|
112
|
+
return Math.round(ns / 1e3) / 1e3;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function sampleEventLoopDelay(): EventLoopDelaySnapshot {
|
|
116
|
+
const histogram = eventLoopDelay;
|
|
117
|
+
if (histogram === null) {
|
|
118
|
+
return { mean_ms: null, p99_ms: null, max_ms: null };
|
|
119
|
+
}
|
|
120
|
+
try {
|
|
121
|
+
return {
|
|
122
|
+
mean_ms: nsToMs(histogram.mean),
|
|
123
|
+
p99_ms: nsToMs(histogram.percentile(99)),
|
|
124
|
+
max_ms: nsToMs(histogram.max),
|
|
125
|
+
};
|
|
126
|
+
} catch {
|
|
127
|
+
return { mean_ms: null, p99_ms: null, max_ms: null };
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export interface SseSubscriberInstrumentation {
|
|
132
|
+
subscribedAtMs: number;
|
|
133
|
+
eventsDelivered: number;
|
|
134
|
+
heartbeatsSent: number;
|
|
135
|
+
clientId: string | null;
|
|
136
|
+
interfaceId: string | null;
|
|
137
|
+
conversationKey: string | null;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export type SseShedReason = "callback_backpressure" | "heartbeat_backpressure";
|
|
141
|
+
|
|
142
|
+
export type SseShedReporter = (
|
|
143
|
+
reason: SseShedReason,
|
|
144
|
+
inst: SseSubscriberInstrumentation,
|
|
145
|
+
) => void;
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Build the structured payload sent to Sentry when an SSE subscriber is
|
|
149
|
+
* shed under backpressure.
|
|
150
|
+
*
|
|
151
|
+
* The conversation key is deliberately excluded: for channel-backed
|
|
152
|
+
* conversations (WhatsApp, Telegram, etc.) the key embeds external
|
|
153
|
+
* identifiers — phone numbers, chat IDs — and Sentry contexts are not
|
|
154
|
+
* run through the PII redactor in `instrument.ts` (only
|
|
155
|
+
* `exception.values`, `breadcrumbs`, and `extra` are). Correlation
|
|
156
|
+
* with the client-side `sse_watchdog_fired` event is achieved via the
|
|
157
|
+
* `client_id` tag + timestamp instead.
|
|
158
|
+
*/
|
|
159
|
+
export function buildSseShedSentryContext(
|
|
160
|
+
reason: SseShedReason,
|
|
161
|
+
inst: SseSubscriberInstrumentation,
|
|
162
|
+
elDelay: EventLoopDelaySnapshot,
|
|
163
|
+
nowMs: number,
|
|
164
|
+
): Record<string, unknown> {
|
|
165
|
+
return {
|
|
166
|
+
reason,
|
|
167
|
+
subscription_age_ms: nowMs - inst.subscribedAtMs,
|
|
168
|
+
events_delivered: inst.eventsDelivered,
|
|
169
|
+
heartbeats_sent: inst.heartbeatsSent,
|
|
170
|
+
client_id: inst.clientId,
|
|
171
|
+
interface_id: inst.interfaceId,
|
|
172
|
+
event_loop_delay_mean_ms: elDelay.mean_ms,
|
|
173
|
+
event_loop_delay_p99_ms: elDelay.p99_ms,
|
|
174
|
+
event_loop_delay_max_ms: elDelay.max_ms,
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Report a backpressure-shed event from an SSE subscriber to logs and Sentry.
|
|
180
|
+
*
|
|
181
|
+
* SSE subscribers are shed when `controller.desiredSize <= 0`: the consumer
|
|
182
|
+
* has stopped reading and the stream's bounded queue is full. From the
|
|
183
|
+
* daemon's side this looks identical to a hung client — and the visible
|
|
184
|
+
* symptom on the client side is the 45 s idle-watchdog firing (Sentry
|
|
185
|
+
* issue `sse_watchdog_fired`). Surfacing the shed lets us time-correlate
|
|
186
|
+
* the two sides and attribute stalls to either backpressure or another
|
|
187
|
+
* cause (network drop, event-loop starvation, etc.).
|
|
188
|
+
*
|
|
189
|
+
* The Sentry call uses level="warning" intentionally: a shed is a
|
|
190
|
+
* saturation event, not an internal error.
|
|
191
|
+
*/
|
|
192
|
+
const defaultSseShedReporter: SseShedReporter = (reason, inst) => {
|
|
193
|
+
const elDelay = sampleEventLoopDelay();
|
|
194
|
+
const sentryContext = buildSseShedSentryContext(
|
|
195
|
+
reason,
|
|
196
|
+
inst,
|
|
197
|
+
elDelay,
|
|
198
|
+
Date.now(),
|
|
199
|
+
);
|
|
200
|
+
log.warn(
|
|
201
|
+
{ ...sentryContext, conversation_key: inst.conversationKey },
|
|
202
|
+
"sse subscriber shed under backpressure",
|
|
203
|
+
);
|
|
204
|
+
|
|
205
|
+
try {
|
|
206
|
+
Sentry.withScope((scope) => {
|
|
207
|
+
scope.setLevel("warning");
|
|
208
|
+
scope.setTag("sse_shed_reason", reason);
|
|
209
|
+
if (inst.clientId) scope.setTag("client_id", inst.clientId);
|
|
210
|
+
if (inst.interfaceId) scope.setTag("interface_id", inst.interfaceId);
|
|
211
|
+
scope.setContext("sse_shed", sentryContext);
|
|
212
|
+
Sentry.captureMessage(`sse_subscriber_shed:${reason}`);
|
|
213
|
+
});
|
|
214
|
+
} catch {
|
|
215
|
+
// Never let a telemetry failure break the SSE path.
|
|
216
|
+
}
|
|
217
|
+
};
|
|
218
|
+
|
|
47
219
|
/**
|
|
48
220
|
* Stream assistant events as Server-Sent Events.
|
|
49
221
|
*
|
|
@@ -63,12 +235,15 @@ const DEFAULT_HEARTBEAT_INTERVAL_MS = 7_000;
|
|
|
63
235
|
* Options (for testing):
|
|
64
236
|
* hub -- override the event hub (defaults to process singleton).
|
|
65
237
|
* heartbeatIntervalMs -- how often to emit keep-alive comments (default 7 s).
|
|
238
|
+
* shedReporter -- override the callback invoked when a subscriber is shed
|
|
239
|
+
* under backpressure (defaults to log + Sentry capture).
|
|
66
240
|
*/
|
|
67
241
|
export function handleSubscribeAssistantEvents(
|
|
68
242
|
args: RouteHandlerArgs,
|
|
69
243
|
options?: {
|
|
70
244
|
hub?: AssistantEventHub;
|
|
71
245
|
heartbeatIntervalMs?: number;
|
|
246
|
+
shedReporter?: SseShedReporter;
|
|
72
247
|
},
|
|
73
248
|
): ReadableStream<Uint8Array> {
|
|
74
249
|
const { queryParams, headers, abortSignal } = args;
|
|
@@ -108,6 +283,7 @@ export function handleSubscribeAssistantEvents(
|
|
|
108
283
|
const hub = options?.hub ?? assistantEventHub;
|
|
109
284
|
const heartbeatIntervalMs =
|
|
110
285
|
options?.heartbeatIntervalMs ?? DEFAULT_HEARTBEAT_INTERVAL_MS;
|
|
286
|
+
const shedReporter = options?.shedReporter ?? defaultSseShedReporter;
|
|
111
287
|
|
|
112
288
|
const ALL_CAPABILITIES: HostProxyCapability[] = [
|
|
113
289
|
"host_bash",
|
|
@@ -134,6 +310,17 @@ export function handleSubscribeAssistantEvents(
|
|
|
134
310
|
let heartbeatTimer: ReturnType<typeof setInterval> | null = null;
|
|
135
311
|
let sub!: AssistantEventSubscription;
|
|
136
312
|
|
|
313
|
+
const instrumentation: SseSubscriberInstrumentation = {
|
|
314
|
+
subscribedAtMs: Date.now(),
|
|
315
|
+
eventsDelivered: 0,
|
|
316
|
+
heartbeatsSent: 0,
|
|
317
|
+
clientId,
|
|
318
|
+
interfaceId,
|
|
319
|
+
conversationKey: conversationKey ?? null,
|
|
320
|
+
};
|
|
321
|
+
|
|
322
|
+
ensureEventLoopDelayMonitorStarted();
|
|
323
|
+
|
|
137
324
|
function cleanup() {
|
|
138
325
|
if (heartbeatTimer) {
|
|
139
326
|
clearInterval(heartbeatTimer);
|
|
@@ -151,11 +338,13 @@ export function handleSubscribeAssistantEvents(
|
|
|
151
338
|
if (!controller) return;
|
|
152
339
|
try {
|
|
153
340
|
if (controller.desiredSize != null && controller.desiredSize <= 0) {
|
|
341
|
+
shedReporter("callback_backpressure", instrumentation);
|
|
154
342
|
sub.dispose();
|
|
155
343
|
cleanup();
|
|
156
344
|
return;
|
|
157
345
|
}
|
|
158
346
|
controller.enqueue(encoder.encode(formatSseFrame(event)));
|
|
347
|
+
instrumentation.eventsDelivered += 1;
|
|
159
348
|
} catch {
|
|
160
349
|
sub.dispose();
|
|
161
350
|
cleanup();
|
|
@@ -205,10 +394,12 @@ export function handleSubscribeAssistantEvents(
|
|
|
205
394
|
}
|
|
206
395
|
|
|
207
396
|
controller.enqueue(encoder.encode(formatSseHeartbeat()));
|
|
397
|
+
instrumentation.heartbeatsSent += 1;
|
|
208
398
|
|
|
209
399
|
heartbeatTimer = setInterval(() => {
|
|
210
400
|
try {
|
|
211
401
|
if (controller.desiredSize != null && controller.desiredSize <= 0) {
|
|
402
|
+
shedReporter("heartbeat_backpressure", instrumentation);
|
|
212
403
|
sub.dispose();
|
|
213
404
|
cleanup();
|
|
214
405
|
return;
|
|
@@ -217,6 +408,7 @@ export function handleSubscribeAssistantEvents(
|
|
|
217
408
|
hub.touchClient(clientId);
|
|
218
409
|
}
|
|
219
410
|
controller.enqueue(encoder.encode(formatSseHeartbeat()));
|
|
411
|
+
instrumentation.heartbeatsSent += 1;
|
|
220
412
|
} catch {
|
|
221
413
|
sub.dispose();
|
|
222
414
|
cleanup();
|
|
@@ -2,14 +2,13 @@
|
|
|
2
2
|
* Route handlers for filing management.
|
|
3
3
|
*
|
|
4
4
|
* `available` reflects whether the filing service is the active background
|
|
5
|
-
* memory job for this instance. When
|
|
5
|
+
* memory job for this instance. When `config.memory.v2.enabled` is true,
|
|
6
6
|
* filing yields to the consolidation job (see consolidation-routes.ts) and
|
|
7
7
|
* returns `available: false` so the UI can hide the row.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { z } from "zod";
|
|
11
11
|
|
|
12
|
-
import { isAssistantFeatureFlagEnabled } from "../../config/assistant-feature-flags.js";
|
|
13
12
|
import { getConfig } from "../../config/loader.js";
|
|
14
13
|
import { FilingService } from "../../filing/filing-service.js";
|
|
15
14
|
import { getLogger } from "../../util/logger.js";
|
|
@@ -19,7 +18,7 @@ import type { RouteDefinition, RouteHandlerArgs } from "./types.js";
|
|
|
19
18
|
const log = getLogger("filing-routes");
|
|
20
19
|
|
|
21
20
|
function isFilingAvailable(): boolean {
|
|
22
|
-
return !
|
|
21
|
+
return !getConfig().memory.v2.enabled;
|
|
23
22
|
}
|
|
24
23
|
|
|
25
24
|
// ---------------------------------------------------------------------------
|
|
@@ -26,11 +26,9 @@ import {
|
|
|
26
26
|
type FeedItem,
|
|
27
27
|
feedItemSchema,
|
|
28
28
|
type FeedItemStatus,
|
|
29
|
-
lowPriorityCollapsedSchema,
|
|
30
29
|
suggestedPromptSchema,
|
|
31
30
|
} from "../../home/feed-types.js";
|
|
32
31
|
import { patchFeedItemStatus, readHomeFeed } from "../../home/feed-writer.js";
|
|
33
|
-
import { runRollupProducer } from "../../home/rollup-producer.js";
|
|
34
32
|
import { getSuggestedPrompts } from "../../home/suggested-prompts.js";
|
|
35
33
|
import {
|
|
36
34
|
addMessage,
|
|
@@ -42,26 +40,6 @@ import type { RouteDefinition, RouteHandlerArgs } from "./types.js";
|
|
|
42
40
|
|
|
43
41
|
const log = getLogger("home-feed-routes");
|
|
44
42
|
|
|
45
|
-
/**
|
|
46
|
-
* Debounce window for the on-visit rollup refresh. A GET on the feed
|
|
47
|
-
* route fires the rollup producer fire-and-forget at most once per
|
|
48
|
-
* window — repeat GETs within this interval (e.g. from a client that
|
|
49
|
-
* polls aggressively, or from multiple panels opening in rapid
|
|
50
|
-
* succession) skip the trigger and just return the cached feed.
|
|
51
|
-
*/
|
|
52
|
-
const ON_VISIT_REFRESH_DEBOUNCE_MS = 10 * 60 * 1000;
|
|
53
|
-
|
|
54
|
-
let lastOnVisitRefreshAt = 0;
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Reset the on-visit debounce gate. Test-only — production callers
|
|
58
|
-
* should never touch this. Exported with an underscore-prefixed name
|
|
59
|
-
* so lint rules can flag misuse.
|
|
60
|
-
*/
|
|
61
|
-
export function __resetOnVisitRefreshStateForTests(): void {
|
|
62
|
-
lastOnVisitRefreshAt = 0;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
43
|
// ---------------------------------------------------------------------------
|
|
66
44
|
// Response / request schemas
|
|
67
45
|
// ---------------------------------------------------------------------------
|
|
@@ -77,7 +55,6 @@ const getHomeFeedResponseSchema = z.object({
|
|
|
77
55
|
updatedAt: z.string(),
|
|
78
56
|
contextBanner: contextBannerSchema,
|
|
79
57
|
suggestedPrompts: z.array(suggestedPromptSchema),
|
|
80
|
-
lowPriorityCollapsed: lowPriorityCollapsedSchema,
|
|
81
58
|
});
|
|
82
59
|
|
|
83
60
|
const patchFeedItemRequestSchema = z.object({
|
|
@@ -139,15 +116,11 @@ export async function handleGetHomeFeed({
|
|
|
139
116
|
const timeAwaySeconds = parsed;
|
|
140
117
|
|
|
141
118
|
const feed = readHomeFeed();
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
const LOW_PRIORITY_THRESHOLD = 30;
|
|
148
|
-
const lowPriorityItems = filtered.filter(
|
|
149
|
-
(item) => item.priority < LOW_PRIORITY_THRESHOLD,
|
|
150
|
-
);
|
|
119
|
+
// v2 schema dropped per-item `minTimeAway` gating; surface every item
|
|
120
|
+
// and let the client decide what to render based on its own
|
|
121
|
+
// session state. `timeAwaySeconds` survives only to feed the
|
|
122
|
+
// context-banner relative-time label.
|
|
123
|
+
const filtered = feed.items;
|
|
151
124
|
|
|
152
125
|
const now = new Date();
|
|
153
126
|
const contextBanner = {
|
|
@@ -156,11 +129,6 @@ export async function handleGetHomeFeed({
|
|
|
156
129
|
newCount: filtered.filter((i) => i.status === "new").length,
|
|
157
130
|
};
|
|
158
131
|
|
|
159
|
-
const lowPriorityCollapsed = {
|
|
160
|
-
count: lowPriorityItems.length,
|
|
161
|
-
itemIds: lowPriorityItems.map((item) => item.id),
|
|
162
|
-
};
|
|
163
|
-
|
|
164
132
|
const suggestedPrompts = await getSuggestedPrompts();
|
|
165
133
|
|
|
166
134
|
log.debug(
|
|
@@ -168,60 +136,20 @@ export async function handleGetHomeFeed({
|
|
|
168
136
|
timeAwayBucket: timeAwayBucket(timeAwaySeconds),
|
|
169
137
|
totalItems: feed.items.length,
|
|
170
138
|
filteredItems: filtered.length,
|
|
171
|
-
lowPriorityCount: lowPriorityItems.length,
|
|
172
139
|
newCount: contextBanner.newCount,
|
|
173
140
|
suggestedPromptsCount: suggestedPrompts.length,
|
|
174
141
|
},
|
|
175
142
|
"GET /v1/home/feed",
|
|
176
143
|
);
|
|
177
144
|
|
|
178
|
-
maybeTriggerOnVisitRollupRefresh(now);
|
|
179
|
-
|
|
180
145
|
return {
|
|
181
146
|
items: filtered,
|
|
182
147
|
updatedAt: feed.updatedAt,
|
|
183
148
|
contextBanner,
|
|
184
149
|
suggestedPrompts,
|
|
185
|
-
lowPriorityCollapsed,
|
|
186
150
|
};
|
|
187
151
|
}
|
|
188
152
|
|
|
189
|
-
function maybeTriggerOnVisitRollupRefresh(now: Date): void {
|
|
190
|
-
const nowMs = now.getTime();
|
|
191
|
-
if (nowMs - lastOnVisitRefreshAt < ON_VISIT_REFRESH_DEBOUNCE_MS) return;
|
|
192
|
-
const previousRefreshAt = lastOnVisitRefreshAt;
|
|
193
|
-
lastOnVisitRefreshAt = nowMs;
|
|
194
|
-
void runRollupProducer(now)
|
|
195
|
-
.then((result) => {
|
|
196
|
-
const skippedBeforeLLM =
|
|
197
|
-
result.skippedReason === "no_provider" ||
|
|
198
|
-
result.skippedReason === "no_actions" ||
|
|
199
|
-
result.skippedReason === "in_flight";
|
|
200
|
-
if (skippedBeforeLLM) {
|
|
201
|
-
if (lastOnVisitRefreshAt === nowMs) {
|
|
202
|
-
lastOnVisitRefreshAt = previousRefreshAt;
|
|
203
|
-
}
|
|
204
|
-
log.debug(
|
|
205
|
-
{ skippedReason: result.skippedReason },
|
|
206
|
-
"On-visit rollup refresh skipped; debounce gate rolled back",
|
|
207
|
-
);
|
|
208
|
-
} else if (result.skippedReason !== null) {
|
|
209
|
-
log.debug(
|
|
210
|
-
{ skippedReason: result.skippedReason },
|
|
211
|
-
"On-visit rollup refresh skipped",
|
|
212
|
-
);
|
|
213
|
-
} else {
|
|
214
|
-
log.info(
|
|
215
|
-
{ wroteCount: result.wroteCount },
|
|
216
|
-
"On-visit rollup refresh completed",
|
|
217
|
-
);
|
|
218
|
-
}
|
|
219
|
-
})
|
|
220
|
-
.catch((err) => {
|
|
221
|
-
log.warn({ err }, "On-visit rollup refresh failed");
|
|
222
|
-
});
|
|
223
|
-
}
|
|
224
|
-
|
|
225
153
|
export async function handlePatchFeedItem({
|
|
226
154
|
pathParams = {},
|
|
227
155
|
body,
|
|
@@ -309,7 +237,7 @@ export const ROUTES: RouteDefinition[] = [
|
|
|
309
237
|
type: "integer",
|
|
310
238
|
required: true,
|
|
311
239
|
description:
|
|
312
|
-
"Seconds since the user was last active in the client. Used to
|
|
240
|
+
"Seconds since the user was last active in the client. Used to compute the context-banner relative-time label.",
|
|
313
241
|
},
|
|
314
242
|
],
|
|
315
243
|
responseBody: getHomeFeedResponseSchema,
|
|
@@ -19,8 +19,13 @@ import type {
|
|
|
19
19
|
HostAppControlResultPayload,
|
|
20
20
|
HostAppControlState,
|
|
21
21
|
} from "../../daemon/message-types/host-app-control.js";
|
|
22
|
+
import {
|
|
23
|
+
enforceSameActorOrThrow,
|
|
24
|
+
SAME_ACTOR_FORBIDDEN_DESCRIPTION,
|
|
25
|
+
} from "../auth/same-actor.js";
|
|
26
|
+
import { resolveActorPrincipalIdForLocalGuardian } from "../local-actor-identity.js";
|
|
22
27
|
import * as pendingInteractions from "../pending-interactions.js";
|
|
23
|
-
import { BadRequestError } from "./errors.js";
|
|
28
|
+
import { BadRequestError, ForbiddenError } from "./errors.js";
|
|
24
29
|
import type { RouteDefinition, RouteHandlerArgs } from "./types.js";
|
|
25
30
|
|
|
26
31
|
const VALID_STATES: ReadonlySet<HostAppControlState> = new Set([
|
|
@@ -33,7 +38,7 @@ const VALID_STATES: ReadonlySet<HostAppControlState> = new Set([
|
|
|
33
38
|
// POST /v1/host-app-control-result
|
|
34
39
|
// ---------------------------------------------------------------------------
|
|
35
40
|
|
|
36
|
-
function handleHostAppControlResult({ body }: RouteHandlerArgs) {
|
|
41
|
+
function handleHostAppControlResult({ body, headers }: RouteHandlerArgs) {
|
|
37
42
|
if (!body || typeof body !== "object") {
|
|
38
43
|
throw new BadRequestError("Request body is required");
|
|
39
44
|
}
|
|
@@ -72,6 +77,34 @@ function handleHostAppControlResult({ body }: RouteHandlerArgs) {
|
|
|
72
77
|
return { accepted: true };
|
|
73
78
|
}
|
|
74
79
|
|
|
80
|
+
// Same-actor binding: when the pending interaction has a targetClientId,
|
|
81
|
+
// validate the submitting client matches and the actor principals align.
|
|
82
|
+
// Mirrors host-browser / host-cu / host-bash result routes.
|
|
83
|
+
if (peeked.targetClientId != null) {
|
|
84
|
+
const headerMap = headers ?? {};
|
|
85
|
+
const submittingClientId =
|
|
86
|
+
headerMap["x-vellum-client-id"]?.trim() || undefined;
|
|
87
|
+
if (!submittingClientId) {
|
|
88
|
+
throw new BadRequestError(
|
|
89
|
+
"x-vellum-client-id header is missing for a targeted host app-control request.",
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
if (submittingClientId !== peeked.targetClientId) {
|
|
93
|
+
throw new ForbiddenError(
|
|
94
|
+
`Client "${submittingClientId}" is not the target for this request (expected "${peeked.targetClientId}"). The targeted client must submit the result.`,
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
const submittingActorPrincipalId = resolveActorPrincipalIdForLocalGuardian(
|
|
98
|
+
headerMap["x-vellum-actor-principal-id"]?.trim() || undefined,
|
|
99
|
+
);
|
|
100
|
+
enforceSameActorOrThrow({
|
|
101
|
+
sourceActorPrincipalId: submittingActorPrincipalId,
|
|
102
|
+
targetActorPrincipalId: peeked.targetActorPrincipalId,
|
|
103
|
+
targetClientId: peeked.targetClientId,
|
|
104
|
+
op: "host_app_control",
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
|
|
75
108
|
const interaction = pendingInteractions.resolve(requestId)!;
|
|
76
109
|
const conversation = findConversation(interaction.conversationId);
|
|
77
110
|
if (!conversation) {
|
|
@@ -129,6 +162,15 @@ export const ROUTES: RouteDefinition[] = [
|
|
|
129
162
|
responseBody: z.object({
|
|
130
163
|
accepted: z.boolean(),
|
|
131
164
|
}),
|
|
165
|
+
additionalResponses: {
|
|
166
|
+
"400": {
|
|
167
|
+
description:
|
|
168
|
+
"x-vellum-client-id header is missing for a targeted host app-control request.",
|
|
169
|
+
},
|
|
170
|
+
"403": {
|
|
171
|
+
description: SAME_ACTOR_FORBIDDEN_DESCRIPTION,
|
|
172
|
+
},
|
|
173
|
+
},
|
|
132
174
|
handler: handleHostAppControlResult,
|
|
133
175
|
},
|
|
134
176
|
];
|
|
@@ -10,15 +10,22 @@ import {
|
|
|
10
10
|
markTargetInvalidated,
|
|
11
11
|
publishCdpEvent,
|
|
12
12
|
} from "../../browser-session/events.js";
|
|
13
|
-
import {
|
|
13
|
+
import {
|
|
14
|
+
enforceSameActorOrThrow,
|
|
15
|
+
SAME_ACTOR_FORBIDDEN_DESCRIPTION,
|
|
16
|
+
} from "../auth/same-actor.js";
|
|
17
|
+
import { resolveActorPrincipalIdForLocalGuardian } from "../local-actor-identity.js";
|
|
14
18
|
import * as pendingInteractions from "../pending-interactions.js";
|
|
15
|
-
import {
|
|
19
|
+
import {
|
|
20
|
+
BadRequestError,
|
|
21
|
+
ConflictError,
|
|
22
|
+
ForbiddenError,
|
|
23
|
+
NotFoundError,
|
|
24
|
+
} from "./errors.js";
|
|
16
25
|
import type { RouteDefinition, RouteHandlerArgs } from "./types.js";
|
|
17
26
|
|
|
18
27
|
/**
|
|
19
|
-
* Result of attempting to resolve a host browser result frame.
|
|
20
|
-
* the HTTP endpoint and the WS relay path so they share the same validation
|
|
21
|
-
* and resolution semantics.
|
|
28
|
+
* Result of attempting to resolve a host browser result frame.
|
|
22
29
|
*
|
|
23
30
|
* Success → the pending interaction was consumed and the conversation was
|
|
24
31
|
* notified.
|
|
@@ -30,8 +37,8 @@ export type HostBrowserResultResolution =
|
|
|
30
37
|
| { ok: true }
|
|
31
38
|
| {
|
|
32
39
|
ok: false;
|
|
33
|
-
code: "BAD_REQUEST" | "NOT_FOUND" | "CONFLICT";
|
|
34
|
-
status: 400 | 404 | 409;
|
|
40
|
+
code: "BAD_REQUEST" | "FORBIDDEN" | "NOT_FOUND" | "CONFLICT";
|
|
41
|
+
status: 400 | 403 | 404 | 409;
|
|
35
42
|
message: string;
|
|
36
43
|
};
|
|
37
44
|
|
|
@@ -40,22 +47,26 @@ export type HostBrowserResultResolution =
|
|
|
40
47
|
* the pending interaction by requestId, validates its kind is
|
|
41
48
|
* `host_browser`, and forwards the response to the owning conversation.
|
|
42
49
|
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
* the
|
|
50
|
+
* Same-actor binding: when the pending interaction has a
|
|
51
|
+
* `targetClientId` (set by the proxy at request time when an actor is
|
|
52
|
+
* known), the submitting client must (a) identify itself via
|
|
53
|
+
* `x-vellum-client-id` matching the captured target, and (b) the
|
|
54
|
+
* submitting actor's principal must match the actor captured for that
|
|
55
|
+
* client at registration time. Mirrors the host-cu / host-bash result
|
|
56
|
+
* routes.
|
|
49
57
|
*
|
|
50
58
|
* This function does NOT perform auth — callers are expected to have
|
|
51
59
|
* already authenticated the caller (the HTTP route uses
|
|
52
60
|
* `requireBoundGuardian`).
|
|
53
61
|
*/
|
|
54
|
-
export function resolveHostBrowserResultByRequestId(
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
62
|
+
export function resolveHostBrowserResultByRequestId(
|
|
63
|
+
frame: {
|
|
64
|
+
requestId?: unknown;
|
|
65
|
+
content?: unknown;
|
|
66
|
+
isError?: unknown;
|
|
67
|
+
},
|
|
68
|
+
headers?: Record<string, string | undefined>,
|
|
69
|
+
): HostBrowserResultResolution {
|
|
59
70
|
const { requestId, content, isError } = frame;
|
|
60
71
|
|
|
61
72
|
if (!requestId || typeof requestId !== "string") {
|
|
@@ -86,11 +97,60 @@ export function resolveHostBrowserResultByRequestId(frame: {
|
|
|
86
97
|
};
|
|
87
98
|
}
|
|
88
99
|
|
|
100
|
+
// Validate submitting client matches the targeted client (if any).
|
|
101
|
+
if (peeked.targetClientId != null) {
|
|
102
|
+
const headerMap = headers ?? {};
|
|
103
|
+
const submittingClientId =
|
|
104
|
+
headerMap["x-vellum-client-id"]?.trim() || undefined;
|
|
105
|
+
if (!submittingClientId) {
|
|
106
|
+
return {
|
|
107
|
+
ok: false,
|
|
108
|
+
code: "BAD_REQUEST",
|
|
109
|
+
status: 400,
|
|
110
|
+
message:
|
|
111
|
+
"x-vellum-client-id header is missing for a targeted host browser request.",
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
if (submittingClientId !== peeked.targetClientId) {
|
|
115
|
+
return {
|
|
116
|
+
ok: false,
|
|
117
|
+
code: "FORBIDDEN",
|
|
118
|
+
status: 403,
|
|
119
|
+
message: `Client "${submittingClientId}" is not the target for this request (expected "${peeked.targetClientId}"). The targeted client must submit the result.`,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Defense-in-depth: require the submitting actor's principal id to match
|
|
124
|
+
// the actor principal id captured when the target client opened its SSE
|
|
125
|
+
// stream. This prevents a different authenticated user with knowledge of
|
|
126
|
+
// both the requestId and target clientId from submitting a result on
|
|
127
|
+
// behalf of the targeted client.
|
|
128
|
+
const submittingActorPrincipalId = resolveActorPrincipalIdForLocalGuardian(
|
|
129
|
+
headerMap["x-vellum-actor-principal-id"]?.trim() || undefined,
|
|
130
|
+
);
|
|
131
|
+
try {
|
|
132
|
+
enforceSameActorOrThrow({
|
|
133
|
+
sourceActorPrincipalId: submittingActorPrincipalId,
|
|
134
|
+
targetActorPrincipalId: peeked.targetActorPrincipalId,
|
|
135
|
+
targetClientId: peeked.targetClientId,
|
|
136
|
+
op: "host_browser",
|
|
137
|
+
});
|
|
138
|
+
} catch (err) {
|
|
139
|
+
// enforceSameActorOrThrow throws ForbiddenError on rejection.
|
|
140
|
+
return {
|
|
141
|
+
ok: false,
|
|
142
|
+
code: "FORBIDDEN",
|
|
143
|
+
status: 403,
|
|
144
|
+
message: err instanceof Error ? err.message : "Same-actor check failed",
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
89
149
|
const normalizedContent = typeof content === "string" ? content : "";
|
|
90
150
|
const normalizedIsError = typeof isError === "boolean" ? isError : false;
|
|
91
151
|
|
|
92
|
-
const
|
|
93
|
-
|
|
152
|
+
const interaction = pendingInteractions.resolve(requestId);
|
|
153
|
+
interaction?.rpcResolve?.({
|
|
94
154
|
content: normalizedContent,
|
|
95
155
|
isError: normalizedIsError,
|
|
96
156
|
});
|
|
@@ -188,13 +248,18 @@ export function resolveHostBrowserSessionInvalidated(frame: {
|
|
|
188
248
|
// POST /v1/host-browser-result
|
|
189
249
|
// ---------------------------------------------------------------------------
|
|
190
250
|
|
|
191
|
-
function handleHostBrowserResult({ body }: RouteHandlerArgs) {
|
|
251
|
+
function handleHostBrowserResult({ body, headers }: RouteHandlerArgs) {
|
|
192
252
|
if (!body || typeof body !== "object") {
|
|
193
253
|
throw new BadRequestError("Request body is required");
|
|
194
254
|
}
|
|
195
255
|
|
|
196
|
-
const resolution = resolveHostBrowserResultByRequestId(
|
|
256
|
+
const resolution = resolveHostBrowserResultByRequestId(
|
|
257
|
+
body,
|
|
258
|
+
headers as Record<string, string | undefined> | undefined,
|
|
259
|
+
);
|
|
197
260
|
if (!resolution.ok) {
|
|
261
|
+
if (resolution.code === "FORBIDDEN")
|
|
262
|
+
throw new ForbiddenError(resolution.message);
|
|
198
263
|
if (resolution.code === "NOT_FOUND")
|
|
199
264
|
throw new NotFoundError(resolution.message);
|
|
200
265
|
if (resolution.code === "CONFLICT")
|
|
@@ -260,6 +325,22 @@ export const ROUTES: RouteDefinition[] = [
|
|
|
260
325
|
responseBody: z.object({
|
|
261
326
|
accepted: z.boolean(),
|
|
262
327
|
}),
|
|
328
|
+
additionalResponses: {
|
|
329
|
+
"400": {
|
|
330
|
+
description:
|
|
331
|
+
"x-vellum-client-id header is missing for a targeted host browser request.",
|
|
332
|
+
},
|
|
333
|
+
"403": {
|
|
334
|
+
description: SAME_ACTOR_FORBIDDEN_DESCRIPTION,
|
|
335
|
+
},
|
|
336
|
+
"404": {
|
|
337
|
+
description: "No pending browser request for the given requestId.",
|
|
338
|
+
},
|
|
339
|
+
"409": {
|
|
340
|
+
description:
|
|
341
|
+
"Pending interaction kind is not host_browser (mismatched proxy ID space).",
|
|
342
|
+
},
|
|
343
|
+
},
|
|
263
344
|
handler: handleHostBrowserResult,
|
|
264
345
|
},
|
|
265
346
|
{
|