@vellumai/assistant 0.8.1 → 0.8.3

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 (630) hide show
  1. package/ARCHITECTURE.md +13 -19
  2. package/Dockerfile +75 -1
  3. package/bun.lock +11 -1
  4. package/docker-entrypoint.sh +17 -0
  5. package/docker-init-apt-root.sh +167 -0
  6. package/docker-kata-apt-env.sh +39 -0
  7. package/docs/plugins.md +88 -47
  8. package/docs/skills.md +9 -7
  9. package/examples/plugins/echo/README.md +27 -27
  10. package/examples/plugins/echo/package.json +3 -0
  11. package/examples/plugins/echo/register.ts +31 -31
  12. package/node_modules/@vellumai/slack-text/src/index.test.ts +114 -14
  13. package/node_modules/@vellumai/slack-text/src/index.ts +82 -18
  14. package/openapi.yaml +642 -5
  15. package/package.json +3 -1
  16. package/scripts/generate-openapi.ts +83 -10
  17. package/scripts/sync-llm-catalog.ts +2 -2
  18. package/scripts/sync-web-search-catalog.ts +47 -25
  19. package/src/__tests__/agent-image-optimize.test.ts +11 -3
  20. package/src/__tests__/agent-loop-exit-reason.test.ts +272 -0
  21. package/src/__tests__/agent-loop-provider-error-recording.test.ts +195 -0
  22. package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +131 -0
  23. package/src/__tests__/anthropic-provider.test.ts +45 -0
  24. package/src/__tests__/app-builder-tool-scripts.test.ts +9 -3
  25. package/src/__tests__/app-executors.test.ts +220 -4
  26. package/src/__tests__/auto-analysis-end-to-end.test.ts +35 -0
  27. package/src/__tests__/bundled-asset.test.ts +6 -6
  28. package/src/__tests__/channel-availability-routes.test.ts +206 -0
  29. package/src/__tests__/channel-delivery-store.test.ts +289 -1
  30. package/src/__tests__/circuit-breaker-pipeline.test.ts +0 -1
  31. package/src/__tests__/clawhub.test.ts +75 -16
  32. package/src/__tests__/compactor-tail-resolution.test.ts +147 -0
  33. package/src/__tests__/config-get-vision-flag.test.ts +136 -0
  34. package/src/__tests__/config-loader-backfill.test.ts +115 -18
  35. package/src/__tests__/config-schema.test.ts +21 -0
  36. package/src/__tests__/config-set-route.test.ts +80 -0
  37. package/src/__tests__/config-sounds-sync.test.ts +97 -0
  38. package/src/__tests__/config-watcher-skill-reseed.test.ts +453 -0
  39. package/src/__tests__/context-search-conversations-source.test.ts +117 -2
  40. package/src/__tests__/context-search-memory-v2-source.test.ts +0 -1
  41. package/src/__tests__/context-search-workspace-source.test.ts +7 -0
  42. package/src/__tests__/context-token-estimator.test.ts +31 -65
  43. package/src/__tests__/conversation-abort-tool-results.test.ts +4 -1
  44. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +1 -0
  45. package/src/__tests__/conversation-agent-loop-overflow.test.ts +92 -92
  46. package/src/__tests__/conversation-agent-loop.test.ts +59 -1
  47. package/src/__tests__/conversation-error.test.ts +42 -3
  48. package/src/__tests__/conversation-fork-crud.test.ts +82 -0
  49. package/src/__tests__/conversation-inference-profile-route.test.ts +40 -4
  50. package/src/__tests__/conversation-lifecycle.test.ts +173 -0
  51. package/src/__tests__/conversation-media-retry.test.ts +19 -8
  52. package/src/__tests__/conversation-message-sync-tags.test.ts +97 -0
  53. package/src/__tests__/conversation-pairing.test.ts +54 -0
  54. package/src/__tests__/conversation-process-callsite.test.ts +4 -1
  55. package/src/__tests__/conversation-provider-retry-repair.test.ts +5 -1
  56. package/src/__tests__/conversation-queue.test.ts +4 -1
  57. package/src/__tests__/conversation-runtime-assembly.test.ts +102 -13
  58. package/src/__tests__/conversation-slash-queue.test.ts +59 -1
  59. package/src/__tests__/conversation-slash-unknown.test.ts +4 -1
  60. package/src/__tests__/conversation-surfaces-table-action.test.ts +360 -0
  61. package/src/__tests__/conversation-sync-tags.test.ts +235 -0
  62. package/src/__tests__/conversation-workspace-injection.test.ts +5 -1
  63. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +5 -1
  64. package/src/__tests__/credential-security-invariants.test.ts +3 -2
  65. package/src/__tests__/date-context.test.ts +45 -0
  66. package/src/__tests__/db-slack-external-content-normalization.test.ts +301 -0
  67. package/src/__tests__/delete-managed-skill-tool.test.ts +55 -13
  68. package/src/__tests__/disk-pressure-tools.test.ts +1 -0
  69. package/src/__tests__/dm-backfill.test.ts +121 -10
  70. package/src/__tests__/document-tool-security.test.ts +258 -0
  71. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +0 -1
  72. package/src/__tests__/edit-propagation.test.ts +33 -0
  73. package/src/__tests__/empty-response-pipeline.test.ts +0 -4
  74. package/src/__tests__/external-plugin-loader.test.ts +151 -55
  75. package/src/__tests__/filing-service.test.ts +140 -0
  76. package/src/__tests__/get-skill-detail-audit.test.ts +0 -4
  77. package/src/__tests__/guardian-action-no-hardcoded-copy.test.ts +0 -1
  78. package/src/__tests__/guardian-dispatch.test.ts +1 -0
  79. package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +43 -62
  80. package/src/__tests__/heartbeat-service.test.ts +24 -164
  81. package/src/__tests__/helpers/channel-test-adapter.ts +0 -2
  82. package/src/__tests__/helpers/tar-fixtures.ts +39 -0
  83. package/src/__tests__/helpers/wait-for.ts +21 -0
  84. package/src/__tests__/history-repair-pipeline.test.ts +0 -3
  85. package/src/__tests__/history-repair.test.ts +73 -0
  86. package/src/__tests__/host-app-control-proxy.test.ts +507 -10
  87. package/src/__tests__/host-proxy-preactivation.test.ts +200 -13
  88. package/src/__tests__/image-credentials.test.ts +1 -1
  89. package/src/__tests__/inbound-slack-persistence.test.ts +2 -0
  90. package/src/__tests__/inference-no-mode-boot-e2e.test.ts +1 -1
  91. package/src/__tests__/inference-profile-reaper.test.ts +4 -2
  92. package/src/__tests__/inference-profile-session-handler.test.ts +18 -6
  93. package/src/__tests__/inference-profile-session-ipc.test.ts +17 -5
  94. package/src/__tests__/injector-background-turn.test.ts +153 -0
  95. package/src/__tests__/injector-chain.test.ts +15 -8
  96. package/src/__tests__/install-skill-routing.test.ts +155 -37
  97. package/src/__tests__/lifecycle-memory-v2-seed.test.ts +99 -3
  98. package/src/__tests__/list-messages-page-latest.test.ts +55 -0
  99. package/src/__tests__/llm-call-pipeline.test.ts +0 -3
  100. package/src/__tests__/llm-callsite-catalog.test.ts +25 -0
  101. package/src/__tests__/llm-catalog-parity.test.ts +58 -13
  102. package/src/__tests__/llm-request-log-agent-loop-exit-reason.test.ts +116 -0
  103. package/src/__tests__/llm-request-log-error-payload.test.ts +138 -0
  104. package/src/__tests__/llm-request-log-source-clickhouse.test.ts +36 -0
  105. package/src/__tests__/llm-request-log-source-factory.test.ts +29 -53
  106. package/src/__tests__/llm-resolver.test.ts +255 -2
  107. package/src/__tests__/llm-usage-store.test.ts +114 -0
  108. package/src/__tests__/managed-profile-guard.test.ts +41 -29
  109. package/src/__tests__/managed-skill-lifecycle.test.ts +109 -18
  110. package/src/__tests__/managed-store.test.ts +84 -192
  111. package/src/__tests__/media-generate-image.test.ts +1 -1
  112. package/src/__tests__/memory-retrieval-pipeline.test.ts +0 -2
  113. package/src/__tests__/messages-after-tiebreaker.test.ts +122 -0
  114. package/src/__tests__/notification-decision-fallback.test.ts +0 -91
  115. package/src/__tests__/notification-decision-strategy.test.ts +14 -31
  116. package/src/__tests__/notification-deep-link.test.ts +15 -0
  117. package/src/__tests__/notification-guardian-path.test.ts +1 -2
  118. package/src/__tests__/notification-platform-adapter.test.ts +5 -4
  119. package/src/__tests__/notification-telegram-adapter.test.ts +1 -0
  120. package/src/__tests__/notification-vellum-adapter.test.ts +113 -0
  121. package/src/__tests__/oauth-commands-routes.test.ts +168 -16
  122. package/src/__tests__/oauth-provider-profiles.test.ts +9 -0
  123. package/src/__tests__/openai-provider.test.ts +242 -3
  124. package/src/__tests__/openai-responses-cutover-guard.test.ts +17 -9
  125. package/src/__tests__/openrouter-provider-only.test.ts +51 -3
  126. package/src/__tests__/openrouter-token-estimation.test.ts +34 -25
  127. package/src/__tests__/overflow-reduce-pipeline.test.ts +0 -2
  128. package/src/__tests__/persistence-pipeline.test.ts +0 -2
  129. package/src/__tests__/{managed-proxy-context.test.ts → platform-proxy-context.test.ts} +7 -2
  130. package/src/__tests__/platform.test.ts +2 -0
  131. package/src/__tests__/plugin-api-shim.test.ts +125 -0
  132. package/src/__tests__/plugin-bootstrap.test.ts +10 -36
  133. package/src/__tests__/plugin-external-api.test.ts +68 -0
  134. package/src/__tests__/plugin-registry.test.ts +0 -77
  135. package/src/__tests__/plugin-route-contribution.test.ts +0 -1
  136. package/src/__tests__/plugin-skill-contribution.test.ts +0 -2
  137. package/src/__tests__/plugin-tool-contribution.test.ts +16 -15
  138. package/src/__tests__/plugin-types.test.ts +3 -13
  139. package/src/__tests__/process-message-background-slack.test.ts +8 -1
  140. package/src/__tests__/process-message-display-content.test.ts +421 -0
  141. package/src/__tests__/provider-catalog-visibility.test.ts +158 -0
  142. package/src/__tests__/provider-error-scenarios.test.ts +111 -0
  143. package/src/__tests__/{provider-managed-proxy-integration.test.ts → provider-platform-proxy-integration.test.ts} +33 -31
  144. package/src/__tests__/scaffold-managed-skill-tool.test.ts +65 -13
  145. package/src/__tests__/schedule-routes.test.ts +50 -3
  146. package/src/__tests__/schedule-store.test.ts +94 -0
  147. package/src/__tests__/scheduler-reuse-conversation.test.ts +54 -7
  148. package/src/__tests__/schema-transforms.test.ts +20 -0
  149. package/src/__tests__/search-skills-unified.test.ts +0 -5
  150. package/src/__tests__/{secret-routes-managed-proxy.test.ts → secret-routes-platform-proxy.test.ts} +1 -1
  151. package/src/__tests__/server-history-render.test.ts +43 -0
  152. package/src/__tests__/skill-load-feature-flag.test.ts +0 -12
  153. package/src/__tests__/skill-load-tool.test.ts +27 -89
  154. package/src/__tests__/skill-memory.test.ts +23 -3
  155. package/src/__tests__/skills-file-content-endpoint.test.ts +9 -38
  156. package/src/__tests__/skills-files-catalog-fallback.test.ts +0 -3
  157. package/src/__tests__/skills-install-extract.test.ts +49 -38
  158. package/src/__tests__/skills-install-staging.test.ts +159 -0
  159. package/src/__tests__/skills-uninstall.test.ts +9 -41
  160. package/src/__tests__/skills.test.ts +51 -58
  161. package/src/__tests__/slack-channel-config.test.ts +9 -0
  162. package/src/__tests__/subagent-tool-filtering.test.ts +50 -0
  163. package/src/__tests__/system-prompt.test.ts +670 -63
  164. package/src/__tests__/terminal-tools.test.ts +28 -1
  165. package/src/__tests__/thread-backfill.test.ts +557 -27
  166. package/src/__tests__/title-generate-pipeline.test.ts +0 -13
  167. package/src/__tests__/token-estimate-pipeline.test.ts +0 -3
  168. package/src/__tests__/tool-error-pipeline.test.ts +0 -3
  169. package/src/__tests__/tool-execute-pipeline.test.ts +0 -5
  170. package/src/__tests__/tool-executor-lifecycle-events.test.ts +1 -1
  171. package/src/__tests__/tool-executor.test.ts +16 -4
  172. package/src/__tests__/tool-result-truncate-pipeline.test.ts +0 -12
  173. package/src/__tests__/turn-events-store.test.ts +256 -0
  174. package/src/__tests__/twilio-routes.test.ts +4 -0
  175. package/src/__tests__/user-plugin-loader.test.ts +0 -7
  176. package/src/__tests__/voice-session-bridge.test.ts +198 -0
  177. package/src/__tests__/web-search-catalog-parity.test.ts +32 -10
  178. package/src/__tests__/workspace-migration-057-repair-stale-gemini-model-ids.test.ts +115 -3
  179. package/src/__tests__/workspace-migration-072-seed-reply-suggestion-callsite.test.ts +50 -0
  180. package/src/__tests__/workspace-migration-073-repair-recall-callsite-empty-profile.test.ts +153 -0
  181. package/src/__tests__/workspace-migration-085-memory-v2-bm25-b-reembed-disabled-v2-pages.test.ts +220 -0
  182. package/src/__tests__/workspace-migration-086-revert-stale-gemini-mis-rewrites.test.ts +269 -0
  183. package/src/__tests__/workspace-migration-087-memory-router-balanced-profile.test.ts +228 -0
  184. package/src/__tests__/workspace-migration-remove-legacy-skills-index.test.ts +309 -0
  185. package/src/__tests__/workspace-migrations-runner.test.ts +111 -3
  186. package/src/a2a/__tests__/agent-card.test.ts +98 -0
  187. package/src/a2a/__tests__/e2e-a2a-channel.test.ts +597 -0
  188. package/src/a2a/__tests__/protocol-helpers.test.ts +113 -0
  189. package/src/a2a/__tests__/task-store.test.ts +246 -0
  190. package/src/a2a/agent-card.ts +58 -0
  191. package/src/a2a/feature-gate.ts +8 -0
  192. package/src/a2a/protocol-constants.ts +21 -0
  193. package/src/a2a/protocol-errors.ts +50 -0
  194. package/src/a2a/protocol-types.ts +162 -0
  195. package/src/a2a/task-store.ts +168 -0
  196. package/src/acp/resolve-agent.ts +1 -1
  197. package/src/agent/image-optimize.ts +13 -5
  198. package/src/agent/loop.ts +167 -18
  199. package/src/calls/voice-session-bridge.ts +61 -42
  200. package/src/channels/config.ts +9 -0
  201. package/src/channels/types.ts +122 -0
  202. package/src/cli/__tests__/unknown-command.test.ts +24 -0
  203. package/src/cli/commands/__tests__/changelog.test.ts +304 -319
  204. package/src/cli/{__tests__ → commands/__tests__}/notifications.test.ts +201 -28
  205. package/src/cli/commands/__tests__/schedules.test.ts +960 -0
  206. package/src/cli/commands/changelog.ts +106 -42
  207. package/src/cli/commands/conversations.ts +102 -17
  208. package/src/cli/commands/default-action.ts +10 -53
  209. package/src/cli/commands/notifications.ts +388 -346
  210. package/src/cli/commands/plugins.ts +252 -0
  211. package/src/cli/commands/schedules.ts +683 -0
  212. package/src/cli/commands/telemetry.ts +40 -0
  213. package/src/cli/lib/__tests__/cli-colors.test.ts +48 -0
  214. package/src/cli/lib/__tests__/confirm-prompt.test.ts +159 -0
  215. package/src/cli/lib/__tests__/install-from-github.test.ts +355 -0
  216. package/src/cli/lib/__tests__/list-installed-plugins.test.ts +154 -0
  217. package/src/cli/lib/__tests__/search-plugins.test.ts +261 -0
  218. package/src/cli/lib/__tests__/uninstall-plugin.test.ts +124 -0
  219. package/src/cli/lib/__tests__/unknown-command.test.ts +106 -0
  220. package/src/cli/lib/cli-colors.ts +12 -0
  221. package/src/cli/lib/confirm-prompt.ts +79 -0
  222. package/src/cli/lib/install-from-github.ts +303 -0
  223. package/src/cli/lib/list-installed-plugins.ts +137 -0
  224. package/src/cli/lib/search-plugins.ts +163 -0
  225. package/src/cli/lib/uninstall-plugin.ts +82 -0
  226. package/src/cli/lib/unknown-command.ts +111 -0
  227. package/src/cli/program.ts +52 -2
  228. package/src/config/assistant-feature-flags.ts +24 -54
  229. package/src/config/bundled-skills/app-builder/SKILL.md +140 -22
  230. package/src/config/bundled-skills/app-builder/TOOLS.json +7 -0
  231. package/src/config/bundled-skills/computer-use/TOOLS.json +15 -52
  232. package/src/config/bundled-skills/document/SKILL.md +23 -3
  233. package/src/config/bundled-skills/document/TOOLS.json +53 -0
  234. package/src/config/bundled-skills/document/tools/document-delete.ts +12 -0
  235. package/src/config/bundled-skills/document/tools/document-list.ts +12 -0
  236. package/src/config/bundled-skills/document/tools/document-read.ts +12 -0
  237. package/src/config/bundled-skills/phone-calls/SKILL.md +1 -1
  238. package/src/config/bundled-skills/skill-management/SKILL.md +2 -2
  239. package/src/config/bundled-skills/skill-management/TOOLS.json +7 -7
  240. package/src/config/bundled-tool-registry.ts +6 -0
  241. package/src/config/call-site-defaults.ts +105 -0
  242. package/src/config/feature-flag-registry.json +41 -9
  243. package/src/config/llm-resolver.ts +52 -1
  244. package/src/config/loader.ts +64 -38
  245. package/src/config/schema.ts +9 -10
  246. package/src/config/schemas/__tests__/llm-request-logs.test.ts +36 -0
  247. package/src/config/schemas/__tests__/memory-v2.test.ts +3 -3
  248. package/src/config/schemas/channels.ts +17 -0
  249. package/src/config/schemas/compaction.ts +28 -0
  250. package/src/config/schemas/conversations.ts +10 -0
  251. package/src/config/schemas/heartbeat.ts +23 -0
  252. package/src/config/schemas/llm-request-logs.ts +31 -7
  253. package/src/config/schemas/llm.ts +1 -0
  254. package/src/config/schemas/memory-retrieval.ts +18 -0
  255. package/src/config/schemas/memory-retrospective.ts +1 -1
  256. package/src/config/schemas/memory-v2.ts +4 -4
  257. package/src/config/schemas/memory.ts +3 -1
  258. package/src/config/schemas/tools.ts +14 -0
  259. package/src/config/seed-inference-profiles.ts +99 -29
  260. package/src/config/skills.ts +3 -96
  261. package/src/context/compactor.ts +1107 -0
  262. package/src/context/token-estimator.ts +34 -36
  263. package/src/context/window-manager.ts +197 -1520
  264. package/src/credential-execution/managed-catalog.ts +37 -0
  265. package/src/credential-health/credential-health-service.ts +280 -19
  266. package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +33 -18
  267. package/src/daemon/__tests__/conversation-tool-setup-exclude.test.ts +138 -0
  268. package/src/daemon/__tests__/conversation-tool-setup.test.ts +74 -0
  269. package/src/daemon/approval-generators.ts +8 -6
  270. package/src/daemon/config-watcher.ts +94 -31
  271. package/src/daemon/conversation-agent-loop-handlers.ts +78 -0
  272. package/src/daemon/conversation-agent-loop.ts +198 -11
  273. package/src/daemon/conversation-error.ts +171 -37
  274. package/src/daemon/conversation-lifecycle.ts +53 -40
  275. package/src/daemon/conversation-messaging.ts +25 -6
  276. package/src/daemon/conversation-process.ts +49 -12
  277. package/src/daemon/conversation-runtime-assembly.ts +25 -1
  278. package/src/daemon/conversation-slash.ts +12 -5
  279. package/src/daemon/conversation-store.ts +11 -4
  280. package/src/daemon/conversation-tool-setup.ts +39 -7
  281. package/src/daemon/conversation.ts +33 -8
  282. package/src/daemon/date-context.ts +40 -0
  283. package/src/daemon/external-plugins-bootstrap.ts +217 -181
  284. package/src/daemon/first-greeting.ts +22 -2
  285. package/src/daemon/guardian-action-generators.ts +1 -125
  286. package/src/daemon/handlers/__tests__/config-a2a-complete.test.ts +248 -0
  287. package/src/daemon/handlers/__tests__/config-a2a-invite.test.ts +154 -0
  288. package/src/daemon/handlers/__tests__/config-a2a-redeem.test.ts +133 -0
  289. package/src/daemon/handlers/__tests__/config-a2a.test.ts +95 -0
  290. package/src/daemon/handlers/config-a2a.ts +289 -0
  291. package/src/daemon/handlers/config-model.ts +6 -5
  292. package/src/daemon/handlers/config-slack-channel.ts +15 -3
  293. package/src/daemon/handlers/conversations.ts +1 -0
  294. package/src/daemon/handlers/shared.ts +14 -5
  295. package/src/daemon/handlers/skills.ts +111 -108
  296. package/src/daemon/history-repair.ts +28 -1
  297. package/src/daemon/host-app-control-proxy.ts +153 -27
  298. package/src/daemon/host-proxy-preactivation.ts +85 -18
  299. package/src/daemon/lifecycle.ts +89 -91
  300. package/src/daemon/meet-host-supervisor.ts +5 -4
  301. package/src/daemon/memory-v2-startup.ts +85 -0
  302. package/src/daemon/message-protocol.ts +1 -0
  303. package/src/daemon/message-types/conversations.ts +25 -0
  304. package/src/daemon/message-types/messages.ts +61 -0
  305. package/src/daemon/message-types/notifications.ts +21 -0
  306. package/src/daemon/message-types/subagents.ts +1 -0
  307. package/src/daemon/message-types/sync.ts +1 -0
  308. package/src/daemon/pkb-reminder-builder.test.ts +11 -54
  309. package/src/daemon/pkb-reminder-builder.ts +5 -20
  310. package/src/daemon/plugin-source-watcher.ts +146 -0
  311. package/src/daemon/process-message.ts +24 -3
  312. package/src/daemon/server.ts +11 -2
  313. package/src/daemon/skill-memory-refresh.ts +33 -0
  314. package/src/daemon/wake-target-adapter.ts +2 -0
  315. package/src/documents/document-store.ts +221 -3
  316. package/src/embedded/plugin-api.ts +40 -0
  317. package/src/export/__tests__/transcript-formatter.test.ts +121 -0
  318. package/src/export/transcript-formatter.ts +54 -20
  319. package/src/filing/filing-service.ts +39 -0
  320. package/src/heartbeat/__tests__/heartbeat-service.test.ts +135 -6
  321. package/src/heartbeat/heartbeat-run-store.ts +2 -1
  322. package/src/heartbeat/heartbeat-service.ts +73 -189
  323. package/src/home/__tests__/feed-types.test.ts +80 -0
  324. package/src/home/feed-types.ts +36 -2
  325. package/src/home/post-connect-feed.ts +1 -0
  326. package/src/index.ts +18 -1
  327. package/src/ipc/cli-client.ts +147 -45
  328. package/src/live-voice/__tests__/live-voice-stt.test.ts +57 -0
  329. package/src/mcp/client.ts +20 -4
  330. package/src/media/image-credentials.ts +3 -3
  331. package/src/memory/__tests__/bookmark-crud.test.ts +33 -27
  332. package/src/memory/__tests__/conversation-queries.test.ts +483 -0
  333. package/src/memory/__tests__/jobs-worker-v2-graph-trigger-embed.test.ts +113 -0
  334. package/src/memory/__tests__/memory-retrospective-enqueue.test.ts +2 -50
  335. package/src/memory/__tests__/memory-retrospective-job.test.ts +87 -4
  336. package/src/memory/__tests__/memory-retrospective-startup-cleanup.test.ts +119 -14
  337. package/src/memory/__tests__/message-content.test.ts +35 -0
  338. package/src/memory/bookmark-crud.ts +42 -10
  339. package/src/memory/context-search/sources/conversations.ts +62 -2
  340. package/src/memory/context-search/sources/workspace.ts +4 -0
  341. package/src/memory/conversation-crud.ts +63 -19
  342. package/src/memory/conversation-queries.ts +197 -11
  343. package/src/memory/conversation-title-service.ts +26 -4
  344. package/src/memory/db-init.ts +12 -0
  345. package/src/memory/delivery-crud.ts +152 -5
  346. package/src/memory/embedding-backend.ts +4 -4
  347. package/src/memory/external-conversation-store.ts +66 -5
  348. package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +150 -12
  349. package/src/memory/graph/conversation-graph-memory.ts +49 -21
  350. package/src/memory/graph/tools.ts +9 -40
  351. package/src/memory/indexer.ts +34 -29
  352. package/src/memory/invite-store.ts +53 -0
  353. package/src/memory/jobs/__tests__/embed-concept-page.test.ts +73 -0
  354. package/src/memory/jobs/embed-concept-page.ts +20 -11
  355. package/src/memory/jobs-worker.ts +6 -1
  356. package/src/memory/llm-request-log-source-clickhouse.ts +24 -12
  357. package/src/memory/llm-request-log-source.ts +19 -52
  358. package/src/memory/llm-request-log-store.ts +92 -1
  359. package/src/memory/llm-usage-store.ts +125 -5
  360. package/src/memory/memory-retrospective-enqueue.ts +1 -20
  361. package/src/memory/memory-retrospective-job.ts +33 -6
  362. package/src/memory/memory-retrospective-startup-cleanup.ts +72 -5
  363. package/src/memory/message-content.ts +1 -1
  364. package/src/memory/migrations/109-external-conversation-bindings.ts +15 -4
  365. package/src/memory/migrations/229-delete-private-conversations.test.ts +38 -1
  366. package/src/memory/migrations/229-delete-private-conversations.ts +7 -0
  367. package/src/memory/migrations/247-external-conversation-binding-thread-id.ts +78 -0
  368. package/src/memory/migrations/248-create-onboarding-events.ts +21 -0
  369. package/src/memory/migrations/249-normalize-slack-external-content.ts +240 -0
  370. package/src/memory/migrations/250-provider-connection-base-url-and-models.ts +28 -0
  371. package/src/memory/migrations/251-a2a-tasks.ts +49 -0
  372. package/src/memory/migrations/252-llm-request-log-agent-loop-exit-reason.ts +32 -0
  373. package/src/memory/migrations/index.ts +9 -0
  374. package/src/memory/migrations/registry.ts +16 -0
  375. package/src/memory/onboarding-events-store.ts +106 -0
  376. package/src/memory/schema/a2a.ts +15 -0
  377. package/src/memory/schema/bookmarks.ts +0 -2
  378. package/src/memory/schema/calls.ts +1 -0
  379. package/src/memory/schema/index.ts +1 -0
  380. package/src/memory/schema/inference.ts +3 -3
  381. package/src/memory/schema/infrastructure.ts +13 -0
  382. package/src/memory/turn-events-store.ts +127 -2
  383. package/src/memory/v2/__tests__/activation-store.test.ts +25 -23
  384. package/src/memory/v2/__tests__/activation.test.ts +0 -8
  385. package/src/memory/v2/__tests__/cli-command-store.test.ts +404 -0
  386. package/src/memory/v2/__tests__/frontmatter-sweep.test.ts +25 -4
  387. package/src/memory/v2/__tests__/injection.test.ts +288 -11
  388. package/src/memory/v2/__tests__/migration.test.ts +87 -0
  389. package/src/memory/v2/__tests__/page-index.test.ts +83 -0
  390. package/src/memory/v2/__tests__/prompts-router.test.ts +58 -6
  391. package/src/memory/v2/__tests__/qdrant.test.ts +66 -3
  392. package/src/memory/v2/__tests__/router.test.ts +15 -0
  393. package/src/memory/v2/__tests__/skill-store.test.ts +387 -8
  394. package/src/memory/v2/__tests__/static-context.test.ts +12 -1
  395. package/src/memory/v2/activation-store.ts +14 -16
  396. package/src/memory/v2/cli-command-content.ts +19 -0
  397. package/src/memory/v2/cli-command-store.ts +304 -0
  398. package/src/memory/v2/frontmatter-sweep.ts +7 -1
  399. package/src/memory/v2/injection.ts +81 -26
  400. package/src/memory/v2/migration.ts +49 -19
  401. package/src/memory/v2/page-index.ts +63 -8
  402. package/src/memory/v2/prompts/router.ts +11 -8
  403. package/src/memory/v2/prompts/sweep.ts +2 -2
  404. package/src/memory/v2/qdrant.ts +135 -7
  405. package/src/memory/v2/router.ts +9 -8
  406. package/src/memory/v2/skill-store.ts +120 -35
  407. package/src/memory/v2/static-context.ts +4 -4
  408. package/src/memory/v2/types.ts +23 -0
  409. package/src/messaging/providers/a2a/__tests__/deliver.test.ts +274 -0
  410. package/src/messaging/providers/a2a/deliver.ts +156 -0
  411. package/src/messaging/providers/gmail/client.ts +9 -2
  412. package/src/messaging/providers/index.ts +11 -2
  413. package/src/messaging/providers/slack/__tests__/adapter-token-routing.test.ts +45 -5
  414. package/src/messaging/providers/slack/__tests__/download.test.ts +231 -0
  415. package/src/messaging/providers/slack/adapter.ts +43 -5
  416. package/src/messaging/providers/slack/client.ts +27 -0
  417. package/src/messaging/providers/slack/deep-link.ts +65 -0
  418. package/src/messaging/providers/slack/download.ts +104 -0
  419. package/src/messaging/providers/slack/message-metadata.test.ts +32 -0
  420. package/src/messaging/providers/slack/message-metadata.ts +27 -0
  421. package/src/messaging/providers/slack/render-transcript.test.ts +134 -0
  422. package/src/messaging/providers/slack/render-transcript.ts +69 -5
  423. package/src/messaging/providers/slack/types.ts +20 -1
  424. package/src/notifications/__tests__/broadcaster.test.ts +203 -0
  425. package/src/notifications/__tests__/decision-engine.test.ts +283 -0
  426. package/src/notifications/__tests__/deterministic-checks.test.ts +286 -0
  427. package/src/notifications/__tests__/emit-signal-home-feed.test.ts +1 -0
  428. package/src/notifications/__tests__/home-feed-side-effect.test.ts +430 -7
  429. package/src/notifications/adapters/macos.ts +12 -2
  430. package/src/notifications/broadcaster.ts +29 -4
  431. package/src/notifications/conversation-pairing.ts +2 -1
  432. package/src/notifications/copy-composer.ts +17 -64
  433. package/src/notifications/decision-engine.ts +113 -45
  434. package/src/notifications/deterministic-checks.ts +96 -0
  435. package/src/notifications/emit-signal.ts +21 -1
  436. package/src/notifications/home-feed-side-effect.ts +138 -5
  437. package/src/notifications/signal.ts +3 -5
  438. package/src/notifications/types.ts +8 -0
  439. package/src/oauth/connection-resolver.ts +8 -4
  440. package/src/oauth/platform-connection.test.ts +43 -3
  441. package/src/oauth/platform-connection.ts +19 -6
  442. package/src/oauth/seed-providers.ts +10 -1
  443. package/src/permissions/checker.ts +2 -0
  444. package/src/permissions/ipc-risk-types.ts +1 -0
  445. package/src/permissions/question-prompter.test.ts +416 -0
  446. package/src/permissions/question-prompter.ts +294 -0
  447. package/src/platform/client.test.ts +1 -1
  448. package/src/platform/client.ts +1 -1
  449. package/src/plugin-api/constants.ts +26 -0
  450. package/src/plugin-api/index.ts +34 -1
  451. package/src/plugin-api/types.ts +104 -22
  452. package/src/plugins/defaults/circuit-breaker.ts +0 -5
  453. package/src/plugins/defaults/compaction.ts +0 -4
  454. package/src/plugins/defaults/empty-response.ts +0 -2
  455. package/src/plugins/defaults/history-repair.ts +0 -2
  456. package/src/plugins/defaults/injectors.ts +74 -22
  457. package/src/plugins/defaults/llm-call.ts +0 -2
  458. package/src/plugins/defaults/memory-retrieval.ts +0 -1
  459. package/src/plugins/defaults/overflow-reduce.ts +0 -1
  460. package/src/plugins/defaults/persistence.ts +0 -2
  461. package/src/plugins/defaults/title-generate.ts +0 -5
  462. package/src/plugins/defaults/token-estimate.ts +0 -2
  463. package/src/plugins/defaults/tool-error.ts +0 -7
  464. package/src/plugins/defaults/tool-execute.ts +0 -2
  465. package/src/plugins/defaults/tool-result-truncate.ts +0 -4
  466. package/src/plugins/ensure-plugin-api-shim.ts +96 -0
  467. package/src/plugins/external-api.ts +104 -0
  468. package/src/plugins/external-plugin-loader.ts +187 -42
  469. package/src/plugins/feature-gate.ts +22 -0
  470. package/src/plugins/pipeline.ts +37 -0
  471. package/src/plugins/registry.ts +48 -80
  472. package/src/plugins/types.ts +40 -26
  473. package/src/plugins/user-loader.ts +21 -2
  474. package/src/proactive-artifact/aux-message-injector.ts +11 -0
  475. package/src/proactive-artifact/job.test.ts +37 -5
  476. package/src/prompts/__tests__/system-prompt.test.ts +10 -43
  477. package/src/prompts/__tests__/task-progress-hint-section.test.ts +95 -0
  478. package/src/prompts/normalize-onboarding.ts +27 -0
  479. package/src/prompts/sections.ts +302 -0
  480. package/src/prompts/system-prompt.ts +63 -174
  481. package/src/prompts/templates/BOOTSTRAP.md +17 -1
  482. package/src/prompts/templates/system-sections.ts +164 -0
  483. package/src/providers/__tests__/inference.test.ts +24 -7
  484. package/src/providers/anthropic/client.ts +28 -28
  485. package/src/providers/call-site-routing.ts +24 -6
  486. package/src/providers/connection-resolution.ts +68 -11
  487. package/src/providers/inference/__tests__/adapter-factory-openai-compatible.test.ts +74 -0
  488. package/src/providers/inference/__tests__/connections-openai-compatible.test.ts +175 -0
  489. package/src/providers/inference/__tests__/connections-status-label.test.ts +15 -0
  490. package/src/providers/inference/adapter-factory.ts +32 -6
  491. package/src/providers/inference/auth.ts +12 -0
  492. package/src/providers/inference/backfill.ts +14 -1
  493. package/src/providers/inference/connections.ts +159 -34
  494. package/src/providers/inference/resolve-auth.ts +14 -4
  495. package/src/providers/model-catalog.ts +249 -12
  496. package/src/providers/model-intents.ts +3 -3
  497. package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +235 -0
  498. package/src/providers/openai/chat-completions-provider.ts +169 -8
  499. package/src/providers/openrouter/client.ts +49 -4
  500. package/src/providers/{managed-proxy → platform-proxy}/constants.ts +4 -2
  501. package/src/providers/{managed-proxy → platform-proxy}/context.ts +3 -3
  502. package/src/providers/provider-availability.ts +17 -2
  503. package/src/providers/provider-catalog-visibility.ts +38 -0
  504. package/src/providers/provider-send-message.ts +27 -12
  505. package/src/providers/registry.ts +52 -15
  506. package/src/providers/retry.ts +47 -1
  507. package/src/runtime/__tests__/agent-wake.test.ts +152 -0
  508. package/src/runtime/agent-wake.ts +103 -15
  509. package/src/runtime/auth/route-policy.ts +21 -1
  510. package/src/runtime/btw-sidechain.ts +2 -0
  511. package/src/runtime/http-server.ts +7 -16
  512. package/src/runtime/http-types.ts +19 -47
  513. package/src/runtime/migrations/origin-mode.ts +1 -1
  514. package/src/runtime/pending-interactions.ts +1 -0
  515. package/src/runtime/routes/__tests__/bookmark-routes.test.ts +17 -0
  516. package/src/runtime/routes/__tests__/consolidation-routes.test.ts +258 -0
  517. package/src/runtime/routes/__tests__/conversation-management-routes.test.ts +5 -1
  518. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +172 -23
  519. package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +275 -44
  520. package/src/runtime/routes/__tests__/llm-call-sites-routes.test.ts +12 -0
  521. package/src/runtime/routes/__tests__/question-routes.test.ts +395 -0
  522. package/src/runtime/routes/__tests__/tts-routes.test.ts +64 -1
  523. package/src/runtime/routes/acp-routes-list.test.ts +143 -0
  524. package/src/runtime/routes/acp-routes.ts +5 -3
  525. package/src/runtime/routes/auth-routes.ts +1 -1
  526. package/src/runtime/routes/bookmark-routes.ts +5 -3
  527. package/src/runtime/routes/btw-routes.ts +5 -1
  528. package/src/runtime/routes/channel-availability-routes.ts +126 -0
  529. package/src/runtime/routes/consolidation-routes.ts +100 -0
  530. package/src/runtime/routes/conversation-cli-routes.ts +44 -3
  531. package/src/runtime/routes/conversation-list-routes.ts +3 -20
  532. package/src/runtime/routes/conversation-management-routes.ts +17 -42
  533. package/src/runtime/routes/conversation-query-routes.ts +99 -35
  534. package/src/runtime/routes/conversation-routes.ts +97 -11
  535. package/src/runtime/routes/documents-routes.ts +25 -86
  536. package/src/runtime/routes/group-routes.ts +5 -0
  537. package/src/runtime/routes/inbound-conversation.ts +28 -8
  538. package/src/runtime/routes/inbound-message-handler.ts +236 -41
  539. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +111 -0
  540. package/src/runtime/routes/inbound-stages/background-dispatch.ts +32 -1
  541. package/src/runtime/routes/inbound-stages/edit-intercept.ts +17 -4
  542. package/src/runtime/routes/index.ts +8 -0
  543. package/src/runtime/routes/inference-profile-session-handler.ts +17 -44
  544. package/src/runtime/routes/inference-profile-session-reaper.ts +7 -21
  545. package/src/runtime/routes/inference-provider-connection-routes.ts +199 -22
  546. package/src/runtime/routes/integrations/a2a.ts +235 -0
  547. package/src/runtime/routes/integrations/slack/share.ts +4 -52
  548. package/src/runtime/routes/integrations/slack/token.ts +43 -0
  549. package/src/runtime/routes/integrations/twilio.ts +6 -13
  550. package/src/runtime/routes/llm-call-sites-routes.ts +11 -1
  551. package/src/runtime/routes/notification-routes.ts +1 -1
  552. package/src/runtime/routes/oauth-commands-routes.ts +105 -15
  553. package/src/runtime/routes/oauth-lifecycle-routes.ts +43 -0
  554. package/src/runtime/routes/question-routes.ts +259 -0
  555. package/src/runtime/routes/rename-conversation-routes.ts +2 -33
  556. package/src/runtime/routes/schedule-routes.ts +4 -7
  557. package/src/runtime/routes/subagents-routes.ts +98 -18
  558. package/src/runtime/routes/telemetry-routes.ts +27 -0
  559. package/src/runtime/routes/tts-routes.ts +27 -2
  560. package/src/runtime/routes/workspace-routes.test.ts +43 -0
  561. package/src/runtime/routes/workspace-routes.ts +28 -0
  562. package/src/runtime/services/conversation-serializer.ts +39 -7
  563. package/src/runtime/sync/resource-sync-events.ts +93 -1
  564. package/src/schedule/schedule-store.ts +27 -2
  565. package/src/schedule/scheduler.ts +9 -1
  566. package/src/security/__tests__/untrusted-content.test.ts +86 -0
  567. package/src/security/untrusted-content.ts +93 -8
  568. package/src/skills/catalog-files.ts +1 -1
  569. package/src/skills/catalog-install.ts +233 -116
  570. package/src/skills/clawhub.ts +70 -13
  571. package/src/skills/managed-store.ts +4 -119
  572. package/src/skills/skillssh-registry.ts +27 -48
  573. package/src/subagent/manager.ts +17 -7
  574. package/src/telemetry/types.ts +113 -1
  575. package/src/telemetry/usage-telemetry-reporter.test.ts +312 -5
  576. package/src/telemetry/usage-telemetry-reporter.ts +113 -7
  577. package/src/tools/apps/executors.ts +58 -7
  578. package/src/tools/ask-question/ask-question-tool.test.ts +509 -0
  579. package/src/tools/ask-question/ask-question-tool.ts +304 -0
  580. package/src/tools/browser/browser-execution.ts +15 -11
  581. package/src/tools/computer-use/definitions.ts +3 -3
  582. package/src/tools/credentials/vault.ts +1 -1
  583. package/src/tools/document/document-tool.ts +124 -1
  584. package/src/tools/filesystem/edit.ts +1 -1
  585. package/src/tools/filesystem/list.ts +1 -1
  586. package/src/tools/filesystem/read.ts +1 -1
  587. package/src/tools/filesystem/write.ts +5 -2
  588. package/src/tools/host-filesystem/transfer.ts +1 -1
  589. package/src/tools/host-terminal/host-shell.ts +1 -1
  590. package/src/tools/memory/register.ts +1 -9
  591. package/src/tools/permission-checker.ts +1 -1
  592. package/src/tools/registry.ts +17 -7
  593. package/src/tools/schedule/create.ts +2 -2
  594. package/src/tools/schema-transforms.ts +7 -2
  595. package/src/tools/side-effects.ts +1 -0
  596. package/src/tools/skills/delete-managed.ts +4 -4
  597. package/src/tools/skills/execute.ts +1 -1
  598. package/src/tools/skills/scaffold-managed.ts +3 -2
  599. package/src/tools/subagent/notify-parent.ts +1 -1
  600. package/src/tools/system/request-permission.ts +2 -2
  601. package/src/tools/terminal/safe-env.ts +60 -1
  602. package/src/tools/tool-manifest.ts +2 -0
  603. package/src/tools/types.ts +107 -21
  604. package/src/tools/ui-surface/definitions.ts +6 -5
  605. package/src/tts/__tests__/provider-adapters.test.ts +76 -2
  606. package/src/tts/providers/elevenlabs-provider.ts +75 -1
  607. package/src/types/onboarding-context.ts +2 -0
  608. package/src/util/errors.ts +17 -0
  609. package/src/util/platform.ts +10 -0
  610. package/src/watcher/__tests__/engine.test.ts +22 -0
  611. package/src/watcher/engine.ts +6 -2
  612. package/src/workspace/migrations/057-repair-stale-gemini-model-ids.ts +80 -15
  613. package/src/workspace/migrations/072-seed-reply-suggestion-callsite.ts +35 -22
  614. package/src/workspace/migrations/073-repair-recall-callsite-empty-profile.ts +3 -1
  615. package/src/workspace/migrations/083-system-prompt-prefix-to-file.ts +191 -0
  616. package/src/workspace/migrations/084-remove-legacy-skills-index.ts +276 -0
  617. package/src/workspace/migrations/085-memory-v2-bm25-b-reembed-disabled-v2-pages.ts +137 -0
  618. package/src/workspace/migrations/086-revert-stale-gemini-mis-rewrites.ts +198 -0
  619. package/src/workspace/migrations/087-memory-router-balanced-profile.ts +91 -0
  620. package/src/workspace/migrations/registry.ts +10 -0
  621. package/src/workspace/migrations/runner.ts +39 -9
  622. package/src/workspace/migrations/types.ts +4 -0
  623. package/examples/plugins/echo/bun.lock +0 -25
  624. package/src/__tests__/context-window-manager.test.ts +0 -2481
  625. package/src/__tests__/guardian-action-conversation-turn.test.ts +0 -441
  626. package/src/context/__tests__/compact-prompt.test.ts +0 -63
  627. package/src/context/prompts/compact.md +0 -26
  628. package/src/memory/graph/__tests__/remember-description.test.ts +0 -55
  629. package/src/prompts/__tests__/build-cli-reference-section.test.ts +0 -37
  630. package/src/runtime/guardian-action-conversation-turn.ts +0 -99
