@vellumai/assistant 0.8.0 → 0.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (692) hide show
  1. package/AGENTS.md +11 -0
  2. package/Dockerfile +5 -4
  3. package/README.md +2 -2
  4. package/docker-entrypoint.sh +16 -0
  5. package/eslint-rules/__tests__/cli-no-daemon-internals.test.ts +420 -0
  6. package/eslint-rules/cli-no-daemon-internals.js +283 -0
  7. package/eslint.config.mjs +12 -0
  8. package/knip.json +2 -1
  9. package/node_modules/@vellumai/skill-host-contracts/src/client.ts +10 -1
  10. package/openapi.yaml +4847 -1698
  11. package/package.json +3 -1
  12. package/scripts/generate-openapi.ts +52 -4
  13. package/scripts/sync-llm-catalog.ts +165 -0
  14. package/scripts/sync-web-search-catalog.ts +107 -0
  15. package/src/__tests__/actor-trust-resolver-address-fallback.test.ts +169 -0
  16. package/src/__tests__/agent-loop-override-profile.test.ts +26 -1
  17. package/src/__tests__/anthropic-provider.test.ts +92 -2
  18. package/src/__tests__/app-control-flow.test.ts +7 -0
  19. package/src/__tests__/assistant-events-sse-shed.test.ts +232 -0
  20. package/src/__tests__/avatar-identity-sync.test.ts +87 -0
  21. package/src/__tests__/background-workers-disk-pressure.test.ts +11 -22
  22. package/src/__tests__/btw-routes.test.ts +1 -0
  23. package/src/__tests__/call-site-routing-provider.test.ts +172 -45
  24. package/src/__tests__/cancel-resolves-conversation-key.test.ts +44 -3
  25. package/src/__tests__/channel-policy.test.ts +12 -0
  26. package/src/__tests__/checker.test.ts +89 -0
  27. package/src/__tests__/cli-memory-v2-reembed-skills.test.ts +35 -7
  28. package/src/__tests__/compact-event-conversation-id-guard.test.ts +33 -5
  29. package/src/__tests__/compaction-strip-metadata-clear.test.ts +26 -1
  30. package/src/__tests__/config-loader-backfill.test.ts +526 -102
  31. package/src/__tests__/config-loader-corrupt.test.ts +68 -0
  32. package/src/__tests__/config-loader-platform-defaults.test.ts +77 -23
  33. package/src/__tests__/config-schema-cmd.test.ts +63 -29
  34. package/src/__tests__/config-schema.test.ts +14 -3
  35. package/src/__tests__/config-set-platform-guard.test.ts +75 -152
  36. package/src/__tests__/config-set-route.test.ts +198 -0
  37. package/src/__tests__/config-watcher.test.ts +6 -0
  38. package/src/__tests__/contacts-tools.test.ts +51 -199
  39. package/src/__tests__/context-search-agent-protocol.test.ts +21 -2
  40. package/src/__tests__/context-search-agent-runner.test.ts +22 -138
  41. package/src/__tests__/context-search-conversations-source.test.ts +42 -16
  42. package/src/__tests__/context-search-fanout.test.ts +20 -157
  43. package/src/__tests__/context-search-memory-v2-source.test.ts +3 -3
  44. package/src/__tests__/context-search-types.test.ts +7 -2
  45. package/src/__tests__/context-window-manager.test.ts +389 -1
  46. package/src/__tests__/conversation-agent-loop-overflow.test.ts +1 -0
  47. package/src/__tests__/conversation-crud-inference-profile.test.ts +100 -0
  48. package/src/__tests__/conversation-error.test.ts +38 -0
  49. package/src/__tests__/conversation-fork-crud.test.ts +241 -1
  50. package/src/__tests__/conversation-inference-profile-route.test.ts +14 -14
  51. package/src/__tests__/conversation-init.benchmark.test.ts +1 -0
  52. package/src/__tests__/conversation-lifecycle.test.ts +124 -0
  53. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +100 -1
  54. package/src/__tests__/conversation-process-callsite.test.ts +21 -1
  55. package/src/__tests__/conversation-runtime-assembly.test.ts +4 -4
  56. package/src/__tests__/conversation-slash-commands.test.ts +194 -2
  57. package/src/__tests__/conversation-surfaces-app-control.test.ts +323 -3
  58. package/src/__tests__/credential-security-invariants.test.ts +5 -6
  59. package/src/__tests__/daemon-credential-client.test.ts +56 -1
  60. package/src/__tests__/db-activation-state-fk-cascade.test.ts +132 -0
  61. package/src/__tests__/db-conversation-inference-profile-migration.test.ts +37 -0
  62. package/src/__tests__/db-memory-graph-event-date-repair.test.ts +43 -20
  63. package/src/__tests__/db-proxy-transaction.test.ts +206 -0
  64. package/src/__tests__/external-plugin-loader.test.ts +458 -0
  65. package/src/__tests__/filing-service.test.ts +23 -3
  66. package/src/__tests__/fixtures/mock-chrome-extension.ts +5 -0
  67. package/src/__tests__/gateway-only-guard.test.ts +0 -1
  68. package/src/__tests__/graph-extraction-event-date.test.ts +34 -0
  69. package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +0 -8
  70. package/src/__tests__/heartbeat-disk-pressure.test.ts +21 -8
  71. package/src/__tests__/heartbeat-service.test.ts +50 -233
  72. package/src/__tests__/history-repair.test.ts +89 -0
  73. package/src/__tests__/host-app-control-proxy.test.ts +109 -1
  74. package/src/__tests__/host-app-control-routes.test.ts +247 -1
  75. package/src/__tests__/host-browser-proxy.test.ts +416 -20
  76. package/src/__tests__/host-browser-routes.test.ts +325 -33
  77. package/src/__tests__/host-proxy-preactivation.test.ts +211 -0
  78. package/src/__tests__/inference-no-mode-boot-e2e.test.ts +246 -0
  79. package/src/__tests__/inference-profile-reaper.test.ts +154 -0
  80. package/src/__tests__/inference-profile-session-handler.test.ts +398 -0
  81. package/src/__tests__/inference-profile-session-ipc.test.ts +236 -0
  82. package/src/__tests__/inline-skill-load-permissions.test.ts +6 -1
  83. package/src/__tests__/install-skill-routing.test.ts +2 -2
  84. package/src/__tests__/lifecycle-memory-v2-seed.test.ts +15 -0
  85. package/src/__tests__/llm-callsite-catalog.test.ts +20 -1
  86. package/src/__tests__/llm-catalog-parity.test.ts +146 -0
  87. package/src/__tests__/llm-request-log-source-clickhouse.test.ts +188 -0
  88. package/src/__tests__/llm-request-log-source-factory.test.ts +124 -0
  89. package/src/__tests__/llm-resolver.test.ts +46 -0
  90. package/src/__tests__/managed-profile-guard.test.ts +131 -2
  91. package/src/__tests__/mcp-auth-routes.test.ts +1 -0
  92. package/src/__tests__/mcp-cli.test.ts +182 -220
  93. package/src/__tests__/mcp-health-check.test.ts +56 -27
  94. package/src/__tests__/memory-jobs-worker-lanes.test.ts +18 -11
  95. package/src/__tests__/message-complete-display-id.test.ts +175 -0
  96. package/src/__tests__/notification-platform-adapter.test.ts +229 -0
  97. package/src/__tests__/oauth-cli.test.ts +38 -2009
  98. package/src/__tests__/oauth-commands-routes.test.ts +711 -0
  99. package/src/__tests__/oauth-connect-routes.test.ts +174 -11
  100. package/src/__tests__/oauth-providers-routes.test.ts +14 -10
  101. package/src/__tests__/openai-responses-cutover-guard.test.ts +33 -12
  102. package/src/__tests__/openai-responses-provider.test.ts +17 -0
  103. package/src/__tests__/plugin-bootstrap.test.ts +31 -2
  104. package/src/__tests__/plugin-route-contribution.test.ts +31 -3
  105. package/src/__tests__/plugin-tool-contribution.test.ts +31 -3
  106. package/src/__tests__/plugin-types.test.ts +13 -11
  107. package/src/__tests__/process-message-background-slack.test.ts +46 -0
  108. package/src/__tests__/profile-entry-status.test.ts +43 -0
  109. package/src/__tests__/provider-managed-proxy-integration.test.ts +12 -4
  110. package/src/__tests__/provider-registry-ollama.test.ts +12 -4
  111. package/src/__tests__/provider-send-message-override-profile.test.ts +10 -4
  112. package/src/__tests__/relay-server.test.ts +118 -0
  113. package/src/__tests__/retry-thinking-tool-choice.test.ts +15 -0
  114. package/src/__tests__/schedule-retry.test.ts +56 -4
  115. package/src/__tests__/schedule-routes.test.ts +104 -0
  116. package/src/__tests__/scheduler-disk-pressure.test.ts +0 -4
  117. package/src/__tests__/scheduler-recurrence.test.ts +87 -34
  118. package/src/__tests__/scheduler-reuse-conversation.test.ts +161 -5
  119. package/src/__tests__/scheduler-wake.test.ts +0 -63
  120. package/src/__tests__/secret-allowlist.test.ts +1 -0
  121. package/src/__tests__/secret-routes-managed-proxy.test.ts +12 -4
  122. package/src/__tests__/shell-credential-ref.test.ts +95 -3
  123. package/src/__tests__/shell-tool-proxy-mode.test.ts +14 -0
  124. package/src/__tests__/skill-load-feature-flag.test.ts +1 -0
  125. package/src/__tests__/skill-load-tool.test.ts +2 -4
  126. package/src/__tests__/subagent-call-site-routing.test.ts +78 -16
  127. package/src/__tests__/suggestion-routes.test.ts +3 -3
  128. package/src/__tests__/sync-message-contract.test.ts +63 -0
  129. package/src/__tests__/task-scheduler.test.ts +88 -23
  130. package/src/__tests__/update-bulletin-job.test.ts +96 -193
  131. package/src/__tests__/usage-cli.test.ts +11 -73
  132. package/src/__tests__/user-plugin-loader.test.ts +145 -0
  133. package/src/__tests__/vercel-config.test.ts +168 -0
  134. package/src/__tests__/web-search-catalog-parity.test.ts +86 -0
  135. package/src/__tests__/web-search.test.ts +303 -2
  136. package/src/__tests__/workspace-migration-039-drop-legacy-llm-keys.test.ts +1 -21
  137. package/src/__tests__/workspace-migration-057-repair-stale-gemini-model-ids.test.ts +58 -0
  138. package/src/__tests__/workspace-migration-069-seed-onboarding-threads.test.ts +53 -20
  139. package/src/__tests__/workspace-migration-072-seed-reply-suggestion-callsite.test.ts +191 -0
  140. package/src/__tests__/workspace-migration-076-drop-services-inference-mode.test.ts +211 -0
  141. package/src/__tests__/workspace-migration-077-seed-memory-router-callsite.test.ts +174 -0
  142. package/src/__tests__/workspace-migration-079-home-feed-notification-only.test.ts +323 -0
  143. package/src/__tests__/workspace-migration-080-restrict-vercel-api-token-metadata.test.ts +299 -0
  144. package/src/__tests__/workspace-migration-081-backfill-bash-allowed-tools.test.ts +410 -0
  145. package/src/__tests__/workspace-migration-082-backfill-managed-profile-labels.test.ts +268 -0
  146. package/src/__tests__/workspace-migration-unify-llm-callsite-configs.test.ts +3 -3
  147. package/src/__tests__/workspace-release-notes-feature-flag-guard.test.ts +115 -0
  148. package/src/acp/__tests__/helpers/which-stub.ts +4 -2
  149. package/src/acp/resolve-agent.test.ts +25 -0
  150. package/src/acp/resolve-agent.ts +13 -2
  151. package/src/acp/session-manager.ts +14 -0
  152. package/src/approvals/guardian-request-resolvers.ts +32 -87
  153. package/src/calls/relay-server.ts +35 -0
  154. package/src/calls/relay-setup-router.ts +36 -0
  155. package/src/calls/types.ts +1 -0
  156. package/src/calls/voice-session-bridge.ts +23 -4
  157. package/src/channels/config.ts +14 -1
  158. package/src/channels/types.ts +1 -0
  159. package/src/cli/AGENTS.md +164 -4
  160. package/src/cli/__tests__/notifications.test.ts +54 -0
  161. package/src/cli/commands/__tests__/avatar.test.ts +540 -0
  162. package/src/cli/commands/__tests__/backup.test.ts +236 -776
  163. package/src/cli/commands/__tests__/cache.test.ts +1 -1
  164. package/src/cli/commands/__tests__/changelog.test.ts +593 -0
  165. package/src/cli/commands/__tests__/channel-verification-sessions.test.ts +503 -0
  166. package/src/cli/commands/__tests__/conversations-import.test.ts +515 -0
  167. package/src/cli/commands/__tests__/domain-register.test.ts +140 -167
  168. package/src/cli/commands/__tests__/domain-status.test.ts +137 -76
  169. package/src/cli/commands/__tests__/email-attachment.test.ts +314 -337
  170. package/src/cli/commands/__tests__/email-core.test.ts +579 -0
  171. package/src/cli/commands/__tests__/image-generation.test.ts +87 -824
  172. package/src/cli/commands/__tests__/inference-send.test.ts +30 -266
  173. package/src/cli/commands/__tests__/inference-session.test.ts +423 -0
  174. package/src/cli/commands/__tests__/memory-v2.test.ts +81 -110
  175. package/src/cli/commands/__tests__/skills.test.ts +563 -0
  176. package/src/cli/commands/__tests__/status.test.ts +249 -0
  177. package/src/cli/commands/__tests__/stt.test.ts +320 -0
  178. package/src/cli/commands/__tests__/tts-synthesize.test.ts +4 -603
  179. package/src/cli/commands/__tests__/tts.test.ts +321 -0
  180. package/src/cli/commands/__tests__/webhooks.test.ts +86 -511
  181. package/src/cli/commands/attachment.ts +8 -3
  182. package/src/cli/commands/audit.ts +95 -64
  183. package/src/cli/commands/auth.ts +61 -58
  184. package/src/cli/commands/avatar.ts +276 -390
  185. package/src/cli/commands/backup.ts +409 -505
  186. package/src/cli/commands/bash.ts +9 -5
  187. package/src/cli/commands/browser.ts +28 -9
  188. package/src/cli/commands/cache.ts +9 -4
  189. package/src/cli/commands/changelog.ts +414 -0
  190. package/src/cli/commands/channel-verification-sessions.ts +238 -317
  191. package/src/cli/commands/clients.ts +8 -3
  192. package/src/cli/commands/completions.ts +9 -9
  193. package/src/cli/commands/config.ts +102 -72
  194. package/src/cli/commands/contacts.ts +575 -696
  195. package/src/cli/commands/conversations-defer.ts +17 -69
  196. package/src/cli/commands/conversations-import.ts +90 -253
  197. package/src/cli/commands/conversations.ts +346 -436
  198. package/src/cli/commands/credential-execution.ts +9 -6
  199. package/src/cli/commands/credentials.ts +456 -736
  200. package/src/cli/commands/domain.ts +128 -206
  201. package/src/cli/commands/email.ts +606 -794
  202. package/src/cli/commands/gateway.ts +8 -1
  203. package/src/cli/commands/image-generation.ts +157 -205
  204. package/src/cli/commands/inference-providers.ts +352 -0
  205. package/src/cli/commands/inference-session.ts +415 -0
  206. package/src/cli/commands/inference.ts +87 -65
  207. package/src/cli/commands/keys.ts +8 -3
  208. package/src/cli/commands/mcp.ts +103 -287
  209. package/src/cli/commands/memory-v2.ts +162 -516
  210. package/src/cli/commands/notifications.ts +33 -7
  211. package/src/cli/commands/oauth/apps.ts +292 -261
  212. package/src/cli/commands/oauth/connect.ts +176 -297
  213. package/src/cli/commands/oauth/disconnect.ts +16 -215
  214. package/src/cli/commands/oauth/index.ts +49 -45
  215. package/src/cli/commands/oauth/mode.ts +43 -199
  216. package/src/cli/commands/oauth/ping.ts +17 -125
  217. package/src/cli/commands/oauth/providers.ts +732 -921
  218. package/src/cli/commands/oauth/request.ts +60 -350
  219. package/src/cli/commands/oauth/shared.ts +11 -121
  220. package/src/cli/commands/oauth/status.ts +31 -121
  221. package/src/cli/commands/oauth/token.ts +13 -55
  222. package/src/cli/commands/pending.ts +19 -10
  223. package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +133 -183
  224. package/src/cli/commands/platform/__tests__/connect.test.ts +66 -181
  225. package/src/cli/commands/platform/__tests__/disconnect.test.ts +71 -227
  226. package/src/cli/commands/platform/__tests__/status.test.ts +169 -287
  227. package/src/cli/commands/platform/connect.ts +16 -80
  228. package/src/cli/commands/platform/disconnect.ts +14 -112
  229. package/src/cli/commands/platform/index.ts +177 -246
  230. package/src/cli/commands/routes.ts +153 -336
  231. package/src/cli/commands/sequence.ts +316 -360
  232. package/src/cli/commands/skills.ts +449 -671
  233. package/src/cli/commands/status.ts +58 -37
  234. package/src/cli/commands/stt.ts +94 -262
  235. package/src/cli/commands/task.ts +14 -40
  236. package/src/cli/commands/trust.ts +8 -3
  237. package/src/cli/commands/tts.ts +162 -167
  238. package/src/cli/commands/ui.ts +35 -42
  239. package/src/cli/commands/usage.ts +188 -126
  240. package/src/cli/commands/watchers.ts +8 -3
  241. package/src/cli/commands/webhooks.ts +99 -193
  242. package/src/cli/lib/__tests__/register-command.test.ts +85 -0
  243. package/src/cli/lib/daemon-credential-client.ts +4 -5
  244. package/src/cli/lib/nested-value.ts +44 -0
  245. package/src/cli/lib/open-browser.ts +36 -0
  246. package/src/cli/lib/register-command.ts +19 -0
  247. package/src/cli/lib/time-ago.ts +34 -0
  248. package/src/cli/program.ts +2 -4
  249. package/src/cli/utils/__tests__/conversation-id.test.ts +66 -0
  250. package/src/cli/utils/__tests__/parse-duration.test.ts +49 -0
  251. package/src/cli/utils/conversation-id.ts +30 -0
  252. package/src/cli/utils/parse-duration.ts +41 -0
  253. package/src/config/acp-defaults.test.ts +5 -1
  254. package/src/config/acp-defaults.ts +11 -4
  255. package/src/config/bundled-skills/acp/TOOLS.json +2 -2
  256. package/src/config/bundled-skills/app-control/TOOLS.json +32 -0
  257. package/src/config/bundled-skills/contacts/SKILL.md +12 -45
  258. package/src/config/bundled-skills/contacts/TOOLS.json +0 -57
  259. package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +0 -12
  260. package/src/config/bundled-skills/messaging/tools/messaging-send.ts +0 -58
  261. package/src/config/bundled-tool-registry.ts +0 -2
  262. package/src/config/feature-flag-registry.json +16 -0
  263. package/src/config/llm-resolver.ts +16 -1
  264. package/src/config/loader.ts +76 -14
  265. package/src/config/raw-config-utils.ts +2 -30
  266. package/src/config/schema.ts +4 -0
  267. package/src/config/schemas/__tests__/memory-v2.test.ts +49 -0
  268. package/src/config/schemas/call-site-catalog.ts +29 -7
  269. package/src/config/schemas/llm-request-logs.ts +57 -0
  270. package/src/config/schemas/llm.ts +52 -2
  271. package/src/config/schemas/memory-retrospective.ts +48 -0
  272. package/src/config/schemas/memory-v2.ts +32 -1
  273. package/src/config/schemas/memory.ts +4 -0
  274. package/src/config/schemas/services.ts +15 -12
  275. package/src/config/seed-inference-profiles.ts +195 -134
  276. package/src/contacts/contact-store.ts +0 -61
  277. package/src/context/window-manager.ts +191 -5
  278. package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +79 -0
  279. package/src/daemon/__tests__/conversation-tool-setup.test.ts +109 -4
  280. package/src/daemon/__tests__/daemon-skill-host.test.ts +10 -4
  281. package/src/daemon/approval-generators.ts +23 -29
  282. package/src/daemon/config-watcher.ts +2 -0
  283. package/src/daemon/conversation-agent-loop-handlers.ts +24 -0
  284. package/src/daemon/conversation-agent-loop.ts +127 -97
  285. package/src/daemon/conversation-error.ts +21 -0
  286. package/src/daemon/conversation-lifecycle.ts +46 -5
  287. package/src/daemon/conversation-process.ts +36 -19
  288. package/src/daemon/conversation-runtime-assembly.ts +14 -5
  289. package/src/daemon/conversation-slash.ts +175 -23
  290. package/src/daemon/conversation-store.ts +17 -10
  291. package/src/daemon/conversation-surfaces.ts +76 -12
  292. package/src/daemon/conversation-tool-setup.ts +24 -14
  293. package/src/daemon/conversation.ts +48 -9
  294. package/src/daemon/external-plugins-bootstrap.ts +18 -8
  295. package/src/daemon/guardian-action-generators.ts +7 -22
  296. package/src/daemon/handlers/config-model.ts +8 -126
  297. package/src/daemon/handlers/config-slack-channel.ts +10 -7
  298. package/src/daemon/handlers/config-vercel.ts +3 -1
  299. package/src/daemon/handlers/skills.ts +84 -5
  300. package/src/daemon/history-repair.ts +33 -6
  301. package/src/daemon/host-app-control-proxy.ts +44 -19
  302. package/src/daemon/host-bash-proxy.ts +85 -158
  303. package/src/daemon/host-browser-proxy.ts +96 -35
  304. package/src/daemon/host-proxy-base.ts +13 -1
  305. package/src/daemon/host-proxy-preactivation.ts +25 -1
  306. package/src/daemon/identity-helpers.ts +19 -0
  307. package/src/daemon/lifecycle.ts +42 -43
  308. package/src/daemon/meet-host-supervisor.ts +15 -15
  309. package/src/daemon/memory-v2-startup.ts +9 -2
  310. package/src/daemon/message-protocol.ts +6 -0
  311. package/src/daemon/message-types/bookmarks.ts +18 -0
  312. package/src/daemon/message-types/conversations.ts +12 -9
  313. package/src/daemon/message-types/messages.ts +9 -1
  314. package/src/daemon/message-types/sync.ts +60 -0
  315. package/src/daemon/pkb-reminder-builder.test.ts +54 -13
  316. package/src/daemon/pkb-reminder-builder.ts +21 -7
  317. package/src/daemon/process-message.ts +56 -23
  318. package/src/daemon/server.ts +23 -18
  319. package/src/daemon/shutdown-handlers.ts +0 -2
  320. package/src/daemon/tool-setup-types.ts +9 -0
  321. package/src/daemon/tool-side-effects.ts +6 -4
  322. package/src/daemon/wake-target-adapter.ts +11 -0
  323. package/src/export/transcript-formatter.ts +61 -2
  324. package/src/filing/filing-service.ts +40 -53
  325. package/src/heartbeat/__tests__/heartbeat-service.test.ts +359 -0
  326. package/src/heartbeat/heartbeat-run-store.ts +2 -1
  327. package/src/heartbeat/heartbeat-service.ts +148 -127
  328. package/src/home/__tests__/feed-types.test.ts +63 -131
  329. package/src/home/__tests__/feed-writer.test.ts +77 -278
  330. package/src/home/__tests__/post-connect-feed.test.ts +9 -12
  331. package/src/home/feed-types.ts +19 -73
  332. package/src/home/feed-writer.ts +25 -156
  333. package/src/home/post-connect-feed.ts +1 -3
  334. package/src/ipc/__tests__/cli-ipc.test.ts +2 -0
  335. package/src/ipc/__tests__/email-ipc.test.ts +506 -0
  336. package/src/ipc/__tests__/exit-helper.test.ts +104 -0
  337. package/src/ipc/__tests__/streaming-client.test.ts +237 -0
  338. package/src/ipc/__tests__/streaming-framing.test.ts +142 -0
  339. package/src/ipc/assistant-server.ts +55 -6
  340. package/src/ipc/cli-client.ts +370 -50
  341. package/src/ipc/routes/db-proxy-transaction.ts +151 -0
  342. package/src/ipc/skill-routes/__tests__/events-ipc.test.ts +60 -0
  343. package/src/ipc/skill-routes/events.ts +30 -3
  344. package/src/live-voice/__tests__/live-voice-session-manager.test.ts +46 -0
  345. package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +1 -0
  346. package/src/live-voice/live-voice-session-manager.ts +11 -4
  347. package/src/live-voice/live-voice-session.ts +14 -6
  348. package/src/memory/__tests__/bookmark-crud.test.ts +258 -0
  349. package/src/memory/__tests__/bookmark-schema.test.ts +181 -0
  350. package/src/memory/__tests__/conversation-types.test.ts +36 -0
  351. package/src/memory/__tests__/find-most-recent-retrospective-for.test.ts +130 -0
  352. package/src/memory/__tests__/memory-retrospective-enqueue.test.ts +177 -0
  353. package/src/memory/__tests__/memory-retrospective-job.test.ts +328 -0
  354. package/src/memory/__tests__/memory-retrospective-startup-cleanup.test.ts +213 -0
  355. package/src/memory/__tests__/memory-retrospective-trigger-check.test.ts +90 -0
  356. package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +69 -0
  357. package/src/memory/__tests__/memory-v2-concept-frequency.test.ts +3 -0
  358. package/src/memory/bookmark-crud.ts +179 -0
  359. package/src/memory/context-search/__tests__/agent-runner-redaction.test.ts +31 -9
  360. package/src/memory/context-search/agent-protocol.ts +5 -1
  361. package/src/memory/context-search/agent-runner.ts +60 -85
  362. package/src/memory/context-search/limits.ts +1 -4
  363. package/src/memory/context-search/search.ts +23 -113
  364. package/src/memory/context-search/sources/conversations.ts +18 -6
  365. package/src/memory/context-search/sources/memory-v2.ts +39 -14
  366. package/src/memory/context-search/sources/memory.ts +7 -0
  367. package/src/memory/context-search/sources/workspace.ts +13 -10
  368. package/src/memory/context-search/types.ts +1 -1
  369. package/src/memory/conversation-bootstrap.ts +11 -0
  370. package/src/memory/conversation-crud.ts +312 -10
  371. package/src/memory/conversation-queries.ts +9 -5
  372. package/src/memory/conversation-title-service.ts +1 -0
  373. package/src/memory/conversation-types.ts +16 -0
  374. package/src/memory/db-init.ts +14 -0
  375. package/src/memory/embedding-backend.ts +2 -1
  376. package/src/memory/embedding-runtime-manager.ts +1 -2
  377. package/src/memory/graph/__tests__/remember-description.test.ts +55 -0
  378. package/src/memory/graph/conversation-graph-memory.ts +76 -5
  379. package/src/memory/graph/extraction.ts +4 -0
  380. package/src/memory/graph/graph-memory-state-store.ts +16 -3
  381. package/src/memory/graph/tool-handlers.ts +17 -7
  382. package/src/memory/graph/tools.ts +44 -5
  383. package/src/memory/indexer.ts +17 -0
  384. package/src/memory/jobs/__tests__/embed-concept-page.test.ts +13 -15
  385. package/src/memory/jobs/embed-concept-page.ts +45 -9
  386. package/src/memory/jobs-store.ts +51 -1
  387. package/src/memory/jobs-worker.ts +52 -3
  388. package/src/memory/llm-request-log-source-clickhouse.ts +317 -0
  389. package/src/memory/llm-request-log-source-local.ts +26 -0
  390. package/src/memory/llm-request-log-source.ts +97 -0
  391. package/src/memory/llm-request-log-store.ts +1 -1
  392. package/src/memory/memory-retrospective-constants.ts +13 -0
  393. package/src/memory/memory-retrospective-enqueue.ts +114 -0
  394. package/src/memory/memory-retrospective-job.ts +351 -0
  395. package/src/memory/memory-retrospective-startup-cleanup.ts +108 -0
  396. package/src/memory/memory-retrospective-state.ts +162 -0
  397. package/src/memory/memory-retrospective-trigger-check.ts +91 -0
  398. package/src/memory/memory-v2-activation-log-store.ts +49 -5
  399. package/src/memory/memory-v2-concept-frequency.ts +4 -0
  400. package/src/memory/message-content.ts +38 -1
  401. package/src/memory/migrations/227-add-conversation-inference-profile.ts +6 -1
  402. package/src/memory/migrations/228-rename-inference-profile-snake-case.ts +20 -7
  403. package/src/memory/migrations/229-delete-private-conversations.test.ts +70 -1
  404. package/src/memory/migrations/229-delete-private-conversations.ts +12 -0
  405. package/src/memory/migrations/231-repair-memory-graph-event-dates.ts +16 -2
  406. package/src/memory/migrations/240-conversation-inference-profile-session.ts +25 -0
  407. package/src/memory/migrations/241-activation-state-fk-cascade.ts +50 -0
  408. package/src/memory/migrations/242-message-bookmarks.ts +38 -0
  409. package/src/memory/migrations/243-provider-connections.ts +68 -0
  410. package/src/memory/migrations/244-provider-connection-status-label.ts +23 -0
  411. package/src/memory/migrations/245-memory-retrospective-state.ts +36 -0
  412. package/src/memory/migrations/246-backfill-provider-connection-label.ts +81 -0
  413. package/src/memory/migrations/__tests__/244-provider-connection-status-label.test.ts +84 -0
  414. package/src/memory/migrations/__tests__/245-memory-retrospective-state.test.ts +125 -0
  415. package/src/memory/migrations/__tests__/246-backfill-provider-connection-label.test.ts +192 -0
  416. package/src/memory/migrations/index.ts +7 -0
  417. package/src/memory/published-pages-store.ts +16 -0
  418. package/src/memory/schema/bookmarks.ts +38 -0
  419. package/src/memory/schema/conversations.ts +2 -0
  420. package/src/memory/schema/index.ts +2 -0
  421. package/src/memory/schema/inference.ts +29 -0
  422. package/src/memory/schema/memory-core.ts +9 -0
  423. package/src/memory/search/semantic.ts +1 -4
  424. package/src/memory/v2/__tests__/__snapshots__/prompts-router.test.ts.snap +27 -0
  425. package/src/memory/v2/__tests__/activation-store.test.ts +5 -5
  426. package/src/memory/v2/__tests__/activation.test.ts +11 -4
  427. package/src/memory/v2/__tests__/backfill-jobs.test.ts +38 -21
  428. package/src/memory/v2/__tests__/consolidation-job.test.ts +123 -135
  429. package/src/memory/v2/__tests__/edge-index.test.ts +1 -1
  430. package/src/memory/v2/__tests__/frontmatter-sweep.test.ts +111 -0
  431. package/src/memory/v2/__tests__/injection.test.ts +628 -10
  432. package/src/memory/v2/__tests__/migration.test.ts +7 -3
  433. package/src/memory/v2/__tests__/page-index.test.ts +277 -0
  434. package/src/memory/v2/__tests__/page-store.test.ts +14 -1
  435. package/src/memory/v2/__tests__/prompts-router.test.ts +257 -0
  436. package/src/memory/v2/__tests__/qdrant.test.ts +72 -0
  437. package/src/memory/v2/__tests__/reranker.test.ts +4 -4
  438. package/src/memory/v2/__tests__/router.test.ts +516 -0
  439. package/src/memory/v2/__tests__/sim.test.ts +45 -1
  440. package/src/memory/v2/__tests__/skill-store.test.ts +58 -3
  441. package/src/memory/v2/__tests__/static-context.test.ts +7 -22
  442. package/src/memory/v2/__tests__/sweep-job.test.ts +95 -0
  443. package/src/memory/v2/activation-store.ts +34 -5
  444. package/src/memory/v2/activation.ts +40 -27
  445. package/src/memory/v2/backfill-jobs.ts +17 -84
  446. package/src/memory/v2/consolidation-job.ts +85 -78
  447. package/src/memory/v2/frontmatter-sweep.ts +91 -0
  448. package/src/memory/v2/injection.ts +440 -109
  449. package/src/memory/v2/migration.ts +117 -20
  450. package/src/memory/v2/page-index.ts +191 -0
  451. package/src/memory/v2/page-store.ts +3 -0
  452. package/src/memory/v2/prompts/consolidation.ts +9 -7
  453. package/src/memory/v2/prompts/router.ts +192 -0
  454. package/src/memory/v2/qdrant.ts +100 -87
  455. package/src/memory/v2/reranker.ts +14 -7
  456. package/src/memory/v2/router.ts +322 -0
  457. package/src/memory/v2/sim.ts +25 -12
  458. package/src/memory/v2/skill-store.ts +118 -29
  459. package/src/memory/v2/static-context.ts +16 -9
  460. package/src/memory/v2/sweep-job.ts +122 -96
  461. package/src/memory/v2/types.ts +10 -6
  462. package/src/memory/validation.ts +13 -0
  463. package/src/notifications/__tests__/emit-signal-home-feed.test.ts +182 -0
  464. package/src/notifications/__tests__/home-feed-side-effect.test.ts +199 -0
  465. package/src/notifications/__tests__/signal-registry.test.ts +17 -0
  466. package/src/notifications/adapters/platform.ts +171 -0
  467. package/src/notifications/conversation-pairing.ts +2 -2
  468. package/src/notifications/copy-composer.ts +15 -0
  469. package/src/notifications/destination-resolver.ts +21 -0
  470. package/src/notifications/emit-signal.ts +28 -1
  471. package/src/notifications/home-feed-side-effect.ts +111 -0
  472. package/src/notifications/signal.ts +5 -0
  473. package/src/permissions/checker.ts +12 -0
  474. package/src/permissions/ipc-risk-types.ts +2 -0
  475. package/src/plugin-api/index.ts +13 -0
  476. package/src/plugin-api/package.json +12 -0
  477. package/src/plugin-api/types.ts +62 -0
  478. package/src/plugins/defaults/injectors.ts +19 -3
  479. package/src/plugins/external-plugin-loader.ts +294 -0
  480. package/src/plugins/types.ts +46 -30
  481. package/src/plugins/user-loader.ts +64 -41
  482. package/src/proactive-artifact/job.test.ts +12 -4
  483. package/src/proactive-artifact/job.ts +4 -0
  484. package/src/proactive-artifact/trigger-state.test.ts +9 -0
  485. package/src/proactive-artifact/trigger-state.ts +4 -0
  486. package/src/prompts/__tests__/system-prompt.test.ts +105 -0
  487. package/src/prompts/system-prompt.ts +22 -1
  488. package/src/prompts/update-bulletin-job.ts +61 -73
  489. package/src/providers/__tests__/dispatch-connection-routing.test.ts +279 -0
  490. package/src/providers/__tests__/inference.test.ts +288 -0
  491. package/src/providers/__tests__/provider-env-vars.test.ts +6 -0
  492. package/src/providers/__tests__/provider-secret-catalog.test.ts +6 -0
  493. package/src/providers/__tests__/retry-callsite.test.ts +14 -32
  494. package/src/providers/__tests__/satellite-connection-routing.test.ts +510 -0
  495. package/src/providers/__tests__/search-provider-catalog.test.ts +80 -0
  496. package/src/providers/anthropic/client.ts +95 -26
  497. package/src/providers/call-site-routing.ts +94 -16
  498. package/src/providers/connection-resolution.ts +163 -0
  499. package/src/providers/inference/__tests__/connections-status-label.test.ts +250 -0
  500. package/src/providers/inference/adapter-factory.ts +173 -0
  501. package/src/providers/inference/auth.ts +112 -0
  502. package/src/providers/inference/backfill.ts +196 -0
  503. package/src/providers/inference/connections.ts +356 -0
  504. package/src/providers/inference/resolve-auth.ts +65 -0
  505. package/src/providers/model-catalog.ts +104 -6
  506. package/src/providers/openai/responses-provider.ts +4 -2
  507. package/src/providers/provider-env-vars.ts +17 -7
  508. package/src/providers/provider-secret-catalog.ts +49 -30
  509. package/src/providers/provider-send-message.ts +41 -20
  510. package/src/providers/registry.ts +143 -159
  511. package/src/providers/retry.ts +18 -10
  512. package/src/providers/search-provider-catalog.ts +121 -0
  513. package/src/runtime/AGENTS.md +18 -5
  514. package/src/runtime/__tests__/background-job-runner.test.ts +357 -0
  515. package/src/runtime/__tests__/pre-first-message-gate.test.ts +82 -0
  516. package/src/runtime/actor-trust-resolver.ts +32 -10
  517. package/src/runtime/agent-wake.ts +35 -6
  518. package/src/runtime/assistant-event-hub.ts +3 -85
  519. package/src/runtime/auth/route-policy.ts +303 -8
  520. package/src/runtime/auth/same-actor.ts +2 -0
  521. package/src/runtime/background-job-runner.ts +339 -0
  522. package/src/runtime/btw-sidechain.ts +1 -0
  523. package/src/runtime/http-router.ts +36 -1
  524. package/src/runtime/http-server.ts +31 -5
  525. package/src/runtime/http-types.ts +2 -0
  526. package/src/runtime/middleware/__tests__/request-logger.test.ts +162 -0
  527. package/src/runtime/middleware/request-logger.ts +62 -1
  528. package/src/runtime/pre-first-message-gate.ts +83 -0
  529. package/src/runtime/routes/__tests__/backup-routes.test.ts +8 -1
  530. package/src/runtime/routes/__tests__/bookmark-routes.test.ts +251 -0
  531. package/src/runtime/routes/__tests__/connection-routes-vs-cli-parity.test.ts +142 -0
  532. package/src/runtime/routes/__tests__/conversation-management-routes.test.ts +315 -0
  533. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +189 -0
  534. package/src/runtime/routes/__tests__/home-feed-routes.test.ts +15 -136
  535. package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +736 -0
  536. package/src/runtime/routes/__tests__/memory-v2-routes.test.ts +4 -4
  537. package/src/runtime/routes/__tests__/stt-routes.test.ts +5 -1
  538. package/src/runtime/routes/__tests__/surface-action-routes.test.ts +384 -0
  539. package/src/runtime/routes/__tests__/tts-routes.test.ts +6 -2
  540. package/src/runtime/routes/acp-routes.ts +10 -8
  541. package/src/runtime/routes/app-management-routes.ts +228 -3
  542. package/src/runtime/routes/approval-routes.ts +0 -18
  543. package/src/runtime/routes/audit-routes.ts +43 -0
  544. package/src/runtime/routes/auth-routes.ts +72 -0
  545. package/src/runtime/routes/avatar-routes.ts +273 -20
  546. package/src/runtime/routes/backup-routes.ts +406 -2
  547. package/src/runtime/routes/bookmark-routes.ts +154 -0
  548. package/src/runtime/routes/channel-verification-routes.ts +2 -1
  549. package/src/runtime/routes/contact-routes.ts +0 -160
  550. package/src/runtime/routes/conversation-cli-routes.ts +192 -0
  551. package/src/runtime/routes/conversation-management-routes.ts +30 -43
  552. package/src/runtime/routes/conversation-query-routes.ts +334 -86
  553. package/src/runtime/routes/conversation-routes.ts +31 -10
  554. package/src/runtime/routes/conversations-import-routes.ts +229 -0
  555. package/src/runtime/routes/credential-routes.ts +540 -0
  556. package/src/runtime/routes/debug-routes.ts +2 -2
  557. package/src/runtime/routes/document-pdf-renderer.ts +5 -1
  558. package/src/runtime/routes/domain-routes.ts +167 -0
  559. package/src/runtime/routes/email-routes.ts +603 -0
  560. package/src/runtime/routes/errors.ts +2 -2
  561. package/src/runtime/routes/events-routes.ts +192 -0
  562. package/src/runtime/routes/home-feed-routes.ts +6 -78
  563. package/src/runtime/routes/host-app-control-routes.ts +44 -2
  564. package/src/runtime/routes/host-browser-routes.ts +103 -22
  565. package/src/runtime/routes/http-adapter.ts +2 -0
  566. package/src/runtime/routes/identity-routes.ts +5 -0
  567. package/src/runtime/routes/image-generation-routes.ts +99 -0
  568. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +137 -1
  569. package/src/runtime/routes/inbound-stages/background-dispatch.ts +87 -7
  570. package/src/runtime/routes/inbound-stages/guardian-reply-intercept.test.ts +156 -0
  571. package/src/runtime/routes/inbound-stages/guardian-reply-intercept.ts +22 -4
  572. package/src/runtime/routes/index.ts +36 -0
  573. package/src/runtime/routes/inference-profile-session-handler.ts +312 -0
  574. package/src/runtime/routes/inference-profile-session-reaper.ts +98 -0
  575. package/src/runtime/routes/inference-profile-session-routes.ts +146 -0
  576. package/src/runtime/routes/inference-provider-connection-routes.ts +317 -0
  577. package/src/runtime/routes/inference-send-routes.ts +115 -0
  578. package/src/runtime/routes/integrations/twilio.ts +1 -0
  579. package/src/runtime/routes/mcp-auth-routes.ts +283 -9
  580. package/src/runtime/routes/memory-v2-routes.ts +13 -398
  581. package/src/runtime/routes/notification-routes.ts +2 -0
  582. package/src/runtime/routes/oauth-apps.ts +112 -7
  583. package/src/runtime/routes/oauth-commands-routes.ts +1007 -0
  584. package/src/runtime/routes/oauth-connect-routes.ts +67 -5
  585. package/src/runtime/routes/oauth-providers.ts +298 -8
  586. package/src/runtime/routes/platform-routes.ts +336 -0
  587. package/src/runtime/routes/playground/inject-failures.ts +2 -1
  588. package/src/runtime/routes/playground/reset-circuit.ts +2 -1
  589. package/src/runtime/routes/playground/state.ts +2 -1
  590. package/src/runtime/routes/publish-routes.ts +221 -0
  591. package/src/runtime/routes/schedule-routes.ts +82 -0
  592. package/src/runtime/routes/sequence-routes.ts +291 -0
  593. package/src/runtime/routes/settings-routes.ts +2 -10
  594. package/src/runtime/routes/skills-routes.ts +31 -1
  595. package/src/runtime/routes/stt-routes.ts +240 -3
  596. package/src/runtime/routes/surface-action-routes.ts +43 -7
  597. package/src/runtime/routes/tts-routes.ts +67 -0
  598. package/src/runtime/routes/types.ts +32 -0
  599. package/src/runtime/routes/user-routes-cli.ts +243 -0
  600. package/src/runtime/routes/webhook-routes.ts +165 -0
  601. package/src/runtime/sync/resource-sync-events.ts +25 -0
  602. package/src/runtime/sync/sync-publisher.test.ts +105 -0
  603. package/src/runtime/sync/sync-publisher.ts +21 -0
  604. package/src/schedule/scheduler.ts +200 -123
  605. package/src/security/__tests__/provider-key-env-fallback.test.ts +12 -6
  606. package/src/security/secret-patterns.ts +3 -0
  607. package/src/sequence/engine.ts +38 -40
  608. package/src/subagent/manager.ts +20 -15
  609. package/src/tools/browser/__tests__/browser-execution-acquire.test.ts +206 -0
  610. package/src/tools/browser/browser-execution.ts +15 -4
  611. package/src/tools/browser/cdp-client/__tests__/factory.test.ts +174 -0
  612. package/src/tools/browser/cdp-client/cdp-inspect/__tests__/ws-transport.test.ts +16 -13
  613. package/src/tools/browser/cdp-client/extension-cdp-client.ts +24 -1
  614. package/src/tools/browser/cdp-client/factory.ts +66 -5
  615. package/src/tools/browser/runtime-check.ts +77 -0
  616. package/src/tools/memory/register.test.ts +3 -3
  617. package/src/tools/memory/register.ts +9 -1
  618. package/src/tools/network/__tests__/web-search.test.ts +156 -0
  619. package/src/tools/network/web-search.ts +280 -37
  620. package/src/tools/permission-checker.ts +13 -5
  621. package/src/tools/subagent/spawn.ts +3 -3
  622. package/src/tools/terminal/shell.ts +44 -0
  623. package/src/usage/attribution.ts +3 -2
  624. package/src/util/pricing.ts +86 -160
  625. package/src/watcher/__tests__/engine.test.ts +301 -0
  626. package/src/watcher/constants.ts +7 -0
  627. package/src/watcher/engine.ts +90 -90
  628. package/src/workspace/migrations/046-seed-conversation-starters-callsite.ts +6 -9
  629. package/src/workspace/migrations/054-seed-recall-callsite.ts +10 -1
  630. package/src/workspace/migrations/057-repair-stale-gemini-model-ids.ts +28 -4
  631. package/src/workspace/migrations/069-seed-onboarding-threads.ts +8 -2
  632. package/src/workspace/migrations/072-seed-reply-suggestion-callsite.ts +104 -0
  633. package/src/workspace/migrations/073-repair-recall-callsite-empty-profile.ts +93 -0
  634. package/src/workspace/migrations/074-drop-deprecated-secret-detection-keys.ts +117 -0
  635. package/src/workspace/migrations/075-memory-v2-bm25-b-default-reembed.ts +61 -0
  636. package/src/workspace/migrations/076-drop-services-inference-mode.ts +62 -0
  637. package/src/workspace/migrations/077-seed-memory-router-callsite.ts +89 -0
  638. package/src/workspace/migrations/078-release-notes-tavily-web-search.ts +66 -0
  639. package/src/workspace/migrations/079-home-feed-notification-only.ts +197 -0
  640. package/src/workspace/migrations/080-restrict-vercel-api-token-metadata.ts +182 -0
  641. package/src/workspace/migrations/081-backfill-bash-allowed-tools-for-injection-credentials.ts +160 -0
  642. package/src/workspace/migrations/082-backfill-managed-profile-labels.ts +154 -0
  643. package/src/workspace/migrations/registry.ts +22 -0
  644. package/src/workspace/migrations/runner.ts +13 -2
  645. package/src/workspace/migrations/types.ts +13 -3
  646. package/src/workspace/provider-commit-message-generator.ts +3 -2
  647. package/src/__tests__/context-search-pkb-source.test.ts +0 -498
  648. package/src/__tests__/credentials-cli.test.ts +0 -1225
  649. package/src/__tests__/memory-admin-recall.test.ts +0 -213
  650. package/src/approvals/__tests__/guardian-feed-event.test.ts +0 -303
  651. package/src/cli/commands/__tests__/email-download.test.ts +0 -260
  652. package/src/cli/commands/__tests__/email-list.test.ts +0 -216
  653. package/src/cli/commands/__tests__/email-register.test.ts +0 -186
  654. package/src/cli/commands/__tests__/email-send.test.ts +0 -416
  655. package/src/cli/commands/__tests__/email-status.test.ts +0 -185
  656. package/src/cli/commands/__tests__/email-unregister.test.ts +0 -168
  657. package/src/cli/commands/__tests__/routes.test.ts +0 -562
  658. package/src/cli/commands/__tests__/stt-transcribe.test.ts +0 -454
  659. package/src/cli/commands/autonomy.ts +0 -365
  660. package/src/cli/commands/memory.ts +0 -424
  661. package/src/cli/commands/oauth/__tests__/connect.test.ts +0 -947
  662. package/src/cli/commands/oauth/__tests__/disconnect.test.ts +0 -686
  663. package/src/cli/commands/oauth/__tests__/mode.test.ts +0 -632
  664. package/src/cli/commands/oauth/__tests__/ping.test.ts +0 -631
  665. package/src/cli/commands/oauth/__tests__/providers-delete.test.ts +0 -573
  666. package/src/cli/commands/oauth/__tests__/providers-register.test.ts +0 -330
  667. package/src/cli/commands/oauth/__tests__/providers-update.test.ts +0 -521
  668. package/src/cli/commands/oauth/__tests__/status.test.ts +0 -551
  669. package/src/cli/commands/oauth/__tests__/token.test.ts +0 -420
  670. package/src/cli/lib/daemon-avatar-client.ts +0 -37
  671. package/src/config/bundled-skills/contacts/tools/contact-upsert.ts +0 -87
  672. package/src/config/bundled-skills/messaging/tools/__tests__/messaging-feed-events.test.ts +0 -207
  673. package/src/daemon/__tests__/conversation-feed-event.test.ts +0 -304
  674. package/src/heartbeat/__tests__/heartbeat-feed-event.test.ts +0 -233
  675. package/src/home/__tests__/assistant-feed-authoring.test.ts +0 -156
  676. package/src/home/__tests__/emit-feed-event.test.ts +0 -169
  677. package/src/home/__tests__/feed-population-integration.test.ts +0 -312
  678. package/src/home/__tests__/feed-scheduler.test.ts +0 -222
  679. package/src/home/__tests__/phase5-exit-criteria.test.ts +0 -229
  680. package/src/home/__tests__/platform-gmail-digest.test.ts +0 -222
  681. package/src/home/__tests__/rollup-producer.test.ts +0 -507
  682. package/src/home/assistant-feed-authoring.ts +0 -135
  683. package/src/home/emit-feed-event.ts +0 -169
  684. package/src/home/feed-scheduler.ts +0 -281
  685. package/src/home/platform-gmail-digest.ts +0 -163
  686. package/src/home/rewrite-command-preview.ts +0 -66
  687. package/src/home/rewrite-feed-title.ts +0 -58
  688. package/src/home/rollup-producer.ts +0 -426
  689. package/src/memory/admin.ts +0 -326
  690. package/src/memory/context-search/sources/pkb.ts +0 -476
  691. package/src/memory/graph/compaction.ts +0 -299
  692. /package/src/cli/{commands → lib}/cache-fs.ts +0 -0
