@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
|
@@ -32,6 +32,19 @@ const COMPACTION_TOOL_RESULT_MAX_CHARS = 6_000;
|
|
|
32
32
|
const MIN_COMPACTABLE_PERSISTED_MESSAGES = 2;
|
|
33
33
|
const INTERNAL_CONTEXT_SUMMARY_MESSAGES = new WeakSet<Message>();
|
|
34
34
|
|
|
35
|
+
/**
|
|
36
|
+
* Hard cap on the verbatim tail-anchor block we splice into the
|
|
37
|
+
* post-compaction summary message (see `extractTailAssistantText`). 1500
|
|
38
|
+
* chars (~375 tokens) covers a few paragraphs of recent assistant
|
|
39
|
+
* narration without bloating the summary. When the tail exceeds this
|
|
40
|
+
* size we keep the END (most recent text), since "next step" / "now I'll
|
|
41
|
+
* …" statements typically live at the end of the assistant's last text
|
|
42
|
+
* block and that's the part the post-compaction model needs most.
|
|
43
|
+
*/
|
|
44
|
+
const TAIL_ANCHOR_MAX_CHARS = 1500;
|
|
45
|
+
const TAIL_ANCHOR_OPEN_TAG = "<verbatim_tail>";
|
|
46
|
+
const TAIL_ANCHOR_CLOSE_TAG = "</verbatim_tail>";
|
|
47
|
+
|
|
35
48
|
/**
|
|
36
49
|
* When the existing summary is this fraction or more of the per-summary
|
|
37
50
|
* token budget, inject a "compress older content aggressively" instruction
|
|
@@ -488,13 +501,45 @@ export class ContextWindowManager {
|
|
|
488
501
|
};
|
|
489
502
|
}
|
|
490
503
|
|
|
491
|
-
const
|
|
504
|
+
const keepPlanInitial = this.pickKeepBoundary(messages, userTurnStarts, {
|
|
492
505
|
minKeepRecentUserTurns: options?.minKeepRecentUserTurns,
|
|
493
506
|
targetInputTokensOverride: options?.targetInputTokensOverride,
|
|
494
507
|
conversationOriginChannel: options?.conversationOriginChannel,
|
|
495
508
|
force: options?.force,
|
|
496
509
|
previousEstimatedInputTokens,
|
|
497
510
|
});
|
|
511
|
+
// Under force (user-explicit `/compact`), never route through the
|
|
512
|
+
// "already fits" / "truncated tool results without summarization"
|
|
513
|
+
// early-return — those are no-op responses to a direct user command.
|
|
514
|
+
// The boundary can collapse to the summary in two cases the
|
|
515
|
+
// projection-optimism clamp in pickKeepBoundary does not cover:
|
|
516
|
+
// 1. `adjustForToolPairs` walked the boundary back through a
|
|
517
|
+
// tool_use/tool_result chain at the start of the conversation.
|
|
518
|
+
// 2. The binary search settled below `userTurnStarts.length` (so
|
|
519
|
+
// the clamp at the top of pickKeepBoundary did not fire) but
|
|
520
|
+
// `adjustForToolPairs` still walked the resulting boundary
|
|
521
|
+
// backwards past `summaryOffset`.
|
|
522
|
+
// Rescue: restore the binary search's intended keep depth (capped at
|
|
523
|
+
// `length - 1` so we always summarize at least one turn) and bypass
|
|
524
|
+
// `adjustForToolPairs`. The kept region's first message may then
|
|
525
|
+
// contain a `tool_result` whose matching `tool_use` lives in the
|
|
526
|
+
// compacted region; we strip such orphans below before assembling
|
|
527
|
+
// the final messages array so the next agent turn does not fail
|
|
528
|
+
// when sending to the LLM.
|
|
529
|
+
const forceRescueApplied =
|
|
530
|
+
options?.force === true &&
|
|
531
|
+
keepPlanInitial.keepFromIndex <= summaryOffset &&
|
|
532
|
+
userTurnStarts.length >= 2;
|
|
533
|
+
const safeKeepTurns = Math.max(
|
|
534
|
+
1,
|
|
535
|
+
Math.min(keepPlanInitial.keepTurns, userTurnStarts.length - 1),
|
|
536
|
+
);
|
|
537
|
+
const keepPlan = forceRescueApplied
|
|
538
|
+
? {
|
|
539
|
+
keepFromIndex: userTurnStarts[userTurnStarts.length - safeKeepTurns],
|
|
540
|
+
keepTurns: safeKeepTurns,
|
|
541
|
+
}
|
|
542
|
+
: keepPlanInitial;
|
|
498
543
|
if (keepPlan.keepFromIndex <= summaryOffset) {
|
|
499
544
|
// All turns fit after truncation projection, but the real in-memory
|
|
500
545
|
// messages may still contain un-truncated tool results. Apply truncation
|
|
@@ -511,6 +556,14 @@ export class ContextWindowManager {
|
|
|
511
556
|
toolTokenBudget: this.toolTokenBudget,
|
|
512
557
|
})
|
|
513
558
|
: previousEstimatedInputTokens;
|
|
559
|
+
// Under force with only one user turn, the rescue above could not
|
|
560
|
+
// fire — there is nothing earlier to summarize. Surface that
|
|
561
|
+
// explicitly instead of "conversation already fits..." so the user
|
|
562
|
+
// knows why `/compact` did not produce a summary.
|
|
563
|
+
const noSummarizationReason =
|
|
564
|
+
options?.force && userTurnStarts.length < 2
|
|
565
|
+
? "only one user turn — nothing earlier to compact"
|
|
566
|
+
: "conversation already fits within the compaction target";
|
|
514
567
|
return {
|
|
515
568
|
messages: truncatedMessages,
|
|
516
569
|
compacted: didTruncate,
|
|
@@ -527,7 +580,7 @@ export class ContextWindowManager {
|
|
|
527
580
|
summaryText: existingSummary ?? "",
|
|
528
581
|
reason: didTruncate
|
|
529
582
|
? "truncated tool results without summarization"
|
|
530
|
-
:
|
|
583
|
+
: noSummarizationReason,
|
|
531
584
|
};
|
|
532
585
|
}
|
|
533
586
|
|
|
@@ -645,9 +698,15 @@ export class ContextWindowManager {
|
|
|
645
698
|
};
|
|
646
699
|
}
|
|
647
700
|
|
|
701
|
+
// `severePressure` already bypasses this guard to keep context from
|
|
702
|
+
// overflowing. Forced compaction also bypasses: when the user
|
|
703
|
+
// explicitly types `/compact` we must summarize whatever is
|
|
704
|
+
// available rather than return "insufficient compactable persisted
|
|
705
|
+
// messages" — that is a no-op response to a direct user command.
|
|
648
706
|
if (
|
|
649
707
|
compactedPersistedMessages < MIN_COMPACTABLE_PERSISTED_MESSAGES &&
|
|
650
|
-
!severePressure
|
|
708
|
+
!severePressure &&
|
|
709
|
+
!options?.force
|
|
651
710
|
) {
|
|
652
711
|
return {
|
|
653
712
|
messages,
|
|
@@ -688,7 +747,6 @@ export class ContextWindowManager {
|
|
|
688
747
|
signal,
|
|
689
748
|
options?.overrideProfile ?? null,
|
|
690
749
|
);
|
|
691
|
-
const summary = summaryUpdate.summary;
|
|
692
750
|
const summaryInputTokens = summaryUpdate.inputTokens;
|
|
693
751
|
const summaryOutputTokens = summaryUpdate.outputTokens;
|
|
694
752
|
const summaryModel = summaryUpdate.model;
|
|
@@ -704,6 +762,19 @@ export class ContextWindowManager {
|
|
|
704
762
|
}
|
|
705
763
|
const summaryCalls = 1;
|
|
706
764
|
|
|
765
|
+
// Force-keep the most recent assistant text from the compactable region
|
|
766
|
+
// by splicing it verbatim into the summary message. This is independent
|
|
767
|
+
// of what the LLM summarizer chose to surface — when compaction
|
|
768
|
+
// interrupts a long assistant work span, this anchor preserves the
|
|
769
|
+
// model's last self-narration ("Next step: …", "About to …") so the
|
|
770
|
+
// post-compaction model has unambiguous continuity instead of falling
|
|
771
|
+
// back to a "where am I?" recovery shape.
|
|
772
|
+
const tailAnchorText = extractTailAssistantText(compactableMessages);
|
|
773
|
+
const summary =
|
|
774
|
+
tailAnchorText != null
|
|
775
|
+
? appendTailAnchorToSummary(summaryUpdate.summary, tailAnchorText)
|
|
776
|
+
: summaryUpdate.summary;
|
|
777
|
+
|
|
707
778
|
// Media (images, files) in kept turns is preserved naturally — those
|
|
708
779
|
// turns are carried forward as-is and their token cost is already
|
|
709
780
|
// accounted for by pickKeepBoundary's estimatePromptTokens call.
|
|
@@ -716,7 +787,14 @@ export class ContextWindowManager {
|
|
|
716
787
|
messages.slice(keepPlan.keepFromIndex),
|
|
717
788
|
COMPACTION_TOOL_RESULT_MAX_CHARS,
|
|
718
789
|
);
|
|
719
|
-
|
|
790
|
+
// The force-rescue boundary bypasses `adjustForToolPairs`, so the
|
|
791
|
+
// kept region may contain `tool_result` blocks whose matching
|
|
792
|
+
// `tool_use` is in the (now-compacted) prefix. Strip those orphans
|
|
793
|
+
// so the next agent turn does not fail with an LLM API error.
|
|
794
|
+
const keptMessages = forceRescueApplied
|
|
795
|
+
? stripOrphanToolResults(truncatedKeptMessages)
|
|
796
|
+
: truncatedKeptMessages;
|
|
797
|
+
const compactedMessages = [summaryMessage, ...keptMessages];
|
|
720
798
|
const estimatedInputTokens = estimatePromptTokens(
|
|
721
799
|
compactedMessages,
|
|
722
800
|
this.systemPrompt,
|
|
@@ -1251,6 +1329,53 @@ function adjustForToolPairs(
|
|
|
1251
1329
|
return idx;
|
|
1252
1330
|
}
|
|
1253
1331
|
|
|
1332
|
+
/**
|
|
1333
|
+
* Strip `tool_result` blocks whose matching `tool_use` is not present in
|
|
1334
|
+
* the message array. Used by the force-rescue path in `_maybeCompact`
|
|
1335
|
+
* which bypasses `adjustForToolPairs` to honor user-explicit `/compact`
|
|
1336
|
+
* commands — the kept region's first user message can otherwise contain
|
|
1337
|
+
* an orphan `tool_result`, which the LLM API rejects.
|
|
1338
|
+
*
|
|
1339
|
+
* A user message that contains only orphan `tool_result` blocks is
|
|
1340
|
+
* dropped entirely; partial messages keep the surviving content blocks.
|
|
1341
|
+
*/
|
|
1342
|
+
function stripOrphanToolResults(messages: Message[]): Message[] {
|
|
1343
|
+
const knownToolUseIds = new Set<string>();
|
|
1344
|
+
for (const msg of messages) {
|
|
1345
|
+
if (msg.role !== "assistant") continue;
|
|
1346
|
+
for (const block of msg.content) {
|
|
1347
|
+
if (
|
|
1348
|
+
(block.type === "tool_use" || block.type === "server_tool_use") &&
|
|
1349
|
+
"id" in block
|
|
1350
|
+
) {
|
|
1351
|
+
knownToolUseIds.add((block as { id: string }).id);
|
|
1352
|
+
}
|
|
1353
|
+
}
|
|
1354
|
+
}
|
|
1355
|
+
|
|
1356
|
+
return messages.flatMap((msg) => {
|
|
1357
|
+
if (msg.role !== "user") return [msg];
|
|
1358
|
+
let stripped = false;
|
|
1359
|
+
const filtered = msg.content.filter((block) => {
|
|
1360
|
+
if (
|
|
1361
|
+
(block.type === "tool_result" ||
|
|
1362
|
+
block.type === "web_search_tool_result") &&
|
|
1363
|
+
"tool_use_id" in block
|
|
1364
|
+
) {
|
|
1365
|
+
const id = (block as { tool_use_id: string }).tool_use_id;
|
|
1366
|
+
if (!knownToolUseIds.has(id)) {
|
|
1367
|
+
stripped = true;
|
|
1368
|
+
return false;
|
|
1369
|
+
}
|
|
1370
|
+
}
|
|
1371
|
+
return true;
|
|
1372
|
+
});
|
|
1373
|
+
if (!stripped) return [msg];
|
|
1374
|
+
if (filtered.length === 0) return [];
|
|
1375
|
+
return [{ ...msg, content: filtered }];
|
|
1376
|
+
});
|
|
1377
|
+
}
|
|
1378
|
+
|
|
1254
1379
|
export function getSummaryFromContextMessage(
|
|
1255
1380
|
message: Message | undefined,
|
|
1256
1381
|
): string | null {
|
|
@@ -1286,6 +1411,67 @@ export function createContextSummaryMessage(summary: string): Message {
|
|
|
1286
1411
|
return message;
|
|
1287
1412
|
}
|
|
1288
1413
|
|
|
1414
|
+
/**
|
|
1415
|
+
* Walk `messages` backward and return the concatenated text content of the
|
|
1416
|
+
* most recent assistant message that contains at least one non-empty text
|
|
1417
|
+
* block. tool_use / tool_result / image / unknown blocks are skipped. The
|
|
1418
|
+
* result is trimmed and (if longer than `maxChars`) clamped from the START
|
|
1419
|
+
* so the END — where "next step" / "now I'll …" narration tends to land —
|
|
1420
|
+
* is preserved.
|
|
1421
|
+
*
|
|
1422
|
+
* Returns `null` when no eligible assistant text is found (e.g. compactable
|
|
1423
|
+
* region was all user/tool messages, or all assistant messages were
|
|
1424
|
+
* tool_use-only). The caller treats `null` as "no anchor to splice".
|
|
1425
|
+
*
|
|
1426
|
+
* Used by `_maybeCompact` to force-keep the last assistant text from the
|
|
1427
|
+
* compactable region into the post-compaction summary message, so the
|
|
1428
|
+
* model's most recent self-narration survives summarization regardless of
|
|
1429
|
+
* whether the LLM summarizer chose to surface it.
|
|
1430
|
+
*/
|
|
1431
|
+
export function extractTailAssistantText(
|
|
1432
|
+
messages: Message[],
|
|
1433
|
+
maxChars: number = TAIL_ANCHOR_MAX_CHARS,
|
|
1434
|
+
): string | null {
|
|
1435
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
1436
|
+
const message = messages[i];
|
|
1437
|
+
if (message?.role !== "assistant") continue;
|
|
1438
|
+
const text = extractText(message.content).trim();
|
|
1439
|
+
if (text.length === 0) continue;
|
|
1440
|
+
if (text.length <= maxChars) return text;
|
|
1441
|
+
// Keep the END — most recent narration wins.
|
|
1442
|
+
const truncated = safeStringSlice(
|
|
1443
|
+
text,
|
|
1444
|
+
text.length - maxChars,
|
|
1445
|
+
text.length,
|
|
1446
|
+
);
|
|
1447
|
+
return `[...truncated] ${truncated}`;
|
|
1448
|
+
}
|
|
1449
|
+
return null;
|
|
1450
|
+
}
|
|
1451
|
+
|
|
1452
|
+
/**
|
|
1453
|
+
* Splice a verbatim tail-anchor block onto the end of the LLM-produced
|
|
1454
|
+
* summary text. The tag-wrapped block is structurally distinct from any
|
|
1455
|
+
* `## ` section the LLM might generate, so it survives section-boundary
|
|
1456
|
+
* clamping in `clampSummaryAtSectionBoundary` (which only runs on the LLM
|
|
1457
|
+
* summary itself, before this splice).
|
|
1458
|
+
*
|
|
1459
|
+
* Idempotent: if the summary already ends with a `<verbatim_tail>…` block
|
|
1460
|
+
* (e.g. from a prior compaction whose summary was carried forward as
|
|
1461
|
+
* `existingSummary`), it is replaced rather than stacked, so successive
|
|
1462
|
+
* compactions don't accumulate stale tails.
|
|
1463
|
+
*/
|
|
1464
|
+
export function appendTailAnchorToSummary(
|
|
1465
|
+
summary: string,
|
|
1466
|
+
tailText: string,
|
|
1467
|
+
): string {
|
|
1468
|
+
const trimmed = summary.trimEnd();
|
|
1469
|
+
const existingOpen = trimmed.lastIndexOf(TAIL_ANCHOR_OPEN_TAG);
|
|
1470
|
+
const base =
|
|
1471
|
+
existingOpen >= 0 ? trimmed.slice(0, existingOpen).trimEnd() : trimmed;
|
|
1472
|
+
return `${base}\n\n${TAIL_ANCHOR_OPEN_TAG}\n${tailText.trim()}\n${TAIL_ANCHOR_CLOSE_TAG}`;
|
|
1473
|
+
}
|
|
1474
|
+
|
|
1289
1475
|
/**
|
|
1290
1476
|
* Build content blocks for the summary prompt. Returns a mix of text blocks
|
|
1291
1477
|
* (for the scaffolding, existing summary, and serialized non-image content)
|
|
@@ -56,6 +56,16 @@ let autoAnalyzeEnabled = true;
|
|
|
56
56
|
// `disposeConversation` must skip the `graph_extract` enqueue.
|
|
57
57
|
const autoAnalysisConversations = new Set<string>();
|
|
58
58
|
|
|
59
|
+
// Toggles the `memory.v2.enabled` flag the disposal code reads via
|
|
60
|
+
// `getConfig()`. Defaults to false so the bulk of the suite — which asserts
|
|
61
|
+
// v1 graph_extract still fires — keeps its semantics. The dedicated v2 cases
|
|
62
|
+
// flip this to true.
|
|
63
|
+
let v2Enabled = false;
|
|
64
|
+
|
|
65
|
+
mock.module("../../config/loader.js", () => ({
|
|
66
|
+
getConfig: () => ({ memory: { v2: { enabled: v2Enabled } } }),
|
|
67
|
+
}));
|
|
68
|
+
|
|
59
69
|
mock.module("../../memory/auto-analysis-guard.js", () => ({
|
|
60
70
|
AUTO_ANALYSIS_SOURCE: "auto-analysis",
|
|
61
71
|
isAutoAnalysisConversation: (conversationId: string) =>
|
|
@@ -81,6 +91,27 @@ mock.module("../../memory/auto-analysis-enqueue.js", () => ({
|
|
|
81
91
|
},
|
|
82
92
|
}));
|
|
83
93
|
|
|
94
|
+
let memoryRetroEnabled = false;
|
|
95
|
+
const memoryRetroCalls: Array<{
|
|
96
|
+
conversationId: string;
|
|
97
|
+
trigger: string;
|
|
98
|
+
}> = [];
|
|
99
|
+
|
|
100
|
+
mock.module("../../memory/memory-retrospective-enqueue.js", () => ({
|
|
101
|
+
enqueueMemoryRetrospectiveIfEnabled: (args: {
|
|
102
|
+
conversationId: string;
|
|
103
|
+
trigger: string;
|
|
104
|
+
}) => {
|
|
105
|
+
if (!memoryRetroEnabled) return;
|
|
106
|
+
memoryRetroCalls.push(args);
|
|
107
|
+
},
|
|
108
|
+
// Also export sibling functions other modules import from this file, so
|
|
109
|
+
// mocking it here doesn't break transitive imports loaded during the
|
|
110
|
+
// `disposeConversation` dynamic-import chain.
|
|
111
|
+
enqueueMemoryRetrospectiveOnCompaction: () => {},
|
|
112
|
+
isMemoryRetrospectiveConversation: (_id: string) => false,
|
|
113
|
+
}));
|
|
114
|
+
|
|
84
115
|
// Stub all side-effecting cleanup helpers that disposeConversation chains
|
|
85
116
|
// into after the enqueue block. We assert on enqueue behavior only.
|
|
86
117
|
mock.module("../../tools/browser/browser-screencast.js", () => ({
|
|
@@ -158,8 +189,11 @@ describe("disposeConversation — auto-analysis enqueue", () => {
|
|
|
158
189
|
beforeEach(() => {
|
|
159
190
|
memoryJobCalls.length = 0;
|
|
160
191
|
autoAnalyzeCalls.length = 0;
|
|
192
|
+
memoryRetroCalls.length = 0;
|
|
161
193
|
autoAnalyzeEnabled = true;
|
|
194
|
+
memoryRetroEnabled = false;
|
|
162
195
|
autoAnalysisConversations.clear();
|
|
196
|
+
v2Enabled = false;
|
|
163
197
|
});
|
|
164
198
|
|
|
165
199
|
test("guardian conversation with auto-analyze ON — enqueues both graph_extract and conversation_analyze (via helper)", () => {
|
|
@@ -313,4 +347,81 @@ describe("disposeConversation — auto-analysis enqueue", () => {
|
|
|
313
347
|
}));
|
|
314
348
|
autoAnalyzeEnabled = originalEnabled;
|
|
315
349
|
});
|
|
350
|
+
|
|
351
|
+
test("memory v2 enabled — graph_extract enqueue is suppressed (auto-analysis still runs)", () => {
|
|
352
|
+
// Under memory v2, the v1 graph has no readers (retrieval is bypassed at
|
|
353
|
+
// conversation-graph-memory.ts), so producing extraction jobs just fills
|
|
354
|
+
// the queue with stale work. Auto-analysis is orthogonal and must keep
|
|
355
|
+
// running.
|
|
356
|
+
v2Enabled = true;
|
|
357
|
+
const ctx = makeDisposeContext({
|
|
358
|
+
conversationId: "conv-v2-on",
|
|
359
|
+
trustClass: "guardian",
|
|
360
|
+
});
|
|
361
|
+
|
|
362
|
+
disposeConversation(ctx);
|
|
363
|
+
|
|
364
|
+
expect(memoryJobCalls).toHaveLength(0);
|
|
365
|
+
expect(autoAnalyzeCalls).toHaveLength(1);
|
|
366
|
+
expect(autoAnalyzeCalls[0]).toEqual({
|
|
367
|
+
conversationId: "conv-v2-on",
|
|
368
|
+
trigger: "lifecycle",
|
|
369
|
+
});
|
|
370
|
+
});
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
describe("disposeConversation — memory-retrospective lifecycle safety net", () => {
|
|
374
|
+
beforeEach(() => {
|
|
375
|
+
memoryJobCalls.length = 0;
|
|
376
|
+
autoAnalyzeCalls.length = 0;
|
|
377
|
+
memoryRetroCalls.length = 0;
|
|
378
|
+
autoAnalyzeEnabled = false;
|
|
379
|
+
memoryRetroEnabled = false;
|
|
380
|
+
autoAnalysisConversations.clear();
|
|
381
|
+
v2Enabled = false;
|
|
382
|
+
});
|
|
383
|
+
|
|
384
|
+
test("guardian conversation + flag on — enqueues memory-retrospective with trigger 'lifecycle'", () => {
|
|
385
|
+
memoryRetroEnabled = true;
|
|
386
|
+
const ctx = makeDisposeContext({
|
|
387
|
+
conversationId: "conv-retro",
|
|
388
|
+
trustClass: "guardian",
|
|
389
|
+
});
|
|
390
|
+
|
|
391
|
+
disposeConversation(ctx);
|
|
392
|
+
|
|
393
|
+
expect(memoryRetroCalls).toHaveLength(1);
|
|
394
|
+
expect(memoryRetroCalls[0]).toEqual({
|
|
395
|
+
conversationId: "conv-retro",
|
|
396
|
+
trigger: "lifecycle",
|
|
397
|
+
});
|
|
398
|
+
});
|
|
399
|
+
|
|
400
|
+
test("flag off — no memory-retrospective enqueue", () => {
|
|
401
|
+
memoryRetroEnabled = false;
|
|
402
|
+
const ctx = makeDisposeContext({
|
|
403
|
+
conversationId: "conv-retro-off",
|
|
404
|
+
trustClass: "guardian",
|
|
405
|
+
});
|
|
406
|
+
|
|
407
|
+
disposeConversation(ctx);
|
|
408
|
+
|
|
409
|
+
expect(memoryRetroCalls).toHaveLength(0);
|
|
410
|
+
});
|
|
411
|
+
|
|
412
|
+
test("untrusted actor — no memory-retrospective enqueue even when flag is on", () => {
|
|
413
|
+
memoryRetroEnabled = true;
|
|
414
|
+
const ctx = makeDisposeContext({
|
|
415
|
+
conversationId: "conv-retro-untrusted",
|
|
416
|
+
trustClass: "unknown",
|
|
417
|
+
});
|
|
418
|
+
|
|
419
|
+
disposeConversation(ctx);
|
|
420
|
+
|
|
421
|
+
// The outer trust-class guard in disposeConversation gates ALL three
|
|
422
|
+
// enqueues (graph_extract, auto-analyze, memory-retrospective). When
|
|
423
|
+
// the actor is untrusted, none of them fire.
|
|
424
|
+
expect(memoryRetroCalls).toHaveLength(0);
|
|
425
|
+
expect(autoAnalyzeCalls).toHaveLength(0);
|
|
426
|
+
});
|
|
316
427
|
});
|
|
@@ -20,10 +20,11 @@
|
|
|
20
20
|
* hasNoClient flag.
|
|
21
21
|
*
|
|
22
22
|
* Cross-client exception: tools whose capabilities are in
|
|
23
|
-
* CROSS_CLIENT_EXPOSED_CAPABILITIES (host_bash, host_file)
|
|
24
|
-
* non-host-proxy interfaces (
|
|
25
|
-
* is connected via the event hub.
|
|
26
|
-
* is
|
|
23
|
+
* CROSS_CLIENT_EXPOSED_CAPABILITIES (host_bash, host_file, host_browser)
|
|
24
|
+
* are allowed for non-host-proxy interactive interfaces ("web", "ios")
|
|
25
|
+
* when at least one capable client is connected via the event hub.
|
|
26
|
+
* chrome-extension is excluded as a security boundary, regardless of
|
|
27
|
+
* whether the capability is technically supported elsewhere.
|
|
27
28
|
*/
|
|
28
29
|
|
|
29
30
|
import { beforeEach, describe, expect, mock, test } from "bun:test";
|
|
@@ -358,6 +359,110 @@ describe("isToolActiveForContext — cross-client exposure for host_file_*", ()
|
|
|
358
359
|
});
|
|
359
360
|
});
|
|
360
361
|
|
|
362
|
+
describe("isToolActiveForContext — cross-client exposure for host_browser", () => {
|
|
363
|
+
// host_browser cross-client routing was shipped in PR #27489 (host-
|
|
364
|
+
// browser-via-macos-host-proxy); LLM-exposure for non-host-proxy
|
|
365
|
+
// transports is added by including "host_browser" in
|
|
366
|
+
// CROSS_CLIENT_EXPOSED_CAPABILITIES. Web and iOS turns can now drive a
|
|
367
|
+
// connected macOS or chrome-extension client via the event hub.
|
|
368
|
+
test("host_browser is exposed for web transport when a host_browser client is connected", () => {
|
|
369
|
+
mockClientCountByCapability.set("host_browser", 1);
|
|
370
|
+
expect(
|
|
371
|
+
isToolActiveForContext(
|
|
372
|
+
"host_browser",
|
|
373
|
+
makeCtx({ hasNoClient: false, transportInterface: "web" }),
|
|
374
|
+
),
|
|
375
|
+
).toBe(true);
|
|
376
|
+
});
|
|
377
|
+
|
|
378
|
+
test("host_browser is exposed for ios transport when a host_browser client is connected", () => {
|
|
379
|
+
// INTERACTIVE_INTERFACES = {macos, ios, web}; ios goes through the same
|
|
380
|
+
// cross-client branch as web because supportsHostProxy("ios", *) is
|
|
381
|
+
// false. This pins the parity guarantee.
|
|
382
|
+
mockClientCountByCapability.set("host_browser", 1);
|
|
383
|
+
expect(
|
|
384
|
+
isToolActiveForContext(
|
|
385
|
+
"host_browser",
|
|
386
|
+
makeCtx({ hasNoClient: false, transportInterface: "ios" }),
|
|
387
|
+
),
|
|
388
|
+
).toBe(true);
|
|
389
|
+
});
|
|
390
|
+
|
|
391
|
+
test("host_browser is NOT exposed for web when no host_browser client is connected", () => {
|
|
392
|
+
mockClientCountByCapability.set("host_browser", 0);
|
|
393
|
+
expect(
|
|
394
|
+
isToolActiveForContext(
|
|
395
|
+
"host_browser",
|
|
396
|
+
makeCtx({ hasNoClient: false, transportInterface: "web" }),
|
|
397
|
+
),
|
|
398
|
+
).toBe(false);
|
|
399
|
+
});
|
|
400
|
+
|
|
401
|
+
test("host_browser is NOT exposed for ios when no host_browser client is connected", () => {
|
|
402
|
+
mockClientCountByCapability.set("host_browser", 0);
|
|
403
|
+
expect(
|
|
404
|
+
isToolActiveForContext(
|
|
405
|
+
"host_browser",
|
|
406
|
+
makeCtx({ hasNoClient: false, transportInterface: "ios" }),
|
|
407
|
+
),
|
|
408
|
+
).toBe(false);
|
|
409
|
+
});
|
|
410
|
+
|
|
411
|
+
test("host_browser is NOT exposed when hasNoClient is true (no approval UI)", () => {
|
|
412
|
+
// hasNoClient gate: cross-client exception must not bypass this.
|
|
413
|
+
mockClientCountByCapability.set("host_browser", 1);
|
|
414
|
+
expect(
|
|
415
|
+
isToolActiveForContext(
|
|
416
|
+
"host_browser",
|
|
417
|
+
makeCtx({ hasNoClient: true, transportInterface: "web" }),
|
|
418
|
+
),
|
|
419
|
+
).toBe(false);
|
|
420
|
+
});
|
|
421
|
+
|
|
422
|
+
test("host_browser for macos transport is unaffected by the cross-client exception", () => {
|
|
423
|
+
// macos natively supports host_browser via host proxy — the
|
|
424
|
+
// supportsHostProxy check passes, so the cross-client branch is never
|
|
425
|
+
// reached.
|
|
426
|
+
mockClientCountByCapability.set("host_browser", 0);
|
|
427
|
+
expect(
|
|
428
|
+
isToolActiveForContext(
|
|
429
|
+
"host_browser",
|
|
430
|
+
makeCtx({ hasNoClient: false, transportInterface: "macos" }),
|
|
431
|
+
),
|
|
432
|
+
).toBe(true);
|
|
433
|
+
});
|
|
434
|
+
|
|
435
|
+
test("host_browser for chrome-extension transport is unaffected by the cross-client exception", () => {
|
|
436
|
+
// chrome-extension natively supports host_browser via its own
|
|
437
|
+
// executor (supportsHostProxy("chrome-extension", "host_browser")
|
|
438
|
+
// returns true), so the cross-client branch is never reached. The
|
|
439
|
+
// hasNoClient gate is also bypassed for chrome-extension transports
|
|
440
|
+
// because the extension provides its own approval UI.
|
|
441
|
+
mockClientCountByCapability.set("host_browser", 0);
|
|
442
|
+
expect(
|
|
443
|
+
isToolActiveForContext(
|
|
444
|
+
"host_browser",
|
|
445
|
+
makeCtx({ hasNoClient: true, transportInterface: "chrome-extension" }),
|
|
446
|
+
),
|
|
447
|
+
).toBe(true);
|
|
448
|
+
});
|
|
449
|
+
|
|
450
|
+
test("listClientsByCapability is queried with host_browser, not host_bash or host_file (per-capability invariant)", () => {
|
|
451
|
+
// Defense against any future regression that hardcodes a different
|
|
452
|
+
// capability in the cross-client check. Only host_browser-capable
|
|
453
|
+
// clients should satisfy host_browser exposure.
|
|
454
|
+
mockClientCountByCapability.set("host_bash", 1);
|
|
455
|
+
mockClientCountByCapability.set("host_file", 1);
|
|
456
|
+
mockClientCountByCapability.set("host_browser", 0);
|
|
457
|
+
expect(
|
|
458
|
+
isToolActiveForContext(
|
|
459
|
+
"host_browser",
|
|
460
|
+
makeCtx({ hasNoClient: false, transportInterface: "web" }),
|
|
461
|
+
),
|
|
462
|
+
).toBe(false);
|
|
463
|
+
});
|
|
464
|
+
});
|
|
465
|
+
|
|
361
466
|
describe("HOST_TOOL_NAMES derivation", () => {
|
|
362
467
|
test("HOST_TOOL_NAMES is derived from HOST_TOOL_TO_CAPABILITY", () => {
|
|
363
468
|
// Sanity check: every tool in the names set has a capability mapping.
|
|
@@ -23,8 +23,9 @@ const loggerSpy = {
|
|
|
23
23
|
warn: mock(() => {}),
|
|
24
24
|
error: mock(() => {}),
|
|
25
25
|
};
|
|
26
|
+
const getLoggerSpy = mock((_name: string) => loggerSpy);
|
|
26
27
|
mock.module("../../util/logger.js", () => ({
|
|
27
|
-
getLogger:
|
|
28
|
+
getLogger: getLoggerSpy,
|
|
28
29
|
}));
|
|
29
30
|
|
|
30
31
|
mock.module("../../config/loader.js", () => ({
|
|
@@ -163,12 +164,13 @@ describe("createDaemonSkillHost", () => {
|
|
|
163
164
|
expect(host.speakers).toBeDefined();
|
|
164
165
|
});
|
|
165
166
|
|
|
166
|
-
test("logger.get
|
|
167
|
+
test("logger.get prefixes the scope with the skillId", () => {
|
|
167
168
|
const log = host.logger.get("test-scope");
|
|
168
169
|
log.debug("d", { k: "v" });
|
|
169
170
|
log.info("i");
|
|
170
171
|
log.warn("w");
|
|
171
172
|
log.error("e");
|
|
173
|
+
expect(getLoggerSpy).toHaveBeenCalledWith("meet-join:test-scope");
|
|
172
174
|
expect(loggerSpy.debug).toHaveBeenCalled();
|
|
173
175
|
expect(loggerSpy.info).toHaveBeenCalled();
|
|
174
176
|
expect(loggerSpy.warn).toHaveBeenCalled();
|
|
@@ -255,8 +257,12 @@ describe("createDaemonSkillHost", () => {
|
|
|
255
257
|
});
|
|
256
258
|
expect(handle).toBeDefined();
|
|
257
259
|
expect(registerSkillRouteSpy).toHaveBeenCalled();
|
|
258
|
-
|
|
259
|
-
|
|
260
|
+
const hook = async () => {};
|
|
261
|
+
host.registries.registerShutdownHook("test-hook", hook);
|
|
262
|
+
expect(registerShutdownHookSpy).toHaveBeenCalledWith(
|
|
263
|
+
"meet-join:test-hook",
|
|
264
|
+
hook,
|
|
265
|
+
);
|
|
260
266
|
});
|
|
261
267
|
|
|
262
268
|
test("speakers.createTracker yields a concrete tracker instance", () => {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { loadConfig } from "../config/loader.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { wrapWithCallSiteRouting } from "../providers/call-site-routing.js";
|
|
3
|
+
import { resolveDefaultProvider } from "../providers/connection-resolution.js";
|
|
4
4
|
import type { Provider } from "../providers/types.js";
|
|
5
5
|
import {
|
|
6
6
|
APPROVAL_COPY_MAX_TOKENS,
|
|
@@ -79,15 +79,18 @@ const VALID_DISPOSITIONS: ReadonlySet<string> = new Set([
|
|
|
79
79
|
export function createApprovalCopyGenerator(): ApprovalCopyGenerator {
|
|
80
80
|
return async (context, options = {}) => {
|
|
81
81
|
const config = loadConfig();
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
82
|
+
// Connection-aware default-provider resolution. Throws
|
|
83
|
+
// `ConnectionResolutionError` on hard config errors (missing /
|
|
84
|
+
// unknown / mismatched connection). Returns null on soft credential
|
|
85
|
+
// failures (vault miss, transient auth) — we treat null as "no
|
|
86
|
+
// provider available" and skip generating copy.
|
|
87
|
+
const baseProvider: Provider | null = await resolveDefaultProvider(config);
|
|
88
|
+
if (!baseProvider) return null;
|
|
88
89
|
// Wrap so per-call `callSite` can route to an alternative provider
|
|
89
90
|
// transport when `llm.callSites.<id>.provider` overrides the default.
|
|
90
|
-
|
|
91
|
+
// The `wrapWithCallSiteRouting` helper threads `config` through so the
|
|
92
|
+
// wrapper's per-call resolution is also connection-aware.
|
|
93
|
+
const provider = wrapWithCallSiteRouting(baseProvider, config);
|
|
91
94
|
|
|
92
95
|
const fallbackText =
|
|
93
96
|
options.fallbackText?.trim() || getFallbackMessage(context);
|
|
@@ -136,12 +139,19 @@ export function createApprovalCopyGenerator(): ApprovalCopyGenerator {
|
|
|
136
139
|
export function createApprovalConversationGenerator(): ApprovalConversationGenerator {
|
|
137
140
|
return async (context) => {
|
|
138
141
|
const config = loadConfig();
|
|
139
|
-
|
|
142
|
+
// Connection-aware default + per-call routing. `resolveDefaultProvider`
|
|
143
|
+
// throws `ConnectionResolutionError` on hard config errors (missing /
|
|
144
|
+
// unknown / mismatched connection) and returns null on soft credential
|
|
145
|
+
// failures (vault miss, transient auth) — we treat null as "no
|
|
146
|
+
// provider available" and throw a domain-specific error below. We do
|
|
147
|
+
// not pre-gate on `listProviders()` because the default provider lives
|
|
148
|
+
// behind a `provider_connection` and never appears in the registry's
|
|
149
|
+
// initialization-time provider list.
|
|
150
|
+
const baseProvider = await resolveDefaultProvider(config);
|
|
151
|
+
if (!baseProvider) {
|
|
140
152
|
throw new Error("No provider available for approval conversation");
|
|
141
153
|
}
|
|
142
|
-
const provider = wrapWithCallSiteRouting(
|
|
143
|
-
getProvider(config.llm.default.provider),
|
|
144
|
-
);
|
|
154
|
+
const provider = wrapWithCallSiteRouting(baseProvider, config);
|
|
145
155
|
|
|
146
156
|
const pendingDescription = context.pendingApprovals
|
|
147
157
|
.map((p) => `- Request ${p.requestId}: tool "${p.toolName}"`)
|
|
@@ -212,19 +222,3 @@ export function createApprovalConversationGenerator(): ApprovalConversationGener
|
|
|
212
222
|
return result;
|
|
213
223
|
};
|
|
214
224
|
}
|
|
215
|
-
|
|
216
|
-
/**
|
|
217
|
-
* Wrap a base Provider so per-call `callSite` metadata can route the actual
|
|
218
|
-
* transport to a different provider when `llm.callSites.<id>.provider`
|
|
219
|
-
* differs from the default. Without this wrapper, only request metadata
|
|
220
|
-
* reflects the callSite — the HTTP transport stays bound to the default.
|
|
221
|
-
*/
|
|
222
|
-
function wrapWithCallSiteRouting(base: Provider): Provider {
|
|
223
|
-
return new CallSiteRoutingProvider(base, (name) => {
|
|
224
|
-
try {
|
|
225
|
-
return getProvider(name);
|
|
226
|
-
} catch {
|
|
227
|
-
return undefined;
|
|
228
|
-
}
|
|
229
|
-
});
|
|
230
|
-
}
|
|
@@ -18,6 +18,7 @@ import { getConfig, invalidateConfigCache } from "../config/loader.js";
|
|
|
18
18
|
import type { MemoryCleanupConfig } from "../config/schemas/memory-lifecycle.js";
|
|
19
19
|
import { resetCleanupScheduleThrottle } from "../memory/cleanup-schedule-state.js";
|
|
20
20
|
import { clearEmbeddingBackendCache } from "../memory/embedding-backend.js";
|
|
21
|
+
import { invalidateLlmRequestLogSourceCache } from "../memory/llm-request-log-source.js";
|
|
21
22
|
import { initializeProviders } from "../providers/registry.js";
|
|
22
23
|
import { handleCancelSignal } from "../signals/cancel.js";
|
|
23
24
|
import { handleConversationUndoSignal } from "../signals/conversation-undo.js";
|
|
@@ -140,6 +141,7 @@ export class ConfigWatcher {
|
|
|
140
141
|
return false;
|
|
141
142
|
}
|
|
142
143
|
clearEmbeddingBackendCache();
|
|
144
|
+
invalidateLlmRequestLogSourceCache();
|
|
143
145
|
// If cleanup retention settings changed, reset the cleanup scheduler
|
|
144
146
|
// throttle so the next worker tick re-enqueues jobs with the new values
|
|
145
147
|
// instead of waiting out the remaining enqueueIntervalMs (default 6h).
|