@@ -0,0 +1,683 @@
1
+ import type { Command } from "commander";
2
+
3
+ import { cliIpcCall, exitFromIpcResult } from "../../ipc/cli-client.js";
4
+ import { confirmPrompt } from "../lib/confirm-prompt.js";
5
+ import { registerCommand } from "../lib/register-command.js";
6
+ import { log } from "../logger.js";
7
+ import { writeOutput } from "../output.js";
8
+
9
+ interface ScheduleRecord {
10
+ id: string;
11
+ name: string;
12
+ enabled: boolean;
13
+ syntax: string;
14
+ expression: string | null;
15
+ cronExpression: string | null;
16
+ timezone: string | null;
17
+ message: string;
18
+ script: string | null;
19
+ nextRunAt: number;
20
+ lastRunAt: number | null;
21
+ lastStatus: string | null;
22
+ retryCount: number;
23
+ maxRetries: number;
24
+ retryBackoffMs: number;
25
+ description: string | null;
26
+ mode: string;
27
+ status: string;
28
+ routingIntent: string;
29
+ reuseConversation: boolean;
30
+ wakeConversationId: string | null;
31
+ isOneShot: boolean;
32
+ }
33
+
34
+ interface ListSchedulesResponse {
35
+ schedules: ScheduleRecord[];
36
+ }
37
+
38
+ interface ScheduleRunRecord {
39
+ id: string;
40
+ jobId: string;
41
+ status: string;
42
+ startedAt: number;
43
+ finishedAt: number | null;
44
+ durationMs: number | null;
45
+ output: string | null;
46
+ error: string | null;
47
+ conversationId: string | null;
48
+ createdAt: number;
49
+ }
50
+
51
+ interface ListScheduleRunsResponse {
52
+ runs: ScheduleRunRecord[];
53
+ }
54
+
55
+ export function registerSchedulesCommand(program: Command): void {
56
+ registerCommand(program, {
57
+ name: "schedules",
58
+ transport: "ipc",
59
+ description: "Manage scheduled jobs",
60
+ build: (schedules) => {
61
+ schedules.addHelpText(
62
+ "after",
63
+ `
64
+ Schedules are recurring or one-shot jobs run by the assistant.
65
+
66
+ This CLI namespace is intentionally landing incrementally. Today it supports
67
+ listing schedules, viewing recent run history, enabling/disabling schedules,
68
+ manually executing a schedule one time, and cancelling pending one-shot schedules;
69
+ create, delete, and run inspection will follow as separate slices.
70
+
71
+ Examples:
72
+ $ assistant schedules list
73
+ $ assistant schedules list --all
74
+ $ assistant schedules runs <schedule-id>
75
+ $ assistant schedules runs <schedule-id> --limit 25 --json
76
+ $ assistant schedules disable <schedule-id>
77
+ $ assistant schedules enable <schedule-id>
78
+ $ assistant schedules cancel <schedule-id>
79
+ $ assistant schedules execute <schedule-id>`,
80
+ );
81
+
82
+ schedules
83
+ .command("list")
84
+ .description("List assistant schedules")
85
+ .option(
86
+ "--all",
87
+ "Include deferred schedules that are hidden by default",
88
+ )
89
+ .option("--json", "Machine-readable compact JSON output")
90
+ .addHelpText(
91
+ "after",
92
+ `
93
+ Options:
94
+ --all Include deferred schedules that are normally hidden.
95
+ --json Output the raw schedule list as compact JSON.
96
+
97
+ Examples:
98
+ $ assistant schedules list
99
+ $ assistant schedules list --all
100
+ $ assistant schedules list --json`,
101
+ )
102
+ .action(
103
+ async (opts: { all?: boolean; json?: boolean }, cmd: Command) => {
104
+ const queryParams: Record<string, string> = {};
105
+ if (opts.all) queryParams.include_all = "true";
106
+
107
+ const result = await cliIpcCall<ListSchedulesResponse>(
108
+ "listSchedules",
109
+ { queryParams },
110
+ );
111
+
112
+ if (!result.ok) {
113
+ if (opts.json) {
114
+ writeOutput(cmd, { ok: false, error: result.error });
115
+ } else {
116
+ log.error(result.error ?? "Failed to list schedules");
117
+ }
118
+ process.exitCode = 1;
119
+ return;
120
+ }
121
+
122
+ const response = result.result ?? { schedules: [] };
123
+ const entries = [...response.schedules].sort(
124
+ (a, b) => a.nextRunAt - b.nextRunAt,
125
+ );
126
+
127
+ if (opts.json) {
128
+ writeOutput(cmd, { schedules: entries });
129
+ return;
130
+ }
131
+
132
+ if (entries.length === 0) {
133
+ log.info("No schedules found.");
134
+ return;
135
+ }
136
+
137
+ const rows = entries.map((schedule) => ({
138
+ id: schedule.id,
139
+ name: schedule.name,
140
+ enabled: schedule.enabled ? "enabled" : "disabled",
141
+ mode: schedule.mode,
142
+ schedule: describeSchedule(schedule),
143
+ nextRun: formatTimestamp(schedule.nextRunAt),
144
+ lastStatus: schedule.lastStatus ?? "—",
145
+ }));
146
+
147
+ const headers = [
148
+ "ID",
149
+ "NAME",
150
+ "ENABLED",
151
+ "MODE",
152
+ "SCHEDULE",
153
+ "NEXT RUN",
154
+ "LAST STATUS",
155
+ ];
156
+ const widths = [
157
+ headers[0].length,
158
+ headers[1].length,
159
+ headers[2].length,
160
+ headers[3].length,
161
+ headers[4].length,
162
+ headers[5].length,
163
+ headers[6].length,
164
+ ];
165
+
166
+ for (const row of rows) {
167
+ widths[0] = Math.max(widths[0], row.id.length);
168
+ widths[1] = Math.max(widths[1], row.name.length);
169
+ widths[2] = Math.max(widths[2], row.enabled.length);
170
+ widths[3] = Math.max(widths[3], row.mode.length);
171
+ widths[4] = Math.max(widths[4], row.schedule.length);
172
+ widths[5] = Math.max(widths[5], row.nextRun.length);
173
+ widths[6] = Math.max(widths[6], row.lastStatus.length);
174
+ }
175
+
176
+ const pad = (value: string, width: number) => value.padEnd(width);
177
+ log.info(
178
+ headers
179
+ .map((header, index) => pad(header, widths[index]!))
180
+ .join(" "),
181
+ );
182
+ log.info(widths.map((width) => "─".repeat(width)).join(" "));
183
+ for (const row of rows) {
184
+ log.info(
185
+ [
186
+ row.id,
187
+ row.name,
188
+ row.enabled,
189
+ row.mode,
190
+ row.schedule,
191
+ row.nextRun,
192
+ row.lastStatus,
193
+ ]
194
+ .map((value, index) => pad(value, widths[index]!))
195
+ .join(" "),
196
+ );
197
+ }
198
+ },
199
+ );
200
+
201
+ schedules
202
+ .command("runs <id>")
203
+ .description("List recent runs for a schedule")
204
+ .option("--limit <count>", "Max runs to return (default 10, max 100)")
205
+ .option("--json", "Machine-readable compact JSON output")
206
+ .addHelpText(
207
+ "after",
208
+ `
209
+ Options:
210
+ --limit <count> Max runs to return. The assistant clamps values to 1-100.
211
+ --json Output the raw run list as compact JSON.
212
+
213
+ Arguments:
214
+ <id> Schedule ID (UUID) — run 'assistant schedules list' to find it.
215
+
216
+ Examples:
217
+ $ assistant schedules runs 9f2c4f3a-3f1a-41e4-88e7-abc123
218
+ $ assistant schedules runs 9f2c4f3a-3f1a-41e4-88e7-abc123 --limit 25
219
+ $ assistant schedules runs 9f2c4f3a-3f1a-41e4-88e7-abc123 --json`,
220
+ )
221
+ .action(
222
+ async (
223
+ id: string,
224
+ opts: { limit?: string; json?: boolean },
225
+ cmd: Command,
226
+ ) => {
227
+ const scheduleId = id.trim();
228
+ const queryParams: Record<string, string> = {};
229
+ if (opts.limit != null) queryParams.limit = opts.limit;
230
+
231
+ const result = await cliIpcCall<ListScheduleRunsResponse>(
232
+ "listScheduleRuns",
233
+ { pathParams: { id: scheduleId }, queryParams },
234
+ );
235
+
236
+ if (!result.ok) return exitFromIpcResult(result, cmd);
237
+
238
+ const response = result.result ?? { runs: [] };
239
+ if (opts.json) {
240
+ writeOutput(cmd, response);
241
+ return;
242
+ }
243
+
244
+ const runs = response.runs;
245
+ if (runs.length === 0) {
246
+ log.info(`No runs found for schedule ${scheduleId}.`);
247
+ return;
248
+ }
249
+
250
+ const rows = runs.map((run) => ({
251
+ id: run.id,
252
+ status: run.status,
253
+ startedAt: formatTimestamp(run.startedAt),
254
+ finishedAt: formatNullableTimestamp(run.finishedAt),
255
+ duration: formatDuration(run.durationMs),
256
+ conversation: run.conversationId ?? "—",
257
+ error: run.error ?? "—",
258
+ }));
259
+
260
+ const headers = [
261
+ "ID",
262
+ "STATUS",
263
+ "STARTED",
264
+ "FINISHED",
265
+ "DURATION",
266
+ "CONVERSATION",
267
+ "ERROR",
268
+ ];
269
+ const widths = [
270
+ headers[0].length,
271
+ headers[1].length,
272
+ headers[2].length,
273
+ headers[3].length,
274
+ headers[4].length,
275
+ headers[5].length,
276
+ headers[6].length,
277
+ ];
278
+
279
+ for (const row of rows) {
280
+ widths[0] = Math.max(widths[0], row.id.length);
281
+ widths[1] = Math.max(widths[1], row.status.length);
282
+ widths[2] = Math.max(widths[2], row.startedAt.length);
283
+ widths[3] = Math.max(widths[3], row.finishedAt.length);
284
+ widths[4] = Math.max(widths[4], row.duration.length);
285
+ widths[5] = Math.max(widths[5], row.conversation.length);
286
+ widths[6] = Math.max(widths[6], row.error.length);
287
+ }
288
+
289
+ const pad = (value: string, width: number) => value.padEnd(width);
290
+ log.info(
291
+ headers
292
+ .map((header, index) => pad(header, widths[index]!))
293
+ .join(" "),
294
+ );
295
+ log.info(widths.map((width) => "─".repeat(width)).join(" "));
296
+ for (const row of rows) {
297
+ log.info(
298
+ [
299
+ row.id,
300
+ row.status,
301
+ row.startedAt,
302
+ row.finishedAt,
303
+ row.duration,
304
+ row.conversation,
305
+ row.error,
306
+ ]
307
+ .map((value, index) => pad(value, widths[index]!))
308
+ .join(" "),
309
+ );
310
+ }
311
+ },
312
+ );
313
+
314
+ schedules
315
+ .command("create <name>")
316
+ .description("Create a new recurring schedule")
317
+ .requiredOption(
318
+ "-e, --expression <expr>",
319
+ "Cron or RRULE expression that schedules the fire times",
320
+ )
321
+ .requiredOption(
322
+ "-m, --message <text>",
323
+ "Message body sent to the assistant on each fire",
324
+ )
325
+ .option(
326
+ "-t, --timezone <tz>",
327
+ "IANA timezone for the expression (e.g. America/New_York)",
328
+ )
329
+ .option("--no-enabled", "Create the schedule in a disabled state")
330
+ .option("--json", "Machine-readable compact JSON output")
331
+ .addHelpText(
332
+ "after",
333
+ `
334
+ Options:
335
+ -e, --expression <expr> Cron (e.g. '*/30 * * * *') or RRULE expression.
336
+ -m, --message <text> Message body sent on each fire.
337
+ -t, --timezone <tz> IANA timezone applied to the expression.
338
+ --no-enabled Create the schedule disabled. Defaults to enabled.
339
+ --json Output the updated schedule list as compact JSON.
340
+
341
+ Arguments:
342
+ <name> Display name for the schedule.
343
+
344
+ Behavior:
345
+ Creates a recurring schedule in 'execute' mode. The IPC endpoint is
346
+ currently locked to execute mode; notify/script/wake schedules remain
347
+ reachable only through the in-assistant schedule_create LLM tool.
348
+
349
+ Examples:
350
+ $ assistant schedules create "Heartbeat" \\
351
+ --expression '*/30 * * * *' \\
352
+ --message 'run heartbeat'
353
+ $ assistant schedules create "Morning summary" \\
354
+ --expression '0 9 * * MON-FRI' \\
355
+ --timezone America/New_York \\
356
+ --message 'write the morning summary'
357
+ $ assistant schedules create "Drafted" \\
358
+ --expression '0 0 * * *' \\
359
+ --message 'placeholder' \\
360
+ --no-enabled --json`,
361
+ )
362
+ .action(
363
+ async (
364
+ name: string,
365
+ opts: {
366
+ expression: string;
367
+ message: string;
368
+ timezone?: string;
369
+ enabled: boolean;
370
+ json?: boolean;
371
+ },
372
+ cmd: Command,
373
+ ) => {
374
+ const scheduleName = name.trim();
375
+ if (!scheduleName) {
376
+ const error = "name is required";
377
+ if (opts.json) {
378
+ writeOutput(cmd, { ok: false, error });
379
+ } else {
380
+ log.error(error);
381
+ }
382
+ process.exitCode = 1;
383
+ return;
384
+ }
385
+
386
+ const body: Record<string, unknown> = {
387
+ name: scheduleName,
388
+ expression: opts.expression,
389
+ message: opts.message,
390
+ enabled: opts.enabled,
391
+ };
392
+ if (opts.timezone != null) body.timezone = opts.timezone;
393
+
394
+ const result = await cliIpcCall<ListSchedulesResponse>(
395
+ "createSchedule",
396
+ { body },
397
+ );
398
+
399
+ if (!result.ok) return exitFromIpcResult(result, cmd);
400
+
401
+ const response = result.result ?? { schedules: [] };
402
+ if (opts.json) {
403
+ writeOutput(cmd, response);
404
+ return;
405
+ }
406
+
407
+ log.info(`Created schedule: ${scheduleName}`);
408
+ },
409
+ );
410
+
411
+ schedules
412
+ .command("enable <id>")
413
+ .description("Enable a schedule")
414
+ .option("--json", "Machine-readable compact JSON output")
415
+ .addHelpText(
416
+ "after",
417
+ `
418
+ Options:
419
+ --json Output the updated schedule list as compact JSON.
420
+
421
+ Arguments:
422
+ <id> Schedule ID (UUID) — run 'assistant schedules list --all' to find it.
423
+
424
+ Behavior:
425
+ Enables the schedule so it can run on future matching times. This does not
426
+ execute the schedule immediately; use 'assistant schedules execute <id>' for
427
+ manual run-now behavior.
428
+
429
+ Examples:
430
+ $ assistant schedules enable 9f2c4f3a-3f1a-41e4-88e7-abc123
431
+ $ assistant schedules enable 9f2c4f3a-3f1a-41e4-88e7-abc123 --json`,
432
+ )
433
+ .action(async (id: string, opts: { json?: boolean }, cmd: Command) => {
434
+ await toggleScheduleEnabled(id, true, opts, cmd);
435
+ });
436
+
437
+ schedules
438
+ .command("disable <id>")
439
+ .description("Disable a schedule")
440
+ .option("--json", "Machine-readable compact JSON output")
441
+ .addHelpText(
442
+ "after",
443
+ `
444
+ Options:
445
+ --json Output the updated schedule list as compact JSON.
446
+
447
+ Arguments:
448
+ <id> Schedule ID (UUID) — run 'assistant schedules list --all' to find it.
449
+
450
+ Behavior:
451
+ Disables the schedule so future scheduled fires are skipped until it is
452
+ enabled again. Existing run history is preserved.
453
+
454
+ Examples:
455
+ $ assistant schedules disable 9f2c4f3a-3f1a-41e4-88e7-abc123
456
+ $ assistant schedules disable 9f2c4f3a-3f1a-41e4-88e7-abc123 --json`,
457
+ )
458
+ .action(async (id: string, opts: { json?: boolean }, cmd: Command) => {
459
+ await toggleScheduleEnabled(id, false, opts, cmd);
460
+ });
461
+
462
+ schedules
463
+ .command("cancel <id>")
464
+ .description("Cancel a pending one-shot schedule")
465
+ .option("--json", "Machine-readable compact JSON output")
466
+ .addHelpText(
467
+ "after",
468
+ `
469
+ Options:
470
+ --json Output the updated schedule list as compact JSON.
471
+
472
+ Arguments:
473
+ <id> Schedule ID (UUID) — run 'assistant schedules list --all' to find
474
+ pending one-shot/deferred schedules.
475
+
476
+ Behavior:
477
+ Cancels a pending one-shot schedule. Recurring schedules are not cancellable;
478
+ use 'assistant schedules disable <id>' to pause recurring schedules.
479
+
480
+ Examples:
481
+ $ assistant schedules cancel 9f2c4f3a-3f1a-41e4-88e7-abc123
482
+ $ assistant schedules cancel 9f2c4f3a-3f1a-41e4-88e7-abc123 --json`,
483
+ )
484
+ .action(async (id: string, opts: { json?: boolean }, cmd: Command) => {
485
+ const scheduleId = id.trim();
486
+ const result = await cliIpcCall<ListSchedulesResponse>(
487
+ "cancelSchedule",
488
+ { pathParams: { id: scheduleId } },
489
+ );
490
+
491
+ if (!result.ok) return exitFromIpcResult(result, cmd);
492
+
493
+ const response = result.result ?? { schedules: [] };
494
+ if (opts.json) {
495
+ writeOutput(cmd, response);
496
+ return;
497
+ }
498
+
499
+ log.info(`Cancelled schedule: ${scheduleId}`);
500
+ });
501
+
502
+ schedules
503
+ .command("delete <id>")
504
+ .description("Permanently delete a schedule and its run history")
505
+ .option("--force", "Skip the confirmation prompt")
506
+ .option("--json", "Machine-readable compact JSON output")
507
+ .addHelpText(
508
+ "after",
509
+ `
510
+ Options:
511
+ --force Skip the destructive y/N confirmation prompt. Required when stdin
512
+ is not a TTY (e.g. in scripts and CI).
513
+ --json Output the updated schedule list as compact JSON.
514
+
515
+ Arguments:
516
+ <id> Schedule ID (UUID) — run 'assistant schedules list --all' to find it.
517
+
518
+ Behavior:
519
+ Permanently removes the schedule and its run history. This cannot be undone.
520
+ To temporarily pause a recurring schedule, use
521
+ 'assistant schedules disable <id>' instead.
522
+
523
+ Examples:
524
+ $ assistant schedules delete 9f2c4f3a-3f1a-41e4-88e7-abc123
525
+ $ assistant schedules delete 9f2c4f3a-3f1a-41e4-88e7-abc123 --force
526
+ $ assistant schedules delete 9f2c4f3a-3f1a-41e4-88e7-abc123 --force --json`,
527
+ )
528
+ .action(
529
+ async (
530
+ id: string,
531
+ opts: { force?: boolean; json?: boolean },
532
+ cmd: Command,
533
+ ) => {
534
+ const scheduleId = id.trim();
535
+ if (!scheduleId) {
536
+ const error = "Schedule ID is required";
537
+ if (opts.json) {
538
+ writeOutput(cmd, { ok: false, error });
539
+ } else {
540
+ log.error(error);
541
+ }
542
+ process.exitCode = 1;
543
+ return;
544
+ }
545
+
546
+ if (!opts.force) {
547
+ const decision = await confirmPrompt({
548
+ question: `Delete schedule "${scheduleId}"? [y/N] `,
549
+ isTTY: Boolean(process.stdin.isTTY),
550
+ refuseNonInteractiveMessage: `Refusing to delete schedule "${scheduleId}" non-interactively. Pass --force to confirm.`,
551
+ });
552
+ if (decision === "non-interactive") {
553
+ process.exitCode = 1;
554
+ return;
555
+ }
556
+ if (decision === "denied") {
557
+ log.info("Delete cancelled.");
558
+ return;
559
+ }
560
+ }
561
+
562
+ const result = await cliIpcCall<ListSchedulesResponse>(
563
+ "deleteSchedule",
564
+ { pathParams: { id: scheduleId } },
565
+ );
566
+
567
+ if (!result.ok) return exitFromIpcResult(result, cmd);
568
+
569
+ const response = result.result ?? { schedules: [] };
570
+ if (opts.json) {
571
+ writeOutput(cmd, response);
572
+ return;
573
+ }
574
+
575
+ log.info(`Deleted schedule: ${scheduleId}`);
576
+ },
577
+ );
578
+
579
+ schedules
580
+ .command("execute <id>")
581
+ .description("Execute a schedule one time immediately")
582
+ .option("--json", "Machine-readable compact JSON output")
583
+ .addHelpText(
584
+ "after",
585
+ `
586
+ Options:
587
+ --json Output the run-now result as compact JSON.
588
+
589
+ Arguments:
590
+ <id> Schedule ID (UUID) — run 'assistant schedules list' to find it.
591
+
592
+ Examples:
593
+ $ assistant schedules execute 9f2c4f3a-3f1a-41e4-88e7-abc123
594
+ $ assistant schedules execute 9f2c4f3a-3f1a-41e4-88e7-abc123 --json`,
595
+ )
596
+ .action(async (id: string, opts: { json?: boolean }, cmd: Command) => {
597
+ const scheduleId = id.trim();
598
+ if (!scheduleId) {
599
+ const error = "Schedule ID is required";
600
+ if (opts.json) {
601
+ writeOutput(cmd, { ok: false, error });
602
+ } else {
603
+ log.error(error);
604
+ }
605
+ process.exitCode = 1;
606
+ return;
607
+ }
608
+
609
+ const result = await cliIpcCall<ListSchedulesResponse>(
610
+ "runScheduleNow",
611
+ { pathParams: { id: scheduleId } },
612
+ );
613
+
614
+ if (!result.ok) return exitFromIpcResult(result, cmd);
615
+
616
+ const response = result.result ?? { schedules: [] };
617
+ const schedule = response.schedules.find(
618
+ (entry) => entry.id === scheduleId,
619
+ );
620
+
621
+ if (opts.json) {
622
+ writeOutput(cmd, response);
623
+ return;
624
+ }
625
+
626
+ if (schedule) {
627
+ log.info(`Executed schedule: ${schedule.name} (${schedule.id})`);
628
+ if (schedule.lastStatus) {
629
+ log.info(`Last status: ${schedule.lastStatus}`);
630
+ }
631
+ return;
632
+ }
633
+
634
+ log.info(`Executed schedule: ${scheduleId}`);
635
+ });
636
+ },
637
+ });
638
+ }
639
+
640
+ async function toggleScheduleEnabled(
641
+ id: string,
642
+ enabled: boolean,
643
+ opts: { json?: boolean },
644
+ cmd: Command,
645
+ ): Promise<void> {
646
+ const scheduleId = id.trim();
647
+ const result = await cliIpcCall<ListSchedulesResponse>("toggleSchedule", {
648
+ pathParams: { id: scheduleId },
649
+ body: { enabled },
650
+ });
651
+
652
+ if (!result.ok) return exitFromIpcResult(result, cmd);
653
+
654
+ const response = result.result ?? { schedules: [] };
655
+ if (opts.json) {
656
+ writeOutput(cmd, response);
657
+ return;
658
+ }
659
+
660
+ log.info(`${enabled ? "Enabled" : "Disabled"} schedule: ${scheduleId}`);
661
+ }
662
+
663
+ function describeSchedule(schedule: ScheduleRecord): string {
664
+ if (schedule.isOneShot) return "one-shot";
665
+ const expression = schedule.description ?? schedule.expression ?? "—";
666
+ return schedule.timezone
667
+ ? `${expression} (${schedule.timezone})`
668
+ : expression;
669
+ }
670
+
671
+ function formatTimestamp(value: number): string {
672
+ if (!Number.isFinite(value) || value <= 0) return "—";
673
+ return new Date(value).toISOString();
674
+ }
675
+
676
+ function formatNullableTimestamp(value: number | null): string {
677
+ return value == null ? "—" : formatTimestamp(value);
678
+ }
679
+
680
+ function formatDuration(value: number | null): string {
681
+ if (value == null || !Number.isFinite(value)) return "—";
682
+ return `${value}ms`;
683
+ }