@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
@@ -1,10 +1,10 @@
1
1
  import { v4 as uuid } from "uuid";
2
2
 
3
3
  import { getConfig } from "../../config/loader.js";
4
- import type { Speed } from "../../config/schemas/inference.js";
4
+ import type { LLMCallSite, Speed } from "../../config/schemas/llm.js";
5
5
  import type { HeartbeatService } from "../../heartbeat/heartbeat-service.js";
6
6
  import type { SecretPromptResult } from "../../permissions/secret-prompter.js";
7
- import type { ModelIntent } from "../../providers/types.js";
7
+ import { isPlaceholderSentinelText } from "../../providers/anthropic/client.js";
8
8
  import type { AuthContext } from "../../runtime/auth/types.js";
9
9
  import type { DebouncerMap } from "../../util/debounce.js";
10
10
  import { getLogger } from "../../util/logger.js";
@@ -102,6 +102,22 @@ export interface RenderedHistoryContent {
102
102
  thinkingSegments: string[];
103
103
  }
104
104
 
105
+ /**
106
+ * Slack-specific metadata extracted at the inbound HTTP boundary and threaded
107
+ * through to user-message persistence so the row can be tagged with a
108
+ * `slackMeta` envelope for the chronological renderer.
109
+ */
110
+ export interface SlackInboundMessageMetadata {
111
+ /** Slack channel id (conversation external id) — recorded as `channelId`. */
112
+ channelId: string;
113
+ /** Slack `ts` for this message — required so persistence can record `channelTs`. */
114
+ channelTs: string;
115
+ /** Parent `thread_ts` when the message lives inside a thread; absent for top-level. */
116
+ threadTs?: string;
117
+ /** Resolved sender label (display name preferred, username fallback). */
118
+ displayName?: string;
119
+ }
120
+
105
121
  /**
106
122
  * Optional overrides for conversation creation (e.g. interview mode).
107
123
  */
@@ -128,19 +144,26 @@ export interface ConversationCreateOptions {
128
144
  commandIntent?: { type: string; payload?: string; languageCode?: string };
129
145
  /** Optional callback to receive real-time agent loop events (text deltas, tool starts, etc.). */
130
146
  onEvent?: (msg: ServerMessage) => void;
131
- /**
132
- * Optional model selection strategy for this conversation's agent loop.
133
- * When set, overrides the provider's default model per-turn. Used by the
134
- * auto-analyze loop to route the analysis agent to a dedicated model.
135
- */
136
- modelIntent?: ModelIntent;
137
147
  /**
138
148
  * Optional explicit model override (provider/model string) for this
139
- * conversation's agent loop. Takes precedence over `modelIntent` when
140
- * both are set. Used by the auto-analyze loop to pin the analysis agent
141
- * to a specific model.
149
+ * conversation's agent loop. Used by the auto-analyze loop to pin the
150
+ * analysis agent to a specific model.
142
151
  */
143
152
  modelOverride?: string;
153
+ /**
154
+ * Optional LLM call-site identifier threaded through to the per-call
155
+ * provider config. Adapter callers (heartbeat, filing, schedule, etc.)
156
+ * pass their call-site here so the agent loop routes through
157
+ * `resolveCallSiteConfig` instead of the global default.
158
+ */
159
+ callSite?: LLMCallSite;
160
+ /**
161
+ * Slack inbound metadata captured at the channel ingress boundary. When
162
+ * present (and the turn channel resolves to Slack), persistence writes a
163
+ * `slackMeta` sub-object into the message's `metadata` JSON for the
164
+ * chronological renderer to consume.
165
+ */
166
+ slackInbound?: SlackInboundMessageMetadata;
144
167
  }
145
168
 
