@vellumai/assistant 0.8.0 → 0.8.2

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 (991) hide show
  1. package/AGENTS.md +11 -0
  2. package/ARCHITECTURE.md +2 -7
  3. package/Dockerfile +80 -5
  4. package/README.md +2 -2
  5. package/bun.lock +11 -1
  6. package/docker-entrypoint.sh +21 -0
  7. package/docker-init-apt-root.sh +94 -0
  8. package/docker-kata-apt-env.sh +39 -0
  9. package/docs/plugins.md +88 -47
  10. package/docs/skills.md +9 -7
  11. package/eslint-rules/__tests__/cli-no-daemon-internals.test.ts +420 -0
  12. package/eslint-rules/cli-no-daemon-internals.js +283 -0
  13. package/eslint.config.mjs +12 -0
  14. package/examples/plugins/echo/README.md +27 -27
  15. package/examples/plugins/echo/package.json +3 -0
  16. package/examples/plugins/echo/register.ts +31 -31
  17. package/knip.json +2 -1
  18. package/node_modules/@vellumai/skill-host-contracts/src/client.ts +10 -1
  19. package/node_modules/@vellumai/slack-text/src/index.test.ts +114 -14
  20. package/node_modules/@vellumai/slack-text/src/index.ts +82 -18
  21. package/openapi.yaml +4462 -991
  22. package/package.json +5 -1
  23. package/scripts/generate-openapi.ts +135 -14
  24. package/scripts/sync-llm-catalog.ts +165 -0
  25. package/scripts/sync-web-search-catalog.ts +129 -0
  26. package/src/__tests__/actor-trust-resolver-address-fallback.test.ts +169 -0
  27. package/src/__tests__/agent-image-optimize.test.ts +11 -3
  28. package/src/__tests__/agent-loop-override-profile.test.ts +26 -1
  29. package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +131 -0
  30. package/src/__tests__/anthropic-provider.test.ts +137 -2
  31. package/src/__tests__/app-builder-tool-scripts.test.ts +9 -3
  32. package/src/__tests__/app-control-flow.test.ts +7 -0
  33. package/src/__tests__/app-executors.test.ts +220 -4
  34. package/src/__tests__/assistant-events-sse-shed.test.ts +232 -0
  35. package/src/__tests__/auto-analysis-end-to-end.test.ts +35 -0
  36. package/src/__tests__/avatar-identity-sync.test.ts +87 -0
  37. package/src/__tests__/background-workers-disk-pressure.test.ts +11 -22
  38. package/src/__tests__/btw-routes.test.ts +1 -0
  39. package/src/__tests__/bundled-asset.test.ts +6 -6
  40. package/src/__tests__/call-site-routing-provider.test.ts +172 -45
  41. package/src/__tests__/cancel-resolves-conversation-key.test.ts +44 -3
  42. package/src/__tests__/channel-availability-routes.test.ts +206 -0
  43. package/src/__tests__/channel-delivery-store.test.ts +289 -1
  44. package/src/__tests__/channel-policy.test.ts +12 -0
  45. package/src/__tests__/checker.test.ts +89 -0
  46. package/src/__tests__/circuit-breaker-pipeline.test.ts +0 -1
  47. package/src/__tests__/clawhub.test.ts +75 -16
  48. package/src/__tests__/cli-memory-v2-reembed-skills.test.ts +35 -7
  49. package/src/__tests__/compact-event-conversation-id-guard.test.ts +33 -5
  50. package/src/__tests__/compaction-strip-metadata-clear.test.ts +26 -1
  51. package/src/__tests__/compactor-tail-resolution.test.ts +41 -0
  52. package/src/__tests__/config-loader-backfill.test.ts +526 -102
  53. package/src/__tests__/config-loader-corrupt.test.ts +68 -0
  54. package/src/__tests__/config-loader-platform-defaults.test.ts +77 -23
  55. package/src/__tests__/config-schema-cmd.test.ts +63 -29
  56. package/src/__tests__/config-schema.test.ts +35 -3
  57. package/src/__tests__/config-set-platform-guard.test.ts +75 -152
  58. package/src/__tests__/config-set-route.test.ts +278 -0
  59. package/src/__tests__/config-sounds-sync.test.ts +97 -0
  60. package/src/__tests__/config-watcher-skill-reseed.test.ts +453 -0
  61. package/src/__tests__/config-watcher.test.ts +6 -0
  62. package/src/__tests__/contacts-tools.test.ts +51 -199
  63. package/src/__tests__/context-search-agent-protocol.test.ts +21 -2
  64. package/src/__tests__/context-search-agent-runner.test.ts +22 -138
  65. package/src/__tests__/context-search-conversations-source.test.ts +159 -18
  66. package/src/__tests__/context-search-fanout.test.ts +20 -157
  67. package/src/__tests__/context-search-memory-v2-source.test.ts +3 -4
  68. package/src/__tests__/context-search-types.test.ts +7 -2
  69. package/src/__tests__/context-search-workspace-source.test.ts +7 -0
  70. package/src/__tests__/context-token-estimator.test.ts +1 -0
  71. package/src/__tests__/conversation-abort-tool-results.test.ts +4 -1
  72. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +1 -0
  73. package/src/__tests__/conversation-agent-loop-overflow.test.ts +93 -92
  74. package/src/__tests__/conversation-agent-loop.test.ts +2 -0
  75. package/src/__tests__/conversation-crud-inference-profile.test.ts +100 -0
  76. package/src/__tests__/conversation-error.test.ts +80 -3
  77. package/src/__tests__/conversation-fork-crud.test.ts +323 -1
  78. package/src/__tests__/conversation-inference-profile-route.test.ts +54 -18
  79. package/src/__tests__/conversation-init.benchmark.test.ts +1 -0
  80. package/src/__tests__/conversation-lifecycle.test.ts +297 -0
  81. package/src/__tests__/conversation-message-sync-tags.test.ts +97 -0
  82. package/src/__tests__/conversation-pairing.test.ts +54 -0
  83. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +100 -1
  84. package/src/__tests__/conversation-process-callsite.test.ts +25 -2
  85. package/src/__tests__/conversation-provider-retry-repair.test.ts +5 -1
  86. package/src/__tests__/conversation-queue.test.ts +4 -1
  87. package/src/__tests__/conversation-runtime-assembly.test.ts +80 -13
  88. package/src/__tests__/conversation-slash-commands.test.ts +194 -2
  89. package/src/__tests__/conversation-slash-queue.test.ts +59 -1
  90. package/src/__tests__/conversation-slash-unknown.test.ts +4 -1
  91. package/src/__tests__/conversation-surfaces-app-control.test.ts +323 -3
  92. package/src/__tests__/conversation-surfaces-table-action.test.ts +360 -0
  93. package/src/__tests__/conversation-sync-tags.test.ts +235 -0
  94. package/src/__tests__/conversation-workspace-injection.test.ts +5 -1
  95. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +5 -1
  96. package/src/__tests__/credential-security-invariants.test.ts +8 -8
  97. package/src/__tests__/daemon-credential-client.test.ts +56 -1
  98. package/src/__tests__/db-activation-state-fk-cascade.test.ts +132 -0
  99. package/src/__tests__/db-conversation-inference-profile-migration.test.ts +37 -0
  100. package/src/__tests__/db-memory-graph-event-date-repair.test.ts +43 -20
  101. package/src/__tests__/db-proxy-transaction.test.ts +206 -0
  102. package/src/__tests__/db-slack-external-content-normalization.test.ts +301 -0
  103. package/src/__tests__/delete-managed-skill-tool.test.ts +55 -13
  104. package/src/__tests__/disk-pressure-tools.test.ts +1 -0
  105. package/src/__tests__/dm-backfill.test.ts +121 -10
  106. package/src/__tests__/document-tool-security.test.ts +258 -0
  107. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +0 -1
  108. package/src/__tests__/edit-propagation.test.ts +33 -0
  109. package/src/__tests__/empty-response-pipeline.test.ts +0 -4
  110. package/src/__tests__/external-plugin-loader.test.ts +482 -0
  111. package/src/__tests__/filing-service.test.ts +163 -3
  112. package/src/__tests__/fixtures/mock-chrome-extension.ts +5 -0
  113. package/src/__tests__/gateway-only-guard.test.ts +0 -1
  114. package/src/__tests__/get-skill-detail-audit.test.ts +0 -4
  115. package/src/__tests__/graph-extraction-event-date.test.ts +34 -0
  116. package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +42 -69
  117. package/src/__tests__/heartbeat-disk-pressure.test.ts +21 -8
  118. package/src/__tests__/heartbeat-service.test.ts +50 -233
  119. package/src/__tests__/helpers/tar-fixtures.ts +39 -0
  120. package/src/__tests__/helpers/wait-for.ts +21 -0
  121. package/src/__tests__/history-repair-pipeline.test.ts +0 -3
  122. package/src/__tests__/history-repair.test.ts +162 -0
  123. package/src/__tests__/host-app-control-proxy.test.ts +365 -1
  124. package/src/__tests__/host-app-control-routes.test.ts +247 -1
  125. package/src/__tests__/host-browser-proxy.test.ts +416 -20
  126. package/src/__tests__/host-browser-routes.test.ts +325 -33
  127. package/src/__tests__/host-proxy-preactivation.test.ts +211 -0
  128. package/src/__tests__/image-credentials.test.ts +1 -1
  129. package/src/__tests__/inbound-slack-persistence.test.ts +2 -0
  130. package/src/__tests__/inference-no-mode-boot-e2e.test.ts +246 -0
  131. package/src/__tests__/inference-profile-reaper.test.ts +156 -0
  132. package/src/__tests__/inference-profile-session-handler.test.ts +410 -0
  133. package/src/__tests__/inference-profile-session-ipc.test.ts +248 -0
  134. package/src/__tests__/injector-chain.test.ts +10 -8
  135. package/src/__tests__/inline-skill-load-permissions.test.ts +6 -1
  136. package/src/__tests__/install-skill-routing.test.ts +157 -39
  137. package/src/__tests__/lifecycle-memory-v2-seed.test.ts +107 -3
  138. package/src/__tests__/list-messages-page-latest.test.ts +55 -0
  139. package/src/__tests__/llm-call-pipeline.test.ts +0 -3
  140. package/src/__tests__/llm-callsite-catalog.test.ts +20 -1
  141. package/src/__tests__/llm-catalog-parity.test.ts +190 -2
  142. package/src/__tests__/llm-request-log-source-clickhouse.test.ts +222 -0
  143. package/src/__tests__/llm-request-log-source-factory.test.ts +100 -0
  144. package/src/__tests__/llm-resolver.test.ts +46 -0
  145. package/src/__tests__/llm-usage-store.test.ts +114 -0
  146. package/src/__tests__/managed-profile-guard.test.ts +145 -14
  147. package/src/__tests__/managed-skill-lifecycle.test.ts +109 -18
  148. package/src/__tests__/managed-store.test.ts +84 -192
  149. package/src/__tests__/mcp-auth-routes.test.ts +1 -0
  150. package/src/__tests__/mcp-cli.test.ts +182 -220
  151. package/src/__tests__/mcp-health-check.test.ts +56 -27
  152. package/src/__tests__/media-generate-image.test.ts +1 -1
  153. package/src/__tests__/memory-jobs-worker-lanes.test.ts +18 -11
  154. package/src/__tests__/memory-retrieval-pipeline.test.ts +0 -2
  155. package/src/__tests__/message-complete-display-id.test.ts +175 -0
  156. package/src/__tests__/messages-after-tiebreaker.test.ts +122 -0
  157. package/src/__tests__/notification-platform-adapter.test.ts +229 -0
  158. package/src/__tests__/oauth-cli.test.ts +38 -2009
  159. package/src/__tests__/oauth-commands-routes.test.ts +863 -0
  160. package/src/__tests__/oauth-connect-routes.test.ts +174 -11
  161. package/src/__tests__/oauth-provider-profiles.test.ts +9 -0
  162. package/src/__tests__/oauth-providers-routes.test.ts +14 -10
  163. package/src/__tests__/openai-provider.test.ts +24 -0
  164. package/src/__tests__/openai-responses-cutover-guard.test.ts +48 -19
  165. package/src/__tests__/openai-responses-provider.test.ts +17 -0
  166. package/src/__tests__/overflow-reduce-pipeline.test.ts +0 -2
  167. package/src/__tests__/persistence-pipeline.test.ts +0 -2
  168. package/src/__tests__/{managed-proxy-context.test.ts → platform-proxy-context.test.ts} +1 -1
  169. package/src/__tests__/platform.test.ts +2 -0
  170. package/src/__tests__/plugin-api-shim.test.ts +125 -0
  171. package/src/__tests__/plugin-bootstrap.test.ts +41 -38
  172. package/src/__tests__/plugin-external-api.test.ts +68 -0
  173. package/src/__tests__/plugin-registry.test.ts +0 -77
  174. package/src/__tests__/plugin-route-contribution.test.ts +31 -4
  175. package/src/__tests__/plugin-skill-contribution.test.ts +0 -2
  176. package/src/__tests__/plugin-tool-contribution.test.ts +47 -18
  177. package/src/__tests__/plugin-types.test.ts +15 -23
  178. package/src/__tests__/process-message-background-slack.test.ts +53 -0
  179. package/src/__tests__/process-message-display-content.test.ts +421 -0
  180. package/src/__tests__/profile-entry-status.test.ts +43 -0
  181. package/src/__tests__/provider-catalog-visibility.test.ts +142 -0
  182. package/src/__tests__/provider-error-scenarios.test.ts +111 -0
  183. package/src/__tests__/{provider-managed-proxy-integration.test.ts → provider-platform-proxy-integration.test.ts} +20 -12
  184. package/src/__tests__/provider-registry-ollama.test.ts +12 -4
  185. package/src/__tests__/provider-send-message-override-profile.test.ts +10 -4
  186. package/src/__tests__/relay-server.test.ts +118 -0
  187. package/src/__tests__/retry-thinking-tool-choice.test.ts +15 -0
  188. package/src/__tests__/scaffold-managed-skill-tool.test.ts +65 -13
  189. package/src/__tests__/schedule-retry.test.ts +56 -4
  190. package/src/__tests__/schedule-routes.test.ts +151 -0
  191. package/src/__tests__/schedule-store.test.ts +94 -0
  192. package/src/__tests__/scheduler-disk-pressure.test.ts +0 -4
  193. package/src/__tests__/scheduler-recurrence.test.ts +87 -34
  194. package/src/__tests__/scheduler-reuse-conversation.test.ts +208 -5
  195. package/src/__tests__/scheduler-wake.test.ts +0 -63
  196. package/src/__tests__/schema-transforms.test.ts +20 -0
  197. package/src/__tests__/search-skills-unified.test.ts +0 -5
  198. package/src/__tests__/secret-allowlist.test.ts +1 -0
  199. package/src/__tests__/{secret-routes-managed-proxy.test.ts → secret-routes-platform-proxy.test.ts} +12 -4
  200. package/src/__tests__/server-history-render.test.ts +43 -0
  201. package/src/__tests__/shell-credential-ref.test.ts +95 -3
  202. package/src/__tests__/shell-tool-proxy-mode.test.ts +14 -0
  203. package/src/__tests__/skill-load-feature-flag.test.ts +1 -12
  204. package/src/__tests__/skill-load-tool.test.ts +29 -93
  205. package/src/__tests__/skill-memory.test.ts +23 -3
  206. package/src/__tests__/skills-file-content-endpoint.test.ts +9 -38
  207. package/src/__tests__/skills-files-catalog-fallback.test.ts +0 -3
  208. package/src/__tests__/skills-install-extract.test.ts +49 -38
  209. package/src/__tests__/skills-install-staging.test.ts +159 -0
  210. package/src/__tests__/skills-uninstall.test.ts +9 -41
  211. package/src/__tests__/skills.test.ts +51 -58
  212. package/src/__tests__/slack-channel-config.test.ts +9 -0
  213. package/src/__tests__/subagent-call-site-routing.test.ts +78 -16
  214. package/src/__tests__/subagent-tool-filtering.test.ts +50 -0
  215. package/src/__tests__/suggestion-routes.test.ts +3 -3
  216. package/src/__tests__/sync-message-contract.test.ts +63 -0
  217. package/src/__tests__/system-prompt.test.ts +737 -63
  218. package/src/__tests__/task-scheduler.test.ts +88 -23
  219. package/src/__tests__/terminal-tools.test.ts +28 -1
  220. package/src/__tests__/thread-backfill.test.ts +557 -27
  221. package/src/__tests__/title-generate-pipeline.test.ts +0 -13
  222. package/src/__tests__/token-estimate-pipeline.test.ts +0 -3
  223. package/src/__tests__/tool-error-pipeline.test.ts +0 -3
  224. package/src/__tests__/tool-execute-pipeline.test.ts +0 -5
  225. package/src/__tests__/tool-executor-lifecycle-events.test.ts +1 -1
  226. package/src/__tests__/tool-executor.test.ts +16 -4
  227. package/src/__tests__/tool-result-truncate-pipeline.test.ts +0 -12
  228. package/src/__tests__/turn-events-store.test.ts +256 -0
  229. package/src/__tests__/twilio-routes.test.ts +4 -0
  230. package/src/__tests__/update-bulletin-job.test.ts +96 -193
  231. package/src/__tests__/usage-cli.test.ts +11 -73
  232. package/src/__tests__/user-plugin-loader.test.ts +143 -5
  233. package/src/__tests__/vercel-config.test.ts +168 -0
  234. package/src/__tests__/voice-session-bridge.test.ts +198 -0
  235. package/src/__tests__/web-search-catalog-parity.test.ts +108 -0
  236. package/src/__tests__/web-search.test.ts +303 -2
  237. package/src/__tests__/workspace-migration-039-drop-legacy-llm-keys.test.ts +1 -21
  238. package/src/__tests__/workspace-migration-057-repair-stale-gemini-model-ids.test.ts +170 -0
  239. package/src/__tests__/workspace-migration-069-seed-onboarding-threads.test.ts +53 -20
  240. package/src/__tests__/workspace-migration-072-seed-reply-suggestion-callsite.test.ts +241 -0
  241. package/src/__tests__/workspace-migration-073-repair-recall-callsite-empty-profile.test.ts +153 -0
  242. package/src/__tests__/workspace-migration-076-drop-services-inference-mode.test.ts +211 -0
  243. package/src/__tests__/workspace-migration-077-seed-memory-router-callsite.test.ts +174 -0
  244. package/src/__tests__/workspace-migration-079-home-feed-notification-only.test.ts +323 -0
  245. package/src/__tests__/workspace-migration-080-restrict-vercel-api-token-metadata.test.ts +299 -0
  246. package/src/__tests__/workspace-migration-081-backfill-bash-allowed-tools.test.ts +410 -0
  247. package/src/__tests__/workspace-migration-082-backfill-managed-profile-labels.test.ts +268 -0
  248. package/src/__tests__/workspace-migration-085-memory-v2-bm25-b-reembed-disabled-v2-pages.test.ts +220 -0
  249. package/src/__tests__/workspace-migration-086-revert-stale-gemini-mis-rewrites.test.ts +269 -0
  250. package/src/__tests__/workspace-migration-remove-legacy-skills-index.test.ts +309 -0
  251. package/src/__tests__/workspace-migration-unify-llm-callsite-configs.test.ts +3 -3
  252. package/src/__tests__/workspace-migrations-runner.test.ts +111 -3
  253. package/src/__tests__/workspace-release-notes-feature-flag-guard.test.ts +115 -0
  254. package/src/acp/__tests__/helpers/which-stub.ts +4 -2
  255. package/src/acp/resolve-agent.test.ts +25 -0
  256. package/src/acp/resolve-agent.ts +13 -2
  257. package/src/acp/session-manager.ts +14 -0
  258. package/src/agent/image-optimize.ts +13 -5
  259. package/src/approvals/guardian-request-resolvers.ts +32 -87
  260. package/src/calls/relay-server.ts +35 -0
  261. package/src/calls/relay-setup-router.ts +36 -0
  262. package/src/calls/types.ts +1 -0
  263. package/src/calls/voice-session-bridge.ts +74 -36
  264. package/src/channels/config.ts +14 -1
  265. package/src/channels/types.ts +109 -0
  266. package/src/cli/AGENTS.md +164 -4
  267. package/src/cli/__tests__/notifications.test.ts +54 -0
  268. package/src/cli/__tests__/unknown-command.test.ts +24 -0
  269. package/src/cli/commands/__tests__/avatar.test.ts +540 -0
  270. package/src/cli/commands/__tests__/backup.test.ts +236 -776
  271. package/src/cli/commands/__tests__/cache.test.ts +1 -1
  272. package/src/cli/commands/__tests__/changelog.test.ts +578 -0
  273. package/src/cli/commands/__tests__/channel-verification-sessions.test.ts +503 -0
  274. package/src/cli/commands/__tests__/conversations-import.test.ts +515 -0
  275. package/src/cli/commands/__tests__/domain-register.test.ts +140 -167
  276. package/src/cli/commands/__tests__/domain-status.test.ts +137 -76
  277. package/src/cli/commands/__tests__/email-attachment.test.ts +314 -337
  278. package/src/cli/commands/__tests__/email-core.test.ts +579 -0
  279. package/src/cli/commands/__tests__/image-generation.test.ts +87 -824
  280. package/src/cli/commands/__tests__/inference-send.test.ts +30 -266
  281. package/src/cli/commands/__tests__/inference-session.test.ts +423 -0
  282. package/src/cli/commands/__tests__/memory-v2.test.ts +81 -110
  283. package/src/cli/commands/__tests__/schedules.test.ts +491 -0
  284. package/src/cli/commands/__tests__/skills.test.ts +563 -0
  285. package/src/cli/commands/__tests__/status.test.ts +249 -0
  286. package/src/cli/commands/__tests__/stt.test.ts +320 -0
  287. package/src/cli/commands/__tests__/tts-synthesize.test.ts +4 -603
  288. package/src/cli/commands/__tests__/tts.test.ts +321 -0
  289. package/src/cli/commands/__tests__/webhooks.test.ts +86 -511
  290. package/src/cli/commands/attachment.ts +8 -3
  291. package/src/cli/commands/audit.ts +95 -64
  292. package/src/cli/commands/auth.ts +61 -58
  293. package/src/cli/commands/avatar.ts +276 -390
  294. package/src/cli/commands/backup.ts +409 -505
  295. package/src/cli/commands/bash.ts +9 -5
  296. package/src/cli/commands/browser.ts +28 -9
  297. package/src/cli/commands/cache.ts +9 -4
  298. package/src/cli/commands/changelog.ts +478 -0
  299. package/src/cli/commands/channel-verification-sessions.ts +238 -317
  300. package/src/cli/commands/clients.ts +8 -3
  301. package/src/cli/commands/completions.ts +9 -9
  302. package/src/cli/commands/config.ts +102 -72
  303. package/src/cli/commands/contacts.ts +575 -696
  304. package/src/cli/commands/conversations-defer.ts +17 -69
  305. package/src/cli/commands/conversations-import.ts +90 -253
  306. package/src/cli/commands/conversations.ts +429 -434
  307. package/src/cli/commands/credential-execution.ts +9 -6
  308. package/src/cli/commands/credentials.ts +456 -736
  309. package/src/cli/commands/default-action.ts +10 -53
  310. package/src/cli/commands/domain.ts +128 -206
  311. package/src/cli/commands/email.ts +606 -794
  312. package/src/cli/commands/gateway.ts +8 -1
  313. package/src/cli/commands/image-generation.ts +157 -205
  314. package/src/cli/commands/inference-providers.ts +352 -0
  315. package/src/cli/commands/inference-session.ts +415 -0
  316. package/src/cli/commands/inference.ts +87 -65
  317. package/src/cli/commands/keys.ts +8 -3
  318. package/src/cli/commands/mcp.ts +103 -287
  319. package/src/cli/commands/memory-v2.ts +162 -516
  320. package/src/cli/commands/notifications.ts +342 -304
  321. package/src/cli/commands/oauth/apps.ts +292 -261
  322. package/src/cli/commands/oauth/connect.ts +176 -297
  323. package/src/cli/commands/oauth/disconnect.ts +16 -215
  324. package/src/cli/commands/oauth/index.ts +49 -45
  325. package/src/cli/commands/oauth/mode.ts +43 -199
  326. package/src/cli/commands/oauth/ping.ts +17 -125
  327. package/src/cli/commands/oauth/providers.ts +732 -921
  328. package/src/cli/commands/oauth/request.ts +60 -350
  329. package/src/cli/commands/oauth/shared.ts +11 -121
  330. package/src/cli/commands/oauth/status.ts +31 -121
  331. package/src/cli/commands/oauth/token.ts +13 -55
  332. package/src/cli/commands/pending.ts +19 -10
  333. package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +133 -183
  334. package/src/cli/commands/platform/__tests__/connect.test.ts +66 -181
  335. package/src/cli/commands/platform/__tests__/disconnect.test.ts +71 -227
  336. package/src/cli/commands/platform/__tests__/status.test.ts +169 -287
  337. package/src/cli/commands/platform/connect.ts +16 -80
  338. package/src/cli/commands/platform/disconnect.ts +14 -112
  339. package/src/cli/commands/platform/index.ts +177 -246
  340. package/src/cli/commands/plugins.ts +185 -0
  341. package/src/cli/commands/routes.ts +153 -336
  342. package/src/cli/commands/schedules.ts +391 -0
  343. package/src/cli/commands/sequence.ts +316 -360
  344. package/src/cli/commands/skills.ts +449 -671
  345. package/src/cli/commands/status.ts +58 -37
  346. package/src/cli/commands/stt.ts +94 -262
  347. package/src/cli/commands/task.ts +14 -40
  348. package/src/cli/commands/telemetry.ts +40 -0
  349. package/src/cli/commands/trust.ts +8 -3
  350. package/src/cli/commands/tts.ts +162 -167
  351. package/src/cli/commands/ui.ts +35 -42
  352. package/src/cli/commands/usage.ts +188 -126
  353. package/src/cli/commands/watchers.ts +8 -3
  354. package/src/cli/commands/webhooks.ts +99 -193
  355. package/src/cli/lib/__tests__/cli-colors.test.ts +48 -0
  356. package/src/cli/lib/__tests__/confirm-prompt.test.ts +159 -0
  357. package/src/cli/lib/__tests__/install-from-github.test.ts +355 -0
  358. package/src/cli/lib/__tests__/list-installed-plugins.test.ts +154 -0
  359. package/src/cli/lib/__tests__/register-command.test.ts +85 -0
  360. package/src/cli/lib/__tests__/uninstall-plugin.test.ts +124 -0
  361. package/src/cli/lib/__tests__/unknown-command.test.ts +106 -0
  362. package/src/cli/lib/cli-colors.ts +12 -0
  363. package/src/cli/lib/confirm-prompt.ts +79 -0
  364. package/src/cli/lib/daemon-credential-client.ts +4 -5
  365. package/src/cli/lib/install-from-github.ts +304 -0
  366. package/src/cli/lib/list-installed-plugins.ts +137 -0
  367. package/src/cli/lib/nested-value.ts +44 -0
  368. package/src/cli/lib/open-browser.ts +36 -0
  369. package/src/cli/lib/register-command.ts +19 -0
  370. package/src/cli/lib/time-ago.ts +34 -0
  371. package/src/cli/lib/uninstall-plugin.ts +82 -0
  372. package/src/cli/lib/unknown-command.ts +111 -0
  373. package/src/cli/program.ts +40 -6
  374. package/src/cli/utils/__tests__/conversation-id.test.ts +66 -0
  375. package/src/cli/utils/__tests__/parse-duration.test.ts +49 -0
  376. package/src/cli/utils/conversation-id.ts +30 -0
  377. package/src/cli/utils/parse-duration.ts +41 -0
  378. package/src/config/acp-defaults.test.ts +5 -1
  379. package/src/config/acp-defaults.ts +11 -4
  380. package/src/config/bundled-skills/acp/TOOLS.json +2 -2
  381. package/src/config/bundled-skills/app-builder/SKILL.md +23 -21
  382. package/src/config/bundled-skills/app-builder/TOOLS.json +7 -0
  383. package/src/config/bundled-skills/app-control/TOOLS.json +32 -0
  384. package/src/config/bundled-skills/computer-use/TOOLS.json +15 -52
  385. package/src/config/bundled-skills/contacts/SKILL.md +12 -45
  386. package/src/config/bundled-skills/contacts/TOOLS.json +0 -57
  387. package/src/config/bundled-skills/document/SKILL.md +23 -3
  388. package/src/config/bundled-skills/document/TOOLS.json +53 -0
  389. package/src/config/bundled-skills/document/tools/document-delete.ts +12 -0
  390. package/src/config/bundled-skills/document/tools/document-list.ts +12 -0
  391. package/src/config/bundled-skills/document/tools/document-read.ts +12 -0
  392. package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +0 -12
  393. package/src/config/bundled-skills/messaging/tools/messaging-send.ts +0 -58
  394. package/src/config/bundled-skills/skill-management/SKILL.md +2 -2
  395. package/src/config/bundled-skills/skill-management/TOOLS.json +7 -7
  396. package/src/config/bundled-tool-registry.ts +6 -2
  397. package/src/config/feature-flag-registry.json +57 -1
  398. package/src/config/llm-resolver.ts +16 -1
  399. package/src/config/loader.ts +140 -52
  400. package/src/config/raw-config-utils.ts +2 -30
  401. package/src/config/schema.ts +8 -7
  402. package/src/config/schemas/__tests__/llm-request-logs.test.ts +36 -0
  403. package/src/config/schemas/__tests__/memory-v2.test.ts +49 -0
  404. package/src/config/schemas/call-site-catalog.ts +29 -7
  405. package/src/config/schemas/channels.ts +8 -0
  406. package/src/config/schemas/compaction.ts +28 -0
  407. package/src/config/schemas/heartbeat.ts +9 -0
  408. package/src/config/schemas/llm-request-logs.ts +81 -0
  409. package/src/config/schemas/llm.ts +55 -2
  410. package/src/config/schemas/memory-retrieval.ts +18 -0
  411. package/src/config/schemas/memory-retrospective.ts +48 -0
  412. package/src/config/schemas/memory-v2.ts +32 -1
  413. package/src/config/schemas/memory.ts +4 -0
  414. package/src/config/schemas/services.ts +15 -12
  415. package/src/config/schemas/tools.ts +14 -0
  416. package/src/config/seed-inference-profiles.ts +195 -134
  417. package/src/config/skills.ts +3 -96
  418. package/src/contacts/contact-store.ts +0 -61
  419. package/src/context/compactor.ts +1047 -0
  420. package/src/context/token-estimator.ts +2 -2
  421. package/src/context/window-manager.ts +197 -1334
  422. package/src/credential-execution/managed-catalog.ts +37 -0
  423. package/src/credential-health/credential-health-service.ts +280 -19
  424. package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +113 -0
  425. package/src/daemon/__tests__/conversation-tool-setup-exclude.test.ts +138 -0
  426. package/src/daemon/__tests__/conversation-tool-setup.test.ts +183 -4
  427. package/src/daemon/__tests__/daemon-skill-host.test.ts +10 -4
  428. package/src/daemon/approval-generators.ts +26 -30
  429. package/src/daemon/config-watcher.ts +94 -29
  430. package/src/daemon/conversation-agent-loop-handlers.ts +24 -0
  431. package/src/daemon/conversation-agent-loop.ts +293 -103
  432. package/src/daemon/conversation-error.ts +188 -33
  433. package/src/daemon/conversation-lifecycle.ts +80 -26
  434. package/src/daemon/conversation-messaging.ts +25 -6
  435. package/src/daemon/conversation-process.ts +85 -31
  436. package/src/daemon/conversation-runtime-assembly.ts +30 -6
  437. package/src/daemon/conversation-slash.ts +184 -25
  438. package/src/daemon/conversation-store.ts +24 -10
  439. package/src/daemon/conversation-surfaces.ts +76 -12
  440. package/src/daemon/conversation-tool-setup.ts +63 -21
  441. package/src/daemon/conversation.ts +81 -10
  442. package/src/daemon/external-plugins-bootstrap.ts +231 -185
  443. package/src/daemon/first-greeting.ts +22 -2
  444. package/src/daemon/guardian-action-generators.ts +7 -22
  445. package/src/daemon/handlers/config-model.ts +13 -130
  446. package/src/daemon/handlers/config-slack-channel.ts +25 -10
  447. package/src/daemon/handlers/config-vercel.ts +3 -1
  448. package/src/daemon/handlers/shared.ts +14 -5
  449. package/src/daemon/handlers/skills.ts +166 -84
  450. package/src/daemon/history-repair.ts +61 -7
  451. package/src/daemon/host-app-control-proxy.ts +129 -29
  452. package/src/daemon/host-bash-proxy.ts +85 -158
  453. package/src/daemon/host-browser-proxy.ts +96 -35
  454. package/src/daemon/host-proxy-base.ts +13 -1
  455. package/src/daemon/host-proxy-preactivation.ts +25 -1
  456. package/src/daemon/identity-helpers.ts +19 -0
  457. package/src/daemon/lifecycle.ts +79 -70
  458. package/src/daemon/meet-host-supervisor.ts +20 -19
  459. package/src/daemon/memory-v2-startup.ts +58 -2
  460. package/src/daemon/message-protocol.ts +7 -0
  461. package/src/daemon/message-types/bookmarks.ts +18 -0
  462. package/src/daemon/message-types/conversations.ts +37 -9
  463. package/src/daemon/message-types/messages.ts +70 -1
  464. package/src/daemon/message-types/subagents.ts +1 -0
  465. package/src/daemon/message-types/sync.ts +61 -0
  466. package/src/daemon/pkb-reminder-builder.test.ts +54 -13
  467. package/src/daemon/pkb-reminder-builder.ts +21 -7
  468. package/src/daemon/plugin-source-watcher.ts +146 -0
  469. package/src/daemon/process-message.ts +77 -26
  470. package/src/daemon/server.ts +34 -20
  471. package/src/daemon/shutdown-handlers.ts +0 -2
  472. package/src/daemon/skill-memory-refresh.ts +29 -0
  473. package/src/daemon/tool-setup-types.ts +9 -0
  474. package/src/daemon/tool-side-effects.ts +6 -4
  475. package/src/daemon/wake-target-adapter.ts +11 -0
  476. package/src/documents/document-store.ts +221 -3
  477. package/src/embedded/plugin-api.ts +40 -0
  478. package/src/export/transcript-formatter.ts +61 -2
  479. package/src/filing/filing-service.ts +79 -53
  480. package/src/heartbeat/__tests__/heartbeat-service.test.ts +444 -0
  481. package/src/heartbeat/heartbeat-run-store.ts +3 -1
  482. package/src/heartbeat/heartbeat-service.ts +189 -127
  483. package/src/home/__tests__/feed-types.test.ts +99 -127
  484. package/src/home/__tests__/feed-writer.test.ts +77 -278
  485. package/src/home/__tests__/post-connect-feed.test.ts +9 -12
  486. package/src/home/feed-types.ts +41 -73
  487. package/src/home/feed-writer.ts +25 -156
  488. package/src/home/post-connect-feed.ts +2 -3
  489. package/src/index.ts +18 -1
  490. package/src/ipc/__tests__/cli-ipc.test.ts +2 -0
  491. package/src/ipc/__tests__/email-ipc.test.ts +506 -0
  492. package/src/ipc/__tests__/exit-helper.test.ts +104 -0
  493. package/src/ipc/__tests__/streaming-client.test.ts +237 -0
  494. package/src/ipc/__tests__/streaming-framing.test.ts +142 -0
  495. package/src/ipc/assistant-server.ts +55 -6
  496. package/src/ipc/cli-client.ts +370 -50
  497. package/src/ipc/routes/db-proxy-transaction.ts +151 -0
  498. package/src/ipc/skill-routes/__tests__/events-ipc.test.ts +60 -0
  499. package/src/ipc/skill-routes/events.ts +30 -3
  500. package/src/live-voice/__tests__/live-voice-session-manager.test.ts +46 -0
  501. package/src/live-voice/__tests__/live-voice-stt.test.ts +57 -0
  502. package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +1 -0
  503. package/src/live-voice/live-voice-session-manager.ts +11 -4
  504. package/src/live-voice/live-voice-session.ts +14 -6
  505. package/src/mcp/client.ts +20 -4
  506. package/src/media/image-credentials.ts +3 -3
  507. package/src/memory/__tests__/bookmark-crud.test.ts +264 -0
  508. package/src/memory/__tests__/bookmark-schema.test.ts +181 -0
  509. package/src/memory/__tests__/conversation-queries.test.ts +263 -0
  510. package/src/memory/__tests__/conversation-types.test.ts +36 -0
  511. package/src/memory/__tests__/find-most-recent-retrospective-for.test.ts +130 -0
  512. package/src/memory/__tests__/jobs-worker-v2-graph-trigger-embed.test.ts +113 -0
  513. package/src/memory/__tests__/memory-retrospective-enqueue.test.ts +177 -0
  514. package/src/memory/__tests__/memory-retrospective-job.test.ts +328 -0
  515. package/src/memory/__tests__/memory-retrospective-startup-cleanup.test.ts +318 -0
  516. package/src/memory/__tests__/memory-retrospective-trigger-check.test.ts +90 -0
  517. package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +69 -0
  518. package/src/memory/__tests__/memory-v2-concept-frequency.test.ts +3 -0
  519. package/src/memory/__tests__/message-content.test.ts +35 -0
  520. package/src/memory/bookmark-crud.ts +211 -0
  521. package/src/memory/context-search/__tests__/agent-runner-redaction.test.ts +31 -9
  522. package/src/memory/context-search/agent-protocol.ts +5 -1
  523. package/src/memory/context-search/agent-runner.ts +60 -85
  524. package/src/memory/context-search/limits.ts +1 -4
  525. package/src/memory/context-search/search.ts +23 -113
  526. package/src/memory/context-search/sources/conversations.ts +80 -8
  527. package/src/memory/context-search/sources/memory-v2.ts +39 -14
  528. package/src/memory/context-search/sources/memory.ts +7 -0
  529. package/src/memory/context-search/sources/workspace.ts +17 -10
  530. package/src/memory/context-search/types.ts +1 -1
  531. package/src/memory/conversation-bootstrap.ts +11 -0
  532. package/src/memory/conversation-crud.ts +368 -22
  533. package/src/memory/conversation-queries.ts +116 -12
  534. package/src/memory/conversation-title-service.ts +1 -0
  535. package/src/memory/conversation-types.ts +16 -0
  536. package/src/memory/db-init.ts +20 -0
  537. package/src/memory/delivery-crud.ts +152 -5
  538. package/src/memory/embedding-backend.ts +6 -5
  539. package/src/memory/embedding-runtime-manager.ts +1 -2
  540. package/src/memory/external-conversation-store.ts +66 -5
  541. package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +66 -9
  542. package/src/memory/graph/__tests__/remember-description.test.ts +55 -0
  543. package/src/memory/graph/conversation-graph-memory.ts +92 -5
  544. package/src/memory/graph/extraction.ts +4 -0
  545. package/src/memory/graph/graph-memory-state-store.ts +16 -3
  546. package/src/memory/graph/tool-handlers.ts +17 -7
  547. package/src/memory/graph/tools.ts +45 -6
  548. package/src/memory/indexer.ts +51 -29
  549. package/src/memory/jobs/__tests__/embed-concept-page.test.ts +86 -15
  550. package/src/memory/jobs/embed-concept-page.ts +65 -20
  551. package/src/memory/jobs-store.ts +51 -1
  552. package/src/memory/jobs-worker.ts +57 -3
  553. package/src/memory/llm-request-log-source-clickhouse.ts +324 -0
  554. package/src/memory/llm-request-log-source-local.ts +26 -0
  555. package/src/memory/llm-request-log-source.ts +64 -0
  556. package/src/memory/llm-request-log-store.ts +1 -1
  557. package/src/memory/llm-usage-store.ts +125 -5
  558. package/src/memory/memory-retrospective-constants.ts +13 -0
  559. package/src/memory/memory-retrospective-enqueue.ts +114 -0
  560. package/src/memory/memory-retrospective-job.ts +351 -0
  561. package/src/memory/memory-retrospective-startup-cleanup.ts +175 -0
  562. package/src/memory/memory-retrospective-state.ts +162 -0
  563. package/src/memory/memory-retrospective-trigger-check.ts +91 -0
  564. package/src/memory/memory-v2-activation-log-store.ts +49 -5
  565. package/src/memory/memory-v2-concept-frequency.ts +4 -0
  566. package/src/memory/message-content.ts +38 -1
  567. package/src/memory/migrations/109-external-conversation-bindings.ts +15 -4
  568. package/src/memory/migrations/227-add-conversation-inference-profile.ts +6 -1
  569. package/src/memory/migrations/228-rename-inference-profile-snake-case.ts +20 -7
  570. package/src/memory/migrations/229-delete-private-conversations.test.ts +107 -1
  571. package/src/memory/migrations/229-delete-private-conversations.ts +19 -0
  572. package/src/memory/migrations/231-repair-memory-graph-event-dates.ts +16 -2
  573. package/src/memory/migrations/240-conversation-inference-profile-session.ts +25 -0
  574. package/src/memory/migrations/241-activation-state-fk-cascade.ts +50 -0
  575. package/src/memory/migrations/242-message-bookmarks.ts +38 -0
  576. package/src/memory/migrations/243-provider-connections.ts +68 -0
  577. package/src/memory/migrations/244-provider-connection-status-label.ts +23 -0
  578. package/src/memory/migrations/245-memory-retrospective-state.ts +36 -0
  579. package/src/memory/migrations/246-backfill-provider-connection-label.ts +81 -0
  580. package/src/memory/migrations/247-external-conversation-binding-thread-id.ts +78 -0
  581. package/src/memory/migrations/248-create-onboarding-events.ts +21 -0
  582. package/src/memory/migrations/249-normalize-slack-external-content.ts +240 -0
  583. package/src/memory/migrations/__tests__/244-provider-connection-status-label.test.ts +84 -0
  584. package/src/memory/migrations/__tests__/245-memory-retrospective-state.test.ts +125 -0
  585. package/src/memory/migrations/__tests__/246-backfill-provider-connection-label.test.ts +192 -0
  586. package/src/memory/migrations/index.ts +13 -0
  587. package/src/memory/migrations/registry.ts +8 -0
  588. package/src/memory/onboarding-events-store.ts +106 -0
  589. package/src/memory/published-pages-store.ts +16 -0
  590. package/src/memory/schema/bookmarks.ts +36 -0
  591. package/src/memory/schema/calls.ts +1 -0
  592. package/src/memory/schema/conversations.ts +2 -0
  593. package/src/memory/schema/index.ts +2 -0
  594. package/src/memory/schema/inference.ts +27 -0
  595. package/src/memory/schema/infrastructure.ts +12 -0
  596. package/src/memory/schema/memory-core.ts +9 -0
  597. package/src/memory/search/semantic.ts +1 -4
  598. package/src/memory/turn-events-store.ts +127 -2
  599. package/src/memory/v2/__tests__/__snapshots__/prompts-router.test.ts.snap +27 -0
  600. package/src/memory/v2/__tests__/activation-store.test.ts +5 -5
  601. package/src/memory/v2/__tests__/activation.test.ts +11 -12
  602. package/src/memory/v2/__tests__/backfill-jobs.test.ts +38 -21
  603. package/src/memory/v2/__tests__/consolidation-job.test.ts +123 -135
  604. package/src/memory/v2/__tests__/edge-index.test.ts +1 -1
  605. package/src/memory/v2/__tests__/frontmatter-sweep.test.ts +111 -0
  606. package/src/memory/v2/__tests__/injection.test.ts +726 -18
  607. package/src/memory/v2/__tests__/migration.test.ts +94 -3
  608. package/src/memory/v2/__tests__/page-index.test.ts +360 -0
  609. package/src/memory/v2/__tests__/page-store.test.ts +14 -1
  610. package/src/memory/v2/__tests__/prompts-router.test.ts +309 -0
  611. package/src/memory/v2/__tests__/qdrant.test.ts +138 -3
  612. package/src/memory/v2/__tests__/reranker.test.ts +4 -4
  613. package/src/memory/v2/__tests__/router.test.ts +531 -0
  614. package/src/memory/v2/__tests__/sim.test.ts +45 -1
  615. package/src/memory/v2/__tests__/skill-store.test.ts +445 -11
  616. package/src/memory/v2/__tests__/static-context.test.ts +7 -22
  617. package/src/memory/v2/__tests__/sweep-job.test.ts +95 -0
  618. package/src/memory/v2/activation-store.ts +34 -5
  619. package/src/memory/v2/activation.ts +40 -27
  620. package/src/memory/v2/backfill-jobs.ts +17 -84
  621. package/src/memory/v2/consolidation-job.ts +85 -78
  622. package/src/memory/v2/frontmatter-sweep.ts +91 -0
  623. package/src/memory/v2/injection.ts +466 -109
  624. package/src/memory/v2/migration.ts +147 -20
  625. package/src/memory/v2/page-index.ts +221 -0
  626. package/src/memory/v2/page-store.ts +3 -0
  627. package/src/memory/v2/prompts/consolidation.ts +9 -7
  628. package/src/memory/v2/prompts/router.ts +195 -0
  629. package/src/memory/v2/prompts/sweep.ts +2 -2
  630. package/src/memory/v2/qdrant.ts +234 -93
  631. package/src/memory/v2/reranker.ts +14 -7
  632. package/src/memory/v2/router.ts +323 -0
  633. package/src/memory/v2/sim.ts +25 -12
  634. package/src/memory/v2/skill-store.ts +204 -30
  635. package/src/memory/v2/static-context.ts +16 -9
  636. package/src/memory/v2/sweep-job.ts +122 -96
  637. package/src/memory/v2/types.ts +10 -6
  638. package/src/memory/validation.ts +13 -0
  639. package/src/messaging/providers/slack/__tests__/adapter-token-routing.test.ts +45 -5
  640. package/src/messaging/providers/slack/__tests__/download.test.ts +231 -0
  641. package/src/messaging/providers/slack/adapter.ts +43 -5
  642. package/src/messaging/providers/slack/client.ts +27 -0
  643. package/src/messaging/providers/slack/deep-link.ts +65 -0
  644. package/src/messaging/providers/slack/download.ts +104 -0
  645. package/src/messaging/providers/slack/message-metadata.test.ts +32 -0
  646. package/src/messaging/providers/slack/message-metadata.ts +27 -0
  647. package/src/messaging/providers/slack/render-transcript.test.ts +134 -0
  648. package/src/messaging/providers/slack/render-transcript.ts +69 -5
  649. package/src/messaging/providers/slack/types.ts +20 -1
  650. package/src/notifications/__tests__/emit-signal-home-feed.test.ts +182 -0
  651. package/src/notifications/__tests__/home-feed-side-effect.test.ts +199 -0
  652. package/src/notifications/__tests__/signal-registry.test.ts +17 -0
  653. package/src/notifications/adapters/platform.ts +171 -0
  654. package/src/notifications/conversation-pairing.ts +4 -3
  655. package/src/notifications/copy-composer.ts +15 -0
  656. package/src/notifications/decision-engine.ts +2 -1
  657. package/src/notifications/destination-resolver.ts +21 -0
  658. package/src/notifications/emit-signal.ts +48 -2
  659. package/src/notifications/home-feed-side-effect.ts +165 -0
  660. package/src/notifications/signal.ts +8 -1
  661. package/src/oauth/connection-resolver.ts +8 -4
  662. package/src/oauth/platform-connection.ts +6 -2
  663. package/src/oauth/seed-providers.ts +10 -1
  664. package/src/permissions/checker.ts +14 -0
  665. package/src/permissions/ipc-risk-types.ts +3 -0
  666. package/src/permissions/question-prompter.test.ts +416 -0
  667. package/src/permissions/question-prompter.ts +294 -0
  668. package/src/platform/client.test.ts +1 -1
  669. package/src/platform/client.ts +1 -1
  670. package/src/plugin-api/constants.ts +26 -0
  671. package/src/plugin-api/index.ts +46 -0
  672. package/src/plugin-api/package.json +12 -0
  673. package/src/plugin-api/types.ts +144 -0
  674. package/src/plugins/defaults/circuit-breaker.ts +0 -5
  675. package/src/plugins/defaults/compaction.ts +0 -4
  676. package/src/plugins/defaults/empty-response.ts +0 -2
  677. package/src/plugins/defaults/history-repair.ts +0 -2
  678. package/src/plugins/defaults/injectors.ts +55 -6
  679. package/src/plugins/defaults/llm-call.ts +0 -2
  680. package/src/plugins/defaults/memory-retrieval.ts +0 -1
  681. package/src/plugins/defaults/overflow-reduce.ts +0 -1
  682. package/src/plugins/defaults/persistence.ts +0 -2
  683. package/src/plugins/defaults/title-generate.ts +0 -5
  684. package/src/plugins/defaults/token-estimate.ts +0 -2
  685. package/src/plugins/defaults/tool-error.ts +0 -7
  686. package/src/plugins/defaults/tool-execute.ts +0 -2
  687. package/src/plugins/defaults/tool-result-truncate.ts +0 -4
  688. package/src/plugins/ensure-plugin-api-shim.ts +96 -0
  689. package/src/plugins/external-api.ts +104 -0
  690. package/src/plugins/external-plugin-loader.ts +367 -0
  691. package/src/plugins/feature-gate.ts +22 -0
  692. package/src/plugins/pipeline.ts +37 -0
  693. package/src/plugins/registry.ts +48 -80
  694. package/src/plugins/types.ts +74 -53
  695. package/src/plugins/user-loader.ts +85 -43
  696. package/src/proactive-artifact/aux-message-injector.ts +11 -0
  697. package/src/proactive-artifact/job.test.ts +49 -9
  698. package/src/proactive-artifact/job.ts +4 -0
  699. package/src/proactive-artifact/trigger-state.test.ts +9 -0
  700. package/src/proactive-artifact/trigger-state.ts +4 -0
  701. package/src/prompts/__tests__/system-prompt.test.ts +117 -0
  702. package/src/prompts/__tests__/task-progress-hint-section.test.ts +99 -0
  703. package/src/prompts/normalize-onboarding.ts +27 -0
  704. package/src/prompts/sections.ts +302 -0
  705. package/src/prompts/system-prompt.ts +72 -154
  706. package/src/prompts/templates/BOOTSTRAP.md +17 -1
  707. package/src/prompts/templates/system-sections.ts +173 -0
  708. package/src/prompts/update-bulletin-job.ts +61 -73
  709. package/src/providers/__tests__/dispatch-connection-routing.test.ts +279 -0
  710. package/src/providers/__tests__/inference.test.ts +303 -0
  711. package/src/providers/__tests__/provider-env-vars.test.ts +6 -0
  712. package/src/providers/__tests__/provider-secret-catalog.test.ts +6 -0
  713. package/src/providers/__tests__/retry-callsite.test.ts +14 -32
  714. package/src/providers/__tests__/satellite-connection-routing.test.ts +510 -0
  715. package/src/providers/__tests__/search-provider-catalog.test.ts +80 -0
  716. package/src/providers/anthropic/client.ts +123 -54
  717. package/src/providers/call-site-routing.ts +94 -16
  718. package/src/providers/connection-resolution.ts +170 -0
  719. package/src/providers/inference/__tests__/connections-status-label.test.ts +250 -0
  720. package/src/providers/inference/adapter-factory.ts +210 -0
  721. package/src/providers/inference/auth.ts +112 -0
  722. package/src/providers/inference/backfill.ts +196 -0
  723. package/src/providers/inference/connections.ts +401 -0
  724. package/src/providers/inference/resolve-auth.ts +73 -0
  725. package/src/providers/model-catalog.ts +386 -6
  726. package/src/providers/openai/chat-completions-provider.ts +10 -2
  727. package/src/providers/openai/responses-provider.ts +4 -2
  728. package/src/providers/openrouter/client.ts +7 -0
  729. package/src/providers/{managed-proxy → platform-proxy}/constants.ts +4 -1
  730. package/src/providers/{managed-proxy → platform-proxy}/context.ts +3 -3
  731. package/src/providers/provider-availability.ts +17 -2
  732. package/src/providers/provider-catalog-visibility.ts +36 -0
  733. package/src/providers/provider-env-vars.ts +17 -7
  734. package/src/providers/provider-secret-catalog.ts +49 -30
  735. package/src/providers/provider-send-message.ts +41 -20
  736. package/src/providers/registry.ts +151 -159
  737. package/src/providers/retry.ts +65 -11
  738. package/src/providers/search-provider-catalog.ts +121 -0
  739. package/src/runtime/AGENTS.md +18 -5
  740. package/src/runtime/__tests__/agent-wake.test.ts +152 -0
  741. package/src/runtime/__tests__/background-job-runner.test.ts +357 -0
  742. package/src/runtime/__tests__/pre-first-message-gate.test.ts +82 -0
  743. package/src/runtime/actor-trust-resolver.ts +32 -10
  744. package/src/runtime/agent-wake.ts +64 -7
  745. package/src/runtime/assistant-event-hub.ts +3 -85
  746. package/src/runtime/auth/route-policy.ts +311 -9
  747. package/src/runtime/auth/same-actor.ts +2 -0
  748. package/src/runtime/background-job-runner.ts +339 -0
  749. package/src/runtime/btw-sidechain.ts +3 -0
  750. package/src/runtime/http-router.ts +36 -1
  751. package/src/runtime/http-server.ts +31 -5
  752. package/src/runtime/http-types.ts +21 -0
  753. package/src/runtime/middleware/__tests__/request-logger.test.ts +162 -0
  754. package/src/runtime/middleware/request-logger.ts +62 -1
  755. package/src/runtime/migrations/origin-mode.ts +1 -1
  756. package/src/runtime/pending-interactions.ts +1 -0
  757. package/src/runtime/pre-first-message-gate.ts +83 -0
  758. package/src/runtime/routes/__tests__/backup-routes.test.ts +8 -1
  759. package/src/runtime/routes/__tests__/bookmark-routes.test.ts +268 -0
  760. package/src/runtime/routes/__tests__/connection-routes-vs-cli-parity.test.ts +142 -0
  761. package/src/runtime/routes/__tests__/conversation-management-routes.test.ts +319 -0
  762. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +280 -4
  763. package/src/runtime/routes/__tests__/home-feed-routes.test.ts +15 -136
  764. package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +736 -0
  765. package/src/runtime/routes/__tests__/memory-v2-routes.test.ts +4 -4
  766. package/src/runtime/routes/__tests__/question-routes.test.ts +395 -0
  767. package/src/runtime/routes/__tests__/stt-routes.test.ts +5 -1
  768. package/src/runtime/routes/__tests__/surface-action-routes.test.ts +384 -0
  769. package/src/runtime/routes/__tests__/tts-routes.test.ts +70 -3
  770. package/src/runtime/routes/acp-routes-list.test.ts +143 -0
  771. package/src/runtime/routes/acp-routes.ts +12 -8
  772. package/src/runtime/routes/app-management-routes.ts +228 -3
  773. package/src/runtime/routes/approval-routes.ts +0 -18
  774. package/src/runtime/routes/audit-routes.ts +43 -0
  775. package/src/runtime/routes/auth-routes.ts +72 -0
  776. package/src/runtime/routes/avatar-routes.ts +273 -20
  777. package/src/runtime/routes/backup-routes.ts +406 -2
  778. package/src/runtime/routes/bookmark-routes.ts +156 -0
  779. package/src/runtime/routes/btw-routes.ts +5 -1
  780. package/src/runtime/routes/channel-availability-routes.ts +121 -0
  781. package/src/runtime/routes/channel-verification-routes.ts +2 -1
  782. package/src/runtime/routes/contact-routes.ts +0 -160
  783. package/src/runtime/routes/conversation-cli-routes.ts +233 -0
  784. package/src/runtime/routes/conversation-list-routes.ts +3 -20
  785. package/src/runtime/routes/conversation-management-routes.ts +47 -85
  786. package/src/runtime/routes/conversation-query-routes.ts +350 -97
  787. package/src/runtime/routes/conversation-routes.ts +121 -21
  788. package/src/runtime/routes/conversations-import-routes.ts +229 -0
  789. package/src/runtime/routes/credential-routes.ts +540 -0
  790. package/src/runtime/routes/debug-routes.ts +2 -2
  791. package/src/runtime/routes/document-pdf-renderer.ts +5 -1
  792. package/src/runtime/routes/documents-routes.ts +25 -86
  793. package/src/runtime/routes/domain-routes.ts +167 -0
  794. package/src/runtime/routes/email-routes.ts +603 -0
  795. package/src/runtime/routes/errors.ts +2 -2
  796. package/src/runtime/routes/events-routes.ts +192 -0
  797. package/src/runtime/routes/group-routes.ts +5 -0
  798. package/src/runtime/routes/home-feed-routes.ts +6 -78
  799. package/src/runtime/routes/host-app-control-routes.ts +44 -2
  800. package/src/runtime/routes/host-browser-routes.ts +103 -22
  801. package/src/runtime/routes/http-adapter.ts +2 -0
  802. package/src/runtime/routes/identity-routes.ts +5 -0
  803. package/src/runtime/routes/image-generation-routes.ts +99 -0
  804. package/src/runtime/routes/inbound-conversation.ts +28 -8
  805. package/src/runtime/routes/inbound-message-handler.ts +236 -41
  806. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +248 -1
  807. package/src/runtime/routes/inbound-stages/background-dispatch.ts +118 -7
  808. package/src/runtime/routes/inbound-stages/edit-intercept.ts +17 -4
  809. package/src/runtime/routes/inbound-stages/guardian-reply-intercept.test.ts +156 -0
  810. package/src/runtime/routes/inbound-stages/guardian-reply-intercept.ts +22 -4
  811. package/src/runtime/routes/index.ts +42 -0
  812. package/src/runtime/routes/inference-profile-session-handler.ts +285 -0
  813. package/src/runtime/routes/inference-profile-session-reaper.ts +84 -0
  814. package/src/runtime/routes/inference-profile-session-routes.ts +146 -0
  815. package/src/runtime/routes/inference-provider-connection-routes.ts +361 -0
  816. package/src/runtime/routes/inference-send-routes.ts +115 -0
  817. package/src/runtime/routes/integrations/slack/share.ts +4 -52
  818. package/src/runtime/routes/integrations/slack/token.ts +43 -0
  819. package/src/runtime/routes/integrations/twilio.ts +7 -13
  820. package/src/runtime/routes/mcp-auth-routes.ts +283 -9
  821. package/src/runtime/routes/memory-v2-routes.ts +13 -398
  822. package/src/runtime/routes/notification-routes.ts +3 -1
  823. package/src/runtime/routes/oauth-apps.ts +112 -7
  824. package/src/runtime/routes/oauth-commands-routes.ts +1097 -0
  825. package/src/runtime/routes/oauth-connect-routes.ts +67 -5
  826. package/src/runtime/routes/oauth-lifecycle-routes.ts +43 -0
  827. package/src/runtime/routes/oauth-providers.ts +298 -8
  828. package/src/runtime/routes/platform-routes.ts +336 -0
  829. package/src/runtime/routes/playground/inject-failures.ts +2 -1
  830. package/src/runtime/routes/playground/reset-circuit.ts +2 -1
  831. package/src/runtime/routes/playground/state.ts +2 -1
  832. package/src/runtime/routes/publish-routes.ts +221 -0
  833. package/src/runtime/routes/question-routes.ts +259 -0
  834. package/src/runtime/routes/rename-conversation-routes.ts +2 -33
  835. package/src/runtime/routes/schedule-routes.ts +79 -0
  836. package/src/runtime/routes/sequence-routes.ts +291 -0
  837. package/src/runtime/routes/settings-routes.ts +2 -10
  838. package/src/runtime/routes/skills-routes.ts +31 -1
  839. package/src/runtime/routes/stt-routes.ts +240 -3
  840. package/src/runtime/routes/subagents-routes.ts +57 -18
  841. package/src/runtime/routes/surface-action-routes.ts +43 -7
  842. package/src/runtime/routes/telemetry-routes.ts +27 -0
  843. package/src/runtime/routes/tts-routes.ts +93 -1
  844. package/src/runtime/routes/types.ts +32 -0
  845. package/src/runtime/routes/user-routes-cli.ts +243 -0
  846. package/src/runtime/routes/webhook-routes.ts +165 -0
  847. package/src/runtime/routes/workspace-routes.test.ts +43 -0
  848. package/src/runtime/routes/workspace-routes.ts +28 -0
  849. package/src/runtime/services/conversation-serializer.ts +39 -7
  850. package/src/runtime/sync/resource-sync-events.ts +117 -0
  851. package/src/runtime/sync/sync-publisher.test.ts +105 -0
  852. package/src/runtime/sync/sync-publisher.ts +21 -0
  853. package/src/schedule/schedule-store.ts +27 -2
  854. package/src/schedule/scheduler.ts +208 -123
  855. package/src/security/__tests__/provider-key-env-fallback.test.ts +12 -6
  856. package/src/security/__tests__/untrusted-content.test.ts +86 -0
  857. package/src/security/secret-patterns.ts +3 -0
  858. package/src/security/untrusted-content.ts +93 -8
  859. package/src/sequence/engine.ts +38 -40
  860. package/src/skills/catalog-files.ts +1 -1
  861. package/src/skills/catalog-install.ts +233 -116
  862. package/src/skills/clawhub.ts +70 -13
  863. package/src/skills/managed-store.ts +4 -119
  864. package/src/skills/skillssh-registry.ts +27 -48
  865. package/src/subagent/manager.ts +28 -15
  866. package/src/telemetry/types.ts +113 -1
  867. package/src/telemetry/usage-telemetry-reporter.test.ts +312 -5
  868. package/src/telemetry/usage-telemetry-reporter.ts +113 -7
  869. package/src/tools/apps/executors.ts +58 -7
  870. package/src/tools/ask-question/ask-question-tool.test.ts +509 -0
  871. package/src/tools/ask-question/ask-question-tool.ts +304 -0
  872. package/src/tools/browser/__tests__/browser-execution-acquire.test.ts +206 -0
  873. package/src/tools/browser/browser-execution.ts +29 -14
  874. package/src/tools/browser/cdp-client/__tests__/factory.test.ts +174 -0
  875. package/src/tools/browser/cdp-client/cdp-inspect/__tests__/ws-transport.test.ts +16 -13
  876. package/src/tools/browser/cdp-client/extension-cdp-client.ts +24 -1
  877. package/src/tools/browser/cdp-client/factory.ts +66 -5
  878. package/src/tools/browser/runtime-check.ts +77 -0
  879. package/src/tools/computer-use/definitions.ts +3 -3
  880. package/src/tools/credentials/vault.ts +1 -1
  881. package/src/tools/document/document-tool.ts +124 -1
  882. package/src/tools/filesystem/edit.ts +1 -1
  883. package/src/tools/filesystem/list.ts +1 -1
  884. package/src/tools/filesystem/read.ts +1 -1
  885. package/src/tools/filesystem/write.ts +5 -2
  886. package/src/tools/host-filesystem/transfer.ts +1 -1
  887. package/src/tools/host-terminal/host-shell.ts +1 -1
  888. package/src/tools/memory/register.test.ts +3 -3
  889. package/src/tools/memory/register.ts +9 -1
  890. package/src/tools/network/__tests__/web-search.test.ts +156 -0
  891. package/src/tools/network/web-search.ts +280 -37
  892. package/src/tools/permission-checker.ts +14 -6
  893. package/src/tools/registry.ts +17 -7
  894. package/src/tools/schedule/create.ts +2 -2
  895. package/src/tools/schema-transforms.ts +7 -2
  896. package/src/tools/side-effects.ts +1 -0
  897. package/src/tools/skills/delete-managed.ts +4 -4
  898. package/src/tools/skills/execute.ts +1 -1
  899. package/src/tools/skills/scaffold-managed.ts +3 -2
  900. package/src/tools/subagent/notify-parent.ts +1 -1
  901. package/src/tools/subagent/spawn.ts +3 -3
  902. package/src/tools/system/request-permission.ts +2 -2
  903. package/src/tools/terminal/safe-env.ts +60 -1
  904. package/src/tools/terminal/shell.ts +44 -0
  905. package/src/tools/tool-manifest.ts +2 -0
  906. package/src/tools/types.ts +72 -21
  907. package/src/tools/ui-surface/definitions.ts +6 -5
  908. package/src/tts/__tests__/provider-adapters.test.ts +76 -2
  909. package/src/tts/providers/elevenlabs-provider.ts +75 -1
  910. package/src/types/onboarding-context.ts +2 -0
  911. package/src/usage/attribution.ts +3 -2
  912. package/src/util/errors.ts +17 -0
  913. package/src/util/platform.ts +10 -0
  914. package/src/util/pricing.ts +86 -160
  915. package/src/watcher/__tests__/engine.test.ts +323 -0
  916. package/src/watcher/constants.ts +7 -0
  917. package/src/watcher/engine.ts +94 -90
  918. package/src/workspace/migrations/046-seed-conversation-starters-callsite.ts +6 -9
  919. package/src/workspace/migrations/054-seed-recall-callsite.ts +10 -1
  920. package/src/workspace/migrations/057-repair-stale-gemini-model-ids.ts +94 -5
  921. package/src/workspace/migrations/069-seed-onboarding-threads.ts +8 -2
  922. package/src/workspace/migrations/072-seed-reply-suggestion-callsite.ts +117 -0
  923. package/src/workspace/migrations/073-repair-recall-callsite-empty-profile.ts +95 -0
  924. package/src/workspace/migrations/074-drop-deprecated-secret-detection-keys.ts +117 -0
  925. package/src/workspace/migrations/075-memory-v2-bm25-b-default-reembed.ts +61 -0
  926. package/src/workspace/migrations/076-drop-services-inference-mode.ts +62 -0
  927. package/src/workspace/migrations/077-seed-memory-router-callsite.ts +89 -0
  928. package/src/workspace/migrations/078-release-notes-tavily-web-search.ts +66 -0
  929. package/src/workspace/migrations/079-home-feed-notification-only.ts +197 -0
  930. package/src/workspace/migrations/080-restrict-vercel-api-token-metadata.ts +182 -0
  931. package/src/workspace/migrations/081-backfill-bash-allowed-tools-for-injection-credentials.ts +160 -0
  932. package/src/workspace/migrations/082-backfill-managed-profile-labels.ts +154 -0
  933. package/src/workspace/migrations/083-system-prompt-prefix-to-file.ts +191 -0
  934. package/src/workspace/migrations/084-remove-legacy-skills-index.ts +276 -0
  935. package/src/workspace/migrations/085-memory-v2-bm25-b-reembed-disabled-v2-pages.ts +137 -0
  936. package/src/workspace/migrations/086-revert-stale-gemini-mis-rewrites.ts +198 -0
  937. package/src/workspace/migrations/registry.ts +30 -0
  938. package/src/workspace/migrations/runner.ts +46 -5
  939. package/src/workspace/migrations/types.ts +17 -3
  940. package/src/workspace/provider-commit-message-generator.ts +3 -2
  941. package/examples/plugins/echo/bun.lock +0 -25
  942. package/src/__tests__/context-search-pkb-source.test.ts +0 -498
  943. package/src/__tests__/context-window-manager.test.ts +0 -2093
  944. package/src/__tests__/credentials-cli.test.ts +0 -1225
  945. package/src/__tests__/memory-admin-recall.test.ts +0 -213
  946. package/src/approvals/__tests__/guardian-feed-event.test.ts +0 -303
  947. package/src/cli/commands/__tests__/email-download.test.ts +0 -260
  948. package/src/cli/commands/__tests__/email-list.test.ts +0 -216
  949. package/src/cli/commands/__tests__/email-register.test.ts +0 -186
  950. package/src/cli/commands/__tests__/email-send.test.ts +0 -416
  951. package/src/cli/commands/__tests__/email-status.test.ts +0 -185
  952. package/src/cli/commands/__tests__/email-unregister.test.ts +0 -168
  953. package/src/cli/commands/__tests__/routes.test.ts +0 -562
  954. package/src/cli/commands/__tests__/stt-transcribe.test.ts +0 -454
  955. package/src/cli/commands/autonomy.ts +0 -365
  956. package/src/cli/commands/memory.ts +0 -424
  957. package/src/cli/commands/oauth/__tests__/connect.test.ts +0 -947
  958. package/src/cli/commands/oauth/__tests__/disconnect.test.ts +0 -686
  959. package/src/cli/commands/oauth/__tests__/mode.test.ts +0 -632
  960. package/src/cli/commands/oauth/__tests__/ping.test.ts +0 -631
  961. package/src/cli/commands/oauth/__tests__/providers-delete.test.ts +0 -573
  962. package/src/cli/commands/oauth/__tests__/providers-register.test.ts +0 -330
  963. package/src/cli/commands/oauth/__tests__/providers-update.test.ts +0 -521
  964. package/src/cli/commands/oauth/__tests__/status.test.ts +0 -551
  965. package/src/cli/commands/oauth/__tests__/token.test.ts +0 -420
  966. package/src/cli/lib/daemon-avatar-client.ts +0 -37
  967. package/src/config/bundled-skills/contacts/tools/contact-upsert.ts +0 -87
  968. package/src/config/bundled-skills/messaging/tools/__tests__/messaging-feed-events.test.ts +0 -207
  969. package/src/context/__tests__/compact-prompt.test.ts +0 -63
  970. package/src/context/prompts/compact.md +0 -26
  971. package/src/daemon/__tests__/conversation-feed-event.test.ts +0 -304
  972. package/src/heartbeat/__tests__/heartbeat-feed-event.test.ts +0 -233
  973. package/src/home/__tests__/assistant-feed-authoring.test.ts +0 -156
  974. package/src/home/__tests__/emit-feed-event.test.ts +0 -169
  975. package/src/home/__tests__/feed-population-integration.test.ts +0 -312
  976. package/src/home/__tests__/feed-scheduler.test.ts +0 -222
  977. package/src/home/__tests__/phase5-exit-criteria.test.ts +0 -229
  978. package/src/home/__tests__/platform-gmail-digest.test.ts +0 -222
  979. package/src/home/__tests__/rollup-producer.test.ts +0 -507
  980. package/src/home/assistant-feed-authoring.ts +0 -135
  981. package/src/home/emit-feed-event.ts +0 -169
  982. package/src/home/feed-scheduler.ts +0 -281
  983. package/src/home/platform-gmail-digest.ts +0 -163
  984. package/src/home/rewrite-command-preview.ts +0 -66
  985. package/src/home/rewrite-feed-title.ts +0 -58
  986. package/src/home/rollup-producer.ts +0 -426
  987. package/src/memory/admin.ts +0 -326
  988. package/src/memory/context-search/sources/pkb.ts +0 -476
  989. package/src/memory/graph/compaction.ts +0 -299
  990. package/src/prompts/__tests__/build-cli-reference-section.test.ts +0 -37
  991. /package/src/cli/{commands → lib}/cache-fs.ts +0 -0
