@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,3 +1,6 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+
1
4
  import type { ContextWindowConfig } from "../config/types.js";
2
5
  import type {
3
6
  ContentBlock,
@@ -5,6 +8,7 @@ import type {
5
8
  Message,
6
9
  Provider,
7
10
  } from "../providers/types.js";
11
+ import { resolveBundledDir } from "../util/bundled-asset.js";
8
12
  import { getLogger } from "../util/logger.js";
9
13
  import { safeStringSlice } from "../util/unicode.js";
10
14
  import {
@@ -26,11 +30,38 @@ const COMPACTION_TOOL_RESULT_MAX_CHARS = 6_000;
26
30
  const MIN_COMPACTABLE_PERSISTED_MESSAGES = 2;
27
31
  const INTERNAL_CONTEXT_SUMMARY_MESSAGES = new WeakSet<Message>();
28
32
 
29
- const SUMMARY_SYSTEM_PROMPT = [
33
+ /**
34
+ * Load the compaction summary system prompt from the bundled markdown asset.
35
+ *
36
+ * `resolveBundledDir` handles the compiled-binary case where the caller path
37
+ * points to `/$bunfs/` and the asset lives next to the executable (macOS app
38
+ * bundle `Contents/Resources/` or sibling dir). In source mode it falls back
39
+ * to the sibling `prompts/` directory.
40
+ */
41
+ export function loadCompactPrompt(): string {
42
+ const callerDir = import.meta.dirname ?? __dirname;
43
+ const promptsDir = resolveBundledDir(callerDir, "prompts", "compact-prompts");
44
+ const promptPath = join(promptsDir, "compact.md");
45
+ const contents = readFileSync(promptPath, "utf-8");
46
+ if (contents.length === 0) {
47
+ throw new Error(
48
+ `compact.md at ${promptPath} is empty — compaction summary prompt missing`,
49
+ );
50
+ }
51
+ return contents;
52
+ }
53
+
54
+ /**
55
+ * Hardcoded fallback prompt used when the bundled `compact.md` asset is
56
+ * missing or unreadable, so the daemon can still compact conversations
57
+ * rather than failing module import at startup.
58
+ */
59
+ const SUMMARY_PROMPT_FALLBACK = [
30
60
  "You compress long assistant conversations into durable working memory.",
31
61
  "Focus on actionable state, not prose.",
32
62
  "Preserve concrete facts: goals, constraints, decisions, pending questions, file paths, commands, errors, and TODOs.",
33
63
  "Remove repetition and stale details that were superseded.",
64
+ 'Thread anchors: when a "Retained Thread References" section is present, each listed reply cites its parent via `→ Mxxxxxx`. If that parent appears in the Transcript, preserve its text verbatim (reactions may be aggregated as "N users reacted"). Omit when the section is absent.',
34
65
  "Return concise markdown using these section headers exactly:",
35
66
  "## Goals",
36
67
  "## Constraints",
@@ -40,6 +71,42 @@ const SUMMARY_SYSTEM_PROMPT = [
40
71
  "## Recent Progress",
41
72
  ].join("\n");
42
73
 
74
+ /**
75
+ * Load the compact prompt with graceful fallback. If `loader` throws (missing
76
+ * or unreadable bundled asset, partial deployment, filesystem corruption),
77
+ * logs a warning and returns the hardcoded fallback string so module import
78
+ * never fails. The loader is injectable for testability.
79
+ */
80
+ export function loadCompactPromptOrFallback(
81
+ loader: () => string = loadCompactPrompt,
82
+ ): string {
83
+ try {
84
+ return loader();
85
+ } catch (err) {
86
+ log.warn(
87
+ { err },
88
+ "Failed to load compact.md from bundle; using inline fallback prompt. The bundled asset may be missing or unreadable.",
89
+ );
90
+ return SUMMARY_PROMPT_FALLBACK;
91
+ }
92
+ }
93
+
94
+ const SUMMARY_SYSTEM_PROMPT = loadCompactPromptOrFallback();
95
+
96
+ /**
97
+ * Pattern matching a Slack-style reply tag-line's parent-alias reference.
98
+ * The chronological renderer emits reply lines as
99
+ * `[MM/DD/YY HH:MM @sender → Mxxxxxx]: body`, or, for edited replies,
100
+ * `[MM/DD/YY HH:MM @sender → Mxxxxxx, edited MM/DD/YY HH:MM]: body`. The
101
+ * character after the 6-hex parent alias is therefore `]` for a plain reply
102
+ * or `,` for an edited one — the regex accepts either. `Mxxxxxx` is the
103
+ * first 6 hex chars of sha256(threadTs). A retained-tail text block that
104
+ * contains this pattern is carrying a live reference to a parent that may
105
+ * still live in the compactable region — the summarizer needs to know about
106
+ * it to act on the Thread-anchors clause of SUMMARY_SYSTEM_PROMPT.
107
+ */
108
+ const THREAD_REPLY_REFERENCE_PATTERN = /→ M[0-9a-f]{6}[,\]]/;
109
+
43
110
  export interface ContextWindowResult {
44
111
  messages: Message[];
45
112
  compacted: boolean;
@@ -58,6 +125,13 @@ export interface ContextWindowResult {
58
125
  summaryRawResponses?: unknown[];
59
126
  summaryText: string;
60
127
  reason?: string;
128
+ /**
129
+ * True when the summary LLM call threw and the local fallback produced the
130
+ * summary. Callers use this to distinguish provider-side summary failures
131
+ * from successful compactions so they can apply circuit-breaker logic
132
+ * without losing the fallback-compacted messages.
133
+ */
134
+ summaryFailed?: boolean;
61
135
  }
62
136
 
63
137
  export interface ShouldCompactResult {
@@ -73,13 +147,22 @@ export interface ContextWindowCompactOptions {
73
147
  * Override the minimum number of recent user turns to preserve.
74
148
  * Set to `0` for emergency recovery that can compact the entire history
75
149
  * (except the summary message itself). When omitted, the default floor
76
- * of 1 recent user turn is enforced.
150
+ * is `1` (or `8` when `conversationOriginChannel === "slack"`).
77
151
  */
78
152
  minKeepRecentUserTurns?: number;
153
+ /**
154
+ * Origin channel hint used when `minKeepRecentUserTurns` is omitted.
155
+ * Slack-originated conversations bump the default keep floor so multi-turn
156
+ * thread context (replies, quoted messages) is not summarized away too
157
+ * aggressively. Explicit `minKeepRecentUserTurns` overrides this hint.
158
+ */
159
+ conversationOriginChannel?: string;
79
160
  /**
80
161
  * Override the target input token budget used for keep-boundary
81
- * projected-fit checks. Allows the caller to demand a stricter fit
82
- * than the normal `config.targetInputTokens` during forced recovery.
162
+ * projected-fit checks. Clamped to no looser than `config.targetInputTokens`
163
+ * i.e. the override may only demand a *stricter* fit. Passing a looser
164
+ * value has no effect. Intended for forced recovery paths that need a
165
+ * tighter target than the default.
83
166
  */
84
167
  targetInputTokensOverride?: number;
85
168
  /**
@@ -274,6 +357,8 @@ export class ContextWindowManager {
274
357
  const keepPlan = this.pickKeepBoundary(messages, userTurnStarts, {
275
358
  minKeepRecentUserTurns: options?.minKeepRecentUserTurns,
276
359
  targetInputTokensOverride: options?.targetInputTokensOverride,
360
+ conversationOriginChannel: options?.conversationOriginChannel,
361
+ force: options?.force,
277
362
  });
278
363
  if (keepPlan.keepFromIndex <= summaryOffset) {
279
364
  // All turns fit after truncation projection, but the real in-memory
@@ -447,13 +532,18 @@ export class ContextWindowManager {
447
532
  };
448
533
  }
449
534
 
535
+ const retainedThreadRefs = collectRetainedThreadReferences(
536
+ messages.slice(keepPlan.keepFromIndex),
537
+ );
450
538
  const transcriptBlocks = this.capTranscriptBlocksToTokenBudget(
451
539
  serializeMessagesToContentBlocks(compactableMessages),
452
540
  existingSummary ?? "No previous summary.",
541
+ retainedThreadRefs,
453
542
  );
454
543
  const summaryUpdate = await this.updateSummary(
455
544
  existingSummary ?? "No previous summary.",
456
545
  transcriptBlocks,
546
+ retainedThreadRefs,
457
547
  signal,
458
548
  );
459
549
  const summary = summaryUpdate.summary;
@@ -463,6 +553,7 @@ export class ContextWindowManager {
463
553
  const summaryCacheCreationInputTokens =
464
554
  summaryUpdate.cacheCreationInputTokens;
465
555
  const summaryCacheReadInputTokens = summaryUpdate.cacheReadInputTokens;
556
+ const summaryFailed = summaryUpdate.failed;
466
557
  const summaryRawResponses: unknown[] = [];
467
558
  if (Array.isArray(summaryUpdate.rawResponse)) {
468
559
  summaryRawResponses.push(...summaryUpdate.rawResponse);
@@ -499,7 +590,9 @@ export class ContextWindowManager {
499
590
  // the summary at index 0 as child-owned.
500
591
  this.nonPersistedPrefixCount = Math.max(
501
592
  0,
502
- this.nonPersistedPrefixCount - injectedInCompactable - injectedSummaryOffset,
593
+ this.nonPersistedPrefixCount -
594
+ injectedInCompactable -
595
+ injectedSummaryOffset,
503
596
  );
504
597
  this.summaryIsInjected = false;
505
598
 
@@ -532,6 +625,7 @@ export class ContextWindowManager {
532
625
  summaryCacheReadInputTokens,
533
626
  summaryRawResponses,
534
627
  summaryText: summary,
628
+ summaryFailed,
535
629
  };
536
630
  }
537
631
 
@@ -548,14 +642,24 @@ export class ContextWindowManager {
548
642
  opts?: {
549
643
  minKeepRecentUserTurns?: number;
550
644
  targetInputTokensOverride?: number;
645
+ conversationOriginChannel?: string;
646
+ force?: boolean;
551
647
  },
552
648
  ): { keepFromIndex: number; keepTurns: number } {
649
+ // Slack-originated conversations rely on multi-turn thread context
650
+ // (reply chains, quoted messages, contextual references). Bump the
651
+ // default keep floor for them so compaction does not summarize away
652
+ // recent turns that the next reply may directly cite. Explicit
653
+ // `minKeepRecentUserTurns` (including emergency `0`) wins.
654
+ const defaultTurns = opts?.conversationOriginChannel === "slack" ? 8 : 1;
553
655
  const minFloor = Math.min(
554
- Math.max(0, Math.floor(opts?.minKeepRecentUserTurns ?? 1)),
656
+ Math.max(0, Math.floor(opts?.minKeepRecentUserTurns ?? defaultTurns)),
555
657
  userTurnStarts.length,
556
658
  );
557
- const targetTokens =
558
- opts?.targetInputTokensOverride ?? this.targetInputTokens;
659
+ const targetTokens = Math.min(
660
+ opts?.targetInputTokensOverride ?? this.targetInputTokens,
661
+ this.targetInputTokens,
662
+ );
559
663
 
560
664
  // Binary search for the maximum keepTurns whose projected tokens fit
561
665
  // within the budget. Token count is monotonically non-decreasing with
@@ -597,6 +701,32 @@ export class ContextWindowManager {
597
701
  lo = hi;
598
702
  }
599
703
 
704
+ // Under forced compaction with only the implicit default floor in play,
705
+ // that floor stops being an absolute override when the kept region still
706
+ // exceeds the target. Walk keepTurns below the floor — down to 0 if
707
+ // needed — so /compact can always drive the conversation toward target,
708
+ // even when the floor turn itself is oversized (e.g. a huge paste in the
709
+ // last user message). Exceptions that still treat the floor as hard:
710
+ // - Explicit `minKeepRecentUserTurns` (the caller opted in to that
711
+ // floor; emergency recovery already passes 0 when it wants to go all
712
+ // the way down).
713
+ // - Slack origin (the bumped 8-turn floor protects thread reply chains
714
+ // and quoted-message context that the next reply may directly cite).
715
+ // Automatic mid-loop compaction (force !== true) always honors the floor
716
+ // so the in-flight agent turn isn't summarized away.
717
+ const floorIsImplicitDefault =
718
+ opts?.minKeepRecentUserTurns === undefined &&
719
+ opts?.conversationOriginChannel !== "slack";
720
+ if (
721
+ opts?.force &&
722
+ floorIsImplicitDefault &&
723
+ projectedTokensForKeep(lo) > targetTokens
724
+ ) {
725
+ while (lo > 0 && projectedTokensForKeep(lo) > targetTokens) {
726
+ lo--;
727
+ }
728
+ }
729
+
600
730
  const keepTurns = lo;
601
731
  const rawKeepFromIndex =
602
732
  keepTurns === 0
@@ -628,10 +758,13 @@ export class ContextWindowManager {
628
758
  private capTranscriptBlocksToTokenBudget(
629
759
  blocks: ContentBlock[],
630
760
  currentSummary: string,
761
+ retainedThreadRefs: string[],
631
762
  ): ContentBlock[] {
763
+ const retainedRefsText = retainedThreadRefs.join("\n");
632
764
  const overheadTokens =
633
765
  estimateTextTokens(SUMMARY_SYSTEM_PROMPT) +
634
766
  estimateTextTokens(currentSummary) +
767
+ estimateTextTokens(retainedRefsText) +
635
768
  // Scaffolding text in buildSummaryContentBlocks ("Update the summary...",
636
769
  // section headers, etc.) — generous fixed estimate.
637
770
  200 +
@@ -643,7 +776,9 @@ export class ContextWindowManager {
643
776
  );
644
777
 
645
778
  const estimateBlockTokens = (b: ContentBlock): number =>
646
- estimateContentBlockTokens(b, { providerName: this.estimationProviderName });
779
+ estimateContentBlockTokens(b, {
780
+ providerName: this.estimationProviderName,
781
+ });
647
782
 
648
783
  let totalTokens = 0;
649
784
  for (const block of blocks) {
@@ -656,7 +791,11 @@ export class ContextWindowManager {
656
791
  // images to drop. Images are high-cost and their text context (message
657
792
  // headers, surrounding tool_use/tool_result serializations) is preserved.
658
793
  const result = [...blocks];
659
- for (let i = 0; i < result.length && totalTokens > maxTranscriptTokens; i++) {
794
+ for (
795
+ let i = 0;
796
+ i < result.length && totalTokens > maxTranscriptTokens;
797
+ i++
798
+ ) {
660
799
  if (result[i].type === "image") {
661
800
  totalTokens -= estimateBlockTokens(result[i]);
662
801
  const stub: ContentBlock = {
@@ -674,7 +813,11 @@ export class ContextWindowManager {
674
813
  // than dropping it entirely so the summarizer always has content to work with.
675
814
  let dropUntil = 0;
676
815
  let droppedTokens = 0;
677
- for (let i = 0; i < result.length && totalTokens > maxTranscriptTokens; i++) {
816
+ for (
817
+ let i = 0;
818
+ i < result.length && totalTokens > maxTranscriptTokens;
819
+ i++
820
+ ) {
678
821
  const blockTokens = estimateBlockTokens(result[i]);
679
822
  const excess = totalTokens - maxTranscriptTokens;
680
823
  if (blockTokens > excess && result[i].type === "text") {
@@ -722,6 +865,7 @@ export class ContextWindowManager {
722
865
  private async updateSummary(
723
866
  currentSummary: string,
724
867
  transcriptBlocks: ContentBlock[],
868
+ retainedThreadRefs: string[],
725
869
  signal?: AbortSignal,
726
870
  ): Promise<{
727
871
  summary: string;
@@ -731,12 +875,20 @@ export class ContextWindowManager {
731
875
  cacheCreationInputTokens: number;
732
876
  cacheReadInputTokens: number;
733
877
  rawResponse?: unknown;
878
+ /**
879
+ * True when the provider.sendMessage call threw and the local fallback
880
+ * was used. Callers (the agent loop) use this to drive circuit-breaker
881
+ * state without having to reimplement the fallback themselves.
882
+ */
883
+ failed: boolean;
734
884
  }> {
735
885
  const contentBlocks = buildSummaryContentBlocks(
736
886
  currentSummary,
737
887
  transcriptBlocks,
888
+ retainedThreadRefs,
738
889
  );
739
890
  const summaryMessage: Message = { role: "user", content: contentBlocks };
891
+ let failed = false;
740
892
  try {
741
893
  const response = await this.provider.sendMessage(
742
894
  [summaryMessage],
@@ -759,15 +911,19 @@ export class ContextWindowManager {
759
911
  response.usage.cacheCreationInputTokens ?? 0,
760
912
  cacheReadInputTokens: response.usage.cacheReadInputTokens ?? 0,
761
913
  rawResponse: response.rawResponse,
914
+ failed: false,
762
915
  };
763
916
  }
764
917
  } catch (err) {
918
+ failed = true;
765
919
  log.warn({ err }, "Summary generation failed, using local fallback");
766
920
  }
767
921
 
768
922
  // Fallback: extract text-only transcript for local summary generation.
769
923
  const textTranscript = transcriptBlocks
770
- .filter((b): b is Extract<ContentBlock, { type: "text" }> => b.type === "text")
924
+ .filter(
925
+ (b): b is Extract<ContentBlock, { type: "text" }> => b.type === "text",
926
+ )
771
927
  .map((b) => b.text)
772
928
  .join("\n\n");
773
929
 
@@ -778,6 +934,7 @@ export class ContextWindowManager {
778
934
  model: "",
779
935
  cacheCreationInputTokens: 0,
780
936
  cacheReadInputTokens: 0,
937
+ failed,
781
938
  };
782
939
  }
783
940
 
@@ -854,7 +1011,11 @@ function adjustForToolPairs(
854
1011
  // Collect tool_use_ids referenced by tool_results in this user message
855
1012
  const referencedIds = new Set<string>();
856
1013
  for (const block of msg.content) {
857
- if ((block.type === "tool_result" || block.type === "web_search_tool_result") && "tool_use_id" in block) {
1014
+ if (
1015
+ (block.type === "tool_result" ||
1016
+ block.type === "web_search_tool_result") &&
1017
+ "tool_use_id" in block
1018
+ ) {
858
1019
  referencedIds.add((block as { tool_use_id: string }).tool_use_id);
859
1020
  }
860
1021
  }
@@ -930,26 +1091,68 @@ export function createContextSummaryMessage(summary: string): Message {
930
1091
  function buildSummaryContentBlocks(
931
1092
  currentSummary: string,
932
1093
  transcriptBlocks: ContentBlock[],
1094
+ retainedThreadRefs: string[],
933
1095
  ): ContentBlock[] {
1096
+ const lines = [
1097
+ "Update the summary with new transcript data.",
1098
+ "If new information conflicts with older notes, keep the most recent and explicit detail.",
1099
+ "Keep all unresolved asks and next steps.",
1100
+ "For any images included below, describe their visual content in the summary so the information is preserved after compaction.",
1101
+ "",
1102
+ "### Existing Summary",
1103
+ currentSummary.trim().length > 0 ? currentSummary.trim() : "None.",
1104
+ "",
1105
+ ];
1106
+ if (retainedThreadRefs.length > 0) {
1107
+ lines.push(
1108
+ "### Retained Thread References",
1109
+ "These reply tag lines remain in the live context after compaction. Each `→ Mxxxxxx` cites a parent message by alias; if that parent appears in the Transcript below, preserve its text verbatim.",
1110
+ ...retainedThreadRefs.map((ref) => `- ${ref}`),
1111
+ "",
1112
+ );
1113
+ }
1114
+ lines.push("### Transcript");
934
1115
  return [
935
1116
  {
936
1117
  type: "text",
937
- text: [
938
- "Update the summary with new transcript data.",
939
- "If new information conflicts with older notes, keep the most recent and explicit detail.",
940
- "Keep all unresolved asks and next steps.",
941
- "For any images included below, describe their visual content in the summary so the information is preserved after compaction.",
942
- "",
943
- "### Existing Summary",
944
- currentSummary.trim().length > 0 ? currentSummary.trim() : "None.",
945
- "",
946
- "### Transcript",
947
- ].join("\n"),
1118
+ text: lines.join("\n"),
948
1119
  } as ContentBlock,
949
1120
  ...transcriptBlocks,
950
1121
  ];
951
1122
  }
952
1123
 
1124
+ /**
1125
+ * Scan retained-tail messages for Slack-style reply tag lines that cite a
1126
+ * thread parent via the `→ Mxxxxxx` alias convention. Returns the full tag
1127
+ * line for each match (de-duplicated, order-preserved) so the summarizer
1128
+ * has a concrete list of parents whose text must be preserved verbatim.
1129
+ *
1130
+ * Non-slack conversations and retained tails without any reply markers
1131
+ * produce an empty list — in that case the summarizer is told explicitly
1132
+ * that no verbatim preservation is required.
1133
+ */
1134
+ function collectRetainedThreadReferences(
1135
+ retainedMessages: Message[],
1136
+ ): string[] {
1137
+ const seen = new Set<string>();
1138
+ const out: string[] = [];
1139
+ for (const msg of retainedMessages) {
1140
+ for (const block of msg.content) {
1141
+ if (block.type !== "text") continue;
1142
+ const text = (block as { text: string }).text;
1143
+ for (const line of text.split("\n")) {
1144
+ if (!THREAD_REPLY_REFERENCE_PATTERN.test(line)) continue;
1145
+ const trimmed = line.trim();
1146
+ if (trimmed.length === 0) continue;
1147
+ if (seen.has(trimmed)) continue;
1148
+ seen.add(trimmed);
1149
+ out.push(trimmed);
1150
+ }
1151
+ }
1152
+ }
1153
+ return out;
1154
+ }
1155
+
953
1156
  /**
954
1157
  * Serialize messages into a sequence of content blocks. Text-based content
955
1158
  * (tool calls, tool results, thinking, etc.) is serialized into text blocks.
@@ -970,7 +1173,8 @@ function serializeMessagesToContentBlocks(messages: Message[]): ContentBlock[] {
970
1173
  textLines.length = 0;
971
1174
  }
972
1175
  blocks.push(block);
973
- } else if (block.type === "tool_result") { // guard:allow-tool-result-only — web_search_tool_result handled by serializeBlock via else branch
1176
+ } else if (block.type === "tool_result") {
1177
+ // guard:allow-tool-result-only — web_search_tool_result handled by serializeBlock via else branch
974
1178
  // Extract images from tool_result contentBlocks before serializing.
975
1179
  const collectedImages: ImageContent[] = [];
976
1180
  textLines.push(serializeToolResultBlock(block, collectedImages));
@@ -87,7 +87,6 @@ function mapUserDecisionToCesDecision(
87
87
  userDecision: decision,
88
88
  };
89
89
  case "always_allow":
90
- case "always_allow_high_risk":
91
90
  // Persistent grant — no expiry. CES stores it with expiresAt: null.
92
91
  return {
93
92
  grantDecision: "approved",
@@ -67,17 +67,28 @@ function getManagedBootstrapSocketPath(): string {
67
67
  * a malicious binary there. Removed to close the sandbox-escape vector.
68
68
  *
69
69
  * Search order:
70
- * 1. Alongside the running executable (packaged macOS app:
71
- * `<App>.app/Contents/MacOS/credential-executor`). When running from
72
- * source via `bun run`, `process.execPath` points at the bun binary
73
- * itself, so this path won't exist and the search falls through.
70
+ * 1. Alongside the running executable, but ONLY when running from a
71
+ * packaged macOS app bundle (`<App>.app/Contents/MacOS/credential-executor`).
72
+ * In dev mode, `process.execPath` points at the bun/node install dir
73
+ * (e.g. `~/.bun/bin`), where an unrelated file named `credential-executor`
74
+ * could be picked up by accident.
74
75
  * 2. `<binDir>/credential-executor` — user-installed override (dev flow).
75
76
  */
76
77
  function getLocalBinarySearchPaths(): string[] {
77
- return [
78
- join(dirname(process.execPath), "credential-executor"),
79
- join(getBinDir(), "credential-executor"),
80
- ];
78
+ const paths: string[] = [];
79
+
80
+ // Only check the sibling of process.execPath when running from a packaged
81
+ // app bundle — the .app/Contents/MacOS directory is a controlled location.
82
+ // In dev mode, process.execPath is the bun/node binary (e.g. ~/.bun/bin/bun)
83
+ // and a sibling lookup there could discover an unrelated or untrusted
84
+ // executable.
85
+ const execDir = dirname(process.execPath);
86
+ if (execDir.includes(".app/Contents/MacOS")) {
87
+ paths.push(join(execDir, "credential-executor"));
88
+ }
89
+
90
+ paths.push(join(getBinDir(), "credential-executor"));
91
+ return paths;
81
92
  }
82
93
 
83
94
  // ---------------------------------------------------------------------------
@@ -0,0 +1,109 @@
1
+ import { describe, expect, mock, test } from "bun:test";
2
+
3
+ import { logCesLine } from "./process-manager.js";
4
+
5
+ function makeLogger() {
6
+ return {
7
+ debug: mock((_obj: object, _msg: string) => {}),
8
+ info: mock((_obj: object, _msg: string) => {}),
9
+ warn: mock((_obj: object, _msg: string) => {}),
10
+ error: mock((_obj: object, _msg: string) => {}),
11
+ };
12
+ }
13
+
14
+ describe("logCesLine", () => {
15
+ test("pino JSON INFO line routes to log.info (not log.error)", () => {
16
+ const logger = makeLogger();
17
+ const line = JSON.stringify({
18
+ level: 30,
19
+ msg: "CES ready",
20
+ time: Date.now(),
21
+ });
22
+
23
+ logCesLine(line, 42, logger);
24
+
25
+ expect(logger.info).toHaveBeenCalledTimes(1);
26
+ expect(logger.error).not.toHaveBeenCalled();
27
+ expect(logger.warn).not.toHaveBeenCalled();
28
+ expect(logger.debug).not.toHaveBeenCalled();
29
+
30
+ const [meta, msg] = logger.info.mock.calls[0] as [object, string];
31
+ expect(meta).toEqual({ pid: 42 });
32
+ expect(msg).toBe(`[ces-stderr] ${line}`);
33
+ });
34
+
35
+ test("pino JSON ERROR line routes to log.error", () => {
36
+ const logger = makeLogger();
37
+ const line = JSON.stringify({
38
+ level: 50,
39
+ msg: "credential store failed",
40
+ time: Date.now(),
41
+ });
42
+
43
+ logCesLine(line, 42, logger);
44
+
45
+ expect(logger.error).toHaveBeenCalledTimes(1);
46
+ expect(logger.info).not.toHaveBeenCalled();
47
+ expect(logger.warn).not.toHaveBeenCalled();
48
+ expect(logger.debug).not.toHaveBeenCalled();
49
+ });
50
+
51
+ test("non-JSON fragment like 'args: []' routes to log.info", () => {
52
+ const logger = makeLogger();
53
+
54
+ logCesLine("args: []", 42, logger);
55
+
56
+ expect(logger.info).toHaveBeenCalledTimes(1);
57
+ expect(logger.error).not.toHaveBeenCalled();
58
+ expect(logger.warn).not.toHaveBeenCalled();
59
+ expect(logger.debug).not.toHaveBeenCalled();
60
+
61
+ const [meta, msg] = logger.info.mock.calls[0] as [object, string];
62
+ expect(meta).toEqual({ pid: 42 });
63
+ expect(msg).toBe("[ces-stderr] args: []");
64
+ });
65
+
66
+ test("non-JSON line starting with 'ERROR:' routes to log.error", () => {
67
+ const logger = makeLogger();
68
+
69
+ logCesLine("ERROR: bad thing happened", 42, logger);
70
+
71
+ expect(logger.error).toHaveBeenCalledTimes(1);
72
+ expect(logger.info).not.toHaveBeenCalled();
73
+ expect(logger.warn).not.toHaveBeenCalled();
74
+ expect(logger.debug).not.toHaveBeenCalled();
75
+ });
76
+
77
+ test("pino-pretty timestamped ERROR line routes to log.error", () => {
78
+ const logger = makeLogger();
79
+
80
+ logCesLine("[12:07:37.467] ERROR oh no", 42, logger);
81
+
82
+ expect(logger.error).toHaveBeenCalledTimes(1);
83
+ expect(logger.info).not.toHaveBeenCalled();
84
+ expect(logger.warn).not.toHaveBeenCalled();
85
+ expect(logger.debug).not.toHaveBeenCalled();
86
+ });
87
+
88
+ test("pino-pretty timestamped WARN line routes to log.warn", () => {
89
+ const logger = makeLogger();
90
+
91
+ logCesLine("[12:07:37.467] WARN wat", 42, logger);
92
+
93
+ expect(logger.warn).toHaveBeenCalledTimes(1);
94
+ expect(logger.error).not.toHaveBeenCalled();
95
+ expect(logger.info).not.toHaveBeenCalled();
96
+ expect(logger.debug).not.toHaveBeenCalled();
97
+ });
98
+
99
+ test("pino-pretty timestamped INFO line routes to log.info", () => {
100
+ const logger = makeLogger();
101
+
102
+ logCesLine("[12:07:37.467] INFO starting", 42, logger);
103
+
104
+ expect(logger.info).toHaveBeenCalledTimes(1);
105
+ expect(logger.error).not.toHaveBeenCalled();
106
+ expect(logger.warn).not.toHaveBeenCalled();
107
+ expect(logger.debug).not.toHaveBeenCalled();
108
+ });
109
+ });