@vellumai/assistant 0.5.16 → 0.6.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 (592) hide show
  1. package/AGENTS.md +4 -0
  2. package/ARCHITECTURE.md +69 -16
  3. package/Dockerfile +2 -5
  4. package/bun.lock +6 -2
  5. package/docker-entrypoint.sh +32 -1
  6. package/docs/architecture/integrations.md +1 -1
  7. package/docs/architecture/memory.md +21 -24
  8. package/knip.json +2 -1
  9. package/openapi.yaml +1198 -83
  10. package/package.json +5 -1
  11. package/src/__tests__/actor-token-service.test.ts +68 -0
  12. package/src/__tests__/agent-loop.test.ts +0 -32
  13. package/src/__tests__/always-loaded-tools-guard.test.ts +2 -2
  14. package/src/__tests__/anthropic-provider.test.ts +217 -98
  15. package/src/__tests__/app-compiler.test.ts +120 -0
  16. package/src/__tests__/app-dir-path-guard.test.ts +1 -0
  17. package/src/__tests__/app-executors.test.ts +47 -1
  18. package/src/__tests__/app-source-watcher.test.ts +159 -0
  19. package/src/__tests__/assistant-feature-flags-integration.test.ts +2 -2
  20. package/src/__tests__/call-conversation-messages.test.ts +2 -6
  21. package/src/__tests__/call-domain.test.ts +2 -6
  22. package/src/__tests__/call-pointer-messages.test.ts +2 -14
  23. package/src/__tests__/call-recovery.test.ts +2 -6
  24. package/src/__tests__/call-routes-http.test.ts +2 -6
  25. package/src/__tests__/call-store.test.ts +2 -6
  26. package/src/__tests__/cancel-resolves-conversation-key.test.ts +2 -6
  27. package/src/__tests__/canonical-guardian-store.test.ts +2 -6
  28. package/src/__tests__/channel-delivery-store.test.ts +2 -6
  29. package/src/__tests__/channel-retry-sweep.test.ts +2 -6
  30. package/src/__tests__/checker.test.ts +63 -9
  31. package/src/__tests__/clawhub.test.ts +54 -24
  32. package/src/__tests__/cli-command-risk-guard.test.ts +14 -0
  33. package/src/__tests__/config-schema.test.ts +6 -1
  34. package/src/__tests__/config-set-platform-guard.test.ts +302 -0
  35. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +2 -6
  36. package/src/__tests__/contacts-tools.test.ts +31 -0
  37. package/src/__tests__/context-overflow-reducer.test.ts +86 -0
  38. package/src/__tests__/context-token-estimator.test.ts +175 -10
  39. package/src/__tests__/conversation-agent-loop-overflow.test.ts +13 -6
  40. package/src/__tests__/conversation-agent-loop.test.ts +13 -51
  41. package/src/__tests__/conversation-attachments.test.ts +2 -6
  42. package/src/__tests__/conversation-attention-store.test.ts +2 -6
  43. package/src/__tests__/conversation-clear-safety.test.ts +2 -6
  44. package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +4 -10
  45. package/src/__tests__/conversation-disk-view-integration.test.ts +2 -6
  46. package/src/__tests__/conversation-disk-view.test.ts +2 -6
  47. package/src/__tests__/conversation-error.test.ts +33 -2
  48. package/src/__tests__/conversation-fork-crud.test.ts +2 -6
  49. package/src/__tests__/conversation-history-web-search.test.ts +6 -1
  50. package/src/__tests__/conversation-load-history-repair.test.ts +5 -1
  51. package/src/__tests__/conversation-media-retry.test.ts +91 -0
  52. package/src/__tests__/conversation-runtime-assembly.test.ts +653 -832
  53. package/src/__tests__/conversation-runtime-workspace.test.ts +1 -93
  54. package/src/__tests__/conversation-starter-routes.test.ts +20 -11
  55. package/src/__tests__/conversation-store.test.ts +2 -6
  56. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +17 -4
  57. package/src/__tests__/conversation-usage.test.ts +2 -6
  58. package/src/__tests__/conversation-wipe.test.ts +13 -414
  59. package/src/__tests__/conversation-workspace-cache-state.test.ts +6 -12
  60. package/src/__tests__/conversation-workspace-injection.test.ts +25 -26
  61. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +1 -1
  62. package/src/__tests__/copy-composer-tc-templates.test.ts +335 -0
  63. package/src/__tests__/credential-execution-feature-gates.test.ts +3 -3
  64. package/src/__tests__/credential-execution-shell-lockdown.test.ts +2 -2
  65. package/src/__tests__/credential-security-e2e.test.ts +2 -0
  66. package/src/__tests__/date-context.test.ts +76 -210
  67. package/src/__tests__/db-schedule-syntax-migration.test.ts +16 -1
  68. package/src/__tests__/file-list-tool.test.ts +219 -0
  69. package/src/__tests__/first-greeting.test.ts +1 -1
  70. package/src/__tests__/followup-tools.test.ts +2 -6
  71. package/src/__tests__/graph-extraction-event-date.test.ts +186 -0
  72. package/src/__tests__/guardian-action-conversation-turn.test.ts +2 -6
  73. package/src/__tests__/guardian-action-followup-executor.test.ts +2 -6
  74. package/src/__tests__/guardian-action-followup-store.test.ts +2 -6
  75. package/src/__tests__/guardian-action-grant-mint-consume.test.ts +2 -6
  76. package/src/__tests__/guardian-action-late-reply.test.ts +2 -6
  77. package/src/__tests__/guardian-action-store.test.ts +2 -6
  78. package/src/__tests__/guardian-binding-drift-heal.test.ts +2 -6
  79. package/src/__tests__/guardian-decision-primitive-canonical.test.ts +8 -8
  80. package/src/__tests__/guardian-dispatch.test.ts +2 -6
  81. package/src/__tests__/guardian-grant-minting.test.ts +2 -14
  82. package/src/__tests__/guardian-principal-id-roundtrip.test.ts +2 -6
  83. package/src/__tests__/guardian-routing-invariants.test.ts +192 -6
  84. package/src/__tests__/guardian-routing-state.test.ts +2 -6
  85. package/src/__tests__/guardian-verification-voice-binding.test.ts +2 -6
  86. package/src/__tests__/heartbeat-service.test.ts +180 -3
  87. package/src/__tests__/identity-routes.test.ts +328 -0
  88. package/src/__tests__/inbound-invite-redemption.test.ts +2 -6
  89. package/src/__tests__/injection-block.test.ts +178 -0
  90. package/src/__tests__/install-meta.test.ts +506 -0
  91. package/src/__tests__/install-skill-routing.test.ts +293 -0
  92. package/src/__tests__/invite-redemption-service.test.ts +2 -6
  93. package/src/__tests__/invite-routes-http.test.ts +2 -6
  94. package/src/__tests__/jobs-store-qdrant-breaker.test.ts +17 -28
  95. package/src/__tests__/list-messages-attachments.test.ts +2 -6
  96. package/src/__tests__/list-messages-tool-merge.test.ts +300 -0
  97. package/src/__tests__/llm-context-normalization.test.ts +18 -18
  98. package/src/__tests__/llm-context-route-provider.test.ts +103 -6
  99. package/src/__tests__/llm-request-log-turn-query.test.ts +164 -6
  100. package/src/__tests__/llm-usage-store.test.ts +2 -6
  101. package/src/__tests__/log-export-workspace.test.ts +74 -111
  102. package/src/__tests__/managed-store.test.ts +38 -11
  103. package/src/__tests__/mcp-abort-signal.test.ts +5 -0
  104. package/src/__tests__/mcp-client-auth.test.ts +5 -0
  105. package/src/__tests__/memory-jobs-worker-backoff.test.ts +2 -8
  106. package/src/__tests__/memory-recall-log-store.test.ts +134 -6
  107. package/src/__tests__/memory-upsert-concurrency.test.ts +4 -112
  108. package/src/__tests__/migration-export-streaming.test.ts +304 -0
  109. package/src/__tests__/migration-import-commit-http.test.ts +11 -10
  110. package/src/__tests__/mock-fetch.ts +87 -0
  111. package/src/__tests__/non-member-access-request.test.ts +2 -6
  112. package/src/__tests__/notification-decision-recipient-context.test.ts +282 -0
  113. package/src/__tests__/notification-guardian-path.test.ts +2 -6
  114. package/src/__tests__/oauth-cli.test.ts +364 -2
  115. package/src/__tests__/oauth2-gateway-transport.test.ts +18 -3
  116. package/src/__tests__/onboarding-template-contract.test.ts +62 -14
  117. package/src/__tests__/outlook-attachments.test.ts +301 -0
  118. package/src/__tests__/outlook-automation-tools.test.ts +425 -0
  119. package/src/__tests__/outlook-categories.test.ts +212 -0
  120. package/src/__tests__/outlook-client-automation.test.ts +246 -0
  121. package/src/__tests__/outlook-compose-tools.test.ts +325 -0
  122. package/src/__tests__/outlook-declutter-tools.test.ts +585 -0
  123. package/src/__tests__/outlook-email-watcher.test.ts +322 -0
  124. package/src/__tests__/outlook-follow-up.test.ts +196 -0
  125. package/src/__tests__/outlook-messaging-provider.test.ts +498 -3
  126. package/src/__tests__/outlook-trash.test.ts +77 -0
  127. package/src/__tests__/outlook-unsubscribe.test.ts +250 -0
  128. package/src/__tests__/parser.test.ts +32 -0
  129. package/src/__tests__/permission-checker-host-gate.test.ts +452 -0
  130. package/src/__tests__/permission-controls-v2-flag.test.ts +55 -0
  131. package/src/__tests__/permission-mode-sse.test.ts +418 -0
  132. package/src/__tests__/permission-mode-store.test.ts +277 -0
  133. package/src/__tests__/permission-mode.test.ts +101 -0
  134. package/src/__tests__/platform-bash-auto-approve.test.ts +359 -0
  135. package/src/__tests__/platform-callback-registration.test.ts +4 -4
  136. package/src/__tests__/playbook-execution.test.ts +76 -80
  137. package/src/__tests__/playbook-tools.test.ts +5 -7
  138. package/src/__tests__/profiler-routes.test.ts +502 -0
  139. package/src/__tests__/profiler-run-store.test.ts +441 -0
  140. package/src/__tests__/provider-error-scenarios.test.ts +21 -0
  141. package/src/__tests__/proxy-approval-callback.test.ts +4 -75
  142. package/src/__tests__/rebuild-index-graph-nodes.test.ts +273 -0
  143. package/src/__tests__/registry.test.ts +3 -3
  144. package/src/__tests__/require-fresh-approval.test.ts +64 -2
  145. package/src/__tests__/runtime-events-sse-parity.test.ts +2 -6
  146. package/src/__tests__/runtime-events-sse.test.ts +2 -6
  147. package/src/__tests__/sandbox-host-parity.test.ts +5 -4
  148. package/src/__tests__/schedule-store.test.ts +2 -6
  149. package/src/__tests__/schedule-tools.test.ts +2 -6
  150. package/src/__tests__/scheduler-recurrence.test.ts +1 -5
  151. package/src/__tests__/scheduler-reuse-conversation.test.ts +368 -0
  152. package/src/__tests__/scoped-approval-grants.test.ts +2 -6
  153. package/src/__tests__/scoped-grant-security-matrix.test.ts +2 -6
  154. package/src/__tests__/scrub-corrupted-image-attachments.test.ts +278 -0
  155. package/src/__tests__/search-skills-unified.test.ts +422 -0
  156. package/src/__tests__/secret-onetime-send.test.ts +2 -0
  157. package/src/__tests__/send-endpoint-busy.test.ts +44 -9
  158. package/src/__tests__/sequence-store.test.ts +2 -6
  159. package/src/__tests__/server-history-render.test.ts +2 -6
  160. package/src/__tests__/set-permission-mode.test.ts +274 -0
  161. package/src/__tests__/skill-feature-flags-integration.test.ts +38 -31
  162. package/src/__tests__/skill-feature-flags.test.ts +6 -6
  163. package/src/__tests__/skill-load-feature-flag.test.ts +23 -11
  164. package/src/__tests__/skill-memory.test.ts +2 -741
  165. package/src/__tests__/skills-uninstall.test.ts +2 -2
  166. package/src/__tests__/skills.test.ts +1 -1
  167. package/src/__tests__/slack-inbound-verification.test.ts +2 -6
  168. package/src/__tests__/strip-memory-injections.test.ts +187 -0
  169. package/src/__tests__/subagent-detail.test.ts +84 -0
  170. package/src/__tests__/subagent-disposal.test.ts +308 -0
  171. package/src/__tests__/subagent-manager-notify.test.ts +19 -10
  172. package/src/__tests__/subagent-notify-parent.test.ts +390 -0
  173. package/src/__tests__/subagent-role-registry.test.ts +108 -0
  174. package/src/__tests__/subagent-tool-filtering.test.ts +71 -0
  175. package/src/__tests__/subagent-tools.test.ts +464 -4
  176. package/src/__tests__/system-prompt-ask-mode.test.ts +139 -0
  177. package/src/__tests__/task-compiler.test.ts +2 -6
  178. package/src/__tests__/task-management-tools.test.ts +2 -6
  179. package/src/__tests__/task-memory-cleanup.test.ts +185 -241
  180. package/src/__tests__/task-runner.test.ts +2 -6
  181. package/src/__tests__/task-scheduler.test.ts +2 -6
  182. package/src/__tests__/terminal-tools.test.ts +17 -27
  183. package/src/__tests__/test-preload.ts +7 -0
  184. package/src/__tests__/tool-approval-handler.test.ts +2 -6
  185. package/src/__tests__/tool-executor.test.ts +4 -26
  186. package/src/__tests__/tool-grant-request-escalation.test.ts +2 -6
  187. package/src/__tests__/tool-side-effects-slack-dm.test.ts +277 -0
  188. package/src/__tests__/top-level-renderer.test.ts +10 -13
  189. package/src/__tests__/trust-store.test.ts +1 -1
  190. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +2 -6
  191. package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +118 -8
  192. package/src/__tests__/trusted-contact-multichannel.test.ts +2 -6
  193. package/src/__tests__/trusted-contact-verification.test.ts +2 -6
  194. package/src/__tests__/turn-boundary-resolution.test.ts +2 -6
  195. package/src/__tests__/usage-cache-backfill-migration.test.ts +1 -6
  196. package/src/__tests__/usage-routes.test.ts +2 -6
  197. package/src/__tests__/verification-control-plane-policy.test.ts +0 -2
  198. package/src/__tests__/voice-invite-redemption.test.ts +2 -6
  199. package/src/__tests__/voice-scoped-grant-consumer.test.ts +2 -6
  200. package/src/__tests__/voice-session-bridge.test.ts +2 -6
  201. package/src/__tests__/volume-security-guard.test.ts +2 -0
  202. package/src/__tests__/workspace-lifecycle.test.ts +29 -1
  203. package/src/__tests__/workspace-migration-009-backfill-conversation-disk-view.test.ts +2 -6
  204. package/src/__tests__/workspace-migration-013-repair-conversation-disk-view.test.ts +2 -6
  205. package/src/__tests__/workspace-migration-026-backfill-install-meta.test.ts +558 -0
  206. package/src/__tests__/workspace-migration-028-recover-conversations-from-disk-view.test.ts +387 -0
  207. package/src/__tests__/workspace-policy.test.ts +1 -1
  208. package/src/agent/attachments.ts +7 -2
  209. package/src/agent/image-optimize.ts +165 -0
  210. package/src/agent/loop.ts +7 -15
  211. package/src/approvals/guardian-request-resolvers.ts +24 -0
  212. package/src/avatar/traits-png-sync.ts +3 -3
  213. package/src/bundler/app-compiler.ts +179 -2
  214. package/src/bundler/package-resolver.ts +3 -5
  215. package/src/cli/__tests__/notifications.test.ts +1 -2
  216. package/src/cli/__tests__/run-assistant-command.ts +29 -0
  217. package/src/cli/commands/__tests__/email-download.test.ts +245 -0
  218. package/src/cli/commands/__tests__/email-list.test.ts +192 -0
  219. package/src/cli/commands/__tests__/email-register.test.ts +186 -0
  220. package/src/cli/commands/__tests__/email-send.test.ts +291 -0
  221. package/src/cli/commands/__tests__/email-status.test.ts +181 -0
  222. package/src/cli/commands/__tests__/email-unregister.test.ts +139 -0
  223. package/src/cli/commands/__tests__/routes.test.ts +562 -0
  224. package/src/cli/commands/avatar.ts +3 -3
  225. package/src/cli/commands/config.ts +26 -13
  226. package/src/cli/commands/conversations.ts +1 -8
  227. package/src/cli/commands/doctor.ts +2 -2
  228. package/src/cli/commands/email.ts +584 -835
  229. package/src/cli/commands/memory.ts +37 -84
  230. package/src/cli/commands/notifications.ts +7 -2
  231. package/src/cli/commands/oauth/__tests__/connect.test.ts +2 -2
  232. package/src/cli/commands/oauth/__tests__/disconnect.test.ts +2 -2
  233. package/src/cli/commands/oauth/__tests__/mode.test.ts +8 -1
  234. package/src/cli/commands/oauth/__tests__/status.test.ts +2 -2
  235. package/src/cli/commands/oauth/connect.ts +25 -11
  236. package/src/cli/commands/oauth/mode.ts +7 -0
  237. package/src/cli/commands/oauth/shared.ts +39 -3
  238. package/src/cli/commands/platform/__tests__/connect.test.ts +1 -1
  239. package/src/cli/commands/platform/__tests__/disconnect.test.ts +1 -1
  240. package/src/cli/commands/platform/__tests__/status.test.ts +5 -5
  241. package/src/cli/commands/platform/index.ts +16 -16
  242. package/src/cli/commands/routes.ts +396 -0
  243. package/src/cli/commands/skills.ts +218 -36
  244. package/src/cli/commands/trust.ts +2 -2
  245. package/src/cli/lib/daemon-credential-client.ts +2 -3
  246. package/src/cli/program.ts +2 -0
  247. package/src/cli.ts +1 -120
  248. package/src/config/bundled-skills/acp/TOOLS.json +1 -1
  249. package/src/config/bundled-skills/app-builder/SKILL.md +4 -1
  250. package/src/config/bundled-skills/contacts/SKILL.md +0 -1
  251. package/src/config/bundled-skills/contacts/TOOLS.json +0 -8
  252. package/src/config/bundled-skills/contacts/tools/contact-upsert.ts +0 -4
  253. package/src/config/bundled-skills/gmail/SKILL.md +4 -12
  254. package/src/config/bundled-skills/google-calendar/SKILL.md +1 -9
  255. package/src/config/bundled-skills/messaging/SKILL.md +17 -18
  256. package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +40 -33
  257. package/src/config/bundled-skills/outlook/SKILL.md +189 -0
  258. package/src/config/bundled-skills/outlook/TOOLS.json +530 -0
  259. package/src/config/bundled-skills/outlook/tools/outlook-attachments.ts +85 -0
  260. package/src/config/bundled-skills/outlook/tools/outlook-categories.ts +77 -0
  261. package/src/config/bundled-skills/outlook/tools/outlook-draft.ts +84 -0
  262. package/src/config/bundled-skills/outlook/tools/outlook-follow-up.ts +94 -0
  263. package/src/config/bundled-skills/outlook/tools/outlook-forward.ts +49 -0
  264. package/src/config/bundled-skills/outlook/tools/outlook-outreach-scan.ts +237 -0
  265. package/src/config/bundled-skills/outlook/tools/outlook-rules.ts +161 -0
  266. package/src/config/bundled-skills/outlook/tools/outlook-send-draft.ts +32 -0
  267. package/src/config/bundled-skills/outlook/tools/outlook-sender-digest.ts +272 -0
  268. package/src/config/bundled-skills/outlook/tools/outlook-trash.ts +29 -0
  269. package/src/config/bundled-skills/outlook/tools/outlook-unsubscribe.ts +129 -0
  270. package/src/config/bundled-skills/outlook/tools/outlook-vacation.ts +87 -0
  271. package/src/config/bundled-skills/outlook/tools/shared.ts +20 -0
  272. package/src/config/bundled-skills/outlook-calendar/SKILL.md +51 -0
  273. package/src/config/bundled-skills/outlook-calendar/TOOLS.json +221 -0
  274. package/src/config/bundled-skills/outlook-calendar/calendar-client.ts +252 -0
  275. package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-check-availability.ts +53 -0
  276. package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-create-event.ts +74 -0
  277. package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-get-event.ts +18 -0
  278. package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-list-events.ts +46 -0
  279. package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-rsvp.ts +36 -0
  280. package/src/config/bundled-skills/outlook-calendar/tools/shared.ts +17 -0
  281. package/src/config/bundled-skills/outlook-calendar/types.ts +120 -0
  282. package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +47 -40
  283. package/src/config/bundled-skills/playbooks/tools/playbook-delete.ts +16 -29
  284. package/src/config/bundled-skills/playbooks/tools/playbook-list.ts +16 -18
  285. package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +39 -47
  286. package/src/config/bundled-skills/schedule/SKILL.md +22 -2
  287. package/src/config/bundled-skills/schedule/TOOLS.json +8 -0
  288. package/src/config/bundled-skills/settings/tools/avatar-get.ts +3 -13
  289. package/src/config/bundled-skills/settings/tools/avatar-remove.ts +2 -4
  290. package/src/config/bundled-skills/settings/tools/avatar-update.ts +5 -2
  291. package/src/config/bundled-skills/slack/SKILL.md +3 -7
  292. package/src/config/bundled-skills/subagent/SKILL.md +43 -3
  293. package/src/config/bundled-skills/subagent/TOOLS.json +29 -4
  294. package/src/config/bundled-tool-registry.ts +56 -4
  295. package/src/config/env-registry.ts +78 -8
  296. package/src/config/feature-flag-registry.json +38 -125
  297. package/src/config/schema.ts +8 -0
  298. package/src/config/schemas/filing.ts +51 -0
  299. package/src/config/schemas/heartbeat.ts +15 -12
  300. package/src/config/schemas/memory-lifecycle.ts +12 -0
  301. package/src/config/schemas/platform.ts +8 -0
  302. package/src/config/schemas/security.ts +14 -0
  303. package/src/config/schemas/timeouts.ts +1 -1
  304. package/src/config/skills.ts +18 -7
  305. package/src/context/token-estimator.ts +25 -18
  306. package/src/context/window-manager.ts +6 -2
  307. package/src/credential-execution/process-manager.ts +3 -1
  308. package/src/daemon/app-source-watcher.ts +93 -0
  309. package/src/daemon/config-watcher.ts +79 -1
  310. package/src/daemon/context-overflow-reducer.ts +46 -2
  311. package/src/daemon/conversation-agent-loop-handlers.ts +143 -82
  312. package/src/daemon/conversation-agent-loop.ts +236 -108
  313. package/src/daemon/conversation-error.ts +31 -8
  314. package/src/daemon/conversation-history.ts +4 -19
  315. package/src/daemon/conversation-lifecycle.ts +36 -9
  316. package/src/daemon/conversation-media-retry.ts +85 -7
  317. package/src/daemon/conversation-notifiers.ts +4 -1
  318. package/src/daemon/conversation-process.ts +13 -7
  319. package/src/daemon/conversation-runtime-assembly.ts +305 -306
  320. package/src/daemon/conversation-tool-setup.ts +44 -14
  321. package/src/daemon/conversation-workspace.ts +1 -2
  322. package/src/daemon/conversation.ts +59 -2
  323. package/src/daemon/daemon-control.ts +8 -2
  324. package/src/daemon/date-context.ts +26 -53
  325. package/src/daemon/first-greeting.ts +1 -1
  326. package/src/daemon/handlers/conversations.ts +4 -7
  327. package/src/daemon/handlers/shared.test.ts +143 -0
  328. package/src/daemon/handlers/shared.ts +85 -17
  329. package/src/daemon/handlers/skills.ts +416 -209
  330. package/src/daemon/lifecycle.ts +212 -131
  331. package/src/daemon/main.ts +5 -1
  332. package/src/daemon/message-types/conversations.ts +29 -7
  333. package/src/daemon/message-types/messages.ts +12 -2
  334. package/src/daemon/message-types/schedules.ts +1 -0
  335. package/src/daemon/message-types/settings.ts +6 -0
  336. package/src/daemon/message-types/skills.ts +97 -36
  337. package/src/daemon/profiler-run-store.ts +557 -0
  338. package/src/daemon/providers-setup.ts +5 -0
  339. package/src/daemon/server.ts +100 -11
  340. package/src/daemon/shutdown-handlers.ts +5 -0
  341. package/src/daemon/tool-side-effects.ts +50 -8
  342. package/src/export/transcript-formatter.ts +148 -0
  343. package/src/filing/filing-service.ts +228 -0
  344. package/src/heartbeat/heartbeat-service.ts +97 -7
  345. package/src/hooks/cli.ts +2 -2
  346. package/src/hooks/runner.ts +15 -38
  347. package/src/inbound/platform-callback-registration.ts +14 -14
  348. package/src/mcp/client.ts +6 -0
  349. package/src/mcp/mcp-oauth-provider.ts +149 -27
  350. package/src/memory/admin.ts +42 -75
  351. package/src/memory/app-store.ts +69 -0
  352. package/src/memory/conversation-bootstrap.ts +3 -1
  353. package/src/memory/conversation-crud.ts +211 -288
  354. package/src/memory/conversation-group-migration.ts +157 -0
  355. package/src/memory/conversation-queries.ts +61 -13
  356. package/src/memory/conversation-title-service.ts +1 -0
  357. package/src/memory/db-init.ts +194 -361
  358. package/src/memory/embed.ts +73 -0
  359. package/src/memory/embedding-backend.ts +8 -14
  360. package/src/memory/embedding-runtime-manager.ts +12 -114
  361. package/src/memory/fingerprint.ts +2 -2
  362. package/src/memory/graph/bootstrap.ts +521 -0
  363. package/src/memory/graph/capability-seed.ts +449 -0
  364. package/src/memory/graph/consolidation.ts +725 -0
  365. package/src/memory/graph/conversation-graph-memory.ts +659 -0
  366. package/src/memory/graph/decay.test.ts +208 -0
  367. package/src/memory/graph/decay.ts +195 -0
  368. package/src/memory/graph/extraction-job.ts +74 -0
  369. package/src/memory/graph/extraction.test.ts +936 -0
  370. package/src/memory/graph/extraction.ts +1297 -0
  371. package/src/memory/graph/graph-memory-state-store.ts +37 -0
  372. package/src/memory/graph/graph-search.ts +280 -0
  373. package/src/memory/graph/image-ref-utils.ts +29 -0
  374. package/src/memory/graph/injection.test.ts +513 -0
  375. package/src/memory/graph/injection.ts +469 -0
  376. package/src/memory/graph/inspect.ts +543 -0
  377. package/src/memory/graph/narrative.ts +267 -0
  378. package/src/memory/graph/pattern-scan.ts +269 -0
  379. package/src/memory/graph/retriever.ts +1111 -0
  380. package/src/memory/graph/scoring.test.ts +548 -0
  381. package/src/memory/graph/scoring.ts +232 -0
  382. package/src/memory/graph/serendipity.ts +65 -0
  383. package/src/memory/graph/store.test.ts +1098 -0
  384. package/src/memory/graph/store.ts +838 -0
  385. package/src/memory/graph/tool-handlers.ts +301 -0
  386. package/src/memory/graph/tools.ts +97 -0
  387. package/src/memory/graph/triggers.test.ts +487 -0
  388. package/src/memory/graph/triggers.ts +223 -0
  389. package/src/memory/graph/types.ts +295 -0
  390. package/src/memory/group-crud.ts +191 -0
  391. package/src/memory/indexer.ts +37 -19
  392. package/src/memory/job-handlers/cleanup.ts +32 -42
  393. package/src/memory/job-handlers/conversation-starters.ts +91 -53
  394. package/src/memory/job-handlers/embedding.ts +5 -31
  395. package/src/memory/job-handlers/index-maintenance.ts +23 -11
  396. package/src/memory/job-handlers/summarization.ts +32 -17
  397. package/src/memory/job-utils.ts +1 -1
  398. package/src/memory/jobs-store.ts +21 -31
  399. package/src/memory/jobs-worker.ts +180 -129
  400. package/src/memory/llm-request-log-store.ts +96 -12
  401. package/src/memory/memory-recall-log-store.ts +49 -5
  402. package/src/memory/message-content.ts +1 -0
  403. package/src/memory/migrations/202-memory-graph-tables.ts +130 -0
  404. package/src/memory/migrations/203-drop-memory-items-tables.ts +55 -0
  405. package/src/memory/migrations/204-rename-memory-graph-type-values.ts +46 -0
  406. package/src/memory/migrations/205-memory-graph-image-refs.ts +11 -0
  407. package/src/memory/migrations/206-memory-graph-node-edits.ts +19 -0
  408. package/src/memory/migrations/206-scrub-corrupted-image-attachments.ts +131 -0
  409. package/src/memory/migrations/207-conversation-graph-memory-state.ts +20 -0
  410. package/src/memory/migrations/208-conversations-last-message-at.ts +35 -0
  411. package/src/memory/migrations/209-strip-thinking-from-consolidated.ts +85 -0
  412. package/src/memory/migrations/210-schedule-reuse-conversation.ts +13 -0
  413. package/src/memory/migrations/211-memory-recall-logs-query-context.ts +21 -0
  414. package/src/memory/migrations/212-llm-request-logs-created-at-index.ts +19 -0
  415. package/src/memory/migrations/index.ts +12 -0
  416. package/src/memory/migrations/registry.ts +16 -0
  417. package/src/memory/qdrant-client.ts +44 -17
  418. package/src/memory/schema/conversations.ts +14 -0
  419. package/src/memory/schema/index.ts +1 -0
  420. package/src/memory/schema/infrastructure.ts +8 -1
  421. package/src/memory/schema/memory-core.ts +0 -51
  422. package/src/memory/schema/memory-graph.ts +154 -0
  423. package/src/memory/search/semantic.ts +47 -91
  424. package/src/memory/task-memory-cleanup.ts +58 -61
  425. package/src/messaging/providers/outlook/adapter.ts +8 -1
  426. package/src/messaging/providers/outlook/client.ts +299 -0
  427. package/src/messaging/providers/outlook/types.ts +118 -0
  428. package/src/notifications/adapters/macos.ts +1 -0
  429. package/src/notifications/copy-composer.ts +95 -0
  430. package/src/notifications/decision-engine.ts +35 -0
  431. package/src/notifications/signal.ts +16 -0
  432. package/src/oauth/seed-providers.ts +2 -1
  433. package/src/permissions/checker.ts +36 -4
  434. package/src/permissions/defaults.ts +4 -4
  435. package/src/permissions/permission-mode-store.ts +180 -0
  436. package/src/permissions/permission-mode.ts +31 -0
  437. package/src/permissions/workspace-policy.ts +10 -1
  438. package/src/playbooks/playbook-compiler.ts +19 -18
  439. package/src/playbooks/types.ts +4 -3
  440. package/src/prompts/system-prompt.ts +62 -36
  441. package/src/prompts/templates/BOOTSTRAP-REFERENCE.md +100 -0
  442. package/src/prompts/templates/BOOTSTRAP.md +70 -165
  443. package/src/prompts/templates/HEARTBEAT.md +3 -1
  444. package/src/prompts/templates/SOUL.md +25 -4
  445. package/src/prompts/templates/UPDATES.md +8 -0
  446. package/src/providers/anthropic/client.ts +136 -220
  447. package/src/providers/gemini/client.ts +1 -1
  448. package/src/providers/openai/client.ts +1 -1
  449. package/src/providers/registry.ts +1 -1
  450. package/src/providers/retry.ts +19 -3
  451. package/src/runtime/actor-trust-resolver.ts +5 -1
  452. package/src/runtime/auth/route-policy.ts +30 -0
  453. package/src/runtime/guardian-reply-router.ts +5 -1
  454. package/src/runtime/http-server.ts +55 -5
  455. package/src/runtime/http-types.ts +12 -1
  456. package/src/runtime/middleware/auth.ts +20 -0
  457. package/src/runtime/migrations/vbundle-builder.ts +389 -3
  458. package/src/runtime/migrations/vbundle-importer.ts +8 -6
  459. package/src/runtime/routes/__tests__/user-route-dispatcher.test.ts +378 -0
  460. package/src/runtime/routes/app-management-routes.ts +1 -11
  461. package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +26 -0
  462. package/src/runtime/routes/archive-utils.ts +29 -0
  463. package/src/runtime/routes/attachment-routes.test.ts +106 -0
  464. package/src/runtime/routes/attachment-routes.ts +106 -16
  465. package/src/runtime/routes/avatar-routes.ts +2 -9
  466. package/src/runtime/routes/brain-graph-routes.ts +21 -22
  467. package/src/runtime/routes/btw-routes.ts +22 -1
  468. package/src/runtime/routes/conversation-analysis-routes.ts +173 -0
  469. package/src/runtime/routes/conversation-management-routes.ts +3 -14
  470. package/src/runtime/routes/conversation-query-routes.ts +49 -3
  471. package/src/runtime/routes/conversation-routes.ts +264 -44
  472. package/src/runtime/routes/conversation-starter-routes.ts +2 -2
  473. package/src/runtime/routes/debug-routes.ts +1 -1
  474. package/src/runtime/routes/global-search-routes.ts +21 -19
  475. package/src/runtime/routes/group-routes.ts +207 -0
  476. package/src/runtime/routes/guardian-action-routes.ts +21 -10
  477. package/src/runtime/routes/guardian-bootstrap-routes.ts +23 -19
  478. package/src/runtime/routes/heartbeat-routes.ts +4 -10
  479. package/src/runtime/routes/identity-routes.ts +53 -18
  480. package/src/runtime/routes/inbound-message-handler.ts +19 -0
  481. package/src/runtime/routes/inbound-stages/guardian-activation-intercept.test.ts +292 -0
  482. package/src/runtime/routes/inbound-stages/guardian-activation-intercept.ts +207 -0
  483. package/src/runtime/routes/llm-context-normalization.ts +14 -10
  484. package/src/runtime/routes/log-export-routes.ts +23 -275
  485. package/src/runtime/routes/memory-item-routes.test.ts +170 -247
  486. package/src/runtime/routes/memory-item-routes.ts +341 -388
  487. package/src/runtime/routes/migration-routes.ts +18 -7
  488. package/src/runtime/routes/profiler-routes.ts +350 -0
  489. package/src/runtime/routes/schedule-routes.ts +28 -11
  490. package/src/runtime/routes/settings-routes.ts +95 -8
  491. package/src/runtime/routes/skills-routes.ts +103 -37
  492. package/src/runtime/routes/subagents-routes.ts +28 -7
  493. package/src/runtime/routes/user-route-dispatcher.ts +223 -0
  494. package/src/runtime/routes/user-routes.ts +41 -0
  495. package/src/runtime/routes/work-items-routes.test.ts +2 -6
  496. package/src/runtime/routes/workspace-routes.ts +0 -1
  497. package/src/schedule/schedule-store.ts +30 -0
  498. package/src/schedule/scheduler.ts +52 -18
  499. package/src/security/oauth2.ts +1 -1
  500. package/src/security/secure-keys.ts +4 -8
  501. package/src/shared/provider-env-vars.ts +19 -0
  502. package/src/skills/catalog-cache.ts +5 -0
  503. package/src/skills/catalog-install.ts +25 -16
  504. package/src/skills/clawhub.ts +134 -154
  505. package/src/skills/install-meta.ts +208 -0
  506. package/src/skills/managed-store.ts +29 -18
  507. package/src/skills/skill-memory.ts +12 -229
  508. package/src/skills/skillssh-registry.ts +19 -17
  509. package/src/subagent/index.ts +13 -3
  510. package/src/subagent/manager.ts +308 -29
  511. package/src/subagent/types.ts +68 -0
  512. package/src/tasks/task-runner.ts +7 -5
  513. package/src/telemetry/usage-telemetry-reporter.test.ts +3 -5
  514. package/src/tools/apps/executors.ts +29 -4
  515. package/src/tools/browser/runtime-check.ts +3 -1
  516. package/src/tools/filesystem/list.ts +93 -0
  517. package/src/tools/memory/register.ts +63 -46
  518. package/src/tools/permission-checker.ts +85 -1
  519. package/src/tools/registry.ts +4 -0
  520. package/src/tools/schedule/create.ts +3 -0
  521. package/src/tools/schedule/list.ts +1 -0
  522. package/src/tools/schedule/update.ts +6 -0
  523. package/src/tools/shared/filesystem/errors.ts +5 -0
  524. package/src/tools/shared/filesystem/file-ops-service.ts +90 -2
  525. package/src/tools/shared/filesystem/image-read.ts +22 -85
  526. package/src/tools/shared/filesystem/types.ts +17 -0
  527. package/src/tools/shared/shell-output.ts +31 -2
  528. package/src/tools/subagent/abort.ts +12 -2
  529. package/src/tools/subagent/message.ts +9 -2
  530. package/src/tools/subagent/notify-parent.ts +79 -0
  531. package/src/tools/subagent/read.ts +29 -8
  532. package/src/tools/subagent/resolve.ts +21 -0
  533. package/src/tools/subagent/spawn.ts +2 -0
  534. package/src/tools/subagent/status.ts +11 -1
  535. package/src/tools/system/avatar-generator.ts +3 -3
  536. package/src/tools/system/register.ts +23 -0
  537. package/src/tools/system/set-permission-mode.ts +103 -0
  538. package/src/tools/terminal/parser.ts +30 -5
  539. package/src/tools/terminal/safe-env.ts +17 -1
  540. package/src/tools/tool-manifest.ts +9 -3
  541. package/src/tools/types.ts +2 -0
  542. package/src/util/browser.ts +25 -10
  543. package/src/util/bun-runtime.ts +172 -0
  544. package/src/util/logger.ts +1 -1
  545. package/src/util/platform.ts +50 -17
  546. package/src/watcher/providers/outlook-calendar.ts +343 -0
  547. package/src/watcher/providers/outlook.ts +198 -0
  548. package/src/workspace/migrations/023-move-config-files-to-workspace.ts +2 -2
  549. package/src/workspace/migrations/024-move-runtime-files-to-workspace.ts +2 -2
  550. package/src/workspace/migrations/025-remove-oauth-app-setup-skills.ts +76 -0
  551. package/src/workspace/migrations/026-backfill-install-meta.ts +325 -0
  552. package/src/workspace/migrations/027-remove-orphaned-optimized-images-cache.ts +42 -0
  553. package/src/workspace/migrations/028-recover-conversations-from-disk-view.ts +270 -0
  554. package/src/workspace/migrations/029-seed-pkb.ts +84 -0
  555. package/src/workspace/migrations/registry.ts +10 -0
  556. package/src/workspace/top-level-renderer.ts +5 -9
  557. package/src/__tests__/cli-memory.test.ts +0 -372
  558. package/src/__tests__/clipboard.test.ts +0 -88
  559. package/src/__tests__/context-memory-e2e.test.ts +0 -415
  560. package/src/__tests__/journal-context.test.ts +0 -268
  561. package/src/__tests__/memory-context-benchmark.benchmark.test.ts +0 -297
  562. package/src/__tests__/memory-lifecycle-e2e.test.ts +0 -459
  563. package/src/__tests__/memory-query-builder.test.ts +0 -59
  564. package/src/__tests__/memory-recall-quality.test.ts +0 -1046
  565. package/src/__tests__/memory-regressions.experimental.test.ts +0 -629
  566. package/src/__tests__/memory-regressions.test.ts +0 -3696
  567. package/src/__tests__/memory-retrieval.benchmark.test.ts +0 -295
  568. package/src/cli/cli-memory.ts +0 -176
  569. package/src/daemon/conversation-memory.ts +0 -207
  570. package/src/memory/conversation-starters-cadence.ts +0 -74
  571. package/src/memory/items-extractor.ts +0 -860
  572. package/src/memory/job-handlers/batch-extraction.ts +0 -753
  573. package/src/memory/job-handlers/extraction.ts +0 -40
  574. package/src/memory/job-handlers/journal-carry-forward.test.ts +0 -355
  575. package/src/memory/job-handlers/journal-carry-forward.ts +0 -255
  576. package/src/memory/journal-memory.ts +0 -224
  577. package/src/memory/query-builder.ts +0 -47
  578. package/src/memory/query-expansion.ts +0 -83
  579. package/src/memory/retriever.test.ts +0 -1592
  580. package/src/memory/retriever.ts +0 -1331
  581. package/src/memory/search/formatting.test.ts +0 -140
  582. package/src/memory/search/formatting.ts +0 -262
  583. package/src/memory/search/mmr.ts +0 -139
  584. package/src/memory/search/ranking.ts +0 -15
  585. package/src/memory/search/staleness.ts +0 -40
  586. package/src/memory/search/tier-classifier.ts +0 -18
  587. package/src/memory/search/types.ts +0 -121
  588. package/src/prompts/journal-context.ts +0 -154
  589. package/src/tools/memory/definitions.ts +0 -69
  590. package/src/tools/memory/handlers.test.ts +0 -562
  591. package/src/tools/memory/handlers.ts +0 -434
  592. package/src/util/clipboard.ts +0 -34