@@ -1,33 +1,14 @@
1
1
  /**
2
- * `vellum backup` — manage automated backup configuration and list snapshots.
2
+ * `assistant backup` — manage automated backup configuration and list snapshots.
3
3
  *
4
- * All subcommands run in-process (they do not call the daemon HTTP port).
5
- * Config mutations go through `loadRawConfig` / `setNestedValue` / `saveRawConfig`
6
- * so the on-disk `config.json` is the single source of truth and the daemon's
7
- * config cache is invalidated via `saveRawConfig`.
4
+ * Thin IPC wrapper: each subcommand forwards its request to the daemon via
5
+ * cliIpcCall and never imports daemon-internal modules.
8
6
  */
9
7
 
10
- import { stat } from "node:fs/promises";
11
- import { dirname } from "node:path";
12
-
13
8
  import type { Command } from "commander";
14
9
 
15
- import {
16
- listSnapshotsInDir,
17
- type SnapshotEntry,
18
- } from "../../backup/list-snapshots.js";
19
- import {
20
- getLocalBackupsDir,
21
- resolveOffsiteDestinations,
22
- } from "../../backup/paths.js";
23
- import {
24
- getConfig,
25
- loadRawConfig,
26
- saveRawConfig,
27
- setNestedValue,
28
- } from "../../config/loader.js";
29
- import type { BackupDestination } from "../../config/schema.js";
30
- import { getMemoryCheckpoint } from "../../memory/checkpoints.js";
10
+ import { cliIpcCall, exitFromIpcResult } from "../../ipc/cli-client.js";
11
+ import { registerCommand } from "../lib/register-command.js";
31
12
  import { log } from "../logger.js";
