@vellumai/assistant 0.6.4 → 0.6.5

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.
Files changed (717) hide show
  1. package/.prettierignore +5 -0
  2. package/ARCHITECTURE.md +32 -36
  3. package/Dockerfile +12 -0
  4. package/README.md +3 -4
  5. package/bun.lock +8 -3
  6. package/docs/architecture/integrations.md +1 -20
  7. package/docs/architecture/security.md +16 -16
  8. package/docs/error-handling.md +111 -0
  9. package/docs/skills.md +10 -10
  10. package/docs/stt-provider-onboarding.md +2 -1
  11. package/knip.json +9 -2
  12. package/node_modules/@vellumai/ces-contracts/package.json +2 -1
  13. package/node_modules/@vellumai/ces-contracts/src/__tests__/trust-rules.test.ts +471 -0
  14. package/node_modules/@vellumai/ces-contracts/src/trust-rules.ts +398 -4
  15. package/node_modules/@vellumai/credential-storage/bun.lock +2 -2
  16. package/node_modules/@vellumai/credential-storage/package.json +2 -2
  17. package/node_modules/@vellumai/credential-storage/src/oauth-runtime.ts +20 -2
  18. package/node_modules/@vellumai/egress-proxy/bun.lock +2 -2
  19. package/node_modules/@vellumai/egress-proxy/package.json +2 -2
  20. package/openapi.yaml +123 -11
  21. package/package.json +6 -3
  22. package/scripts/generate-openapi.ts +50 -11
  23. package/src/__tests__/agent-loop-callsite-precedence.test.ts +318 -0
  24. package/src/__tests__/agent-loop-sentry-hygiene.test.ts +137 -0
  25. package/src/__tests__/agent-loop.test.ts +112 -1
  26. package/src/__tests__/anthropic-error-formatting.test.ts +98 -0
  27. package/src/__tests__/anthropic-provider.test.ts +171 -2
  28. package/src/__tests__/approval-cascade.test.ts +31 -10
  29. package/src/__tests__/approval-routes-http.test.ts +134 -10
  30. package/src/__tests__/assistant-attachments.test.ts +44 -0
  31. package/src/__tests__/assistant-feature-flags-integration.test.ts +29 -0
  32. package/src/__tests__/browser-fill-credential.test.ts +1 -1
  33. package/src/__tests__/browser-identifier-parity-guard.test.ts +53 -0
  34. package/src/__tests__/browser-skill-baseline-tool-payload.test.ts +23 -33
  35. package/src/__tests__/browser-skill-endstate.test.ts +51 -182
  36. package/src/__tests__/btw-routes.test.ts +47 -1
  37. package/src/__tests__/call-controller.test.ts +1 -2
  38. package/src/__tests__/call-site-routing-provider.test.ts +214 -0
  39. package/src/__tests__/catalog-cache.test.ts +27 -4
  40. package/src/__tests__/channel-approval-routes.test.ts +4 -4
  41. package/src/__tests__/channel-reply-delivery.test.ts +300 -2
  42. package/src/__tests__/checker.test.ts +428 -501
  43. package/src/__tests__/cli-command-risk-guard.test.ts +30 -33
  44. package/src/__tests__/compaction-circuit-breaker.test.ts +336 -0
  45. package/src/__tests__/compaction.benchmark.test.ts +1 -1
  46. package/src/__tests__/config-analysis.test.ts +11 -28
  47. package/src/__tests__/config-loader-backfill.test.ts +174 -0
  48. package/src/__tests__/config-loader-corrupt.test.ts +183 -0
  49. package/src/__tests__/config-loader-quarantine-bulletin.test.ts +202 -0
  50. package/src/__tests__/config-schema-cmd.test.ts +11 -5
  51. package/src/__tests__/config-schema.test.ts +427 -114
  52. package/src/__tests__/config-watcher.test.ts +2 -2
  53. package/src/__tests__/contact-store-user-file.test.ts +72 -73
  54. package/src/__tests__/contacts-write.test.ts +4 -4
  55. package/src/__tests__/context-token-estimator.test.ts +191 -1
  56. package/src/__tests__/context-window-manager.test.ts +530 -2
  57. package/src/__tests__/conversation-abort-tool-results.test.ts +30 -16
  58. package/src/__tests__/conversation-agent-loop-overflow.test.ts +61 -17
  59. package/src/__tests__/conversation-agent-loop.test.ts +412 -82
  60. package/src/__tests__/conversation-attachments.test.ts +1 -1
  61. package/src/__tests__/conversation-confirmation-signals.test.ts +30 -9
  62. package/src/__tests__/conversation-error.test.ts +37 -6
  63. package/src/__tests__/conversation-history-web-search.test.ts +6 -0
  64. package/src/__tests__/conversation-init.benchmark.test.ts +36 -0
  65. package/src/__tests__/conversation-lifecycle.test.ts +336 -0
  66. package/src/__tests__/conversation-load-history-repair.test.ts +27 -10
  67. package/src/__tests__/conversation-pre-run-repair.test.ts +30 -16
  68. package/src/__tests__/conversation-process-callsite.test.ts +306 -0
  69. package/src/__tests__/conversation-provider-retry-repair.test.ts +30 -16
  70. package/src/__tests__/conversation-queue.test.ts +41 -26
  71. package/src/__tests__/conversation-routes-disk-view.test.ts +29 -1
  72. package/src/__tests__/conversation-routes-slash-commands.test.ts +31 -3
  73. package/src/__tests__/conversation-runtime-assembly.test.ts +2735 -55
  74. package/src/__tests__/conversation-runtime-workspace.test.ts +12 -12
  75. package/src/__tests__/conversation-skill-tools.test.ts +12 -146
  76. package/src/__tests__/conversation-slash-queue.test.ts +34 -19
  77. package/src/__tests__/conversation-slash-unknown.test.ts +30 -16
  78. package/src/__tests__/conversation-speed-override.test.ts +30 -11
  79. package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +1035 -0
  80. package/src/__tests__/conversation-surfaces-standalone.test.ts +630 -0
  81. package/src/__tests__/conversation-title-service.test.ts +2 -2
  82. package/src/__tests__/conversation-tool-setup-batch-authorized.test.ts +1 -1
  83. package/src/__tests__/conversation-unread-route.test.ts +2 -2
  84. package/src/__tests__/conversation-usage.test.ts +3 -1
  85. package/src/__tests__/conversation-workspace-cache-state.test.ts +31 -10
  86. package/src/__tests__/conversation-workspace-injection.test.ts +43 -15
  87. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +44 -16
  88. package/src/__tests__/credential-broker-browser-fill.test.ts +110 -0
  89. package/src/__tests__/credential-security-invariants.test.ts +3 -0
  90. package/src/__tests__/credential-storage-oauth-compat.test.ts +18 -0
  91. package/src/__tests__/credential-storage-static-compat.test.ts +28 -0
  92. package/src/__tests__/credential-vault-unit.test.ts +135 -19
  93. package/src/__tests__/credentials-cli.test.ts +1 -9
  94. package/src/__tests__/cross-provider-web-search.test.ts +84 -0
  95. package/src/__tests__/daemon-server-persist-and-process-callsite.test.ts +92 -0
  96. package/src/__tests__/delete-propagation.test.ts +437 -0
  97. package/src/__tests__/dm-backfill.test.ts +417 -0
  98. package/src/__tests__/dm-persistence.test.ts +227 -0
  99. package/src/__tests__/edit-propagation.test.ts +280 -0
  100. package/src/__tests__/ephemeral-permissions.test.ts +93 -3
  101. package/src/__tests__/estimator-calibration-integration.test.ts +208 -0
  102. package/src/__tests__/estimator-calibration.test.ts +213 -0
  103. package/src/__tests__/extension-id-sync-guard.test.ts +26 -7
  104. package/src/__tests__/file-write-tool.test.ts +151 -1
  105. package/src/__tests__/filing-service.test.ts +255 -0
  106. package/src/__tests__/gemini-provider.test.ts +0 -3
  107. package/src/__tests__/guardian-grant-minting.test.ts +8 -0
  108. package/src/__tests__/headless-browser-interactions.test.ts +1 -1
  109. package/src/__tests__/heartbeat-service.test.ts +96 -15
  110. package/src/__tests__/host-shell-tool.test.ts +124 -18
  111. package/src/__tests__/http-user-message-parity.test.ts +29 -1
  112. package/src/__tests__/inbound-slack-persistence.test.ts +340 -0
  113. package/src/__tests__/intent-routing.test.ts +1 -40
  114. package/src/__tests__/llm-catalog-parity.test.ts +174 -0
  115. package/src/__tests__/llm-context-normalization.test.ts +121 -0
  116. package/src/__tests__/llm-resolver.test.ts +214 -0
  117. package/src/__tests__/llm-schema.test.ts +223 -0
  118. package/src/__tests__/managed-proxy-context.test.ts +6 -2
  119. package/src/__tests__/messaging-skill-split.test.ts +3 -34
  120. package/src/__tests__/migration-import-from-url.test.ts +684 -0
  121. package/src/__tests__/model-intents.test.ts +9 -83
  122. package/src/__tests__/notification-decision-fallback.test.ts +0 -10
  123. package/src/__tests__/notification-decision-identity.test.ts +0 -9
  124. package/src/__tests__/notification-decision-recipient-context.test.ts +0 -9
  125. package/src/__tests__/oauth-store.test.ts +10 -7
  126. package/src/__tests__/oauth2-gateway-transport.test.ts +8 -3
  127. package/src/__tests__/oauth2-refresh-retry.test.ts +279 -0
  128. package/src/__tests__/openai-provider.test.ts +7 -0
  129. package/src/__tests__/openai-responses-provider.test.ts +396 -0
  130. package/src/__tests__/openrouter-provider-only.test.ts +135 -0
  131. package/src/__tests__/outbound-slack-persistence.test.ts +293 -0
  132. package/src/__tests__/permission-checker-host-gate.test.ts +1 -1
  133. package/src/__tests__/permission-mode.test.ts +16 -0
  134. package/src/__tests__/permission-types.test.ts +0 -1
  135. package/src/__tests__/persona-resolver.test.ts +13 -13
  136. package/src/__tests__/pkb-autoinject.test.ts +37 -1
  137. package/src/__tests__/platform-bash-auto-approve.test.ts +1 -1
  138. package/src/__tests__/pricing.test.ts +50 -3
  139. package/src/__tests__/profiler-routes.test.ts +1 -1
  140. package/src/__tests__/provider-commit-message-generator.test.ts +14 -84
  141. package/src/__tests__/provider-env-vars-scope.test.ts +52 -0
  142. package/src/__tests__/provider-error-scenarios.test.ts +135 -6
  143. package/src/__tests__/provider-managed-proxy-integration.test.ts +42 -11
  144. package/src/__tests__/provider-registry-ollama.test.ts +1 -2
  145. package/src/__tests__/proxy-approval-callback.test.ts +0 -1
  146. package/src/__tests__/reaction-persistence.test.ts +560 -0
  147. package/src/__tests__/relay-server.test.ts +1 -1
  148. package/src/__tests__/require-fresh-approval.test.ts +1 -1
  149. package/src/__tests__/retry-openrouter-only-normalization.test.ts +136 -0
  150. package/src/__tests__/retry-thinking-tool-choice.test.ts +226 -0
  151. package/src/__tests__/risk-classifier-parity.test.ts +230 -0
  152. package/src/__tests__/sanitize-config-for-transfer.test.ts +78 -1
  153. package/src/__tests__/secret-ingress-http.test.ts +28 -0
  154. package/src/__tests__/secret-prompter-channel-fallback.test.ts +125 -0
  155. package/src/__tests__/secret-routes-managed-proxy.test.ts +2 -3
  156. package/src/__tests__/secret-scanner-executor.test.ts +1 -1
  157. package/src/__tests__/send-endpoint-busy.test.ts +29 -1
  158. package/src/__tests__/server-history-render.test.ts +31 -0
  159. package/src/__tests__/shell-parser-property.test.ts +13 -13
  160. package/src/__tests__/skill-cache-store.test.ts +182 -0
  161. package/src/__tests__/skills.test.ts +19 -33
  162. package/src/__tests__/slack-app-setup-skill-regression.test.ts +3 -1
  163. package/src/__tests__/slack-skill.test.ts +3 -8
  164. package/src/__tests__/starter-bundle.test.ts +35 -0
  165. package/src/__tests__/subagent-call-site-routing.test.ts +280 -0
  166. package/src/__tests__/suggestion-routes.test.ts +160 -3
  167. package/src/__tests__/system-prompt.test.ts +22 -35
  168. package/src/__tests__/task-runner.test.ts +3 -1
  169. package/src/__tests__/tcc-sandbox-deny.test.ts +198 -0
  170. package/src/__tests__/terminal-tools.test.ts +8 -0
  171. package/src/__tests__/test-support/browser-skill-harness.ts +2 -52
  172. package/src/__tests__/thread-backfill.test.ts +941 -0
  173. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +2 -2
  174. package/src/__tests__/tool-executor-lifecycle-events.test.ts +2 -2
  175. package/src/__tests__/tool-executor.test.ts +60 -94
  176. package/src/__tests__/trust-store.test.ts +442 -109
  177. package/src/__tests__/update-bulletin-job.test.ts +389 -0
  178. package/src/__tests__/usage-cache-backfill-migration.test.ts +3 -1
  179. package/src/__tests__/verification-control-plane-policy.test.ts +1 -22
  180. package/src/__tests__/voice-session-bridge.test.ts +39 -0
  181. package/src/__tests__/volume-security-guard.test.ts +3 -2
  182. package/src/__tests__/web-search-history.test.ts +337 -0
  183. package/src/__tests__/workspace-migration-039-drop-legacy-llm-keys.test.ts +343 -0
  184. package/src/__tests__/workspace-migration-043-release-notes-latex-rendering.test.ts +202 -0
  185. package/src/__tests__/workspace-migration-045-release-notes-meet-avatar.test.ts +210 -0
  186. package/src/__tests__/workspace-migration-drop-user-md.test.ts +11 -11
  187. package/src/__tests__/workspace-migration-unify-llm-callsite-configs.test.ts +841 -0
  188. package/src/__tests__/workspace-policy.test.ts +1 -13
  189. package/src/acp/client-handler.ts +1 -2
  190. package/src/agent/loop.ts +209 -17
  191. package/src/avatar/resvg-lazy.test.ts +136 -0
  192. package/src/avatar/resvg-lazy.ts +82 -9
  193. package/src/avatar/traits-png-sync.ts +21 -1
  194. package/src/browser/__tests__/operations.test.ts +163 -0
  195. package/src/browser/identifiers.ts +51 -0
  196. package/src/browser/operations.ts +660 -0
  197. package/src/browser/types.ts +81 -0
  198. package/src/calls/guardian-question-copy.ts +2 -2
  199. package/src/calls/telephony-stt-routing.ts +1 -1
  200. package/src/calls/voice-session-bridge.ts +1 -0
  201. package/src/cli/AGENTS.md +1 -1
  202. package/src/cli/commands/__tests__/attachment.test.ts +438 -0
  203. package/src/cli/commands/__tests__/browser.test.ts +554 -0
  204. package/src/cli/commands/__tests__/cache.test.ts +623 -0
  205. package/src/cli/commands/__tests__/email-list.test.ts +6 -0
  206. package/src/cli/commands/__tests__/email-send.test.ts +93 -1
  207. package/src/cli/commands/__tests__/image-generation.test.ts +666 -0
  208. package/src/cli/commands/__tests__/inference-send.test.ts +451 -0
  209. package/src/cli/commands/__tests__/stt-transcribe.test.ts +454 -0
  210. package/src/cli/commands/__tests__/task.test.ts +913 -0
  211. package/src/cli/commands/__tests__/tts-synthesize.test.ts +594 -0
  212. package/src/cli/commands/__tests__/ui-confirm.test.ts +650 -0
  213. package/src/cli/commands/__tests__/ui.test.ts +1215 -0
  214. package/src/cli/commands/__tests__/watchers.test.ts +716 -0
  215. package/src/cli/commands/attachment.ts +182 -0
  216. package/src/cli/commands/browser.ts +350 -0
  217. package/src/cli/commands/cache.ts +341 -0
  218. package/src/cli/commands/completions.ts +0 -3
  219. package/src/cli/commands/config.ts +6 -6
  220. package/src/cli/commands/conversations-import.ts +347 -0
  221. package/src/cli/commands/conversations.ts +14 -1
  222. package/src/cli/commands/email.ts +234 -194
  223. package/src/cli/commands/image-generation.ts +300 -0
  224. package/src/cli/commands/inference.ts +200 -0
  225. package/src/cli/commands/memory.ts +127 -17
  226. package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +0 -1
  227. package/src/cli/commands/platform/__tests__/connect.test.ts +0 -1
  228. package/src/cli/commands/platform/__tests__/disconnect.test.ts +0 -1
  229. package/src/cli/commands/platform/__tests__/status.test.ts +0 -1
  230. package/src/cli/commands/stt.ts +339 -0
  231. package/src/cli/commands/task.ts +795 -0
  232. package/src/cli/commands/trust.ts +50 -19
  233. package/src/cli/commands/tts.ts +273 -0
  234. package/src/cli/commands/ui.ts +670 -0
  235. package/src/cli/commands/watchers.ts +509 -0
  236. package/src/cli/lib/daemon-credential-client.ts +0 -19
  237. package/src/cli/program.ts +23 -4
  238. package/src/cli.ts +0 -37
  239. package/src/config/bundled-skills/conversations/tools/rename-conversation.ts +23 -1
  240. package/src/config/bundled-skills/media-processing/services/reduce.ts +1 -1
  241. package/src/config/bundled-skills/messaging/SKILL.md +2 -2
  242. package/src/config/bundled-skills/messaging/TOOLS.json +4 -0
  243. package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +8 -1
  244. package/src/config/bundled-skills/messaging/tools/messaging-read.ts +15 -1
  245. package/src/config/bundled-skills/messaging/tools/messaging-search.ts +21 -1
  246. package/src/config/bundled-skills/messaging/tools/messaging-send.ts +11 -12
  247. package/src/config/bundled-skills/phone-calls/references/CONFIG.md +9 -8
  248. package/src/config/bundled-skills/settings/TOOLS.json +3 -3
  249. package/src/config/bundled-tool-registry.ts +0 -175
  250. package/src/config/env.ts +7 -2
  251. package/src/config/feature-flag-registry.json +25 -9
  252. package/src/config/llm-resolver.ts +128 -0
  253. package/src/config/loader.ts +194 -10
  254. package/src/config/raw-config-utils.ts +30 -2
  255. package/src/config/sanitize-for-transfer.ts +35 -0
  256. package/src/config/schema.ts +30 -41
  257. package/src/config/schemas/analysis.ts +3 -22
  258. package/src/config/schemas/calls.ts +0 -4
  259. package/src/config/schemas/filing.ts +2 -7
  260. package/src/config/schemas/heartbeat.ts +0 -5
  261. package/src/config/schemas/inference.ts +3 -23
  262. package/src/config/schemas/llm.ts +318 -0
  263. package/src/config/schemas/memory-processing.ts +1 -9
  264. package/src/config/schemas/notifications.ts +4 -11
  265. package/src/config/schemas/platform.ts +3 -9
  266. package/src/config/schemas/security.ts +33 -0
  267. package/src/config/schemas/services.ts +9 -4
  268. package/src/config/schemas/stt.ts +1 -0
  269. package/src/config/schemas/tts.ts +53 -0
  270. package/src/config/schemas/updates.ts +1 -1
  271. package/src/config/schemas/workspace-git.ts +3 -40
  272. package/src/config/skills.ts +2 -2
  273. package/src/context/__tests__/compact-prompt.test.ts +45 -0
  274. package/src/context/__tests__/microcompact.test.ts +805 -0
  275. package/src/context/estimator-calibration.ts +136 -0
  276. package/src/context/microcompact.ts +443 -0
  277. package/src/context/prompts/compact.md +12 -0
  278. package/src/context/token-estimator.ts +61 -3
  279. package/src/context/window-manager.ts +229 -25
  280. package/src/credential-execution/approval-bridge.ts +0 -1
  281. package/src/credential-execution/executable-discovery.ts +19 -8
  282. package/src/credential-execution/process-manager.test.ts +109 -0
  283. package/src/credential-execution/process-manager.ts +65 -2
  284. package/src/daemon/approval-generators.ts +29 -4
  285. package/src/daemon/assistant-attachments.ts +24 -13
  286. package/src/daemon/classifier.ts +2 -2
  287. package/src/daemon/config-watcher.ts +0 -1
  288. package/src/daemon/context-overflow-reducer.ts +4 -1
  289. package/src/daemon/conversation-agent-loop-handlers.ts +79 -12
  290. package/src/daemon/conversation-agent-loop.ts +462 -80
  291. package/src/daemon/conversation-attachments.ts +2 -6
  292. package/src/daemon/conversation-error.ts +36 -1
  293. package/src/daemon/conversation-lifecycle.ts +30 -6
  294. package/src/daemon/conversation-messaging.ts +73 -4
  295. package/src/daemon/conversation-process.ts +10 -4
  296. package/src/daemon/conversation-queue-manager.ts +3 -0
  297. package/src/daemon/conversation-runtime-assembly.ts +760 -29
  298. package/src/daemon/conversation-slash.ts +2 -2
  299. package/src/daemon/conversation-surfaces.ts +389 -1
  300. package/src/daemon/conversation-tool-setup.ts +10 -5
  301. package/src/daemon/conversation-usage.ts +1 -1
  302. package/src/daemon/conversation.ts +118 -30
  303. package/src/daemon/external-skills-bootstrap.ts +41 -0
  304. package/src/daemon/guardian-action-generators.ts +34 -14
  305. package/src/daemon/handlers/config-model.test.ts +86 -0
  306. package/src/daemon/handlers/config-model.ts +54 -12
  307. package/src/daemon/handlers/conversations.ts +9 -2
  308. package/src/daemon/handlers/shared.ts +39 -11
  309. package/src/daemon/handlers/skills.ts +2 -2
  310. package/src/daemon/handlers/slack-channel-oauth-install.ts +197 -0
  311. package/src/daemon/lifecycle.ts +76 -14
  312. package/src/daemon/message-types/conversations.ts +14 -0
  313. package/src/daemon/message-types/messages.ts +9 -1
  314. package/src/daemon/message-types/trust.ts +0 -2
  315. package/src/daemon/parse-actual-tokens-from-error.test.ts +57 -1
  316. package/src/daemon/parse-actual-tokens-from-error.ts +66 -0
  317. package/src/daemon/pkb-context-tracker.test.ts +169 -0
  318. package/src/daemon/pkb-context-tracker.ts +125 -0
  319. package/src/daemon/pkb-reminder-builder.test.ts +70 -0
  320. package/src/daemon/pkb-reminder-builder.ts +31 -0
  321. package/src/daemon/providers-setup.ts +6 -0
  322. package/src/daemon/server.ts +117 -9
  323. package/src/daemon/tool-side-effects.ts +0 -9
  324. package/src/daemon/watch-handler.ts +4 -4
  325. package/src/daemon/web-search-history.ts +126 -0
  326. package/src/events/domain-events.ts +0 -1
  327. package/src/filing/filing-service.ts +9 -10
  328. package/src/heartbeat/heartbeat-service.ts +76 -28
  329. package/src/home/__tests__/feed-scheduler.test.ts +39 -11
  330. package/src/home/__tests__/rollup-producer.test.ts +44 -0
  331. package/src/home/assistant-feed-authoring.ts +4 -0
  332. package/src/home/emit-feed-event.ts +4 -0
  333. package/src/home/feed-scheduler.ts +20 -4
  334. package/src/home/feed-types.ts +56 -2
  335. package/src/home/relationship-state-writer.ts +2 -2
  336. package/src/home/rollup-producer.ts +34 -5
  337. package/src/home/suggested-prompts.ts +101 -0
  338. package/src/ipc/__tests__/attachment-ipc.test.ts +213 -0
  339. package/src/ipc/__tests__/browser-ipc.test.ts +339 -0
  340. package/src/ipc/__tests__/cache-ipc.test.ts +266 -0
  341. package/src/ipc/__tests__/socket-path.test.ts +73 -0
  342. package/src/ipc/__tests__/task-ipc.test.ts +577 -0
  343. package/src/ipc/__tests__/ui-request-route.test.ts +495 -0
  344. package/src/ipc/__tests__/watcher-ipc.test.ts +295 -0
  345. package/src/ipc/cli-client.ts +2 -1
  346. package/src/ipc/cli-server.ts +26 -8
  347. package/src/ipc/gateway-client.ts +4 -4
  348. package/src/ipc/routes/attachment.ts +114 -0
  349. package/src/ipc/routes/browser-context.ts +61 -0
  350. package/src/ipc/routes/browser.ts +96 -0
  351. package/src/ipc/routes/cache.ts +96 -0
  352. package/src/ipc/routes/index.ts +17 -1
  353. package/src/ipc/routes/task-queue.ts +226 -0
  354. package/src/ipc/routes/task.ts +173 -0
  355. package/src/ipc/routes/ui-request.ts +50 -0
  356. package/src/ipc/routes/watcher.ts +203 -0
  357. package/src/ipc/socket-path.ts +100 -0
  358. package/src/memory/__tests__/conversation-analyze-job.test.ts +9 -8
  359. package/src/memory/__tests__/conversation-group-migration.test.ts +99 -0
  360. package/src/memory/admin.ts +18 -0
  361. package/src/memory/conversation-analyze-job.ts +14 -13
  362. package/src/memory/conversation-attention-store.ts +13 -6
  363. package/src/memory/conversation-crud.ts +103 -3
  364. package/src/memory/conversation-group-migration.ts +38 -6
  365. package/src/memory/conversation-title-service.ts +7 -4
  366. package/src/memory/db-init.ts +2 -0
  367. package/src/memory/embedding-backend.ts +1 -1
  368. package/src/memory/graph/compaction.ts +299 -0
  369. package/src/memory/graph/consolidation.ts +4 -4
  370. package/src/memory/graph/conversation-graph-memory.ts +89 -29
  371. package/src/memory/graph/extraction.test.ts +272 -2
  372. package/src/memory/graph/extraction.ts +173 -51
  373. package/src/memory/graph/graph-search.test.ts +92 -0
  374. package/src/memory/graph/graph-search.ts +4 -1
  375. package/src/memory/graph/narrative.ts +2 -2
  376. package/src/memory/graph/pattern-scan.ts +2 -2
  377. package/src/memory/graph/retriever.test.ts +459 -0
  378. package/src/memory/graph/retriever.ts +230 -48
  379. package/src/memory/graph/store.ts +41 -0
  380. package/src/memory/graph/tool-handlers.ts +27 -0
  381. package/src/memory/graph/tools.ts +6 -1
  382. package/src/memory/indexer.ts +5 -5
  383. package/src/memory/job-handlers/conversation-starters.ts +23 -20
  384. package/src/memory/job-handlers/summarization.ts +2 -2
  385. package/src/memory/job-utils.ts +7 -1
  386. package/src/memory/jobs/embed-pkb-file.test.ts +168 -0
  387. package/src/memory/jobs/embed-pkb-file.ts +54 -0
  388. package/src/memory/jobs-store.ts +44 -3
  389. package/src/memory/jobs-worker.ts +4 -0
  390. package/src/memory/migrations/140-backfill-usage-cache-accounting.ts +1 -1
  391. package/src/memory/migrations/220-normalize-user-file-by-principal.ts +2 -2
  392. package/src/memory/migrations/222-strip-placeholder-sentinels-from-messages.ts +82 -0
  393. package/src/memory/migrations/index.ts +1 -0
  394. package/src/memory/pkb/pkb-index.test.ts +368 -0
  395. package/src/memory/pkb/pkb-index.ts +255 -0
  396. package/src/memory/pkb/pkb-reconcile.test.ts +251 -0
  397. package/src/memory/pkb/pkb-reconcile.ts +148 -0
  398. package/src/memory/pkb/pkb-search.test.ts +438 -0
  399. package/src/memory/pkb/pkb-search.ts +137 -0
  400. package/src/memory/pkb/types.ts +53 -0
  401. package/src/memory/qdrant-client.ts +122 -1
  402. package/src/memory/slack-thread-store.ts +37 -0
  403. package/src/messaging/providers/gmail/adapter.ts +6 -16
  404. package/src/messaging/providers/gmail/client.ts +22 -0
  405. package/src/messaging/providers/gmail/types.ts +7 -0
  406. package/src/messaging/providers/slack/adapter.ts +14 -2
  407. package/src/messaging/providers/slack/backfill.test.ts +257 -0
  408. package/src/messaging/providers/slack/backfill.ts +101 -0
  409. package/src/messaging/providers/slack/message-metadata.test.ts +316 -0
  410. package/src/messaging/providers/slack/message-metadata.ts +123 -0
  411. package/src/messaging/providers/slack/render-transcript.test.ts +1373 -0
  412. package/src/messaging/providers/slack/render-transcript.ts +443 -0
  413. package/src/messaging/style-analyzer.ts +5 -2
  414. package/src/notifications/README.md +9 -5
  415. package/src/notifications/decision-engine.ts +3 -9
  416. package/src/notifications/preference-extractor.ts +2 -6
  417. package/src/oauth/oauth-store.ts +1 -0
  418. package/src/oauth/platform-connection.test.ts +47 -0
  419. package/src/oauth/platform-connection.ts +15 -5
  420. package/src/oauth/seed-providers.ts +4 -2
  421. package/src/permissions/approval-policy.test.ts +948 -0
  422. package/src/permissions/approval-policy.ts +257 -0
  423. package/src/permissions/bash-risk-classifier.test.ts +1208 -0
  424. package/src/permissions/bash-risk-classifier.ts +707 -0
  425. package/src/permissions/checker.ts +217 -708
  426. package/src/permissions/command-registry.test.ts +535 -0
  427. package/src/permissions/command-registry.ts +825 -0
  428. package/src/permissions/defaults.ts +26 -78
  429. package/src/permissions/file-risk-classifier.test.ts +535 -0
  430. package/src/permissions/file-risk-classifier.ts +274 -0
  431. package/src/permissions/risk-types.ts +205 -0
  432. package/src/permissions/secret-prompter.ts +53 -2
  433. package/src/permissions/skill-risk-classifier.test.ts +311 -0
  434. package/src/permissions/skill-risk-classifier.ts +214 -0
  435. package/src/permissions/trust-client.ts +52 -25
  436. package/src/permissions/trust-store-interface.ts +1 -6
  437. package/src/permissions/trust-store.ts +161 -62
  438. package/src/permissions/types.ts +23 -14
  439. package/src/permissions/web-risk-classifier.test.ts +170 -0
  440. package/src/permissions/web-risk-classifier.ts +89 -0
  441. package/src/permissions/workspace-policy.ts +1 -16
  442. package/src/platform/client.ts +19 -1
  443. package/src/prompts/persona-resolver.ts +3 -3
  444. package/src/prompts/system-prompt.ts +19 -20
  445. package/src/prompts/templates/SOUL.md +2 -2
  446. package/src/prompts/update-bulletin-job.ts +190 -0
  447. package/src/providers/__tests__/context-overflow-error.test.ts +328 -0
  448. package/src/providers/__tests__/provider-env-vars.test.ts +102 -0
  449. package/src/providers/__tests__/retry-callsite.test.ts +424 -0
  450. package/src/providers/anthropic/client.ts +183 -14
  451. package/src/providers/call-site-routing.ts +71 -0
  452. package/src/providers/gemini/client.ts +65 -2
  453. package/src/providers/managed-proxy/constants.ts +2 -1
  454. package/src/providers/model-catalog.ts +501 -33
  455. package/src/providers/model-intents.ts +4 -4
  456. package/src/providers/openai/chat-completions-provider.ts +57 -1
  457. package/src/providers/openai/responses-provider.ts +86 -9
  458. package/src/providers/openrouter/client.ts +76 -9
  459. package/src/providers/provider-env-vars.ts +56 -0
  460. package/src/providers/provider-send-message.ts +22 -5
  461. package/src/providers/ratelimit.ts +4 -0
  462. package/src/providers/registry.ts +19 -8
  463. package/src/providers/retry.ts +174 -39
  464. package/src/providers/speech-to-text/__tests__/resolve.test.ts +55 -0
  465. package/src/providers/speech-to-text/google-gemini-live-stream.ts +4 -4
  466. package/src/providers/speech-to-text/provider-catalog.ts +17 -0
  467. package/src/providers/speech-to-text/resolve.ts +7 -0
  468. package/src/providers/speech-to-text/xai-realtime.test.ts +578 -0
  469. package/src/providers/speech-to-text/xai-realtime.ts +796 -0
  470. package/src/providers/speech-to-text/xai.test.ts +155 -0
  471. package/src/providers/speech-to-text/xai.ts +97 -0
  472. package/src/providers/types.ts +93 -3
  473. package/src/runtime/AGENTS.md +2 -2
  474. package/src/runtime/__tests__/agent-wake.test.ts +43 -2
  475. package/src/runtime/__tests__/interactive-ui.test.ts +673 -0
  476. package/src/runtime/agent-wake.ts +63 -22
  477. package/src/runtime/auth/route-policy.ts +4 -0
  478. package/src/runtime/btw-sidechain.ts +13 -3
  479. package/src/runtime/channel-reply-delivery.ts +106 -2
  480. package/src/runtime/decision-token.ts +116 -0
  481. package/src/runtime/gateway-client.ts +2 -2
  482. package/src/runtime/http-router.ts +32 -0
  483. package/src/runtime/http-server.ts +52 -1
  484. package/src/runtime/http-types.ts +23 -1
  485. package/src/runtime/interactive-ui.ts +362 -0
  486. package/src/runtime/invite-instruction-generator.ts +2 -2
  487. package/src/runtime/migrations/__tests__/gcs-signed-url.test.ts +176 -0
  488. package/src/runtime/migrations/__tests__/vbundle-metadata-merge-integration.test.ts +390 -0
  489. package/src/runtime/migrations/__tests__/vbundle-metadata-merge.test.ts +221 -0
  490. package/src/runtime/migrations/__tests__/vbundle-streaming-importer.test.ts +1540 -0
  491. package/src/runtime/migrations/__tests__/vbundle-streaming-validator.test.ts +453 -0
  492. package/src/runtime/migrations/__tests__/vbundle-tar-stream.test.ts +222 -0
  493. package/src/runtime/migrations/gcs-signed-url.ts +162 -0
  494. package/src/runtime/migrations/vbundle-importer.ts +154 -9
  495. package/src/runtime/migrations/vbundle-metadata-merge.ts +124 -0
  496. package/src/runtime/migrations/vbundle-streaming-importer.ts +2522 -0
  497. package/src/runtime/migrations/vbundle-streaming-validator.ts +244 -0
  498. package/src/runtime/migrations/vbundle-tar-stream.ts +217 -0
  499. package/src/runtime/migrations/vbundle-validator.ts +15 -6
  500. package/src/runtime/routes/__tests__/home-feed-routes.test.ts +111 -0
  501. package/src/runtime/routes/__tests__/migration-import-credential-filter.test.ts +114 -75
  502. package/src/runtime/routes/__tests__/migration-vellum-metadata-reconcile.test.ts +246 -0
  503. package/src/runtime/routes/approval-prompt-ts-tracker.ts +58 -0
  504. package/src/runtime/routes/approval-routes.ts +12 -17
  505. package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +9 -0
  506. package/src/runtime/routes/avatar-routes.ts +20 -4
  507. package/src/runtime/routes/btw-routes.ts +1 -4
  508. package/src/runtime/routes/conversation-management-routes.ts +20 -2
  509. package/src/runtime/routes/conversation-routes.ts +133 -27
  510. package/src/runtime/routes/debug-routes.ts +1 -1
  511. package/src/runtime/routes/diagnostics-routes.ts +6 -4
  512. package/src/runtime/routes/events-routes.ts +16 -0
  513. package/src/runtime/routes/guardian-approval-interception.ts +33 -3
  514. package/src/runtime/routes/guardian-approval-prompt.ts +13 -3
  515. package/src/runtime/routes/home-feed-routes.ts +120 -2
  516. package/src/runtime/routes/inbound-message-handler.ts +912 -2
  517. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +113 -2
  518. package/src/runtime/routes/inbound-stages/background-dispatch.ts +61 -3
  519. package/src/runtime/routes/inbound-stages/edit-intercept.ts +129 -6
  520. package/src/runtime/routes/integrations/slack/channel.ts +25 -3
  521. package/src/runtime/routes/llm-context-normalization.ts +23 -1
  522. package/src/runtime/routes/migration-routes.ts +720 -124
  523. package/src/runtime/routes/settings-routes.ts +4 -2
  524. package/src/runtime/routes/trust-rules-routes.ts +30 -14
  525. package/src/runtime/routes/work-items-routes.test.ts +1 -1
  526. package/src/runtime/routes/work-items-routes.ts +3 -2
  527. package/src/runtime/services/__tests__/analyze-conversation.test.ts +25 -43
  528. package/src/runtime/services/analyze-conversation.ts +12 -16
  529. package/src/runtime/skill-route-registry.ts +28 -6
  530. package/src/schedule/scheduler.ts +8 -0
  531. package/src/security/__tests__/provider-key-env-fallback.test.ts +119 -0
  532. package/src/security/__tests__/untrusted-content.test.ts +109 -0
  533. package/src/security/oauth2.ts +98 -35
  534. package/src/security/secure-keys.ts +7 -8
  535. package/src/security/token-manager.ts +27 -13
  536. package/src/security/untrusted-content.ts +102 -0
  537. package/src/skills/catalog-cache.ts +26 -7
  538. package/src/skills/catalog-install.ts +31 -3
  539. package/src/skills/skill-cache-store.ts +97 -0
  540. package/src/stt/__tests__/daemon-batch-transcriber.test.ts +76 -0
  541. package/src/stt/daemon-batch-transcriber.ts +33 -0
  542. package/src/stt/stt-stream-session.ts +8 -1
  543. package/src/stt/types.ts +5 -1
  544. package/src/subagent/manager.ts +41 -13
  545. package/src/tasks/ephemeral-permissions.ts +9 -4
  546. package/src/telemetry/usage-telemetry-reporter.ts +27 -5
  547. package/src/tools/browser/__tests__/browser-status.test.ts +45 -2
  548. package/src/tools/browser/browser-execution.ts +65 -38
  549. package/src/tools/browser/cdp-client/cdp-inspect/discovery.ts +22 -0
  550. package/src/tools/credentials/tool-policy.ts +39 -5
  551. package/src/tools/credentials/vault.ts +9 -4
  552. package/src/tools/executor.ts +4 -0
  553. package/src/tools/filesystem/write.ts +52 -0
  554. package/src/tools/host-terminal/host-shell.ts +45 -5
  555. package/src/tools/memory/register.test.ts +185 -0
  556. package/src/tools/memory/register.ts +3 -1
  557. package/src/tools/network/web-fetch.ts +20 -10
  558. package/src/tools/network/web-search.ts +19 -4
  559. package/src/tools/permission-checker.ts +36 -15
  560. package/src/tools/policy-context.ts +25 -8
  561. package/src/tools/registry.ts +55 -3
  562. package/src/tools/side-effects.ts +0 -11
  563. package/src/tools/skills/execute.ts +2 -2
  564. package/src/tools/skills/sandbox-runner.ts +5 -2
  565. package/src/tools/terminal/backends/native.ts +51 -2
  566. package/src/tools/terminal/safe-env.ts +3 -2
  567. package/src/tools/terminal/shell.ts +1 -0
  568. package/src/tools/tool-manifest.ts +6 -21
  569. package/src/tools/types.ts +12 -3
  570. package/src/tools/verification-control-plane-policy.ts +1 -1
  571. package/src/tts/__tests__/provider-adapters.test.ts +240 -13
  572. package/src/tts/provider-catalog.ts +18 -0
  573. package/src/tts/providers/index.ts +2 -0
  574. package/src/tts/providers/xai-provider.ts +224 -0
  575. package/src/tts/types.ts +46 -0
  576. package/src/types/tar-stream.d.ts +66 -0
  577. package/src/util/json.ts +17 -0
  578. package/src/util/platform.ts +2 -2
  579. package/src/util/pricing.ts +15 -5
  580. package/src/watcher/engine.ts +1 -1
  581. package/src/watcher/providers/google-calendar.ts +134 -8
  582. package/src/watcher/providers/outlook-calendar.ts +42 -2
  583. package/src/workspace/git-service.ts +23 -4
  584. package/src/workspace/migrations/038-unify-llm-callsite-configs.ts +516 -0
  585. package/src/workspace/migrations/039-drop-legacy-llm-keys.ts +171 -0
  586. package/src/workspace/migrations/040-seed-latency-callsite-defaults.ts +154 -0
  587. package/src/workspace/migrations/041-backfill-google-gmail-settings-scope.ts +57 -0
  588. package/src/workspace/migrations/042-fix-backfill-google-gmail-settings-scope.ts +70 -0
  589. package/src/workspace/migrations/043-release-notes-latex-rendering.ts +75 -0
  590. package/src/workspace/migrations/044-bump-stale-provider-stream-timeout.ts +51 -0
  591. package/src/workspace/migrations/045-release-notes-meet-avatar.ts +130 -0
  592. package/src/workspace/migrations/AGENTS.md +1 -1
  593. package/src/workspace/migrations/registry.ts +16 -0
  594. package/src/workspace/provider-commit-message-generator.ts +19 -38
  595. package/src/__tests__/gmail-archive-fallback.test.ts +0 -193
  596. package/src/__tests__/gmail-archive-gate.test.ts +0 -246
  597. package/src/__tests__/gmail-preferences.test.ts +0 -117
  598. package/src/__tests__/outlook-attachments.test.ts +0 -301
  599. package/src/__tests__/outlook-automation-tools.test.ts +0 -425
  600. package/src/__tests__/outlook-categories.test.ts +0 -212
  601. package/src/__tests__/outlook-compose-tools.test.ts +0 -325
  602. package/src/__tests__/outlook-declutter-tools.test.ts +0 -585
  603. package/src/__tests__/outlook-follow-up.test.ts +0 -196
  604. package/src/__tests__/outlook-trash.test.ts +0 -77
  605. package/src/__tests__/outlook-unsubscribe.test.ts +0 -279
  606. package/src/__tests__/update-bulletin-format.test.ts +0 -181
  607. package/src/__tests__/update-bulletin-state.test.ts +0 -135
  608. package/src/__tests__/update-bulletin.test.ts +0 -478
  609. package/src/__tests__/update-template-contract.test.ts +0 -29
  610. package/src/cli/commands/doctor.ts +0 -341
  611. package/src/config/bundled-skills/browser/SKILL.md +0 -88
  612. package/src/config/bundled-skills/browser/TOOLS.json +0 -516
  613. package/src/config/bundled-skills/browser/tools/browser-attach.ts +0 -12
  614. package/src/config/bundled-skills/browser/tools/browser-click.ts +0 -12
  615. package/src/config/bundled-skills/browser/tools/browser-close.ts +0 -12
  616. package/src/config/bundled-skills/browser/tools/browser-detach.ts +0 -12
  617. package/src/config/bundled-skills/browser/tools/browser-extract.ts +0 -12
  618. package/src/config/bundled-skills/browser/tools/browser-fill-credential.ts +0 -12
  619. package/src/config/bundled-skills/browser/tools/browser-hover.ts +0 -12
  620. package/src/config/bundled-skills/browser/tools/browser-navigate.ts +0 -12
  621. package/src/config/bundled-skills/browser/tools/browser-press-key.ts +0 -12
  622. package/src/config/bundled-skills/browser/tools/browser-screenshot.ts +0 -12
  623. package/src/config/bundled-skills/browser/tools/browser-scroll.ts +0 -12
  624. package/src/config/bundled-skills/browser/tools/browser-select-option.ts +0 -12
  625. package/src/config/bundled-skills/browser/tools/browser-snapshot.ts +0 -12
  626. package/src/config/bundled-skills/browser/tools/browser-status.ts +0 -12
  627. package/src/config/bundled-skills/browser/tools/browser-type.ts +0 -12
  628. package/src/config/bundled-skills/browser/tools/browser-wait-for-download.ts +0 -49
  629. package/src/config/bundled-skills/browser/tools/browser-wait-for.ts +0 -12
  630. package/src/config/bundled-skills/chatgpt-import/SKILL.md +0 -27
  631. package/src/config/bundled-skills/chatgpt-import/TOOLS.json +0 -27
  632. package/src/config/bundled-skills/chatgpt-import/tools/chatgpt-import.ts +0 -378
  633. package/src/config/bundled-skills/gmail/SKILL.md +0 -221
  634. package/src/config/bundled-skills/gmail/TOOLS.json +0 -588
  635. package/src/config/bundled-skills/gmail/tools/gmail-archive.ts +0 -256
  636. package/src/config/bundled-skills/gmail/tools/gmail-attachments.ts +0 -112
  637. package/src/config/bundled-skills/gmail/tools/gmail-draft.ts +0 -44
  638. package/src/config/bundled-skills/gmail/tools/gmail-filters.ts +0 -81
  639. package/src/config/bundled-skills/gmail/tools/gmail-follow-up.ts +0 -108
  640. package/src/config/bundled-skills/gmail/tools/gmail-forward.ts +0 -146
  641. package/src/config/bundled-skills/gmail/tools/gmail-label.ts +0 -53
  642. package/src/config/bundled-skills/gmail/tools/gmail-outreach-scan.ts +0 -347
  643. package/src/config/bundled-skills/gmail/tools/gmail-preferences-tool.ts +0 -59
  644. package/src/config/bundled-skills/gmail/tools/gmail-preferences.ts +0 -82
  645. package/src/config/bundled-skills/gmail/tools/gmail-send-draft.ts +0 -26
  646. package/src/config/bundled-skills/gmail/tools/gmail-sender-digest.ts +0 -347
  647. package/src/config/bundled-skills/gmail/tools/gmail-trash.ts +0 -29
  648. package/src/config/bundled-skills/gmail/tools/gmail-unsubscribe.ts +0 -122
  649. package/src/config/bundled-skills/gmail/tools/gmail-vacation.ts +0 -67
  650. package/src/config/bundled-skills/gmail/tools/scan-result-store.ts +0 -100
  651. package/src/config/bundled-skills/gmail/tools/shared.ts +0 -47
  652. package/src/config/bundled-skills/google-calendar/SKILL.md +0 -51
  653. package/src/config/bundled-skills/google-calendar/TOOLS.json +0 -226
  654. package/src/config/bundled-skills/google-calendar/calendar-client.ts +0 -223
  655. package/src/config/bundled-skills/google-calendar/tools/calendar-check-availability.ts +0 -27
  656. package/src/config/bundled-skills/google-calendar/tools/calendar-create-event.ts +0 -48
  657. package/src/config/bundled-skills/google-calendar/tools/calendar-get-event.ts +0 -19
  658. package/src/config/bundled-skills/google-calendar/tools/calendar-list-events.ts +0 -36
  659. package/src/config/bundled-skills/google-calendar/tools/calendar-rsvp.ts +0 -58
  660. package/src/config/bundled-skills/google-calendar/tools/shared.ts +0 -17
  661. package/src/config/bundled-skills/google-calendar/types.ts +0 -97
  662. package/src/config/bundled-skills/outlook/SKILL.md +0 -196
  663. package/src/config/bundled-skills/outlook/TOOLS.json +0 -530
  664. package/src/config/bundled-skills/outlook/tools/outlook-attachments.ts +0 -85
  665. package/src/config/bundled-skills/outlook/tools/outlook-categories.ts +0 -77
  666. package/src/config/bundled-skills/outlook/tools/outlook-draft.ts +0 -84
  667. package/src/config/bundled-skills/outlook/tools/outlook-follow-up.ts +0 -94
  668. package/src/config/bundled-skills/outlook/tools/outlook-forward.ts +0 -49
  669. package/src/config/bundled-skills/outlook/tools/outlook-outreach-scan.ts +0 -237
  670. package/src/config/bundled-skills/outlook/tools/outlook-rules.ts +0 -161
  671. package/src/config/bundled-skills/outlook/tools/outlook-send-draft.ts +0 -32
  672. package/src/config/bundled-skills/outlook/tools/outlook-sender-digest.ts +0 -272
  673. package/src/config/bundled-skills/outlook/tools/outlook-trash.ts +0 -29
  674. package/src/config/bundled-skills/outlook/tools/outlook-unsubscribe.ts +0 -129
  675. package/src/config/bundled-skills/outlook/tools/outlook-vacation.ts +0 -87
  676. package/src/config/bundled-skills/outlook/tools/shared.ts +0 -20
  677. package/src/config/bundled-skills/outlook-calendar/SKILL.md +0 -51
  678. package/src/config/bundled-skills/outlook-calendar/TOOLS.json +0 -221
  679. package/src/config/bundled-skills/outlook-calendar/calendar-client.ts +0 -252
  680. package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-check-availability.ts +0 -53
  681. package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-create-event.ts +0 -74
  682. package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-get-event.ts +0 -18
  683. package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-list-events.ts +0 -46
  684. package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-rsvp.ts +0 -36
  685. package/src/config/bundled-skills/outlook-calendar/tools/shared.ts +0 -17
  686. package/src/config/bundled-skills/outlook-calendar/types.ts +0 -120
  687. package/src/config/bundled-skills/slack/SKILL.md +0 -108
  688. package/src/config/bundled-skills/tasks/SKILL.md +0 -37
  689. package/src/config/bundled-skills/tasks/TOOLS.json +0 -353
  690. package/src/config/bundled-skills/tasks/icon.svg +0 -34
  691. package/src/config/bundled-skills/tasks/tools/task-delete.ts +0 -12
  692. package/src/config/bundled-skills/tasks/tools/task-list-add.ts +0 -12
  693. package/src/config/bundled-skills/tasks/tools/task-list-remove.ts +0 -12
  694. package/src/config/bundled-skills/tasks/tools/task-list-show.ts +0 -12
  695. package/src/config/bundled-skills/tasks/tools/task-list-update.ts +0 -12
  696. package/src/config/bundled-skills/tasks/tools/task-list.ts +0 -12
  697. package/src/config/bundled-skills/tasks/tools/task-queue-run.ts +0 -12
  698. package/src/config/bundled-skills/tasks/tools/task-run.ts +0 -12
  699. package/src/config/bundled-skills/tasks/tools/task-save.ts +0 -12
  700. package/src/config/bundled-skills/watcher/SKILL.md +0 -31
  701. package/src/config/bundled-skills/watcher/TOOLS.json +0 -167
  702. package/src/config/bundled-skills/watcher/tools/watcher-create.ts +0 -12
  703. package/src/config/bundled-skills/watcher/tools/watcher-delete.ts +0 -12
  704. package/src/config/bundled-skills/watcher/tools/watcher-digest.ts +0 -12
  705. package/src/config/bundled-skills/watcher/tools/watcher-list.ts +0 -12
  706. package/src/config/bundled-skills/watcher/tools/watcher-update.ts +0 -12
  707. package/src/prompts/templates/UPDATES.md +0 -50
  708. package/src/prompts/update-bulletin-format.ts +0 -85
  709. package/src/prompts/update-bulletin-state.ts +0 -58
  710. package/src/prompts/update-bulletin-template-path.ts +0 -13
  711. package/src/prompts/update-bulletin.ts +0 -139
  712. package/src/shared/provider-env-vars.ts +0 -19
  713. package/src/tools/watcher/create.ts +0 -86
  714. package/src/tools/watcher/delete.ts +0 -36
  715. package/src/tools/watcher/digest.ts +0 -54
  716. package/src/tools/watcher/list.ts +0 -83
  717. package/src/tools/watcher/update.ts +0 -71