@@ -691,6 +691,65 @@ export async function getSkill(
691
691
  return { skill: detail };
692
692
  }
693
693
 
694
+ export function getSkillLocalDetail(
695
+ skillId: string,
696
+ ): {
697
+ ok: true;
698
+ id: string;
699
+ name: string;
700
+ description: string;
701
+ emoji: string | null;
702
+ source: string;
703
+ state: string;
704
+ directoryPath: string;
705
+ featureFlag: string | null;
706
+ includes: string[] | null;
707
+ activationHints: string[] | null;
708
+ avoidWhen: string[] | null;
709
+ toolManifest: { valid: boolean; toolCount: number; toolNames: string[] } | null;
710
+ installMeta: Record<string, unknown> | null;
711
+ config: { enabled: boolean; envKeys: string[]; configKeys: string[] } | null;
712
+ } | { ok: false; error: string; status: 404 | 500 } {
713
+ try {
714
+ const catalog = loadSkillCatalog();
715
+ const config = getConfig();
716
+ const resolved = resolveSkillStates(catalog, config);
717
+ const match = resolved.find((r) => r.summary.id === skillId);
718
+ if (!match) {
719
+ return { ok: false, error: `Skill "${skillId}" not found. Run 'assistant skills list' to see available skills.`, status: 404 };
720
+ }
721
+ const { summary, state, configEntry } = match;
722
+ const installMeta = readInstallMeta(summary.directoryPath);
723
+ return {
724
+ ok: true,
725
+ id: summary.id,
726
+ name: summary.displayName,
727
+ description: summary.description,
728
+ emoji: summary.emoji ?? null,
729
+ source: summary.source,
730
+ state,
731
+ directoryPath: summary.directoryPath,
732
+ featureFlag: summary.featureFlag ?? null,
733
+ includes: summary.includes ?? null,
734
+ activationHints: summary.activationHints ?? null,
735
+ avoidWhen: summary.avoidWhen ?? null,
736
+ toolManifest: summary.toolManifest
737
+ ? { valid: summary.toolManifest.valid, toolCount: summary.toolManifest.toolCount, toolNames: summary.toolManifest.toolNames }
738
+ : null,
739
+ installMeta: installMeta ? (installMeta as unknown as Record<string, unknown>) : null,
740
+ config: configEntry
741
+ ? {
742
+ enabled: configEntry.enabled !== false,
743
+ envKeys: configEntry.env ? Object.keys(configEntry.env) : [],
744
+ configKeys: configEntry.config ? Object.keys(configEntry.config) : [],
745
+ }
746
+ : null,
747
+ };
748
+ } catch (err) {
749
+ return { ok: false, error: err instanceof Error ? err.message : String(err), status: 500 };
750
+ }
751
+ }
752
+
694
753
  // ─── Skill file listing ──────────────────────────────────────────────────────