32
13
 
33
14
  // ---------------------------------------------------------------------------
@@ -43,7 +24,7 @@ function formatBytes(bytes: number): string {
43
24
  return `${(bytes / (1024 * 1024 * 1024)).toFixed(2)} GB`;
44
25
  }
45
26
 
46
- /** Format a Date as `YYYY-MM-DD HH:MM UTC`. */
27
+ /** Format an ISO date string as `YYYY-MM-DD HH:MM UTC`. */
47
28
  function formatDate(date: Date): string {
48
29
  const y = date.getUTCFullYear().toString().padStart(4, "0");
49
30
  const mo = (date.getUTCMonth() + 1).toString().padStart(2, "0");
@@ -72,348 +53,19 @@ function formatDurationShort(ms: number): string {
72
53
  return `${days}d ${remHours}h`;
73
54
  }
74
55
 
75
- // ---------------------------------------------------------------------------
76
- // Reachability probe
77
- // ---------------------------------------------------------------------------
78
-
79
- /**
80
- * Check whether an offsite destination's parent directory exists. Mirrors the
81
- * reachability check in the backup worker — if the parent is missing (e.g.
82
- * iCloud Drive not enabled, external SSD unplugged) the destination is
83
- * considered unreachable and we skip it at runtime.
84
- */
85
- async function isDestinationReachable(destPath: string): Promise<boolean> {
86
- try {
87
- await stat(dirname(destPath));
88
- return true;
89
- } catch {
90
- return false;
91
- }
92
- }
93
-
94
- // ---------------------------------------------------------------------------
95
- // Exported handlers — exported so tests can drive them directly.
96
- // ---------------------------------------------------------------------------
97
-
98
- export interface EnableOptions {
99
- interval?: string;
100
- retention?: string;
101
- offsite?: boolean;
102
- }
103
-
104
- export function handleEnable(opts: EnableOptions): void {
105
- const raw = loadRawConfig();
106
- setNestedValue(raw, "backup.enabled", true);
107
-
108
- if (opts.interval !== undefined) {
109
- const hours = Number.parseInt(opts.interval, 10);
110
- if (!Number.isFinite(hours) || hours < 1) {
111
- log.error(
112
- `Invalid --interval "${opts.interval}". Must be a positive integer (hours). ` +
113
- `Run 'vellum backup enable --help' for usage.`,
114
- );
115
- process.exitCode = 1;
116
- return;
117
- }
118
- setNestedValue(raw, "backup.intervalHours", hours);
119
- }
120
-
121
- if (opts.retention !== undefined) {
122
- const count = Number.parseInt(opts.retention, 10);
123
- if (!Number.isFinite(count) || count < 1) {
124
- log.error(
125
- `Invalid --retention "${opts.retention}". Must be a positive integer. ` +
126
- `Run 'vellum backup enable --help' for usage.`,
127
- );
128
- process.exitCode = 1;
129
- return;
130
- }
131
- setNestedValue(raw, "backup.retention", count);
132
- }
133
-
134
- // commander's `.option("--no-offsite", ...)` sets `opts.offsite = false`
135
- // when the flag is present and leaves it `undefined` otherwise. Only a
136
- // literal `false` flips the offsite switch — we never touch `destinations`.
137
- if (opts.offsite === false) {
138
- setNestedValue(raw, "backup.offsite.enabled", false);
139
- }
140
-
141
- saveRawConfig(raw);
142
-
143
- const cfg = getConfig().backup;
144
- log.info(
145
- `Automatic backups enabled (interval=${cfg.intervalHours}h, retention=${cfg.retention}, offsite=${cfg.offsite.enabled ? "on" : "off"})`,
146
- );
147
- }
148
-
149
- export function handleDisable(): void {
150
- const raw = loadRawConfig();
151
- setNestedValue(raw, "backup.enabled", false);
152
- saveRawConfig(raw);
153
- log.info("Automatic backups disabled");
154
- }
155
-
156
- // ---------------------------------------------------------------------------
157
- // destinations subgroup handlers
158
- // ---------------------------------------------------------------------------
159
-
160
- /**
161
- * Load the raw destinations array, materializing the iCloud default on first
162
- * touch. Returns the array plus the raw config so callers can mutate and
163
- * re-persist.
164
- *
165
- * When `backup.offsite.destinations` is `null` in config, the runtime uses the
166
- * iCloud default — but that default is implicit. On first `add`/`remove`/
167
- * `set-encrypt`, we need to make it explicit so subsequent mutations have
168
- * something to mutate.
169
- */
170
- function loadDestinationsForMutation(): {
171
- raw: Record<string, unknown>;
172
- destinations: BackupDestination[];
173
- } {
174
- const raw = loadRawConfig();
175
- const current = getConfig().backup.offsite.destinations;
176
- const destinations = resolveOffsiteDestinations(current);
177
- return { raw, destinations };
178
- }
179
-
180
- export async function handleDestinationsList(): Promise<void> {
181
- const cfg = getConfig().backup;
182
- const destinations = resolveOffsiteDestinations(cfg.offsite.destinations);
183
-
184
- if (destinations.length === 0) {
185
- log.info("No offsite destinations configured");
186
- return;
187
- }
188
-
189
- const pathW = Math.max(4, ...destinations.map((d) => d.path.length));
190
- log.info("Path".padEnd(pathW) + " " + "Encrypted");
191
- log.info("-".repeat(pathW + 2 + 9));
192
- for (const d of destinations) {
193
- log.info(d.path.padEnd(pathW) + " " + (d.encrypt ? "yes" : "no"));
194
- }
195
- }
196
-
197
- export interface DestinationAddOptions {
198
- plaintext?: boolean;
199
- }
200
-
201
- export function handleDestinationsAdd(
202
- path: string,
203
- opts: DestinationAddOptions,
204
- ): void {
205
- const { raw, destinations } = loadDestinationsForMutation();
206
-
207
- if (destinations.some((d) => d.path === path)) {
208
- log.error(
209
- `Destination "${path}" already exists. Run 'vellum backup destinations list' to see configured destinations.`,
210
- );
211
- process.exitCode = 1;
212
- return;
213
- }
214
-
215
- const next: BackupDestination[] = [
216
- ...destinations,
217
- { path, encrypt: !opts.plaintext },
218
- ];
219
- setNestedValue(raw, "backup.offsite.destinations", next);
220
- saveRawConfig(raw);
221
- log.info(
222
- `Added destination ${path} (${opts.plaintext ? "plaintext" : "encrypted"})`,
223
- );
224
- }
225
-
226
- export function handleDestinationsRemove(path: string): void {
227
- const { raw, destinations } = loadDestinationsForMutation();
228
-
229
- const filtered = destinations.filter((d) => d.path !== path);
230
- if (filtered.length === destinations.length) {
231
- log.error(
232
- `Destination "${path}" not found. Run 'vellum backup destinations list' to see configured destinations.`,
233
- );
234
- process.exitCode = 1;
235
- return;
236
- }
237
-
238
- setNestedValue(raw, "backup.offsite.destinations", filtered);
239
- saveRawConfig(raw);
240
- log.info(`Removed destination ${path}`);
241
- }
242
-
243
- export function handleDestinationsSetEncrypt(
244
- path: string,
245
- value: string,
246
- ): void {
247
- const normalized = value.toLowerCase();
248
- if (normalized !== "true" && normalized !== "false") {
249
- log.error(
250
- `Invalid encrypt value "${value}". Must be "true" or "false". ` +
251
- `Run 'vellum backup destinations set-encrypt --help' for usage.`,
252
- );
253
- process.exitCode = 1;
254
- return;
255
- }
256
- const encrypt = normalized === "true";
257
-
258
- const { raw, destinations } = loadDestinationsForMutation();
259
- const idx = destinations.findIndex((d) => d.path === path);
260
- if (idx === -1) {
261
- log.error(
262
- `Destination "${path}" not found. Run 'vellum backup destinations list' to see configured destinations.`,
263
- );
264
- process.exitCode = 1;
265
- return;
266
- }
267
-
268
- const next = destinations.map((d, i) => (i === idx ? { ...d, encrypt } : d));
269
- setNestedValue(raw, "backup.offsite.destinations", next);
270
- saveRawConfig(raw);
271
- log.info(`Set ${path} encrypt=${encrypt ? "true" : "false"}`);
272
- }
273
-
274
- // ---------------------------------------------------------------------------
275
- // status
276
- // ---------------------------------------------------------------------------
277
-
278
- export async function handleStatus(): Promise<void> {
279
- const cfg = getConfig().backup;
280
-
281
- log.info(`Automatic backups: ${cfg.enabled ? "enabled" : "disabled"}`);
282
- log.info(`Interval: every ${cfg.intervalHours}h`);
283
- log.info(`Retention: ${cfg.retention} snapshots per destination`);
284
-
285
- // Last / next run — both gated on a valid checkpoint. The daemon records
286
- // `backup:last_run_at` as a unix-millis string.
287
- const lastRunRaw = getMemoryCheckpoint("backup:last_run_at");
288
- const lastRunMs = lastRunRaw ? Number.parseInt(lastRunRaw, 10) : NaN;
289
- const now = Date.now();
290
- if (!Number.isNaN(lastRunMs)) {
291
- const lastRunDate = new Date(lastRunMs);
292
- log.info(
293
- `Last run: ${formatDate(lastRunDate)} (${formatDurationShort(now - lastRunMs)} ago)`,
294
- );
295
- if (cfg.enabled) {
296
- const intervalMs = cfg.intervalHours * 3600 * 1000;
297
- const nextMs = lastRunMs + intervalMs;
298
- const delta = nextMs - now;
299
- if (delta <= 0) {
300
- log.info(`Next run: due now`);
301
- } else {
302
- log.info(`Next run: in ${formatDurationShort(delta)}`);
303
- }
304
- }
305
- } else {
306
- log.info(`Last run: never`);
307
- if (cfg.enabled) {
308
- log.info(`Next run: on next tick`);
309
- }
310
- }
311
-
312
- // Local directory line — include snapshot count so users can confirm the
313
- // pool size matches retention.
314
- const localDir = getLocalBackupsDir(cfg.localDirectory);
315
- const localSnapshots = await listSnapshotsInDir(localDir);
316
- log.info(
317
- `Local directory: ${localDir} (${localSnapshots.length} snapshots)`,
318
- );
319
-
320
- // Offsite destinations — resolve the iCloud default, probe reachability
321
- // for each, and report snapshot counts.
322
- log.info(`Offsite:`);
323
- if (!cfg.offsite.enabled) {
324
- log.info(` (disabled)`);
325
- return;
326
- }
327
- const destinations = resolveOffsiteDestinations(cfg.offsite.destinations);
328
- if (destinations.length === 0) {
329
- log.info(` (no destinations configured)`);
330
- return;
331
- }
332
- for (const dest of destinations) {
333
- const reachable = await isDestinationReachable(dest.path);
334
- const tag = reachable ? "[OK]" : "[unreachable]";
335
- const enc = dest.encrypt ? "encrypted" : "plaintext";
336
- const snapshots = reachable ? await listSnapshotsInDir(dest.path) : [];
337
- const suffix = reachable ? "" : " -- parent directory not reachable";
338
- log.info(
339
- ` ${tag} ${dest.path} (${enc}, ${snapshots.length} snapshots)${suffix}`,
340
- );
341
- }
342
- }
343
-
344
- // ---------------------------------------------------------------------------
345
- // list
346
- // ---------------------------------------------------------------------------
347
-
348
- /** Print a snapshot table for a group of entries. */
349
- function printSnapshotGroup(heading: string, entries: SnapshotEntry[]): void {
350
- log.info(heading);
351
- if (entries.length === 0) {
352
- log.info(" (none)");
353
- return;
354
- }
355
- const tsW = 19;
356
- const sizeW = 10;
357
- const encW = 9;
358
- log.info(
359
- " " +
360
- "Timestamp".padEnd(tsW) +
361
- " " +
362
- "Size".padEnd(sizeW) +
363
- " " +
364
- "Encrypted".padEnd(encW) +
365
- " " +
366
- "Filename",
367
- );
368
- for (const e of entries) {
369
- log.info(
370
- " " +
371
- formatDate(e.createdAt).padEnd(tsW) +
372
- " " +
373
- formatBytes(e.sizeBytes).padEnd(sizeW) +
374
- " " +
375
- (e.encrypted ? "yes" : "no").padEnd(encW) +
376
- " " +
377
- e.filename,
378
- );
379
- }
380
- }
381
-
382
- export async function handleList(): Promise<void> {
383
- const cfg = getConfig().backup;
384
- const localDir = getLocalBackupsDir(cfg.localDirectory);
385
- const localSnapshots = await listSnapshotsInDir(localDir);
386
- printSnapshotGroup(`Local: ${localDir}`, localSnapshots);
387
-
388
- if (!cfg.offsite.enabled) return;
389
- const destinations = resolveOffsiteDestinations(cfg.offsite.destinations);
390
- for (const dest of destinations) {
391
- const entries = await listSnapshotsInDir(dest.path);
392
- const tag = dest.encrypt ? "encrypted" : "plaintext";
393
- log.info("");
394
- printSnapshotGroup(`Offsite: ${dest.path} (${tag})`, entries);
395
- }
396
- }
397
-
398
- // ---------------------------------------------------------------------------
399
- // ---------------------------------------------------------------------------
400
-
401
-
402
-
403
56
  // ---------------------------------------------------------------------------
404
57
  // Command wiring
405
58
  // ---------------------------------------------------------------------------
406
59
 
407
60
  export function registerBackupCommand(program: Command): void {
408
- const backup = program
409
- .command("backup")
410
- .description(
411
- "Manage automated backup configuration and list snapshots",
412
- );
413
-
414
- backup.addHelpText(
415
- "after",
416
- `
61
+ registerCommand(program, {
62
+ name: "backup",
63
+ transport: "ipc",
64
+ description: "Manage automated backup configuration and list snapshots",
65
+ build: (backup) => {
66
+ backup.addHelpText(
67
+ "after",
68
+ `
417
69
  Backups capture a snapshot of the assistant workspace (config, conversations,
418
70
  trust rules, hooks, the SQLite database) as a .vbundle file. Credentials are
419
71
  NOT included — they live in the OS keychain / CES and users re-authenticate
@@ -427,71 +79,105 @@ plaintext — plaintext only makes sense when the user owns physical access to
427
79
  the medium (e.g. an external SSD).
428
80
 
429
81
  Examples:
430
- $ vellum backup enable --interval 6 --retention 3
431
- $ vellum backup destinations add /Volumes/BackupSSD/vellum --plaintext
432
- $ vellum backup status
433
- $ vellum backup list`,
434
- );
82
+ $ assistant backup enable --interval 6 --retention 3
83
+ $ assistant backup destinations add /Volumes/BackupSSD/vellum --plaintext
84
+ $ assistant backup status
85
+ $ assistant backup list`,
86
+ );
435
87
 
436
- backup
437
- .command("enable")
438
- .description("Enable automated backups")
439
- .option(
440
- "--interval <hours>",
441
- "Hours between automated backups (1-168). Defaults to 6.",
442
- )
443
- .option(
444
- "--retention <n>",
445
- "Snapshots to retain per destination (1-100). Defaults to 3.",
446
- )
447
- .option(
448
- "--no-offsite",
449
- "Disable offsite backup (local only). Does not touch the destinations list.",
450
- )
451
- .addHelpText(
452
- "after",
453
- `
88
+ backup
89
+ .command("enable")
90
+ .description("Enable automated backups")
91
+ .option(
92
+ "--interval <hours>",
93
+ "Hours between automated backups (1-168). Defaults to 6.",
94
+ )
95
+ .option(
96
+ "--retention <n>",
97
+ "Snapshots to retain per destination (1-100). Defaults to 3.",
98
+ )
99
+ .option(
100
+ "--no-offsite",
101
+ "Disable offsite backup (local only). Does not touch the destinations list.",
102
+ )
103
+ .addHelpText(
104
+ "after",
105
+ `
454
106
  Sets backup.enabled = true in config.json. Optionally overrides intervalHours,
455
107
  retention, and the offsite.enabled flag. Does NOT modify
456
- backup.offsite.destinations — use 'vellum backup destinations add/remove' to
108
+ backup.offsite.destinations — use 'assistant backup destinations add/remove' to
457
109
  manage those.
458
110
 
459
111
  Examples:
460
- $ vellum backup enable
461
- $ vellum backup enable --interval 12 --retention 14
462
- $ vellum backup enable --no-offsite`,
463
- )
464
- .action((opts: EnableOptions) => {
465
- handleEnable(opts);
466
- });
467
-
468
- backup
469
- .command("disable")
470
- .description("Disable automated backups")
471
- .addHelpText(
472
- "after",
473
- `
112
+ $ assistant backup enable
113
+ $ assistant backup enable --interval 12 --retention 14
114
+ $ assistant backup enable --no-offsite`,
115
+ )
116
+ .action(
117
+ async (
118
+ opts: { interval?: string; retention?: string; offsite?: boolean },
119
+ cmd: Command,
120
+ ) => {
121
+ const r = await cliIpcCall("backup_enable", {
122
+ body: {
123
+ ...(opts.interval !== undefined && {
124
+ intervalHours: Number.parseInt(opts.interval, 10),
125
+ }),
126
+ ...(opts.retention !== undefined && {
127
+ retention: Number.parseInt(opts.retention, 10),
128
+ }),
129
+ ...(opts.offsite === false && { offsiteEnabled: false }),
130
+ },
131
+ });
132
+ if (!r.ok)
133
+ return exitFromIpcResult(
134
+ { ok: false, error: r.error, statusCode: r.statusCode },
135
+ cmd,
136
+ );
137
+ const cfg = r.result as {
138
+ intervalHours: number;
139
+ retention: number;
140
+ offsite: { enabled: boolean };
141
+ };
142
+ log.info(
143
+ `Automatic backups enabled (interval=${cfg.intervalHours}h, retention=${cfg.retention}, offsite=${cfg.offsite.enabled ? "on" : "off"})`,
144
+ );
145
+ },
146
+ );
147
+
148
+ backup
149
+ .command("disable")
150
+ .description("Disable automated backups")
151
+ .addHelpText(
152
+ "after",
153
+ `
474
154
  Sets backup.enabled = false in config.json. Existing snapshots are untouched;
475
155
  only the automated worker stops creating new ones.
476
156
 
477
157
  Examples:
478
- $ vellum backup disable`,
479
- )
480
- .action(() => {
481
- handleDisable();
482
- });
483
-
484
- // ---------------------------------------------------------------------------
485
- // destinations — subgroup
486
- // ---------------------------------------------------------------------------
487
-
488
- const destinations = backup
489
- .command("destinations")
490
- .description("Manage offsite backup destinations");
491
-
492
- destinations.addHelpText(
493
- "after",
494
- `
158
+ $ assistant backup disable`,
159
+ )
160
+ .action(async (_opts: unknown, cmd: Command) => {
161
+ const r = await cliIpcCall("backup_disable");
162
+ if (!r.ok)
163
+ return exitFromIpcResult(
164
+ { ok: false, error: r.error, statusCode: r.statusCode },
165
+ cmd,
166
+ );
167
+ log.info("Automatic backups disabled");
168
+ });
169
+
170
+ // -----------------------------------------------------------------------
171
+ // destinations — subgroup
172
+ // -----------------------------------------------------------------------
173
+
174
+ const destinations = backup
175
+ .command("destinations")
176
+ .description("Manage offsite backup destinations");
177
+
178
+ destinations.addHelpText(
179
+ "after",
180
+ `
495
181
  Offsite destinations are absolute paths the backup worker writes a copy of
496
182
  each snapshot to after the local write succeeds. The default destination is
497
183
  the iCloud Drive VellumAssistant folder, and it is used implicitly until an
@@ -504,39 +190,57 @@ are written as .vbundle.enc (AES-256-GCM). When false, snapshots are copied
504
190
  as plaintext .vbundle — only use this for media you control physically.
505
191
 
506
192
  Examples:
507
- $ vellum backup destinations list
508
- $ vellum backup destinations add /Volumes/BackupSSD/vellum --plaintext
509
- $ vellum backup destinations remove /Volumes/BackupSSD/vellum
510
- $ vellum backup destinations set-encrypt /Volumes/BackupSSD/vellum false`,
511
- );
193
+ $ assistant backup destinations list
194
+ $ assistant backup destinations add /Volumes/BackupSSD/vellum --plaintext
195
+ $ assistant backup destinations remove /Volumes/BackupSSD/vellum
196
+ $ assistant backup destinations set-encrypt /Volumes/BackupSSD/vellum false`,
197
+ );
512
198
 
513
- destinations
514
- .command("list")
515
- .description("List configured offsite destinations")
516
- .addHelpText(
517
- "after",
518
- `
199
+ destinations
200
+ .command("list")
201
+ .description("List configured offsite destinations")
202
+ .addHelpText(
203
+ "after",
204
+ `
519
205
  Resolves the current destinations array (materializing the iCloud default if
520
206
  no explicit array is configured) and prints a table with the path and
521
207
  encryption flag per row.
522
208
 
523
209
  Examples:
524
- $ vellum backup destinations list`,
525
- )
526
- .action(async () => {
527
- await handleDestinationsList();
528
- });
529
-
530
- destinations
531
- .command("add <path>")
532
- .description("Add an offsite backup destination")
533
- .option(
534
- "--plaintext",
535
- "Write snapshots as plaintext .vbundle (default is AES-256-GCM encrypted .vbundle.enc)",
536
- )
537
- .addHelpText(
538
- "after",
539
- `
210
+ $ assistant backup destinations list`,
211
+ )
212
+ .action(async (_opts: unknown, cmd: Command) => {
213
+ const r = await cliIpcCall<{
214
+ destinations: Array<{ path: string; encrypt: boolean }>;
215
+ }>("backup_destinations_list");
216
+ if (!r.ok)
217
+ return exitFromIpcResult(
218
+ { ok: false, error: r.error, statusCode: r.statusCode },
219
+ cmd,
220
+ );
221
+ const { destinations: dests } = r.result!;
222
+ if (dests.length === 0) {
223
+ log.info("No offsite destinations configured");
224
+ return;
225
+ }
226
+ const pathW = Math.max(4, ...dests.map((d) => d.path.length));
227
+ log.info("Path".padEnd(pathW) + " " + "Encrypted");
228
+ log.info("-".repeat(pathW + 2 + 9));
229
+ for (const d of dests) {
230
+ log.info(d.path.padEnd(pathW) + " " + (d.encrypt ? "yes" : "no"));
231
+ }
232
+ });
233
+
234
+ destinations
235
+ .command("add <path>")
236
+ .description("Add an offsite backup destination")
237
+ .option(
238
+ "--plaintext",
239
+ "Write snapshots as plaintext .vbundle (default is AES-256-GCM encrypted .vbundle.enc)",
240
+ )
241
+ .addHelpText(
242
+ "after",
243
+ `
540
244
  Arguments:
541
245
  path Absolute path to the destination directory. Must be on a mount the
542
246
  caller controls; the backup worker writes files inside this
@@ -547,64 +251,107 @@ the iCloud default is materialized first so the new entry appends to a
547
251
  2-element array rather than replacing the default.
548
252
 
549
253
  Examples:
550
- $ vellum backup destinations add /Volumes/BackupSSD/vellum --plaintext
551
- $ vellum backup destinations add ~/Dropbox/VellumAssistant/backups`,
552
- )
553
- .action((path: string, opts: DestinationAddOptions) => {
554
- handleDestinationsAdd(path, opts);
555
- });
556
-
557
- destinations
558
- .command("remove <path>")
559
- .description("Remove an offsite backup destination by path")
560
- .addHelpText(
561
- "after",
562
- `
254
+ $ assistant backup destinations add /Volumes/BackupSSD/vellum --plaintext
255
+ $ assistant backup destinations add ~/Dropbox/VellumAssistant/backups`,
256
+ )
257
+ .action(
258
+ async (path: string, opts: { plaintext?: boolean }, cmd: Command) => {
259
+ const r = await cliIpcCall("backup_destinations_add", {
260
+ body: {
261
+ path,
262
+ encrypt: !opts.plaintext,
263
+ },
264
+ });
265
+ if (!r.ok)
266
+ return exitFromIpcResult(
267
+ { ok: false, error: r.error, statusCode: r.statusCode },
268
+ cmd,
269
+ );
270
+ log.info(
271
+ `Added destination ${path} (${opts.plaintext ? "plaintext" : "encrypted"})`,
272
+ );
273
+ },
274
+ );
275
+
276
+ destinations
277
+ .command("remove <path>")
278
+ .description("Remove an offsite backup destination by path")
279
+ .addHelpText(
280
+ "after",
281
+ `
563
282
  Arguments:
564
283
  path Exact path match of the destination to remove. Run
565
- 'vellum backup destinations list' to see configured paths.
284
+ 'assistant backup destinations list' to see configured paths.
566
285
 
567
286
  Errors if no destination with the given path exists.
568
287
 
569
288
  Examples:
570
- $ vellum backup destinations remove /Volumes/BackupSSD/vellum`,
571
- )
572
- .action((path: string) => {
573
- handleDestinationsRemove(path);
574
- });
575
-
576
- destinations
577
- .command("set-encrypt <path> <value>")
578
- .description("Toggle encryption for an existing destination")
579
- .addHelpText(
580
- "after",
581
- `
289
+ $ assistant backup destinations remove /Volumes/BackupSSD/vellum`,
290
+ )
291
+ .action(async (path: string, _opts: unknown, cmd: Command) => {
292
+ const r = await cliIpcCall("backup_destinations_remove", { body: { path } });
293
+ if (!r.ok)
294
+ return exitFromIpcResult(
295
+ { ok: false, error: r.error, statusCode: r.statusCode },
296
+ cmd,
297
+ );
298
+ log.info(`Removed destination ${path}`);
299
+ });
300
+
301
+ destinations
302
+ .command("set-encrypt <path> <value>")
303
+ .description("Toggle encryption for an existing destination")
304
+ .addHelpText(
305
+ "after",
306
+ `
582
307
  Arguments:
583
308
  path Exact path match of an existing destination. Run
584
- 'vellum backup destinations list' to see configured paths.
309
+ 'assistant backup destinations list' to see configured paths.
585
310
  value "true" to encrypt, "false" for plaintext writes.
586
311
 
587
312
  Errors if no destination with the given path exists. Existing snapshot files
588
313
  are not modified; only future writes honour the new setting.
589
314
 
590
315
  Examples:
591
- $ vellum backup destinations set-encrypt /Volumes/BackupSSD/vellum false
592
- $ vellum backup destinations set-encrypt /Volumes/BackupSSD/vellum true`,
593
- )
594
- .action((path: string, value: string) => {
595
- handleDestinationsSetEncrypt(path, value);
596
- });
597
-
598
- // ---------------------------------------------------------------------------
599
- // status / list
600
- // ---------------------------------------------------------------------------
601
-
602
- backup
603
- .command("status")
604
- .description("Show backup status and next-run timing")
605
- .addHelpText(
606
- "after",
607
- `
316
+ $ assistant backup destinations set-encrypt /Volumes/BackupSSD/vellum false
317
+ $ assistant backup destinations set-encrypt /Volumes/BackupSSD/vellum true`,
318
+ )
319
+ .action(
320
+ async (path: string, value: string, _opts: unknown, cmd: Command) => {
321
+ const normalized = value.toLowerCase();
322
+ if (normalized !== "true" && normalized !== "false") {
323
+ log.error(
324
+ `Invalid encrypt value "${value}". Must be "true" or "false". ` +
325
+ `Run 'assistant backup destinations set-encrypt --help' for usage.`,
326
+ );
327
+ process.exitCode = 1;
328
+ return;
329
+ }
330
+ const r = await cliIpcCall("backup_destinations_set_encrypt", {
331
+ body: {
332
+ path,
333
+ encrypt: normalized === "true",
334
+ },
335
+ });
336
+ if (!r.ok)
337
+ return exitFromIpcResult(
338
+ { ok: false, error: r.error, statusCode: r.statusCode },
339
+ cmd,
340
+ );
341
+ log.info(`Set ${path} encrypt=${normalized}`);
342
+ },
343
+ );
344
+
345
+ // -----------------------------------------------------------------------
346
+ // status / list
347
+ // -----------------------------------------------------------------------
348
+
349
+ backup
350
+ .command("status")
351
+ .description("Show backup status and next-run timing")
352
+ .addHelpText(
353
+ "after",
354
+ `
608
355
  Reports enabled/disabled state, interval and retention, last-run and next-run
609
356
  timing (from the backup:last_run_at memory checkpoint), and a per-destination
610
357
  reachability probe. Unreachable destinations (parent directory missing, e.g.
@@ -612,27 +359,184 @@ iCloud Drive not enabled or external volume unplugged) are flagged
612
359
  [unreachable] and skipped by the worker.
613
360
 
614
361
  Examples:
615
- $ vellum backup status`,
616
- )
617
- .action(async () => {
618
- await handleStatus();
619
- });
620
-
621
- backup
622
- .command("list")
623
- .description("List all backup snapshots, grouped by destination")
624
- .addHelpText(
625
- "after",
626
- `
362
+ $ assistant backup status`,
363
+ )
364
+ .action(async (_opts: unknown, cmd: Command) => {
365
+ const r = await cliIpcCall<{
366
+ enabled: boolean;
367
+ intervalHours: number;
368
+ retention: number;
369
+ lastRunAt: string | null;
370
+ nextRunAt: string | null;
371
+ localDir: string;
372
+ localSnapshotCount: number;
373
+ offsiteEnabled: boolean;
374
+ offsite: Array<{
375
+ path: string;
376
+ encrypt: boolean;
377
+ reachable: boolean;
378
+ snapshotCount: number;
379
+ }>;
380
+ }>("backup_status");
381
+ if (!r.ok)
382
+ return exitFromIpcResult(
383
+ { ok: false, error: r.error, statusCode: r.statusCode },
384
+ cmd,
385
+ );
386
+ const s = r.result!;
387
+ const now = Date.now();
388
+
389
+ log.info(`Automatic backups: ${s.enabled ? "enabled" : "disabled"}`);
390
+ log.info(`Interval: every ${s.intervalHours}h`);
391
+ log.info(
392
+ `Retention: ${s.retention} snapshots per destination`,
393
+ );
394
+
395
+ if (s.lastRunAt) {
396
+ const lastRunMs = new Date(s.lastRunAt).getTime();
397
+ log.info(
398
+ `Last run: ${formatDate(new Date(s.lastRunAt))} (${formatDurationShort(now - lastRunMs)} ago)`,
399
+ );
400
+ if (s.enabled && s.nextRunAt) {
401
+ const nextMs = new Date(s.nextRunAt).getTime();
402
+ const delta = nextMs - now;
403
+ if (delta <= 0) {
404
+ log.info(`Next run: due now`);
405
+ } else {
406
+ log.info(`Next run: in ${formatDurationShort(delta)}`);
407
+ }
408
+ }
409
+ } else {
410
+ log.info(`Last run: never`);
411
+ if (s.enabled) {
412
+ log.info(`Next run: on next tick`);
413
+ }
414
+ }
415
+
416
+ log.info(
417
+ `Local directory: ${s.localDir} (${s.localSnapshotCount} snapshots)`,
418
+ );
419
+
420
+ log.info(
421
+ `Offsite: ${s.offsiteEnabled ? "enabled" : "disabled"}`,
422
+ );
423
+ if (!s.offsiteEnabled) {
424
+ return;
425
+ }
426
+ if (s.offsite.length === 0) {
427
+ log.info(` (no destinations configured)`);
428
+ return;
429
+ }
430
+ for (const dest of s.offsite) {
431
+ const tag = dest.reachable ? "[OK]" : "[unreachable]";
432
+ const enc = dest.encrypt ? "encrypted" : "plaintext";
433
+ const suffix = dest.reachable
434
+ ? ""
435
+ : " -- parent directory not reachable";
436
+ log.info(
437
+ ` ${tag} ${dest.path} (${enc}, ${dest.snapshotCount} snapshots)${suffix}`,
438
+ );
439
+ }
440
+ });
441
+
442
+ backup
443
+ .command("list")
444
+ .description("List all backup snapshots, grouped by destination")
445
+ .addHelpText(
446
+ "after",
447
+ `
627
448
  Prints a per-destination table of snapshots with timestamp, size, and
628
449
  encryption flag. Local destination is listed first, followed by each offsite
629
450
  destination. Unreachable destinations are listed with an empty snapshot set.
630
451
 
631
452
  Examples:
632
- $ vellum backup list`,
633
- )
634
- .action(async () => {
635
- await handleList();
636
- });
453
+ $ assistant backup list`,
454
+ )
455
+ .action(async (_opts: unknown, cmd: Command) => {
456
+ const r = await cliIpcCall<{
457
+ local: Array<{
458
+ filename: string;
459
+ createdAt: string;
460
+ sizeBytes: number;
461
+ encrypted: boolean;
462
+ }>;
463
+ offsite: Array<{
464
+ destination: { path: string; encrypt: boolean };
465
+ snapshots: Array<{
466
+ filename: string;
467
+ createdAt: string;
468
+ sizeBytes: number;
469
+ encrypted: boolean;
470
+ }>;
471
+ reachable: boolean;
472
+ }>;
473
+ offsiteEnabled: boolean;
474
+ nextRunAt: string | null;
475
+ }>("backups_list");
476
+ if (!r.ok)
477
+ return exitFromIpcResult(
478
+ { ok: false, error: r.error, statusCode: r.statusCode },
479
+ cmd,
480
+ );
481
+ const data = r.result!;
482
+
483
+ printSnapshotGroup(`Local:`, data.local);
484
+
485
+ if (!data.offsiteEnabled) return;
486
+ for (const dest of data.offsite) {
487
+ const tag = dest.destination.encrypt ? "encrypted" : "plaintext";
488
+ log.info("");
489
+ printSnapshotGroup(
490
+ `Offsite: ${dest.destination.path} (${tag})`,
491
+ dest.snapshots,
492
+ );
493
+ }
494
+ });
495
+ },
496
+ });
497
+ }
637
498
 