146
169
  /**
@@ -329,6 +352,11 @@ export function renderHistoryContent(content: unknown): RenderedHistoryContent {
329
352
  // path — e.g. empty segments between consecutive tool_use blocks that
330
353
  // break tool-call grouping in the UI.
331
354
  if (block.text.trim().length === 0) continue;
355
+ // Drop Anthropic provider placeholder sentinels. These are injected
356
+ // into outbound API requests to preserve role alternation and must
357
+ // never be rendered to users. Belt-and-suspenders with the persist-
358
+ // time filter in cleanAssistantContent and migration 222.
359
+ if (isPlaceholderSentinelText(block.text)) continue;
332
360
  textParts.push(block.text);
333
361
  ensureSegment();
334
362
  currentSegmentParts.push(block.text);
@@ -1517,7 +1517,7 @@ export async function draftSkill(
1517
1517
  if (missing.length > 0) {
1518
1518
  let llmGenerated = false;
1519
1519
  try {
1520
- const provider = await getConfiguredProvider();
1520
+ const provider = await getConfiguredProvider("skillCategoryInference");
1521
1521
  if (provider) {
1522
1522
  const { signal, cleanup } = createTimeout(LLM_DRAFT_TIMEOUT_MS);
1523
1523
  try {
@@ -1539,7 +1539,7 @@ export async function draftSkill(
1539
1539
  [],
1540
1540
  undefined,
1541
1541
  {
1542
- config: { modelIntent: "latency-optimized", max_tokens: 256 },
1542
+ config: { callSite: "skillCategoryInference", max_tokens: 256 },
1543
1543
  signal,
1544
1544
  },
1545
1545
  );
@@ -0,0 +1,197 @@
1
+ /**
2
+ * Runs an OAuth2 loopback flow to install the user's Slack app and capture
3
+ * bot + user tokens in a single exchange.
4
+ *
5
+ * Prerequisites: client_id, client_secret, and app_token must already be
6
+ * stored in the credential vault (service: slack_channel).
7
+ *
8
+ * The handler reads client credentials from secure storage, starts a
9
+ * loopback OAuth server on port 17322, opens the browser to Slack's
10
+ * authorize URL, and waits for the user to click "Allow". Slack's
11
+ * oauth.v2.access response contains both the bot token (access_token)
12
+ * and user token (authed_user.access_token). Both are stored via
13
+ * setSlackChannelConfig.
14
+ */
15
+
16
+ import { credentialKey } from "../../security/credential-key.js";
17
+ import { startOAuth2Flow } from "../../security/oauth2.js";
18
+ import { getSecureKeyAsync } from "../../security/secure-keys.js";
19
+ import { openInHostBrowser } from "../../util/browser.js";
20
+ import { getLogger } from "../../util/logger.js";
21
+ import { setSlackChannelConfig } from "./config-slack-channel.js";
22
+
23
+ const log = getLogger("slack-channel-oauth-install");
24
+
25
+ /** Port pre-registered for Slack in seed-providers.ts. */
26
+ const SLACK_LOOPBACK_PORT = 17322;
27
+
28
+ /** Bot scopes matching the manifest in SKILL.md. */
29
+ const BOT_SCOPES = [
30
+ "app_mentions:read",
31
+ "assistant:write",
32
+ "channels:history",
33
+ "channels:join",
34
+ "channels:read",
35
+ "chat:write",
36
+ "files:read",
37
+ "files:write",
38
+ "groups:history",
39
+ "groups:read",
40
+ "im:history",
41
+ "im:read",
42
+ "im:write",
43
+ "mpim:history",
44
+ "mpim:read",
45
+ "reactions:read",
46
+ "reactions:write",
47
+ "users:read",
48
+ ];
49
+
50
+ /** User scopes matching the manifest in SKILL.md. */
51
+ const USER_SCOPES = [
52
+ "channels:history",
53
+ "channels:read",
54
+ "groups:history",
55
+ "groups:read",
56
+ "im:history",
57
+ "im:read",
58
+ "mpim:history",
59
+ "mpim:read",
60
+ "users:read",
61
+ "search:read",
62
+ "reactions:read",
63
+ ];
64
+
65
+ export interface SlackOAuthInstallResult {
66
+ success: boolean;
67
+ hasBotToken: boolean;
68
+ hasUserToken: boolean;
69
+ error?: string;
70
+ }
71
+
72
+ export async function runSlackChannelOAuthInstall(): Promise<SlackOAuthInstallResult> {
73
+ // Read client credentials from secure storage
74
+ const clientId = await getSecureKeyAsync(
75
+ credentialKey("slack_channel", "client_id"),
76
+ );
77
+ if (!clientId) {
78
+ return {
79
+ success: false,
80
+ hasBotToken: false,
81
+ hasUserToken: false,
82
+ error:
83
+ "Client ID not found in credential store. Store it first via credential_store prompt (service: slack_channel, field: client_id).",
84
+ };
85
+ }
86
+
87
+ const clientSecret = await getSecureKeyAsync(
88
+ credentialKey("slack_channel", "client_secret"),
89
+ );
90
+ if (!clientSecret) {
91
+ return {
92
+ success: false,
93
+ hasBotToken: false,
94
+ hasUserToken: false,
95
+ error:
96
+ "Client Secret not found in credential store. Store it first via credential_store prompt (service: slack_channel, field: client_secret).",
97
+ };
98
+ }
99
+
100
+ const appToken = await getSecureKeyAsync(
101
+ credentialKey("slack_channel", "app_token"),
102
+ );
103
+ if (!appToken) {
104
+ return {
105
+ success: false,
106
+ hasBotToken: false,
107
+ hasUserToken: false,
108
+ error:
109
+ "App Token not found in credential store. Store it first via credential_store prompt (service: slack_channel, field: app_token).",
110
+ };
111
+ }
112
+
113
+ log.info("Starting Slack OAuth install flow via loopback");
114
+
115
+ let result;
116
+ try {
117
+ result = await startOAuth2Flow(
118
+ {
119
+ authorizeUrl: "https://slack.com/oauth/v2/authorize",
120
+ tokenExchangeUrl: "https://slack.com/api/oauth.v2.access",
121
+ scopes: BOT_SCOPES,
122
+ clientId,
123
+ clientSecret,
124
+ scopeSeparator: ",",
125
+ authorizeParams: {
126
+ user_scope: USER_SCOPES.join(","),
127
+ },
128
+ },
129
+ {
130
+ openUrl: (url) => openInHostBrowser(url),
131
+ },
132
+ {
133
+ callbackTransport: "loopback",
134
+ loopbackPort: SLACK_LOOPBACK_PORT,
135
+ },
136
+ );
137
+ } catch (err) {
138
+ const msg = err instanceof Error ? err.message : String(err);
139
+ log.error({ err: msg }, "Slack OAuth install flow failed");
140
+ return {
141
+ success: false,
142
+ hasBotToken: false,
143
+ hasUserToken: false,
144
+ error: `OAuth flow failed: ${msg}`,
145
+ };
146
+ }
147
+
148
+ // Slack's oauth.v2.access returns:
149
+ // access_token: "xoxb-..." (bot token)
150
+ // authed_user: { access_token: "xoxp-..." } (user token)
151
+ const raw = result.rawTokenResponse;
152
+ const botToken = raw.access_token as string | undefined;
153
+ const authedUser = raw.authed_user as { access_token?: string } | undefined;
154
+ const userToken = authedUser?.access_token as string | undefined;
155
+
156
+ if (!botToken) {
157
+ log.error(
158
+ { rawKeys: Object.keys(raw) },
159
+ "Slack OAuth response missing bot access_token",
160
+ );
161
+ return {
162
+ success: false,
163
+ hasBotToken: false,
164
+ hasUserToken: false,
165
+ error:
166
+ "Slack OAuth response did not include a bot token (access_token). The app may not have bot scopes configured.",
167
+ };
168
+ }
169
+
170
+ log.info(
171
+ { hasBotToken: true, hasUserToken: !!userToken },
172
+ "Slack OAuth tokens received, storing via setSlackChannelConfig",
173
+ );
174
+
175
+ // Store bot token (and user token if present) via the Slack channel handler,
176
+ // which validates tokens and persists workspace metadata.
177
+ const configResult = await setSlackChannelConfig(
178
+ botToken,
179
+ appToken,
180
+ userToken,
181
+ );
182
+
183
+ if (!configResult.success) {
184
+ return {
185
+ success: false,
186
+ hasBotToken: false,
187
+ hasUserToken: false,
188
+ error: configResult.error ?? "Failed to store Slack tokens",
189
+ };
190
+ }
191
+
192
+ return {
193
+ success: true,
194
+ hasBotToken: true,
195
+ hasUserToken: !!userToken,
196
+ };
197
+ }
@@ -1,3 +1,5 @@
1
+ import { join } from "node:path";
2
+
1
3
  import { config as dotenvConfig } from "dotenv";