@@ -9,6 +9,7 @@ import {
9
9
  getSummaryFromContextMessage,
10
10
  } from "../context/window-manager.js";
11
11
  import type {
12
+ ContentBlock,
12
13
  Message,
13
14
  Provider,
14
15
  ProviderResponse,
@@ -36,9 +37,10 @@ function makeConfig(
36
37
 
37
38
  function createProvider(
38
39
  fn: (messages: Message[]) => ProviderResponse | Promise<ProviderResponse>,
40
+ name: string = "mock",
39
41
  ): Provider {
40
42
  return {
41
- name: "mock",
43
+ name,
42
44
  async sendMessage(messages: Message[]): Promise<ProviderResponse> {
43
45
  return fn(messages);
44
46
  },
@@ -242,6 +244,63 @@ describe("ContextWindowManager", () => {
242
244
  expect(result.summaryText).toContain("## Recent Progress");
243
245
  });
244
246
 
247
+ test("marks summaryFailed when the provider throws and fallback runs", async () => {
248
+ // The agent-loop circuit breaker distinguishes "LLM call failed but
249
+ // fallback rescued us" from "compaction succeeded end-to-end". The
250
+ // fallback path must set summaryFailed:true so callers can count
251
+ // consecutive failures without losing the compacted messages.
252
+ const provider = createProvider(async () => {
253
+ throw new Error("provider unavailable");
254
+ });
255
+ const manager = new ContextWindowManager({
256
+ provider,
257
+ systemPrompt: "system prompt",
258
+ config: makeConfig({
259
+ maxInputTokens: 260,
260
+ targetBudgetRatio: 0.59,
261
+ }),
262
+ });
263
+ const long = "z".repeat(220);
264
+ const history = [
265
+ message("user", `task ${long}`),
266
+ message("assistant", `result ${long}`),
267
+ message("user", `followup ${long}`),
268
+ ];
269
+
270
+ const result = await manager.maybeCompact(history);
271
+ expect(result.compacted).toBe(true);
272
+ expect(result.summaryFailed).toBe(true);
273
+ });
274
+
275
+ test("does not mark summaryFailed on a successful provider call", async () => {
276
+ const provider = createProvider(() => ({
277
+ content: [
278
+ { type: "text", text: "## Goals\n- summary produced by provider" },
279
+ ],
280
+ model: "mock-model",
281
+ usage: { inputTokens: 60, outputTokens: 12 },
282
+ stopReason: "end_turn",
283
+ }));
284
+ const manager = new ContextWindowManager({
285
+ provider,
286
+ systemPrompt: "system prompt",
287
+ config: makeConfig({
288
+ maxInputTokens: 260,
289
+ targetBudgetRatio: 0.59,
290
+ }),
291
+ });
292
+ const long = "z".repeat(220);
293
+ const history = [
294
+ message("user", `task ${long}`),
295
+ message("assistant", `result ${long}`),
296
+ message("user", `followup ${long}`),
297
+ ];
298
+
299
+ const result = await manager.maybeCompact(history);
300
+ expect(result.compacted).toBe(true);
301
+ expect(result.summaryFailed).toBe(false);
302
+ });
303
+
245
304
  test("serializes file blocks for summary chunks", async () => {
246
305
  const prompts: string[] = [];
247
306
  const provider = createProvider((messages) => {
@@ -261,8 +320,9 @@ describe("ContextWindowManager", () => {
261
320
  provider,
262
321
  systemPrompt: "system prompt",
263
322
  config: makeConfig({
264
- maxInputTokens: 550,
323
+ maxInputTokens: 620,
265
324
  targetBudgetRatio: 0.59,
325
+ compactThreshold: 0.5,
266
326
  }),
267
327
  });
268
328
  const long = "f".repeat(500);
@@ -834,6 +894,143 @@ describe("ContextWindowManager", () => {
834
894
  );
835
895
  });
836
896
 
897
+ test("force compaction with loose target override still summarizes persisted messages", async () => {
898
+ // `pickKeepBoundary` clamps `targetInputTokensOverride` to
899
+ // `config.targetInputTokens`, so a loose override cannot
900
+ // short-circuit summarization into the truncate-only early-exit.
901
+
902
+ let summaryCalls = 0;
903
+ const provider = createProvider(() => {
904
+ summaryCalls += 1;
905
+ return {
906
+ content: [{ type: "text", text: "## Goals\n- real summary" }],
907
+ model: "mock-model",
908
+ usage: { inputTokens: 80, outputTokens: 20 },
909
+ stopReason: "end_turn",
910
+ };
911
+ });
912
+
913
+ // Scaled from prod (max 200k → 1000) preserving key ratios: the
914
+ // loose override (~0.85×max) is ~17× the post-compaction target
915
+ // (~0.05×max), so history between the two exercises the clamp.
916
+ const manager = new ContextWindowManager({
917
+ provider,
918
+ systemPrompt: "system prompt",
919
+ config: makeConfig({
920
+ maxInputTokens: 1000,
921
+ targetBudgetRatio: 0.1,
922
+ summaryBudgetRatio: 0.05,
923
+ compactThreshold: 0.3,
924
+ }),
925
+ });
926
+
927
+ // History in the "no-op zone": above threshold (300), below override (850).
928
+ const long = "x".repeat(180);
929
+ const history: Message[] = [
930
+ message("user", `u1 ${long}`),
931
+ message("assistant", `a1 ${long}`),
932
+ message("user", `u2 ${long}`),
933
+ message("assistant", `a2 ${long}`),
934
+ message("user", `u3 ${long}`),
935
+ message("assistant", `a3 ${long}`),
936
+ message("user", `u4 ${long}`),
937
+ message("assistant", `a4 ${long}`),
938
+ message("user", `u5 ${long}`),
939
+ ];
940
+
941
+ const preflightBudgetAnalog = Math.floor(1000 * 0.85);
942
+ const result = await manager.maybeCompact(history, undefined, {
943
+ force: true,
944
+ targetInputTokensOverride: preflightBudgetAnalog,
945
+ });
946
+
947
+ // Guard: we're actually above the compact threshold.
948
+ expect(result.previousEstimatedInputTokens).toBeGreaterThan(
949
+ result.thresholdTokens,
950
+ );
951
+
952
+ // A real summarization happened (not the truncate-only no-op).
953
+ expect(result.compactedPersistedMessages).toBeGreaterThan(0);
954
+ expect(summaryCalls).toBeGreaterThan(0);
955
+ });
956
+
957
+ test("force=true compacts below minFloor when a kept turn exceeds target", async () => {
958
+ // A giant paste in the last user turn means minFloor=1 alone exceeds target.
959
+ // Under force, pickKeepBoundary should walk keepTurns below minFloor (down to
960
+ // 0) so the huge block falls into the compacted region and gets summarized
961
+ // instead of being kept at full size.
962
+ const provider = createProvider(() => ({
963
+ content: [{ type: "text", text: "## Goals\n- compressed large paste" }],
964
+ model: "mock-model",
965
+ usage: { inputTokens: 120, outputTokens: 20 },
966
+ stopReason: "end_turn",
967
+ }));
968
+ const manager = new ContextWindowManager({
969
+ provider,
970
+ systemPrompt: "system prompt",
971
+ config: makeConfig({ maxInputTokens: 600, targetBudgetRatio: 0.2 }),
972
+ });
973
+ const hugePaste = "p".repeat(4000); // ~1000 tokens, well above targetInputTokens
974
+ const history: Message[] = [
975
+ message("user", "u1 small"),
976
+ message("assistant", "a1 small"),
977
+ message("user", `u2 ${hugePaste}`),
978
+ ];
979
+
980
+ const result = await manager.maybeCompact(history, undefined, {
981
+ force: true,
982
+ });
983
+
984
+ expect(result.compacted).toBe(true);
985
+ // With force=true the kept region is empty; all turns including the oversized
986
+ // paste were summarized, so the compacted result is just the summary.
987
+ expect(result.messages).toHaveLength(1);
988
+ expect(result.compactedMessages).toBe(history.length);
989
+ expect(getSummaryFromContextMessage(result.messages[0])).toContain(
990
+ "compressed large paste",
991
+ );
992
+ expect(result.estimatedInputTokens).toBeLessThan(
993
+ result.previousEstimatedInputTokens,
994
+ );
995
+ });
996
+
997
+ test("force=false honors minFloor even when the kept turn exceeds target", async () => {
998
+ // Same oversized paste, but without force the algorithm must preserve the
999
+ // minFloor=1 recent turn (auto mid-loop compaction needs the in-flight turn
1000
+ // intact). Anything compactable before the floor still gets summarized.
1001
+ const provider = createProvider(() => ({
1002
+ content: [{ type: "text", text: "## Goals\n- summary" }],
1003
+ model: "mock-model",
1004
+ usage: { inputTokens: 60, outputTokens: 10 },
1005
+ stopReason: "end_turn",
1006
+ }));
1007
+ const manager = new ContextWindowManager({
1008
+ provider,
1009
+ systemPrompt: "system prompt",
1010
+ config: makeConfig({ maxInputTokens: 600, targetBudgetRatio: 0.2 }),
1011
+ });
1012
+ const hugePaste = "p".repeat(4000);
1013
+ const history: Message[] = [
1014
+ message("user", "u1 small"),
1015
+ message("assistant", "a1 small"),
1016
+ message("user", "u2 small"),
1017
+ message("assistant", "a2 small"),
1018
+ message("user", `u3 ${hugePaste}`),
1019
+ ];
1020
+
1021
+ const result = await manager.maybeCompact(history);
1022
+
1023
+ expect(result.compacted).toBe(true);
1024
+ // The oversized last user turn is retained verbatim; the kept array starts
1025
+ // with the summary followed by the messages from that turn onward.
1026
+ const lastUser = result.messages
1027
+ .filter((m) => m.role === "user")
1028
+ .map((m) => (m.content[0].type === "text" ? m.content[0].text : ""))
1029
+ .find((t) => t.startsWith("u3 "));
1030
+ expect(lastUser).toBeDefined();
1031
+ expect(lastUser!.length).toBeGreaterThan(hugePaste.length);
1032
+ });
1033
+
837
1034
  test("shouldCompact returns needed=false with estimatedTokens when below threshold", () => {
838
1035
  const provider = createProvider(() => {
839
1036
  throw new Error("should not be called");
@@ -1096,6 +1293,197 @@ describe("ContextWindowManager", () => {
1096
1293
  expect(manager.nonPersistedPrefixCount).toBe(0);
1097
1294
  });
1098
1295
 
1296
+ test("summary system prompt instructs verbatim thread-anchor preservation", async () => {
1297
+ const capturedSystemPrompts: (string | undefined)[] = [];
1298
+ const provider: Provider = {
1299
+ name: "mock",
1300
+ async sendMessage(
1301
+ _messages: Message[],
1302
+ _tools,
1303
+ systemPrompt,
1304
+ ): Promise<ProviderResponse> {
1305
+ capturedSystemPrompts.push(systemPrompt);
1306
+ return {
1307
+ content: [
1308
+ {
1309
+ type: "text",
1310
+ text: "## Goals\n- preserved thread parent verbatim",
1311
+ },
1312
+ ],
1313
+ model: "mock-model",
1314
+ usage: { inputTokens: 60, outputTokens: 12 },
1315
+ stopReason: "end_turn",
1316
+ };
1317
+ },
1318
+ };
1319
+ const manager = new ContextWindowManager({
1320
+ provider,
1321
+ systemPrompt: "system prompt",
1322
+ config: makeConfig({ maxInputTokens: 600 }),
1323
+ });
1324
+ const long = "x".repeat(240);
1325
+ // Simulate a Slack-style transcript where an old user "thread parent"
1326
+ // message is about to be compacted while a later reply survives in the
1327
+ // retained tail. The clause being asserted instructs the summarizer to
1328
+ // preserve that parent verbatim — we cannot verify the model's behavior
1329
+ // here (the provider is a stub), so we instead assert the clause itself
1330
+ // reaches the summarizer.
1331
+ const history: Message[] = [
1332
+ message("user", `parent: kickoff plan ${long}`),
1333
+ message("assistant", `a1 ${long}`),
1334
+ message("user", `u2 ${long}`),
1335
+ message("assistant", `a2 ${long}`),
1336
+ message("user", `reply-in-thread ${long}`),
1337
+ message("assistant", `a3 ${long}`),
1338
+ ];
1339
+
1340
+ const result = await manager.maybeCompact(history);
1341
+ expect(result.compacted).toBe(true);
1342
+ expect(capturedSystemPrompts.length).toBeGreaterThan(0);
1343
+ const seenPrompt = capturedSystemPrompts[0];
1344
+ expect(seenPrompt).toBeDefined();
1345
+ expect(seenPrompt).toContain("Thread anchors");
1346
+ expect(seenPrompt).toContain("verbatim");
1347
+ });
1348
+
1349
+ test("summary prompt lists retained-tail thread-reply references", async () => {
1350
+ const capturedMessages: Message[][] = [];
1351
+ const provider: Provider = {
1352
+ name: "mock",
1353
+ async sendMessage(messages: Message[]): Promise<ProviderResponse> {
1354
+ capturedMessages.push(messages);
1355
+ return {
1356
+ content: [{ type: "text", text: "## Goals\n- ok" }],
1357
+ model: "mock-model",
1358
+ usage: { inputTokens: 60, outputTokens: 12 },
1359
+ stopReason: "end_turn",
1360
+ };
1361
+ },
1362
+ };
1363
+ const manager = new ContextWindowManager({
1364
+ provider,
1365
+ systemPrompt: "system prompt",
1366
+ config: makeConfig({ maxInputTokens: 600 }),
1367
+ });
1368
+ const long = "x".repeat(240);
1369
+ // Compactable region ends before the retained tail, which contains a
1370
+ // Slack-style reply line that cites its parent via `→ M1a2b3c`. The
1371
+ // summary prompt must surface that reference so the Thread-anchors
1372
+ // instruction has something to act on.
1373
+ const history: Message[] = [
1374
+ message("user", `[11/14/23 14:25 @alice]: parent kickoff ${long}`),
1375
+ message("assistant", `a1 ${long}`),
1376
+ message("user", `u2 ${long}`),
1377
+ message("assistant", `a2 ${long}`),
1378
+ message("user", `[11/14/23 14:28 @bob → M1a2b3c]: reply ${long}`),
1379
+ message("assistant", `a3 ${long}`),
1380
+ ];
1381
+
1382
+ const result = await manager.maybeCompact(history);
1383
+ expect(result.compacted).toBe(true);
1384
+ expect(capturedMessages.length).toBeGreaterThan(0);
1385
+ const userPromptText = capturedMessages[0]
1386
+ .flatMap((m) => m.content)
1387
+ .filter(
1388
+ (b): b is Extract<ContentBlock, { type: "text" }> => b.type === "text",
1389
+ )
1390
+ .map((b) => b.text)
1391
+ .join("\n");
1392
+ expect(userPromptText).toContain("### Retained Thread References");
1393
+ expect(userPromptText).toContain("→ M1a2b3c");
1394
+ });
1395
+
1396
+ test("summary prompt lists retained-tail thread-reply references for edited replies", async () => {
1397
+ const capturedMessages: Message[][] = [];
1398
+ const provider: Provider = {
1399
+ name: "mock",
1400
+ async sendMessage(messages: Message[]): Promise<ProviderResponse> {
1401
+ capturedMessages.push(messages);
1402
+ return {
1403
+ content: [{ type: "text", text: "## Goals\n- ok" }],
1404
+ model: "mock-model",
1405
+ usage: { inputTokens: 60, outputTokens: 12 },
1406
+ stopReason: "end_turn",
1407
+ };
1408
+ },
1409
+ };
1410
+ const manager = new ContextWindowManager({
1411
+ provider,
1412
+ systemPrompt: "system prompt",
1413
+ config: makeConfig({ maxInputTokens: 600 }),
1414
+ });
1415
+ const long = "x".repeat(240);
1416
+ // An edited reply renders with `, edited …` between the parent alias and
1417
+ // the closing bracket: `→ Mxxxxxx, edited MM/DD/YY HH:MM]`. The regex
1418
+ // must still flag these lines so retention works for edited replies.
1419
+ const history: Message[] = [
1420
+ message("user", `[11/14/23 14:25 @alice]: parent kickoff ${long}`),
1421
+ message("assistant", `a1 ${long}`),
1422
+ message("user", `u2 ${long}`),
1423
+ message("assistant", `a2 ${long}`),
1424
+ message(
1425
+ "user",
1426
+ `[11/14/23 14:28 @bob → M1a2b3c, edited 11/14/23 14:32]: reply ${long}`,
1427
+ ),
1428
+ message("assistant", `a3 ${long}`),
1429
+ ];
1430
+
1431
+ const result = await manager.maybeCompact(history);
1432
+ expect(result.compacted).toBe(true);
1433
+ expect(capturedMessages.length).toBeGreaterThan(0);
1434
+ const userPromptText = capturedMessages[0]
1435
+ .flatMap((m) => m.content)
1436
+ .filter(
1437
+ (b): b is Extract<ContentBlock, { type: "text" }> => b.type === "text",
1438
+ )
1439
+ .map((b) => b.text)
1440
+ .join("\n");
1441
+ expect(userPromptText).toContain("### Retained Thread References");
1442
+ expect(userPromptText).toContain("→ M1a2b3c, edited 11/14/23 14:32");
1443
+ });
1444
+
1445
+ test("summary prompt omits retained references when retained tail has no thread markers", async () => {
1446
+ const capturedMessages: Message[][] = [];
1447
+ const provider: Provider = {
1448
+ name: "mock",
1449
+ async sendMessage(messages: Message[]): Promise<ProviderResponse> {
1450
+ capturedMessages.push(messages);
1451
+ return {
1452
+ content: [{ type: "text", text: "## Goals\n- ok" }],
1453
+ model: "mock-model",
1454
+ usage: { inputTokens: 60, outputTokens: 12 },
1455
+ stopReason: "end_turn",
1456
+ };
1457
+ },
1458
+ };
1459
+ const manager = new ContextWindowManager({
1460
+ provider,
1461
+ systemPrompt: "system prompt",
1462
+ config: makeConfig({ maxInputTokens: 600 }),
1463
+ });
1464
+ const long = "x".repeat(240);
1465
+ const history: Message[] = [
1466
+ message("user", `u1 ${long}`),
1467
+ message("assistant", `a1 ${long}`),
1468
+ message("user", `u2 ${long}`),
1469
+ message("assistant", `a2 ${long}`),
1470
+ message("user", `u3 ${long}`),
1471
+ message("assistant", `a3 ${long}`),
1472
+ ];
1473
+
1474
+ const result = await manager.maybeCompact(history);
1475
+ expect(result.compacted).toBe(true);
1476
+ const userPromptText = capturedMessages[0]
1477
+ .flatMap((m) => m.content)
1478
+ .filter(
1479
+ (b): b is Extract<ContentBlock, { type: "text" }> => b.type === "text",
1480
+ )
1481
+ .map((b) => b.text)
1482
+ .join("\n");
1483
+ expect(userPromptText).not.toContain("### Retained Thread References");
1484
+ expect(userPromptText).not.toMatch(/→ M[0-9a-f]{6}]/);
1485
+ });
1486
+
1099
1487
  test("does not subtract summaryOffset when summary at index 0 is child-owned from prior compaction", async () => {
1100
1488
  const provider = createProvider(() => ({
1101
1489
  content: [{ type: "text", text: "## Goals\n- next child summary" }],
@@ -1140,4 +1528,144 @@ describe("ContextWindowManager", () => {
1140
1528
  expect(result.compactedPersistedMessages).toBe(2);
1141
1529
  expect(manager.nonPersistedPrefixCount).toBe(0);
1142
1530
  });
1531
+
1532
+ test("Slack origin bumps default minKeepRecentUserTurns to 8", async () => {
1533
+ const provider = createProvider(() => ({
1534
+ content: [{ type: "text", text: "## Goals\n- slack thread context" }],
1535
+ model: "mock-model",
1536
+ usage: { inputTokens: 60, outputTokens: 12 },
1537
+ stopReason: "end_turn",
1538
+ }));
1539
+
1540
+ // Use targetInputTokensOverride so the binary search is forced even
1541
+ // for a small history. Both managers see the same tight budget; the
1542
+ // only knob that varies is conversationOriginChannel.
1543
+ const config = makeConfig({ maxInputTokens: 12_000 });
1544
+ const long = "s".repeat(220);
1545
+ // 9 user turns: enough headroom for Slack's bumped floor of 8 to be
1546
+ // distinguishable from the default floor of 1.
1547
+ const history: Message[] = [];
1548
+ for (let i = 1; i <= 9; i++) {
1549
+ history.push(message("user", `u${i} ${long}`));
1550
+ history.push(message("assistant", `a${i} ${long}`));
1551
+ }
1552
+
1553
+ const slackManager = new ContextWindowManager({
1554
+ provider,
1555
+ systemPrompt: "system prompt",
1556
+ config,
1557
+ });
1558
+ const slackResult = await slackManager.maybeCompact(history, undefined, {
1559
+ force: true,
1560
+ targetInputTokensOverride: 200,
1561
+ conversationOriginChannel: "slack",
1562
+ });
1563
+
1564
+ const defaultManager = new ContextWindowManager({
1565
+ provider,
1566
+ systemPrompt: "system prompt",
1567
+ config,
1568
+ });
1569
+ const defaultResult = await defaultManager.maybeCompact(
1570
+ history,
1571
+ undefined,
1572
+ { force: true, targetInputTokensOverride: 200 },
1573
+ );
1574
+
1575
+ expect(slackResult.compacted).toBe(true);
1576
+ expect(defaultResult.compacted).toBe(true);
1577
+ // Default floor (1 user turn) compacts more of the history than the
1578
+ // Slack floor (8 user turns), which preserves more recent context.
1579
+ expect(defaultResult.compactedMessages).toBeGreaterThan(
1580
+ slackResult.compactedMessages,
1581
+ );
1582
+ // Slack keeps 8 of 9 user turns: 16 kept messages, 2 compacted.
1583
+ expect(slackResult.compactedMessages).toBe(2);
1584
+ });
1585
+
1586
+ test("non-Slack origin keeps default minKeepRecentUserTurns of 1", async () => {
1587
+ const provider = createProvider(() => ({
1588
+ content: [{ type: "text", text: "## Goals\n- standard summary" }],
1589
+ model: "mock-model",
1590
+ usage: { inputTokens: 60, outputTokens: 12 },
1591
+ stopReason: "end_turn",
1592
+ }));
1593
+
1594
+ const config = makeConfig({ maxInputTokens: 12_000 });
1595
+ const long = "n".repeat(220);
1596
+ const history: Message[] = [];
1597
+ for (let i = 1; i <= 9; i++) {
1598
+ history.push(message("user", `u${i} ${long}`));
1599
+ history.push(message("assistant", `a${i} ${long}`));
1600
+ }
1601
+
1602
+ // Telegram origin must behave identically to no-channel-hint default.
1603
+ const telegramManager = new ContextWindowManager({
1604
+ provider,
1605
+ systemPrompt: "system prompt",
1606
+ config,
1607
+ });
1608
+ const telegramResult = await telegramManager.maybeCompact(
1609
+ history,
1610
+ undefined,
1611
+ {
1612
+ force: true,
1613
+ targetInputTokensOverride: 200,
1614
+ conversationOriginChannel: "telegram",
1615
+ },
1616
+ );
1617
+
1618
+ const defaultManager = new ContextWindowManager({
1619
+ provider,
1620
+ systemPrompt: "system prompt",
1621
+ config,
1622
+ });
1623
+ const defaultResult = await defaultManager.maybeCompact(
1624
+ history,
1625
+ undefined,
1626
+ { force: true, targetInputTokensOverride: 200 },
1627
+ );
1628
+
1629
+ expect(telegramResult.compacted).toBe(true);
1630
+ expect(defaultResult.compacted).toBe(true);
1631
+ expect(telegramResult.compactedMessages).toBe(
1632
+ defaultResult.compactedMessages,
1633
+ );
1634
+ });
1635
+
1636
+ test("explicit minKeepRecentUserTurns wins over Slack default", async () => {
1637
+ const provider = createProvider(() => ({
1638
+ content: [{ type: "text", text: "## Goals\n- emergency override" }],
1639
+ model: "mock-model",
1640
+ usage: { inputTokens: 60, outputTokens: 12 },
1641
+ stopReason: "end_turn",
1642
+ }));
1643
+
1644
+ const manager = new ContextWindowManager({
1645
+ provider,
1646
+ systemPrompt: "system prompt",
1647
+ config: makeConfig({
1648
+ maxInputTokens: 260,
1649
+ targetBudgetRatio: 0.28,
1650
+ }),
1651
+ });
1652
+ const long = "e".repeat(220);
1653
+ const history: Message[] = [
1654
+ message("user", `u1 ${long}`),
1655
+ message("assistant", `a1 ${long}`),
1656
+ message("user", `u2 ${long}`),
1657
+ ];
1658
+
1659
+ // Emergency override (`minKeepRecentUserTurns: 0`) must take precedence
1660
+ // over the Slack-bumped default of 8 — this guards the agent loop's
1661
+ // context-too-large recovery path which always passes 0.
1662
+ const result = await manager.maybeCompact(history, undefined, {
1663
+ force: true,
1664
+ minKeepRecentUserTurns: 0,
1665
+ conversationOriginChannel: "slack",
1666
+ });
1667
+ expect(result.compacted).toBe(true);
1668
+ expect(result.compactedMessages).toBe(3);
1669
+ expect(result.messages).toHaveLength(1);
1670
+ });
1143
1671
  });
@@ -25,23 +25,34 @@ mock.module("../providers/registry.js", () => ({
25
25
  mock.module("../config/loader.js", () => ({
26
26
  getConfig: () => ({
27
27
  ui: {},
28
-
29
- provider: "mock-provider",
30
- maxTokens: 4096,
31
- thinking: false,
32
- contextWindow: {
33
- maxInputTokens: 100000,
34
- thresholdTokens: 80000,
35
- preserveRecentMessages: 6,
36
- summaryModel: "mock-model",
37
- maxSummaryTokens: 512,
38
- overflowRecovery: {
39
- enabled: true,
40
- safetyMarginRatio: 0.05,
41
- maxAttempts: 3,
42
- interactiveLatestTurnCompression: "summarize",
43
- nonInteractiveLatestTurnCompression: "truncate",
28
+
29
+ llm: {
30
+ default: {
31
+ provider: "mock-provider",
32
+ model: "mock-model",
33
+ maxTokens: 4096,
34
+ effort: "max" as const,
35
+ speed: "standard" as const,
36
+ temperature: null,
37
+ thinking: { enabled: false, streamThinking: true },
38
+ contextWindow: {
39
+ enabled: true,
40
+ maxInputTokens: 100000,
41
+ targetBudgetRatio: 0.3,
42
+ compactThreshold: 0.8,
43
+ summaryBudgetRatio: 0.05,
44
+ overflowRecovery: {
45
+ enabled: true,
46
+ safetyMarginRatio: 0.05,
47
+ maxAttempts: 3,
48
+ interactiveLatestTurnCompression: "summarize",
49
+ nonInteractiveLatestTurnCompression: "truncate",
50
+ },
51
+ },
44
52
  },
53
+ profiles: {},
54
+ callSites: {},
55
+ pricingOverrides: [],
45
56
  },
46
57
  rateLimit: { maxRequestsPerMinute: 0 },
47
58
  daemon: {
@@ -157,6 +168,9 @@ mock.module("../agent/loop.js", () => ({
157
168
  getToolTokenBudget() {
158
169
  return 0;
159
170
  }
171
+ getActiveModel() {
172
+ return undefined;
173
+ }
160
174
  async run(
161
175
  messages: Message[],
162
176
  onEvent: (event: AgentEvent) => void,