499
+ // ---------------------------------------------------------------------------
500
+ // Snapshot table printer
501
+ // ---------------------------------------------------------------------------
502
+
503
+ function printSnapshotGroup(
504
+ heading: string,
505
+ entries: Array<{
506
+ filename: string;
507
+ createdAt: string;
508
+ sizeBytes: number;
509
+ encrypted: boolean;
510
+ }>,
511
+ ): void {
512
+ log.info(heading);
513
+ if (entries.length === 0) {
514
+ log.info(" (none)");
515
+ return;
516
+ }
517
+ const tsW = 19;
518
+ const sizeW = 10;
519
+ const encW = 9;
520
+ log.info(
521
+ " " +
522
+ "Timestamp".padEnd(tsW) +
523
+ " " +
524
+ "Size".padEnd(sizeW) +
525
+ " " +
526
+ "Encrypted".padEnd(encW) +
527
+ " " +
528
+ "Filename",
529
+ );
530
+ for (const e of entries) {
531
+ log.info(
532
+ " " +
533
+ formatDate(new Date(e.createdAt)).padEnd(tsW) +
534
+ " " +
535
+ formatBytes(e.sizeBytes).padEnd(sizeW) +
536
+ " " +
537
+ (e.encrypted ? "yes" : "no").padEnd(encW) +
538
+ " " +
539
+ e.filename,
540
+ );
541
+ }
638
542
  }