2
4
 
3
5
  import type { BackupWorkerHandle } from "../backup/backup-worker.js";
@@ -72,7 +74,6 @@ import {
72
74
  import { backfillManualTokenConnections } from "../oauth/manual-token-connection.js";
73
75
  import { seedOAuthProviders } from "../oauth/seed-providers.js";
74
76
  import { ensurePromptFiles } from "../prompts/system-prompt.js";
75
- import { syncUpdateBulletinOnStartup } from "../prompts/update-bulletin.js";
76
77
  import { resolveManagedProxyContext } from "../providers/managed-proxy/context.js";
77
78
  import { buildAssistantEvent } from "../runtime/assistant-event.js";
78
79
  import { assistantEventHub } from "../runtime/assistant-event-hub.js";
@@ -89,6 +90,7 @@ import {
89
90
  } from "../runtime/capability-tokens.js";
90
91
  import { ensureVellumGuardianBinding } from "../runtime/guardian-vellum-migration.js";
91
92
  import { RuntimeHttpServer } from "../runtime/http-server.js";
93
+ import { recoverInterruptedImport } from "../runtime/migrations/vbundle-streaming-importer.js";
92
94
  import { startScheduler } from "../schedule/scheduler.js";
93
95
  import {
94
96
  onCesClientChanged,
@@ -278,6 +280,36 @@ export async function runDaemon(): Promise<void> {
278
280
 
279
281
  ensureDataDir();
280
282
 
283
+ // Recover from any streaming `.vbundle` import that was interrupted by a
284
+ // crash or SIGKILL. If the previous process died between
285
+ // `carryOverPreservedPaths` and the atomic workspace swap, the live
286
+ // workspace may be missing `data/db` / `data/qdrant` / etc. The marker
287
+ // at `<workspaceDir>.import-marker.json` (persisted before any rename
288
+ // runs) tells us where the orphaned preserved paths landed; the
289
+ // recovery helper moves them back into the live workspace and cleans
290
+ // up the temp tree. Running this BEFORE `initializeDb()` ensures the
291
+ // DB singleton opens against the fully-restored `assistant.db`.
292
+ try {
293
+ const recoveryResult = await recoverInterruptedImport(getWorkspaceDir());
294
+ if (!recoveryResult.ok) {
295
+ // Rollback is intentionally unresolved — backup/temp/marker are
296
+ // preserved on disk so an operator (or a later retry) can finish
297
+ // the recovery. Log loudly so ops sees it, but don't block start-up:
298
+ // the daemon still needs to come up for diagnostics. The next
299
+ // `streamCommitImport` will refuse to start a new import until the
300
+ // marker is resolved.
301
+ log.error(
302
+ { failedCount: recoveryResult.failedCount },
303
+ "Interrupted-import recovery is INCOMPLETE; leftover .pre-import-* / .import-* scratch dirs remain in the workspace. Manual intervention may be required before the next import can run.",
304
+ );
305
+ }
306
+ } catch (err) {
307
+ log.warn(
308
+ { err },
309
+ "recoverInterruptedImport threw during daemon startup; continuing",
310
+ );
311
+ }
312
+
281
313
  // Load (or generate + persist) the auth signing key so tokens survive
282
314
  // daemon restarts.
283
315
  const signingKey = resolveSigningKey();
@@ -543,18 +575,6 @@ export async function runDaemon(): Promise<void> {
543
575
  log.info("Daemon startup: loading config");
544
576
  const config = loadConfig();
545
577
 
546
- // Run bulletin sync AFTER the config merge + load so that getConfig()
547
- // inside syncUpdateBulletinOnStartup() observes the fully merged config.
548
- // Running it earlier would populate the config cache with pre-merge
549
- // values, poisoning every downstream getConfig() consumer.
550
- if (dbReady) {
551
- try {
552
- syncUpdateBulletinOnStartup();
553
- } catch (err) {
554
- log.warn({ err }, "Bulletin sync failed — continuing startup");
555
- }
556
- }
557
-
558
578
  // Seed module-level ingress state from the workspace config so that
559
579
  // getIngressPublicBaseUrl() returns the correct value immediately after
560
580
  // startup (before any handleIngressConfig("set") call). Without this,
@@ -655,7 +675,9 @@ export async function runDaemon(): Promise<void> {
655
675
  ...(startupProxyCtx.assistantApiKey
656
676
  ? { assistantApiKey: startupProxyCtx.assistantApiKey }
657
677
  : {}),
658
- ...(startupAssistantId ? { assistantId: startupAssistantId } : {}),
678
+ ...(startupAssistantId
679
+ ? { assistantId: startupAssistantId }
680
+ : {}),
659
681
  });
660
682
  if (accepted) {
661
683
  log.info("CES reconnection handshake accepted");
@@ -690,6 +712,24 @@ export async function runDaemon(): Promise<void> {
690
712
  await server.start();
691
713
  log.info("Daemon startup: DaemonServer started");
692
714
 
715
+ // Kick off the update bulletin background job AFTER `server.start()`
716
+ // resolves. `server.start()` installs the default wake resolver (via
717
+ // `registerDefaultWakeResolver()`), which the job depends on to actually
718
+ // invoke the agent. Dispatching before that point races the resolver
719
+ // registration and causes `wakeAgentForOpportunity()` to silently return
720
+ // `{invoked: false}`, leaving an orphan background conversation and a
721
+ // wasted LLM title-generation call every startup.
722
+ //
723
+ // Kept fire-and-forget (`void import(...).then(...).catch(...)`) so the
724
+ // daemon never blocks startup on it.
725
+ if (dbReady) {
726
+ void import("../prompts/update-bulletin-job.js")
727
+ .then((m) => m.runUpdateBulletinJobIfNeeded())
728
+ .catch((err) =>
729
+ log.warn({ err }, "Update bulletin job failed — continuing startup"),
730
+ );
731
+ }
732
+
693
733
  // Mutable refs for Qdrant, memory worker, and backup worker so background
694
734
  // init can assign them and the shutdown handler always sees the latest value.
695
735
  const bgRefs: {
@@ -774,6 +814,28 @@ export async function runDaemon(): Promise<void> {
774
814
  "Qdrant client initialization failed — memory features will be degraded",
775
815
  );
776
816
  }
817
+
818
+ // Reconcile the PKB Qdrant index against the on-disk tree. Kept
819
+ // inside the `qdrantStarted` guard so we don't call
820
+ // `getQdrantClient()` (which throws "not initialized") on every
821
+ // startup when Qdrant is unavailable. Fire-and-forget so enqueued
822
+ // re-index jobs drain in the background and first-turn latency
823
+ // stays unaffected.
824
+ void (async () => {
825
+ try {
826
+ const { reconcilePkbIndex } =
827
+ await import("../memory/pkb/pkb-reconcile.js");
828
+ const { PKB_WORKSPACE_SCOPE } =
829
+ await import("../memory/pkb/types.js");
830
+ const pkbRoot = join(getWorkspaceDir(), "pkb");
831
+ await reconcilePkbIndex(pkbRoot, PKB_WORKSPACE_SCOPE);
832
+ } catch (err) {
833
+ log.warn(
834
+ { err },
835
+ "PKB index reconciliation failed — continuing startup",
836
+ );
837
+ }
838
+ })();
777
839
  }
778
840
 
779
841
  log.info("Daemon startup: starting memory worker");
@@ -434,6 +434,19 @@ export interface ContextCompacted {
434
434
  summaryModel: string;
435
435
  }
436
436
 
437
+ /**
438
+ * Emitted when the compaction circuit breaker trips. After three consecutive
439
+ * summary-LLM failures (with local fallback covering each), auto-compaction is
440
+ * suspended until `openUntil` to avoid repeatedly hammering a broken provider.
441
+ * User-initiated compaction (`/compact`, `force: true`) bypasses the breaker.
442
+ */
443
+ export interface CompactionCircuitOpen {
444
+ type: "compaction_circuit_open";
445
+ reason: "3_consecutive_failures";
446
+ /** Timestamp (ms since epoch) when the breaker will allow auto-compaction again. */
447
+ openUntil: number;
448
+ }
449
+
437
450
  export type ConversationErrorCode =
438
451
  | "PROVIDER_NETWORK"
439
452
  | "PROVIDER_RATE_LIMIT"
@@ -531,6 +544,7 @@ export type _ConversationsServerMessages =
531
544
  | UsageUpdate
532
545
  | UsageResponse
533
546
  | ContextCompacted
547
+ | CompactionCircuitOpen
534
548
  | ConversationErrorMessage
535
549
  | ConversationInfo
536
550
  | ConversationTitleUpdated
@@ -23,6 +23,10 @@ export interface UserMessage {
23
23
  microphonePermissionGranted?: boolean;
24
24
  /** Structured command intent — bypasses text parsing when present. */
25
25
  commandIntent?: CommandIntent;
26
+ /** Client-generated correlation nonce for echo dedup. See
27
+ * `UserMessageEcho.clientMessageId` — the server echoes this value
28
+ * back on the matching `user_message_echo` event. */
29
+ clientMessageId?: string;
26
30
  }
27
31
 
28
32
  export interface ConfirmationResponse {
@@ -33,7 +37,6 @@ export interface ConfirmationResponse {
33
37
  | "allow_10m"
34
38
  | "allow_conversation"
35
39
  | "always_allow"
36
- | "always_allow_high_risk"
37
40
  | "deny"
38
41
  | "always_deny";
39
42
  selectedPattern?: string;
@@ -67,6 +70,11 @@ export interface UserMessageEcho {
67
70
  /** Server-generated request ID for the send. Allows correlation with
68
71
  * `message_queued` / `message_dequeued` events for the same turn. */
69
72
  requestId?: string;
73
+ /** Client-generated correlation nonce from the HTTP POST body. Echoed
74
+ * back so the originating client can dedupe its optimistic row even
75
+ * if the SSE echo beats the 202 response. Absent for synthetic echoes
76
+ * (e.g. surface-action prompts) that did not originate from a client POST. */
77
+ clientMessageId?: string;
70
78
  }
71
79
 
72
80
  export interface AssistantTextDelta {
@@ -8,8 +8,6 @@ export interface AddTrustRule {
8
8
  pattern: string;
9
9
  scope: string;
10
10
  decision: "allow" | "deny" | "ask";
11
- /** When true, the rule also covers high-risk invocations. */
12
- allowHighRisk?: boolean;
13
11
  /** Execution target override for this rule. */
14
12
  executionTarget?: "host" | "sandbox";
15
13
  }
@@ -1,6 +1,7 @@
1
1
  import { describe, expect, test } from "bun:test";
2
2
 
3
- import { parseActualTokensFromError } from "./conversation-agent-loop.js";
3
+ import { ContextOverflowError } from "../providers/types.js";
4
+ import { parseActualTokensFromError } from "./parse-actual-tokens-from-error.js";
4
5
 
5
6
  describe("parseActualTokensFromError", () => {
6
7
  test("returns null for null input", () => {
@@ -68,4 +69,59 @@ describe("parseActualTokensFromError", () => {
68
69
  test("returns null when no numeric pattern matches", () => {
69
70
  expect(parseActualTokensFromError("context window exceeded")).toBeNull();
70
71
  });
72
+
73
+ // ── Typed-error branch ─────────────────────────────────────────────
74
+
75
+ test("prefers ContextOverflowError.actualTokens over string-regex match", () => {
76
+ // Message would regex-parse to 999999, but typed field wins.
77
+ const err = new ContextOverflowError(
78
+ "Anthropic API error (400): prompt is too long: 999999 tokens > 200000 maximum",
79
+ "anthropic",
80
+ {
81
+ actualTokens: 242201,
82
+ maxTokens: 200000,
83
+ },
84
+ );
85
+ expect(parseActualTokensFromError(err)).toBe(242201);
86
+ });
87
+
88
+ test("falls back to regex when ContextOverflowError has no actualTokens", () => {
89
+ const err = new ContextOverflowError(
90
+ "OpenAI API error (400): too many input tokens: 150000 > 128000",
91
+ "openai",
92
+ {},
93
+ );
94
+ expect(parseActualTokensFromError(err)).toBe(150000);
95
+ });
96
+
97
+ test("returns null when ContextOverflowError has neither typed field nor matching message", () => {
98
+ const err = new ContextOverflowError("context window exceeded", "openai");
99
+ expect(parseActualTokensFromError(err)).toBeNull();
100
+ });
101
+
102
+ test("typed-error parsing takes precedence over string regex even when both present", () => {
103
+ // String has 999999 tokens > 200000; typed field says 242201.
104
+ // The typed field MUST win — this is the core contract.
105
+ const err = new ContextOverflowError(
106
+ "prompt is too long: 999999 tokens > 200000 maximum",
107
+ "anthropic",
108
+ { actualTokens: 242201 },
109
+ );
110
+ expect(parseActualTokensFromError(err)).toBe(242201);
111
+ });
112
+
113
+ test("accepts an untyped Error instance and parses its message", () => {
114
+ const err = new Error("prompt is too long: 242201 tokens > 200000 maximum");
115
+ expect(parseActualTokensFromError(err)).toBe(242201);
116
+ });
117
+
118
+ test("ignores non-numeric/invalid actualTokens on typed error", () => {
119
+ // actualTokens of 0 should fall through (typed check requires > 0).
120
+ const err = new ContextOverflowError(
121
+ "prompt is too long: 242201 tokens > 200000 maximum",
122
+ "anthropic",
123
+ { actualTokens: 0 },
124
+ );
125
+ expect(parseActualTokensFromError(err)).toBe(242201);
126
+ });
71
127
  });
@@ -0,0 +1,66 @@
1
+ import { isContextOverflowError } from "../providers/types.js";
2
+
3
+ /**
4
+ * Parse the actual token count reported by the provider for a
5
+ * context-too-large failure.
6
+ *
7
+ * Prefers the typed `ContextOverflowError.actualTokens` field when the
8
+ * thrown error is one. Falls back to regex-parsing the message for patterns
9
+ * like:
10
+ * "prompt is too long: 242201 tokens > 200000 maximum" (Anthropic)
11
+ * "too many input tokens: 242201 > 200000" (OpenAI)
12
+ *
13
+ * The regex path remains a safety net for provider-adapter paths (e.g.
14
+ * managed-proxy rewrappers) that surface untyped errors.
15
+ *
16
+ * Accepts a raw error object, an `Error` instance, or a plain string.
17
+ * Returns the actual token count, or `null` when it cannot be determined.
18
+ */
19
+ export function parseActualTokensFromError(
20
+ errorOrMessage: unknown,
21
+ ): number | null {
22
+ // Typed path — the provider client wrapped a matching upstream error as
23
+ // ContextOverflowError. Use the parsed field directly when available.
24
+ if (isContextOverflowError(errorOrMessage)) {
25
+ const actual = errorOrMessage.actualTokens;
26
+ if (typeof actual === "number" && actual > 0) return actual;
27
+ // Typed error without `actualTokens` — fall through to regex-parse the
28
+ // underlying message in case the upstream body carries it in text form.
29
+ return parseFromMessage(errorOrMessage.message ?? null);
30
+ }
31
+
32
+ // Untyped path — accept either an Error or a string.
33
+ if (errorOrMessage == null) return null;
34
+ if (typeof errorOrMessage === "string") {
35
+ return parseFromMessage(errorOrMessage);
36
+ }
37
+ if (typeof errorOrMessage === "object" && "message" in errorOrMessage) {
38
+ const msg = (errorOrMessage as { message?: unknown }).message;
39
+ if (typeof msg === "string") return parseFromMessage(msg);
40
+ }
41
+ return null;
42
+ }
43
+
44
+ function parseFromMessage(errorMessage: string | null): number | null {
45
+ if (!errorMessage) return null;
46
+
47
+ // Match patterns like "242201 tokens > 200000" or "242201 > 200000 maximum"
48
+ const match = errorMessage.match(
49
+ /(\d[\d,]*)\s*tokens?\s*[>≥]|:\s*(\d[\d,]*)\s*[>≥]/i,
50
+ );
51
+ if (match) {
52
+ const raw = (match[1] || match[2]).replace(/,/g, "");
53
+ const parsed = parseInt(raw, 10);
54
+ if (!isNaN(parsed) && parsed > 0) return parsed;
55
+ }
56
+
57
+ // Fallback: match "too many input tokens: N > M"
58
+ const fallback = errorMessage.match(/(\d[\d,]*)\s*[>≥]\s*\d/);
59
+ if (fallback) {
60
+ const raw = fallback[1].replace(/,/g, "");
61
+ const parsed = parseInt(raw, 10);
62
+ if (!isNaN(parsed) && parsed > 0) return parsed;
63
+ }
64
+
65
+ return null;
66
+ }