@@ -25,6 +25,8 @@ import { githubProvider } from "../watcher/providers/github.js";
25
25
  import { gmailProvider } from "../watcher/providers/gmail.js";
26
26
  import { googleCalendarProvider } from "../watcher/providers/google-calendar.js";
27
27
  import { linearProvider } from "../watcher/providers/linear.js";
28
+ import { outlookProvider } from "../watcher/providers/outlook.js";
29
+ import { outlookCalendarProvider } from "../watcher/providers/outlook-calendar.js";
28
30
  const log = getLogger("lifecycle");
29
31
 
30
32
  export async function initializeProvidersAndTools(
@@ -135,6 +137,9 @@ export function registerWatcherProviders(): void {
135
137
  registerWatcherProvider(googleCalendarProvider);
136
138
  registerWatcherProvider(githubProvider);
137
139
  registerWatcherProvider(linearProvider);
140
+ registerWatcherProvider(outlookProvider);
141
+ registerWatcherProvider(outlookCalendarProvider);
142
+
138
143
  initWatcherEngine();
139
144
  }
140
145
 
@@ -11,6 +11,7 @@ import {
11
11
  createAssistantMessage,
12
12
  createUserMessage,
13
13
  } from "../agent/message-types.js";
14
+ import { compileApp } from "../bundler/app-compiler.js";
14
15
  import {
15
16
  type ChannelId,
16
17
  type InterfaceId,
@@ -22,6 +23,7 @@ import { onContactChange } from "../contacts/contact-events.js";
22
23
  import type { CesClient } from "../credential-execution/client.js";
23
24
  import type { CesProcessManager } from "../credential-execution/process-manager.js";
24
25
  import type { HeartbeatService } from "../heartbeat/heartbeat-service.js";
26
+ import { getApp, getAppDirPath, isMultifileApp } from "../memory/app-store.js";
25
27
  import * as attachmentsStore from "../memory/attachments-store.js";
26
28
  import {
27
29
  createCanonicalGuardianRequest,
@@ -49,6 +51,7 @@ import { bridgeConfirmationRequestToGuardian } from "../runtime/confirmation-req
49
51
  import * as pendingInteractions from "../runtime/pending-interactions.js";
50
52
  import { checkIngressForSecrets } from "../security/secret-ingress.js";
51
53
  import { redactSecrets } from "../security/secret-scanner.js";
54
+ import { updatePublishedAppDeployment } from "../services/published-app-updater.js";
52
55
  import { registerCancelCallback } from "../signals/cancel.js";
53
56
  import { registerConversationUndoCallback } from "../signals/conversation-undo.js";
54
57
  import { appendEventToStream } from "../signals/event-stream.js";
@@ -57,10 +60,12 @@ import { getSubagentManager } from "../subagent/index.js";
57
60
  import { summarizeToolInput } from "../tools/tool-input-summary.js";
58
61
  import { getLogger } from "../util/logger.js";
59
62
  import {
63
+ getAvatarImagePath,
60
64
  getSandboxWorkingDir,
61
65
  getWorkspacePromptPath,
62
66
  } from "../util/platform.js";
63
67
  import { registerDaemonCallbacks } from "../work-items/work-item-runner.js";
68
+ import { AppSourceWatcher } from "./app-source-watcher.js";
64
69
  import { ConfigWatcher } from "./config-watcher.js";
65
70
  import {
66
71
  Conversation,
@@ -71,6 +76,7 @@ import { ConversationEvictor } from "./conversation-evictor.js";
71
76
  import { formatCompactResult } from "./conversation-process.js";
72
77
  import { resolveChannelCapabilities } from "./conversation-runtime-assembly.js";
73
78
  import { resolveSlash, type SlashContext } from "./conversation-slash.js";
79
+ import { refreshSurfacesForApp } from "./conversation-surfaces.js";
74
80
  import { undoLastMessage } from "./handlers/conversations.js";
75
81
  import { parseIdentityFields } from "./handlers/identity.js";
76
82
  import type {
@@ -201,13 +207,10 @@ function makePendingInteractionRegistrar(
201
207
  guardianPrincipalId: trustContext?.guardianPrincipalId ?? undefined,
202
208
  toolName: msg.toolName,
203
209
  commandPreview:
204
- redactSecrets(
205
- summarizeToolInput(msg.toolName, inputRecord),
206
- ) || undefined,
210
+ redactSecrets(summarizeToolInput(msg.toolName, inputRecord)) ||
211
+ undefined,
207
212
  riskLevel: msg.riskLevel,
208
- activityText: activityRaw
209
- ? redactSecrets(activityRaw)
210
- : undefined,
213
+ activityText: activityRaw ? redactSecrets(activityRaw) : undefined,
211
214
  executionTarget: msg.executionTarget,
212
215
  status: "pending",
213
216
  requestCode: generateCanonicalRequestCode(),
@@ -271,6 +274,7 @@ export class DaemonServer {
271
274
 
272
275
  // Composed subsystems
273
276
  private configWatcher = new ConfigWatcher();
277
+ private appSourceWatcher = new AppSourceWatcher();
274
278
 
275
279
  // CES (Credential Execution Service) — process-level singleton.
276
280
  // Lifecycle is managed by startCesProcess() in lifecycle.ts; the server
@@ -369,7 +373,28 @@ export class DaemonServer {
369
373
  { channelId: transport.channelId },
370
374
  "Transport metadata received",
371
375
  );
372
- conversation.setTransportHints(transport.hints);
376
+
377
+ // Build enriched hints: interface ID first, then host environment (macOS
378
+ // only), then any client-provided hints.
379
+ const enrichedHints: string[] = [];
380
+
381
+ const interfaceLabel = parseInterfaceId(transport.interfaceId) ?? "vellum";
382
+ enrichedHints.push(`User is messaging from interface: ${interfaceLabel}`);
383
+
384
+ if (transport.interfaceId === "macos") {
385
+ if (transport.hostHomeDir) {
386
+ enrichedHints.push(`Host home directory: ${transport.hostHomeDir}`);
387
+ }
388
+ if (transport.hostUsername) {
389
+ enrichedHints.push(`Host username: ${transport.hostUsername}`);
390
+ }
391
+ }
392
+
393
+ if (transport.hints) {
394
+ enrichedHints.push(...transport.hints);
395
+ }
396
+
397
+ conversation.setTransportHints(enrichedHints);
373
398
  }
374
399
 
375
400
  constructor() {
@@ -523,6 +548,55 @@ export class DaemonServer {
523
548
  }
524
549
  }
525
550
 
551
+ private broadcastSoundsConfigUpdated(): void {
552
+ this.broadcast({ type: "sounds_config_updated" });
553
+ }
554
+
555
+ private broadcastAvatarUpdated(): void {
556
+ this.broadcast({
557
+ type: "avatar_updated",
558
+ avatarPath: getAvatarImagePath(),
559
+ });
560
+ }
561
+
562
+ /**
563
+ * Handle a detected app source file change from the filesystem watcher.
564
+ * Recompiles multifile apps and refreshes surfaces across ALL conversations.
565
+ */
566
+ private handleAppSourceChange(appId: string): void {
567
+ const app = getApp(appId);
568
+ if (!app) return;
569
+
570
+ const doRefresh = () => {
571
+ for (const conversation of this.conversations.values()) {
572
+ refreshSurfacesForApp(conversation, appId, { fileChange: true });
573
+ }
574
+ this.broadcast({ type: "app_files_changed", appId });
575
+ void updatePublishedAppDeployment(appId);
576
+ };
577
+
578
+ if (isMultifileApp(app)) {
579
+ const appDir = getAppDirPath(appId);
580
+ void compileApp(appDir)
581
+ .then((result) => {
582
+ if (!result.ok) {
583
+ log.warn(
584
+ { appId, errors: result.errors },
585
+ "Recompile failed on app source change",
586
+ );
587
+ }
588
+ doRefresh();
589
+ })
590
+ .catch((err) => {
591
+ log.warn({ appId, err }, "Recompile threw on app source change");
592
+ doRefresh();
593
+ });
594
+ return;
595
+ }
596
+
597
+ doRefresh();
598
+ }
599
+
526
600
  // ── Server lifecycle ────────────────────────────────────────────────
527
601
 
528
602
  async start(): Promise<void> {
@@ -625,9 +699,18 @@ export class DaemonServer {
625
699
  if (conversation.isProcessing()) {
626
700
  // Hydrate file data now — the queue path won't re-read from
627
701
  // the attachment store, so base64 content must be inline.
628
- for (const att of resolvedAttachments) {
702
+ for (let i = resolvedAttachments.length - 1; i >= 0; i--) {
703
+ const att = resolvedAttachments[i];
629
704
  if (att.filePath && !att.data) {
630
- att.data = readFileSync(att.filePath).toString("base64");
705
+ try {
706
+ att.data = readFileSync(att.filePath).toString("base64");
707
+ } catch (err) {
708
+ log.warn(
709
+ { err, path: att.filePath },
710
+ "Failed to read queued signal attachment, skipping",
711
+ );
712
+ resolvedAttachments.splice(i, 1);
713
+ }
631
714
  }
632
715
  }
633
716
  const requestId = crypto.randomUUID();
@@ -663,8 +746,12 @@ export class DaemonServer {
663
746
  this.configWatcher.start(
664
747
  () => this.evictConversationsForReload(),
665
748
  () => this.broadcastIdentityChanged(),
749
+ () => this.broadcastSoundsConfigUpdated(),
750
+ () => this.broadcastAvatarUpdated(),
666
751
  );
667
752
 
753
+ this.appSourceWatcher.start((appId) => this.handleAppSourceChange(appId));
754
+
668
755
  // Broadcast contacts_changed to all clients when any contact mutation occurs.
669
756
  this.unsubscribeContactChange = onContactChange(() => {
670
757
  this.broadcast({ type: "contacts_changed" });
@@ -678,6 +765,7 @@ export class DaemonServer {
678
765
  disposeAcpSessionManager();
679
766
  this.evictor.stop();
680
767
  this.configWatcher.stop();
768
+ this.appSourceWatcher.stop();
681
769
  if (this.unsubscribeContactChange) {
682
770
  this.unsubscribeContactChange();
683
771
  this.unsubscribeContactChange = null;
@@ -1003,7 +1091,7 @@ export class DaemonServer {
1003
1091
  // Guard: don't replace an active proxy during concurrent turn races —
1004
1092
  // another request may have started processing between the isProcessing()
1005
1093
  // check above and the await on ensureActorScopedHistory().
1006
- if (resolvedInterface === "macos" || resolvedInterface === "ios") {
1094
+ if (resolvedInterface === "macos") {
1007
1095
  if (!conversation.isProcessing() || !conversation.hostBashProxy) {
1008
1096
  conversation.setHostBashProxy(
1009
1097
  new HostBashProxy(conversation.getCurrentSender(), (requestId) => {
@@ -1360,8 +1448,9 @@ export class DaemonServer {
1360
1448
  */
1361
1449
  async getConversationForMessages(
1362
1450
  conversationId: string,
1451
+ options?: ConversationCreateOptions,
1363
1452
  ): Promise<Conversation> {
1364
- return this.getOrCreateConversation(conversationId);
1453
+ return this.getOrCreateConversation(conversationId, options);
1365
1454
  }
1366
1455
 
1367
1456
  /**
@@ -1,5 +1,6 @@
1
1
  import * as Sentry from "@sentry/node";
2
2
 
3
+ import type { FilingService } from "../filing/filing-service.js";
3
4
  import type { HeartbeatService } from "../heartbeat/heartbeat-service.js";
4
5
  import type { HookManager } from "../hooks/manager.js";
5
6
  import type { McpServerManager } from "../mcp/manager.js";
@@ -7,6 +8,7 @@ import { getSqlite, resetDb } from "../memory/db.js";
7
8
  import type { QdrantManager } from "../memory/qdrant-manager.js";
8
9
  import type { RuntimeHttpServer } from "../runtime/http-server.js";
9
10
  import { browserManager } from "../tools/browser/browser-manager.js";
11
+ import { cleanupShellOutputTempFiles } from "../tools/shared/shell-output.js";
10
12
  import { getLogger } from "../util/logger.js";
11
13
  import { getEnrichmentService } from "../workspace/commit-message-enrichment-service.js";
12
14
  import type { WorkspaceHeartbeatService } from "../workspace/heartbeat-service.js";
@@ -18,6 +20,7 @@ export interface ShutdownDeps {
18
20
  server: DaemonServer;
19
21
  workspaceHeartbeat: WorkspaceHeartbeatService;
20
22
  heartbeat: HeartbeatService;
23
+ filing: FilingService;
21
24
  hookManager: HookManager;
22
25
  runtimeHttp: RuntimeHttpServer | null;
23
26
  scheduler: { stop(): void };
@@ -51,6 +54,7 @@ export function installShutdownHandlers(deps: ShutdownDeps): void {
51
54
 
52
55
  await deps.workspaceHeartbeat.stop();
53
56
  await deps.heartbeat.stop();
57
+ await deps.filing.stop();
54
58
 
55
59
  try {
56
60
  await deps.hookManager.trigger("daemon-stop", { pid: process.pid });
@@ -105,6 +109,7 @@ export function installShutdownHandlers(deps: ShutdownDeps): void {
105
109
 
106
110
  if (deps.runtimeHttp) await deps.runtimeHttp.stop();
107
111
  await browserManager.closeAllPages();
112
+ cleanupShellOutputTempFiles();
108
113
  deps.scheduler.stop();
109
114
  deps.getMemoryWorker()?.stop();
110
115
 
@@ -10,6 +10,7 @@
10
10
  import { compileApp } from "../bundler/app-compiler.js";
11
11
  import { generateAppIcon } from "../media/app-icon-generator.js";
12
12
  import { getApp, getAppDirPath, isMultifileApp } from "../memory/app-store.js";
13
+ import { findActiveSession } from "../runtime/channel-verification-service.js";
13
14
  import { deliverVerificationSlack } from "../runtime/verification-outbound-actions.js";
14
15
  import { updatePublishedAppDeployment } from "../services/published-app-updater.js";
15
16
  import type { ToolExecutionResult } from "../tools/types.js";
@@ -157,12 +158,32 @@ registerHook(
157
158
  },
158
159
  );
159
160
 
160
- // Trigger compilation + surface refresh + broadcast when an app is refreshed.
161
+ // Trigger surface refresh + broadcast when an app is refreshed.
162
+ // If the executor already compiled (multifile path), skip the redundant
163
+ // recompile and just refresh surfaces / broadcast / deploy directly.
161
164
  registerHook(
162
165
  "app_refresh",
163
- (_name, input, _result, { ctx, broadcastToAllClients }) => {
166
+ (_name, input, result, { ctx, broadcastToAllClients }) => {
164
167
  const appId = input.app_id as string | undefined;
165
- if (appId) {
168
+ if (!appId) return;
169
+
170
+ // executeAppRefresh already compiled multifile apps and included a
171
+ // "compiled" field in the result. Skip the expensive recompile and
172
+ // go straight to surface refresh + broadcast + deploy.
173
+ let alreadyCompiled = false;
174
+ try {
175
+ const parsed = JSON.parse(result.content) as { compiled?: boolean };
176
+ alreadyCompiled = parsed.compiled !== undefined;
177
+ } catch {
178
+ // Result wasn't valid JSON — fall through to handleAppChange.
179
+ }
180
+
181
+ if (alreadyCompiled) {
182
+ const opts = { fileChange: true };
183
+ refreshSurfacesForApp(ctx, appId, opts);
184
+ broadcastToAllClients?.({ type: "app_files_changed", appId });
185
+ void updatePublishedAppDeployment(appId);
186
+ } else {
166
187
  handleAppChange(ctx, appId, broadcastToAllClients, { fileChange: true });
167
188
  }
168
189
  },
@@ -222,18 +243,39 @@ registerHook("bash", (_name, input, result) => {
222
243
  type PendingDm = { userId: string; text: string; assistantId: string };
223
244
  type Parsed = { _pendingSlackDm?: PendingDm };
224
245
 
225
- const dispatch = (parsed: Parsed) => {
246
+ // Returns "delivered" when DM was sent, "rejected" when _pendingSlackDm
247
+ // was found but failed validation, or null when the field was absent.
248
+ const dispatch = (parsed: Parsed): "delivered" | "rejected" | null => {
226
249
  if (parsed._pendingSlackDm) {
227
250
  const { userId, text, assistantId } = parsed._pendingSlackDm;
251
+
252
+ // Validate that an active Slack verification session exists and
253
+ // that the destination matches the userId in the parsed payload.
254
+ const session = findActiveSession("slack");
255
+ if (!session) {
256
+ log.warn(
257
+ { userId, assistantId },
258
+ "Bash hook: no active Slack verification session — ignoring _pendingSlackDm",
259
+ );
260
+ return "rejected";
261
+ }
262
+ if (session.destinationAddress !== userId) {
263
+ log.warn(
264
+ { userId, expected: session.destinationAddress, assistantId },
265
+ "Bash hook: Slack DM userId does not match active session destination — ignoring",
266
+ );
267
+ return "rejected";
268
+ }
269
+
228
270
  deliverVerificationSlack(userId, text, assistantId);
229
- return true;
271
+ return "delivered";
230
272
  }
231
- return false;
273
+ return null;
232
274
  };
233
275
 
234
276
  // Try full content first (handles pretty-printed single-object JSON)
235
277
  try {
236
- if (dispatch(JSON.parse(result.content.trim()) as Parsed)) return;
278
+ if (dispatch(JSON.parse(result.content.trim()) as Parsed) !== null) return;
237
279
  } catch {
238
280
  // Not a single JSON object — fall back to line-by-line for
239
281
  // multi-object output (e.g. cancel + create chained with &&).
@@ -242,7 +284,7 @@ registerHook("bash", (_name, input, result) => {
242
284
  const trimmed = line.trim();
243
285
  if (!trimmed.startsWith("{")) continue;
244
286
  try {
245
- if (dispatch(JSON.parse(trimmed) as Parsed)) return;
287
+ if (dispatch(JSON.parse(trimmed) as Parsed) === "delivered") return;
246
288
  } catch {
247
289
  continue;
248
290
  }
@@ -0,0 +1,148 @@
1
+ /**
2
+ * Transcript formatter for conversation analysis.
3
+ *
4
+ * Builds a markdown transcript of a conversation, including inline
5
+ * subagent conversation sections when present in message metadata.
6
+ */
7
+
8
+ import {
9
+ getConversation,
10
+ getMessages,
11
+ messageMetadataSchema,
12
+ } from "../memory/conversation-crud.js";
13
+ import { truncate } from "../util/truncate.js";
14
+
15
+ interface ContentBlock {
16
+ type: string;
17
+ text?: string;
18
+ name?: string;
19
+ input?: Record<string, unknown>;
20
+ content?: string;
21
+ tool_use_id?: string;
22
+ is_error?: boolean;
23
+ source?: { media_type?: string; filename?: string };
24
+ }
25
+
26
+ function formatTimestamp(ms: number): string {
27
+ return new Date(ms).toISOString().replace("T", " ").slice(0, 19);
28
+ }
29
+
30
+ function extractAnalysisText(blocks: ContentBlock[]): string {
31
+ const parts: string[] = [];
32
+ for (const block of blocks) {
33
+ switch (block.type) {
34
+ case "text":
35
+ if (block.text) parts.push(block.text);
36
+ break;
37
+ case "tool_use":
38
+ parts.push(
39
+ `[Tool: ${block.name}] ${JSON.stringify(block.input ?? {})}`,
40
+ );
41
+ break;
42
+ case "tool_result":
43
+ if (block.is_error) {
44
+ parts.push(`[Error: ${block.content ?? ""}]`);
45
+ } else {
46
+ parts.push(`[Result: ${truncate(block.content ?? "", 500)}]`);
47
+ }
48
+ break;
49
+ case "server_tool_use":
50
+ parts.push(`[Web search: ${block.name ?? "web_search"}]`);
51
+ break;
52
+ case "web_search_tool_result":
53
+ parts.push("[Web search results]");
54
+ break;
55
+ case "image":
56
+ parts.push("[Image attachment]");
57
+ break;
58
+ case "file":
59
+ parts.push(`[File: ${block.source?.filename ?? "unknown"}]`);
60
+ break;
61
+ case "thinking":
62
+ case "redacted_thinking":
63
+ // Skip internal model reasoning blocks
64
+ break;
65
+ }
66
+ }
67
+ return parts.join("\n");
68
+ }
69
+
70
+ function formatRole(role: string): string {
71
+ return role === "user" ? "User" : "Assistant";
72
+ }
73
+
74
+ function formatSubagentMessages(msgs: ReturnType<typeof getMessages>): string {
75
+ const lines: string[] = [];
76
+ for (const msg of msgs) {
77
+ const role = formatRole(msg.role);
78
+ const time = formatTimestamp(msg.createdAt);
79
+ const content = parseContent(msg.content);
80
+ const text = extractAnalysisText(content);
81
+ if (text) {
82
+ lines.push(`> **${role}** (${time})`);
83
+ for (const line of text.split("\n")) {
84
+ lines.push(`> ${line}`);
85
+ }
86
+ lines.push(">");
87
+ }
88
+ }
89
+ return lines.join("\n");
90
+ }
91
+
92
+ function parseContent(raw: string): ContentBlock[] {
93
+ try {
94
+ return JSON.parse(raw) as ContentBlock[];
95
+ } catch {
96
+ return [{ type: "text", text: raw }];
97
+ }
98
+ }
99
+
100
+ export function buildAnalysisTranscript(conversationId: string): string {
101
+ const conversation = getConversation(conversationId);
102
+ if (!conversation) {
103
+ return `# Conversation not found: ${conversationId}\n`;
104
+ }
105
+
106
+ const allMessages = getMessages(conversationId);
107
+ const title = conversation.title ?? "Untitled";
108
+ const lines: string[] = [];
109
+
110
+ lines.push(`# Conversation: ${title}`);
111
+ lines.push(`Created: ${formatTimestamp(conversation.createdAt)}`);
112
+ lines.push("");
113
+
114
+ for (const msg of allMessages) {
115
+ const role = formatRole(msg.role);
116
+ const time = formatTimestamp(msg.createdAt);
117
+ const content = parseContent(msg.content);
118
+ const text = extractAnalysisText(content);
119
+
120
+ lines.push(`## ${role} (${time})`);
121
+ lines.push(text);
122
+ lines.push("");
123
+
124
+ // Check for subagent notifications in metadata
125
+ if (msg.metadata) {
126
+ try {
127
+ const parsed = messageMetadataSchema.safeParse(JSON.parse(msg.metadata));
128
+ if (parsed.success && parsed.data.subagentNotification) {
129
+ const notif = parsed.data.subagentNotification;
130
+ if (
131
+ (notif.status === "completed" || notif.status === "failed" || notif.status === "aborted") &&
132
+ notif.conversationId
133
+ ) {
134
+ const subMessages = getMessages(notif.conversationId);
135
+ lines.push(`### Subagent: ${notif.label} (${notif.status})`);
136
+ lines.push("");
137
+ lines.push(formatSubagentMessages(subMessages));
138
+ lines.push("");
139
+ }
140
+ }
141
+ } catch {
142
+ // Skip unparseable metadata
143
+ }
144
+ }
145
+ }
146
+
147
+ return lines.join("\n");
148
+ }