695
754
 
696
755
  // `SkillFileEntry` lives in `../../skills/catalog-files.ts` to keep a single
@@ -1017,6 +1076,8 @@ export async function installSkill(spec: {
1017
1076
  slug: string;
1018
1077
  version?: string;
1019
1078
  origin?: "clawhub" | "skillssh";
1079
+ catalogOnly?: boolean;
1080
+ overwrite?: boolean;
1020
1081
  contactId?: string;
1021
1082
  }): Promise<
1022
1083
  { success: true; skillId: string } | { success: false; error: string }
@@ -1078,10 +1139,14 @@ export async function installSkill(spec: {
1078
1139
  const vellumCatalog = await getCatalog();
1079
1140
  const catalogEntry = vellumCatalog.find((s) => s.id === spec.slug);
1080
1141
  if (catalogEntry) {
1142
+ // Default `overwrite` to true at the handler boundary to preserve
1143
+ // pre-existing HTTP API behaviour. CLI callers always pass an
1144
+ // explicit boolean (`opts.overwrite ?? false`) so the CLI surface
1145
+ // still defaults to non-destructive installs.
1081
1146
  await installSkillLocally(
1082
1147
  spec.slug,
1083
1148
  catalogEntry,
1084
- true,
1149
+ spec.overwrite ?? true,
1085
1150
  spec.contactId,
1086
1151
  );
1087
1152
 
@@ -1090,13 +1155,19 @@ export async function installSkill(spec: {
1090
1155
  return { success: true, skillId: spec.slug };
1091
1156
  }
1092
1157
  } catch (err) {
1093
- // If catalog lookup/install fails, fall through to community registries
1158
+ if (spec.catalogOnly) {
1159
+ return { success: false, error: `Failed to install catalog skill "${spec.slug}"` };
1160
+ }
1094
1161
  log.warn(
1095
1162
  { err, skillId: spec.slug },
1096
1163
  "Vellum catalog install failed, falling back to community registry",
1097
1164
  );
1098
1165
  }
1099
1166
 
1167
+ if (spec.catalogOnly) {
1168
+ return { success: false, error: `Skill "${spec.slug}" not found in the Vellum catalog` };
1169
+ }
1170
+
1100
1171
  // skills.sh install path: route here when origin is explicitly "skillssh"
1101
1172
  // or when the slug looks like a skills.sh multi-segment format (owner/repo/skill)
1102
1173
  if (
@@ -1104,11 +1175,14 @@ export async function installSkill(spec: {
1104
1175
  (spec.origin !== "clawhub" && looksLikeSkillsShSlug(spec.slug))
1105
1176
  ) {
1106
1177
  const resolved = resolveSkillSource(spec.slug);
1178
+ // Default `overwrite` to true at the handler boundary to preserve
1179
+ // pre-existing HTTP API behaviour (same rationale as the catalog
1180
+ // install path above).
1107
1181
  await installExternalSkill(
1108
1182
  resolved.owner,
1109
1183
  resolved.repo,
1110
1184
  resolved.skillSlug,
1111
- true /* overwrite */,
1185
+ spec.overwrite ?? true,
1112
1186
  resolved.ref ?? spec.version,
1113
1187
  spec.contactId,
1114
1188
  );
@@ -1209,6 +1283,10 @@ export async function uninstallSkill(
1209
1283
  state: "uninstalled",
1210
1284
  });
1211
1285
 
1286
+ // Without this, an uninstalled skill remains queryable in v2 until the
1287
+ // next incidental seed event (enable/disable/install).
1288
+ maybeSeedMemoryV2Skills(getConfig());
1289
+
1212
1290
  return { success: true };
1213
1291
  } catch (err) {
1214
1292
  const message = err instanceof Error ? err.message : String(err);
@@ -1250,6 +1328,7 @@ export async function checkSkillUpdates(): Promise<
1250
1328
 
1251
1329
  export async function searchSkills(
1252
1330
  query: string,
1331
+ limit: number = 25,
1253
1332
  ): Promise<
1254
1333
  | { success: true; skills: SlimSkillResponse[] }
1255
1334
  | { success: false; error: string }
@@ -1290,8 +1369,8 @@ export async function searchSkills(
1290
1369
 
1291
1370
  // Search both community registries in parallel (non-fatal on failure)
1292
1371
  const [clawhubResult, skillsshResult] = await Promise.allSettled([
1293
- clawhubSearch(query),
1294
- searchSkillsRegistry(query, 25),
1372
+ clawhubSearch(query, { limit }),
1373
+ searchSkillsRegistry(query, limit),
1295
1374
  ]);
1296
1375
 
1297
1376
  let clawhubSkills: SlimSkillResponse[] = [];
@@ -68,11 +68,14 @@ export function repairHistory(messages: Message[]): RepairResult {
68
68
  }
69
69
  }
70
70
 
71
- // Ensure every server_tool_use has a paired web_search_tool_result
72
- // in the same assistant message (handles interrupted streams).
73
- // Synthetic results are inserted IMMEDIATELY AFTER their corresponding
74
- // server_tool_use block not appended to the end so that
75
- // ensureToolPairing's split at tool_use boundaries cannot separate them.
71
+ // Pair server-side tool blocks within the same assistant message.
72
+ // Server tools (e.g. web_search) emit server_tool_use + matching
73
+ // web_search_tool_result. Either side can go missing the synthetic
74
+ // result is inserted IMMEDIATELY AFTER the orphan server_tool_use (not
75
+ // appended to the end) so ensureToolPairing's split at tool_use
76
+ // boundaries cannot separate the pair. An orphan
77
+ // web_search_tool_result (no preceding server_tool_use) is downgraded
78
+ // to text — Anthropic rejects the request otherwise.
76
79
  const serverToolIds = new Set(
77
80
  cleanedContent
78
81
  .filter(
@@ -91,11 +94,35 @@ export function repairHistory(messages: Message[]): RepairResult {
91
94
  orphanedServerIds.add(id);
92
95
  }
93
96
  }
97
+ const orphanedWebSearchResultIds = new Set<string>();
98
+ for (const id of matchedServerIds) {
99
+ if (!serverToolIds.has(id)) {
100
+ orphanedWebSearchResultIds.add(id);
101
+ }
102
+ }
94
103
 
95
104
  let repairedContent: ContentBlock[];
96
- if (orphanedServerIds.size > 0) {
105
+ if (orphanedServerIds.size > 0 || orphanedWebSearchResultIds.size > 0) {
97
106
  repairedContent = [];
98
107
  for (const block of cleanedContent) {
108
+ if (
109
+ block.type === "web_search_tool_result" &&
110
+ orphanedWebSearchResultIds.has(
111
+ (block as { tool_use_id: string }).tool_use_id,
112
+ )
113
+ ) {
114
+ repairedContent.push(
115
+ downgradeResult(
116
+ block as {
117
+ type: "web_search_tool_result";
118
+ tool_use_id: string;
119
+ content: unknown;
120
+ },
121
+ ),
122
+ );
123
+ stats.orphanToolResultsDowngraded++;
124
+ continue;
125
+ }
99
126
  repairedContent.push(block);
100
127
  if (
101
128
  block.type === "server_tool_use" &&
@@ -15,9 +15,11 @@
15
15
  * session at a time, and that session is bound to a specific target app.
16
16
  * The lock is module-level (`activeAppControlSession`) because the session
17
17
  * targets the user's actual desktop application, which is a host-wide
18
- * resource. It is acquired on a successful `app_control_start` (storing
19
- * `(conversationId, app)`) and released when the owning proxy's
20
- * `dispose()` fires.
18
+ * resource. It is acquired optimistically when `app_control_start` is
19
+ * dispatched (storing `(conversationId, app)`) so that the synchronous
20
+ * guard and the asynchronous host round-trip cannot race; it is released
21
+ * when the host returns a non-running state, the dispatch fails, or the
22
+ * owning proxy's `dispose()` fires.
21
23
  *
22
24
  * `app_control_start` is the only tool that can acquire the lock — the
23
25
  * user's medium-risk approval at start time is the consent boundary. All
@@ -144,12 +146,12 @@ function checkNonStartAuthorization(
144
146
  // except `stop`, and `stop` short-circuits in conversation-surfaces and
145
147
  // does not reach this method in production. A stop reaching here would
146
148
  // be a defensive bug — surface it explicitly rather than dispatch.
147
- const requestedApp = (input as { app?: string }).app;
148
- if (requestedApp == null) {
149
+ const requestedApp = (input as { app?: unknown }).app;
150
+ if (typeof requestedApp !== "string") {
149
151
  return {
150
152
  content:
151
- "Tool input missing required 'app' field; cannot validate against " +
152
- "the active app-control session.",
153
+ "Tool input missing required string 'app' field; cannot validate " +
154
+ "against the active app-control session.",
153
155
  isError: true,
154
156
  };
155
157
  }
@@ -222,6 +224,8 @@ export class HostAppControlProxy extends HostProxyBase<
222
224
  input: HostAppControlInput,
223
225
  conversationId: string,
224
226
  signal: AbortSignal,
227
+ sourceActorPrincipalId?: string,
228
+ targetClientId?: string,
225
229
  ): Promise<ToolExecutionResult> {
226
230
  if (signal.aborted) {
227
231
  return { content: "Aborted", isError: true };
@@ -235,7 +239,7 @@ export class HostAppControlProxy extends HostProxyBase<
235
239
  if (input.tool === "start") {
236
240
  if (
237
241
  activeAppControlSession != null &&
238
- activeAppControlSession.conversationId !== conversationId
242
+ activeAppControlSession.conversationId !== this.conversationId
239
243
  ) {
240
244
  return {
241
245
  content:
@@ -245,8 +249,21 @@ export class HostAppControlProxy extends HostProxyBase<
245
249
  isError: true,
246
250
  };
247
251
  }
252
+ // Acquire optimistically to close the TOCTOU window between this
253
+ // synchronous guard and the asynchronous `dispatchRequest` below. Two
254
+ // concurrent starts from different conversations would otherwise both
255
+ // see `activeAppControlSession == null` and both pass the guard. The
256
+ // lock is released below if dispatch fails or the host returns a
257
+ // non-running state.
258
+ activeAppControlSession = {
259
+ conversationId: this.conversationId,
260
+ app: input.app,
261
+ };
248
262
  } else {
249
- const sessionError = checkNonStartAuthorization(input, conversationId);
263
+ const sessionError = checkNonStartAuthorization(
264
+ input,
265
+ this.conversationId,
266
+ );
250
267
  if (sessionError != null) {
251
268
  return sessionError;
252
269
  }
@@ -258,9 +275,14 @@ export class HostAppControlProxy extends HostProxyBase<
258
275
  input,
259
276
  conversationId,
260
277
  signal,
278
+ undefined,
279
+ targetClientId,
261
280
  );
262
281
  return this.handleSuccess(input, payload);
263
282
  } catch (err) {
283
+ if (input.tool === "start") {
284
+ this.releaseSessionIfHeld();
285
+ }
264
286
  if (err instanceof HostProxyRequestError) {
265
287
  if (err.reason === "timeout") {
266
288
  log.warn({ toolName }, "Host app-control proxy request timed out");
@@ -279,6 +301,12 @@ export class HostAppControlProxy extends HostProxyBase<
279
301
  }
280
302
  }
281
303
 
304
+ private releaseSessionIfHeld(): void {
305
+ if (activeAppControlSession?.conversationId === this.conversationId) {
306
+ activeAppControlSession = undefined;
307
+ }
308
+ }
309
+
282
310
  // ---------------------------------------------------------------------------
283
311
  // Result handling
284
312
  // ---------------------------------------------------------------------------
@@ -304,13 +332,12 @@ export class HostAppControlProxy extends HostProxyBase<
304
332
  }
305
333
  }
306
334
 
307
- // Store the exact `app` form for validation against subsequent
308
- // non-start tool calls.
309
- if (input.tool === "start" && payload.state === "running") {
310
- activeAppControlSession = {
311
- conversationId: this.conversationId,
312
- app: input.app,
313
- };
335
+ // The optimistic lock acquired in `request()` for `start` stays held
336
+ // only when the host confirms the session is running. Non-running
337
+ // outcomes (missing/minimized) release it so a retry or another
338
+ // conversation can acquire.
339
+ if (input.tool === "start" && payload.state !== "running") {
340
+ this.releaseSessionIfHeld();
314
341
  }
315
342
 
316
343
  return this.formatResult(payload, stuck);
@@ -382,8 +409,6 @@ export class HostAppControlProxy extends HostProxyBase<
382
409
  */
383
410
  override dispose(): void {
384
411
  super.dispose();
385
- if (activeAppControlSession?.conversationId === this.conversationId) {
386
- activeAppControlSession = undefined;
387
- }
412
+ this.releaseSessionIfHeld();
388
413
  }
389
414
  }
@@ -1,10 +1,5 @@
1
- import { v4 as uuid } from "uuid";
2
-
3
1
  import { getConfig } from "../config/loader.js";
4
- import {
5
- assistantEventHub,
6
- broadcastMessage,
7
- } from "../runtime/assistant-event-hub.js";
2
+ import { assistantEventHub } from "../runtime/assistant-event-hub.js";
8
3
  import {
9
4
  ambiguousSameUserError,
10
5
  enforceSameActorOrErrorResult,
@@ -13,14 +8,42 @@ import {
13
8
  import * as pendingInteractions from "../runtime/pending-interactions.js";
14
9
  import { formatShellOutput } from "../tools/shared/shell-output.js";
15
10
  import type { ToolExecutionResult } from "../tools/types.js";
16
- import { AssistantError, ErrorCode } from "../util/errors.js";
17
11
  import { getLogger } from "../util/logger.js";
12
+ import { HostProxyBase, HostProxyRequestError } from "./host-proxy-base.js";
18
13
 
19
14
  const log = getLogger("host-bash-proxy");
20
15
 
21
- export class HostBashProxy {
16
+ export type HostBashInput = {
17
+ command: string;
18
+ working_dir?: string;
19
+ timeout_seconds?: number;
20
+ env?: Record<string, string>;
21
+ targetClientId?: string;
22
+ };
23
+
24
+ type HostBashResultPayload = {
25
+ stdout: string;
26
+ stderr: string;
27
+ exitCode: number | null;
28
+ timedOut: boolean;
29
+ };
30
+
31
+ export class HostBashProxy extends HostProxyBase<
32
+ Record<string, unknown>,
33
+ HostBashResultPayload
34
+ > {
22
35
  private static _instance: HostBashProxy | null = null;
23
36
 
37
+ constructor() {
38
+ super({
39
+ capabilityName: "host_bash",
40
+ requestEventName: "host_bash_request",
41
+ cancelEventName: "host_bash_cancel",
42
+ resultPendingKind: "host_bash",
43
+ disposedMessage: "Host bash proxy disposed",
44
+ });
45
+ }
46
+
24
47
  /**
25
48
  * Lazily-initialized singleton. Availability of an actual desktop
26
49
  * connection is checked at send time via the assistant event hub,
@@ -47,31 +70,15 @@ export class HostBashProxy {
47
70
  HostBashProxy._instance = null;
48
71
  }
49
72
 
50
- /**
51
- * Whether a client with `host_bash` capability is connected.
52
- */
53
- isAvailable(): boolean {
54
- return (
55
- assistantEventHub.getMostRecentClientByCapability("host_bash") != null
56
- );
57
- }
58
-
59
- request(
60
- input: {
61
- command: string;
62
- working_dir?: string;
63
- timeout_seconds?: number;
64
- env?: Record<string, string>;
65
- targetClientId?: string;
66
- },
73
+ async request(
74
+ input: HostBashInput,
67
75
  conversationId: string,
68
76
  signal?: AbortSignal,
69
77
  // Principal ID of the actor on whose behalf this request is initiated.
70
78
  sourceActorPrincipalId?: string,
71
79
  ): Promise<ToolExecutionResult> {
72
80
  if (signal?.aborted) {
73
- const result = formatShellOutput("", "Aborted", null, false, 0);
74
- return Promise.resolve(result);
81
+ return formatShellOutput("", "Aborted", null, false, 0);
75
82
  }
76
83
 
77
84
  let resolvedTargetClientId: string | undefined;
@@ -79,10 +86,10 @@ export class HostBashProxy {
79
86
  if (input.targetClientId) {
80
87
  const target = assistantEventHub.getClientById(input.targetClientId);
81
88
  if (!target || !target.capabilities.includes("host_bash")) {
82
- return Promise.resolve({
89
+ return {
83
90
  content: `Error: client "${input.targetClientId}" is not connected or does not support host_bash. Run \`assistant clients list --capability host_bash\` to see available clients.`,
84
91
  isError: true,
85
- });
92
+ };
86
93
  }
87
94
  resolvedTargetClientId = input.targetClientId;
88
95
  } else {
@@ -97,7 +104,7 @@ export class HostBashProxy {
97
104
  sourceActorPrincipalId,
98
105
  });
99
106
  if (resolved.kind === "ambiguous") {
100
- return Promise.resolve(ambiguousSameUserError("host_bash"));
107
+ return ambiguousSameUserError("host_bash");
101
108
  }
102
109
  resolvedTargetClientId =
103
110
  resolved.kind === "match" ? resolved.clientId : undefined;
@@ -114,98 +121,56 @@ export class HostBashProxy {
114
121
  targetClientId: resolvedTargetClientId,
115
122
  op: "host_bash",
116
123
  });
117
- if (rejection) return Promise.resolve(rejection);
124
+ if (rejection) return rejection;
118
125
  }
119
126
 
120
- const requestId = uuid();
121
-
122
- return new Promise<ToolExecutionResult>((resolve, reject) => {
123
- const shellMaxTimeoutSec = getConfig().timeouts.shellMaxTimeoutSec;
124
- const timeoutSec = input.timeout_seconds ?? shellMaxTimeoutSec;
125
- const proxyTimeoutSec = timeoutSec + 3;
126
-
127
- let detachAbort: () => void = () => {};
128
-
129
- const timer = setTimeout(() => {
130
- pendingInteractions.resolve(requestId);
131
- log.warn(
132
- { requestId, command: input.command },
133
- "Host bash proxy request timed out",
134
- );
135
- const timeoutMessage = resolvedTargetClientId
136
- ? `Host bash proxy timed out waiting for response from client ${resolvedTargetClientId}`
137
- : "Host bash proxy timed out waiting for client response";
138
- resolve(formatShellOutput("", timeoutMessage, null, true, timeoutSec));
139
- }, proxyTimeoutSec * 1000);
140
-
141
- if (signal) {
142
- const onAbort = () => {
143
- if (pendingInteractions.get(requestId)) {
144
- pendingInteractions.resolve(requestId);
145
- try {
146
- broadcastMessage(
147
- {
148
- type: "host_bash_cancel",
149
- requestId,
150
- conversationId,
151
- targetClientId: resolvedTargetClientId,
152
- },
153
- conversationId,
154
- { targetClientId: resolvedTargetClientId },
155
- );
156
- } catch {
157
- // Best-effort cancel notification
158
- }
159
- resolve(formatShellOutput("", "Aborted", null, false, 0));
160
- }
161
- };
162
- signal.addEventListener("abort", onAbort, { once: true });
163
- detachAbort = () => signal.removeEventListener("abort", onAbort);
164
- }
165
-
166
- pendingInteractions.register(requestId, {
127
+ const shellMaxTimeoutSec = getConfig().timeouts.shellMaxTimeoutSec;
128
+ const timeoutSec = input.timeout_seconds ?? shellMaxTimeoutSec;
129
+ const proxyTimeoutMs = (timeoutSec + 3) * 1000;
130
+
131
+ // Spread command fields at the top level of the envelope so the desktop
132
+ // client receives the same flat message shape it has always expected.
133
+ const extraFields: Record<string, unknown> = { command: input.command };
134
+ if (input.working_dir !== undefined) extraFields.working_dir = input.working_dir;
135
+ if (input.timeout_seconds !== undefined)
136
+ extraFields.timeout_seconds = input.timeout_seconds;
137
+ if (input.env && Object.keys(input.env).length > 0) extraFields.env = input.env;
138
+
139
+ try {
140
+ const payload = await this.dispatchRequest(
141
+ "host_bash",
142
+ {},
167
143
  conversationId,
168
- kind: "host_bash",
169
- rpcResolve: resolve as (v: unknown) => void,
170
- rpcReject: reject,
171
- timer,
172
- detachAbort,
173
- targetClientId: resolvedTargetClientId,
174
- targetActorPrincipalId:
175
- resolvedTargetClientId != null
176
- ? assistantEventHub.getActorPrincipalIdForClient(
177
- resolvedTargetClientId,
178
- )
179
- : undefined,
180
- metadata: { timeoutSec },
181
- });
182
-
183
- try {
184
- broadcastMessage(
185
- {
186
- type: "host_bash_request",
187
- requestId,
188
- conversationId,
189
- command: input.command,
190
- working_dir: input.working_dir,
191
- timeout_seconds: input.timeout_seconds,
192
- targetClientId: resolvedTargetClientId,
193
- ...(input.env && Object.keys(input.env).length > 0
194
- ? { env: input.env }
195
- : {}),
196
- },
197
- conversationId,
198
- { targetClientId: resolvedTargetClientId },
199
- );
200
- } catch (err) {
201
- pendingInteractions.resolve(requestId);
202
- log.warn(
203
- { requestId, command: input.command, err },
204
- "Host bash proxy send failed",
205
- );
206
- reject(err instanceof Error ? err : new Error(String(err)));
144
+ signal,
145
+ extraFields,
146
+ resolvedTargetClientId,
147
+ proxyTimeoutMs,
148
+ );
149
+ return formatShellOutput(
150
+ payload.stdout,
151
+ payload.stderr,
152
+ payload.exitCode,
153
+ payload.timedOut,
154
+ timeoutSec,
155
+ );
156
+ } catch (err) {
157
+ if (err instanceof HostProxyRequestError) {
158
+ if (err.reason === "timeout") {
159
+ log.warn(
160
+ { command: input.command },
161
+ "Host bash proxy request timed out",
162
+ );
163
+ const msg = resolvedTargetClientId
164
+ ? `Host bash proxy timed out waiting for response from client ${resolvedTargetClientId}`
165
+ : "Host bash proxy timed out waiting for client response";
166
+ return formatShellOutput("", msg, null, true, timeoutSec);
167
+ }
168
+ if (err.reason === "aborted") {
169
+ return formatShellOutput("", "Aborted", null, false, 0);
170
+ }
207
171
  }
208
- });
172
+ throw err;
173
+ }
209
174
  }
210
175
 
211
176
  /**
@@ -220,45 +185,7 @@ export class HostBashProxy {
220
185
  timedOut: boolean;
221
186
  },
222
187
  ): void {
223
- const interaction = pendingInteractions.resolve(requestId);
224
- if (!interaction?.rpcResolve) {
225
- log.warn({ requestId }, "No pending host bash request for response");
226
- return;
227
- }
228
- const timeoutSec = (interaction.metadata?.timeoutSec as number) ?? 0;
229
- const result = formatShellOutput(
230
- response.stdout,
231
- response.stderr,
232
- response.exitCode,
233
- response.timedOut,
234
- timeoutSec,
235
- );
236
- interaction.rpcResolve(result);
237
- }
238
-
239
- dispose(): void {
240
- for (const entry of pendingInteractions.getByKind("host_bash")) {
241
- pendingInteractions.resolve(entry.requestId);
242
- try {
243
- broadcastMessage(
244
- {
245
- type: "host_bash_cancel",
246
- requestId: entry.requestId,
247
- conversationId: entry.conversationId,
248
- targetClientId: entry.targetClientId,
249
- },
250
- entry.conversationId,
251
- { targetClientId: entry.targetClientId },
252
- );
253
- } catch {
254
- // Best-effort cancel notification — connection may already be closed.
255
- }
256
- entry.rpcReject?.(
257
- new AssistantError(
258
- "Host bash proxy disposed",
259
- ErrorCode.INTERNAL_ERROR,
260
- ),
261
- );
262
- }
188
+ pendingInteractions.resolve(requestId);
189
+ this.resolve(requestId, response);
263
190
  }
264
191
  }