@vellumai/assistant 0.8.7 → 0.8.8-dev.202606052332.17fc8ea

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 (570) hide show
  1. package/Dockerfile +20 -4
  2. package/bun.lock +2 -2
  3. package/docker-entrypoint.sh +4 -2
  4. package/docker-init-apt-root.sh +3 -1
  5. package/docker-kata-apt-env.sh +3 -1
  6. package/docker-kata-runtime-family.sh +12 -0
  7. package/docs/architecture/memory.md +1 -1
  8. package/examples/plugins/echo/README.md +61 -66
  9. package/examples/plugins/echo/hooks/post-tool-use.ts +18 -0
  10. package/examples/plugins/echo/hooks/stop.ts +16 -0
  11. package/examples/plugins/echo/hooks/user-prompt-submit.ts +18 -0
  12. package/examples/plugins/echo/package.json +1 -2
  13. package/examples/plugins/echo/src/emit.ts +19 -0
  14. package/node_modules/@vellumai/skill-host-contracts/src/server-message.ts +3 -3
  15. package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +7 -6
  16. package/openapi.yaml +3378 -335
  17. package/package.json +2 -2
  18. package/scripts/generate-openapi.ts +68 -41
  19. package/src/__tests__/agent-loop-exit-reason.test.ts +35 -93
  20. package/src/__tests__/agent-loop-provider-error-recording.test.ts +1 -1
  21. package/src/__tests__/agent-loop.test.ts +37 -87
  22. package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +2 -0
  23. package/src/__tests__/annotate-activity-metadata.test.ts +262 -0
  24. package/src/__tests__/annotate-risk-options.test.ts +2 -3
  25. package/src/__tests__/anthropic-provider.test.ts +95 -2
  26. package/src/__tests__/app-control-flow.test.ts +1 -1
  27. package/src/__tests__/app-dir-path-guard.test.ts +1 -0
  28. package/src/__tests__/approval-routes-http.test.ts +4 -1
  29. package/src/__tests__/assistant-event-hub.test.ts +25 -0
  30. package/src/__tests__/assistant-events-sse-shed.test.ts +8 -0
  31. package/src/__tests__/{conversation-stream-state.test.ts → assistant-stream-state.test.ts} +252 -91
  32. package/src/__tests__/auth-fallback-events-store.test.ts +116 -0
  33. package/src/__tests__/background-workers-disk-pressure.test.ts +6 -0
  34. package/src/__tests__/btw-routes.test.ts +62 -3
  35. package/src/__tests__/build-persisted-content.test.ts +184 -0
  36. package/src/__tests__/catalog-files.test.ts +1 -1
  37. package/src/__tests__/channel-approval-routes.test.ts +1 -1
  38. package/src/__tests__/channel-approvals.test.ts +1 -1
  39. package/src/__tests__/clawhub-files.test.ts +1 -1
  40. package/src/__tests__/compaction-circuit.test.ts +258 -0
  41. package/src/__tests__/compaction-direct.test.ts +132 -0
  42. package/src/__tests__/compaction.benchmark.test.ts +0 -30
  43. package/src/__tests__/config-watcher.test.ts +1 -1
  44. package/src/__tests__/conversation-abort-tool-results.test.ts +57 -19
  45. package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +6 -5
  46. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +10 -7
  47. package/src/__tests__/conversation-agent-loop-overflow.test.ts +316 -1143
  48. package/src/__tests__/conversation-agent-loop.test.ts +638 -1655
  49. package/src/__tests__/conversation-analysis-routes.test.ts +6 -0
  50. package/src/__tests__/conversation-clean-command.test.ts +5 -2
  51. package/src/__tests__/conversation-history-web-search.test.ts +11 -1
  52. package/src/__tests__/conversation-pairing.test.ts +4 -31
  53. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +6 -0
  54. package/src/__tests__/conversation-provider-retry-repair.test.ts +30 -10
  55. package/src/__tests__/conversation-queue.test.ts +2 -0
  56. package/src/__tests__/conversation-routes-disk-view.test.ts +3 -0
  57. package/src/__tests__/conversation-routes-slash-commands.test.ts +6 -5
  58. package/src/__tests__/conversation-runtime-assembly.test.ts +310 -300
  59. package/src/__tests__/conversation-runtime-workspace.test.ts +105 -45
  60. package/src/__tests__/conversation-slash-commands.test.ts +8 -42
  61. package/src/__tests__/conversation-slash-queue.test.ts +6 -1
  62. package/src/__tests__/conversation-starter-routes.test.ts +14 -6
  63. package/src/__tests__/conversation-surfaces-action-delivery.test.ts +84 -0
  64. package/src/__tests__/conversation-sync-tags.test.ts +27 -15
  65. package/src/__tests__/conversation-title-service.test.ts +135 -2
  66. package/src/__tests__/conversation-workspace-cache-state.test.ts +17 -16
  67. package/src/__tests__/conversation-workspace-injection.test.ts +67 -2
  68. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +7 -6
  69. package/src/__tests__/conversations-import-system-filter.test.ts +101 -0
  70. package/src/__tests__/cross-provider-web-search.test.ts +214 -1
  71. package/src/__tests__/db-acp-history.test.ts +101 -0
  72. package/src/__tests__/db-schedule-syntax-migration.test.ts +5 -0
  73. package/src/__tests__/dm-persistence.test.ts +5 -1
  74. package/src/__tests__/dynamic-page-surface.test.ts +31 -0
  75. package/src/__tests__/empty-response-hook.test.ts +304 -0
  76. package/src/__tests__/feature-flag-test-helpers.ts +2 -2
  77. package/src/__tests__/file-write-tool.test.ts +63 -0
  78. package/src/__tests__/gateway-only-guard.test.ts +12 -2
  79. package/src/__tests__/gemini-image-service.test.ts +13 -0
  80. package/src/__tests__/guardian-grant-minting.test.ts +1 -1
  81. package/src/__tests__/guardian-routing-invariants.test.ts +2 -4
  82. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +1 -1
  83. package/src/__tests__/heartbeat-disk-pressure.test.ts +1 -0
  84. package/src/__tests__/heartbeat-service.test.ts +1 -0
  85. package/src/__tests__/helpers/mock-provider.ts +110 -0
  86. package/src/__tests__/helpers/native-web-search-harness.ts +129 -0
  87. package/src/__tests__/history-repair-hook.test.ts +1 -0
  88. package/src/__tests__/host-app-control-routes.test.ts +1 -1
  89. package/src/__tests__/host-cu-routes-targeted.test.ts +3 -3
  90. package/src/__tests__/identity-intro-cache.test.ts +12 -100
  91. package/src/__tests__/identity-routes.test.ts +248 -7
  92. package/src/__tests__/inbound-slack-persistence.test.ts +5 -1
  93. package/src/__tests__/injector-background-turn.test.ts +3 -9
  94. package/src/__tests__/injector-chain.test.ts +139 -275
  95. package/src/__tests__/injector-disk-pressure.test.ts +75 -41
  96. package/src/__tests__/injector-document-comments.test.ts +3 -3
  97. package/src/__tests__/injector-pkb-v2-silenced.test.ts +30 -22
  98. package/src/__tests__/injector-v3-suppression.test.ts +31 -37
  99. package/src/__tests__/internal-telemetry-routes.test.ts +109 -0
  100. package/src/__tests__/list-messages-hidden-metadata.test.ts +38 -0
  101. package/src/__tests__/list-messages-page-latest.test.ts +60 -0
  102. package/src/__tests__/list-messages-tool-merge.test.ts +20 -0
  103. package/src/__tests__/llm-usage-store.test.ts +223 -1
  104. package/src/__tests__/memory-retrieval-hook.test.ts +297 -0
  105. package/src/__tests__/memory-v2-static-injector.test.ts +103 -35
  106. package/src/__tests__/native-web-search.test.ts +191 -0
  107. package/src/__tests__/onboarding-template-contract.test.ts +2 -0
  108. package/src/__tests__/openai-image-service.test.ts +17 -0
  109. package/src/__tests__/openai-provider.test.ts +31 -1
  110. package/src/__tests__/{overflow-reduce-pipeline.test.ts → overflow-reduction-loop.test.ts} +64 -284
  111. package/src/__tests__/persist-unsendable-image.test.ts +215 -0
  112. package/src/__tests__/persistence-secret-redaction.test.ts +1 -0
  113. package/src/__tests__/pkb-autoinject.test.ts +2 -5
  114. package/src/__tests__/plugin-api-shim.test.ts +3 -6
  115. package/src/__tests__/plugin-bootstrap.test.ts +14 -40
  116. package/src/__tests__/plugin-registry.test.ts +3 -76
  117. package/src/__tests__/plugin-types.test.ts +0 -193
  118. package/src/__tests__/process-message-display-content.test.ts +6 -2
  119. package/src/__tests__/reaction-persistence.test.ts +1 -1
  120. package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +5 -1
  121. package/src/__tests__/resolve-trust-class.test.ts +4 -4
  122. package/src/__tests__/runtime-events-sse-reconnect.test.ts +60 -23
  123. package/src/__tests__/schedule-routes.test.ts +603 -2
  124. package/src/__tests__/schedule-store.test.ts +41 -0
  125. package/src/__tests__/schedule-tools.test.ts +35 -0
  126. package/src/__tests__/send-endpoint-busy.test.ts +4 -1
  127. package/src/__tests__/server-history-render.test.ts +314 -1
  128. package/src/__tests__/skill-feature-flags-integration.test.ts +33 -0
  129. package/src/__tests__/skillssh-files.test.ts +1 -1
  130. package/src/__tests__/subagent-call-site-routing.test.ts +1 -1
  131. package/src/__tests__/subagent-fork-notifications.test.ts +1 -3
  132. package/src/__tests__/subagent-fork-spawn.test.ts +1 -1
  133. package/src/__tests__/subagent-manager-notify.test.ts +1 -3
  134. package/src/__tests__/subagent-notify-parent.test.ts +1 -3
  135. package/src/__tests__/subagent-spawn-tool-fork.test.ts +1 -1
  136. package/src/__tests__/system-prompt.test.ts +20 -0
  137. package/src/__tests__/task-scheduler.test.ts +162 -1
  138. package/src/__tests__/terminal-tools.test.ts +6 -1
  139. package/src/__tests__/title-generate-hook.test.ts +319 -0
  140. package/src/__tests__/tool-error-hook.test.ts +278 -0
  141. package/src/__tests__/tool-preview-lifecycle.test.ts +468 -5
  142. package/src/__tests__/tool-result-metadata-plumbing.test.ts +1 -0
  143. package/src/__tests__/tool-result-truncate-hook.test.ts +127 -0
  144. package/src/__tests__/tool-result-truncation.test.ts +0 -2
  145. package/src/__tests__/ui-choice-copy-surfaces.test.ts +254 -0
  146. package/src/__tests__/ui-work-result-surface.test.ts +159 -0
  147. package/src/__tests__/usage-routes.test.ts +285 -1
  148. package/src/__tests__/user-plugin-loader.test.ts +54 -286
  149. package/src/__tests__/voice-session-bridge.test.ts +6 -3
  150. package/src/__tests__/web-search-backend-failure.test.ts +166 -0
  151. package/src/acp/__tests__/agent-process.test.ts +161 -0
  152. package/src/acp/__tests__/client-handler.test.ts +40 -0
  153. package/src/acp/__tests__/helpers/acp-history-db.ts +82 -0
  154. package/src/acp/__tests__/helpers/exec-file-stub.ts +101 -0
  155. package/src/acp/__tests__/prepare-agent-env.test.ts +137 -0
  156. package/src/acp/__tests__/session-manager-persistence.test.ts +95 -28
  157. package/src/acp/__tests__/session-manager-resume.test.ts +736 -0
  158. package/src/acp/agent-process.ts +61 -1
  159. package/src/acp/auto-install.test.ts +196 -0
  160. package/src/acp/auto-install.ts +177 -0
  161. package/src/acp/client-handler.ts +31 -0
  162. package/src/acp/feature-gate.test.ts +48 -0
  163. package/src/acp/feature-gate.ts +34 -0
  164. package/src/acp/prepare-agent-env.ts +83 -29
  165. package/src/acp/resolve-agent.test.ts +320 -7
  166. package/src/acp/resolve-agent.ts +182 -18
  167. package/src/acp/resume-hint.ts +25 -0
  168. package/src/acp/session-manager.ts +495 -73
  169. package/src/acp/types.ts +8 -0
  170. package/src/agent/compaction-circuit.ts +60 -102
  171. package/src/agent/loop.ts +362 -485
  172. package/src/api/events/assistant-thinking-delta.ts +33 -0
  173. package/src/api/events/tool-output-chunk.ts +45 -0
  174. package/src/api/events/tool-use-preview-start.ts +32 -0
  175. package/src/api/events/trace-event.ts +69 -0
  176. package/src/api/index.ts +48 -13
  177. package/src/api/responses/conversation-message.ts +374 -0
  178. package/src/approvals/guardian-request-resolvers.ts +1 -1
  179. package/src/avatar/__tests__/avatar-store.test.ts +34 -29
  180. package/src/background-wake/next-wake.ts +1 -0
  181. package/src/cli/commands/__tests__/notifications.test.ts +58 -14
  182. package/src/cli/commands/notifications.ts +112 -60
  183. package/src/config/__tests__/feature-flag-registry-guard.test.ts +2 -2
  184. package/src/config/acp-defaults.test.ts +10 -0
  185. package/src/config/acp-defaults.ts +6 -0
  186. package/src/config/assistant-feature-flags.ts +22 -11
  187. package/src/config/bundled-skills/acp/SKILL.md +83 -31
  188. package/src/config/bundled-skills/acp/TOOLS.json +4 -4
  189. package/src/config/bundled-skills/app-builder/SKILL.md +224 -398
  190. package/src/config/bundled-skills/app-builder/TOOLS.json +29 -0
  191. package/src/config/bundled-skills/app-builder/references/DESIGN_SYSTEM.md +48 -0
  192. package/src/config/bundled-skills/app-builder/references/RESPONSIVE.md +57 -0
  193. package/src/config/bundled-skills/app-builder/references/SLIDES.md +38 -0
  194. package/src/config/bundled-skills/app-builder/references/examples/README.md +17 -0
  195. package/src/config/bundled-skills/app-builder/references/examples/expense-tracker.md +515 -0
  196. package/src/config/bundled-skills/app-builder/references/examples/focus-timer.md +342 -0
  197. package/src/config/bundled-skills/app-builder/references/examples/habit-tracker.md +490 -0
  198. package/src/config/bundled-skills/app-builder/tools/app-list.ts +62 -0
  199. package/src/config/bundled-skills/document-editor/SKILL.md +28 -23
  200. package/src/config/bundled-skills/document-editor/TOOLS.json +1 -1
  201. package/src/config/bundled-skills/messaging/SKILL.md +0 -7
  202. package/src/config/bundled-tool-registry.ts +2 -0
  203. package/src/config/feature-flag-cache.ts +3 -3
  204. package/src/config/feature-flag-registry.json +48 -7
  205. package/src/config/schemas/__tests__/memory-v2.test.ts +1 -0
  206. package/src/config/schemas/__tests__/memory-v3.test.ts +25 -0
  207. package/src/config/schemas/heartbeat.ts +9 -0
  208. package/src/config/schemas/llm.ts +1 -0
  209. package/src/config/schemas/memory-v2.ts +8 -0
  210. package/src/config/schemas/memory-v3.ts +8 -0
  211. package/src/config/schemas/platform.ts +8 -0
  212. package/src/config/seed-inference-profiles.ts +2 -2
  213. package/src/config/skills.ts +13 -0
  214. package/src/context/compactor.ts +1 -1
  215. package/src/context/strip-injections.ts +128 -0
  216. package/src/context/token-estimator.ts +23 -0
  217. package/src/context/tool-result-truncation.ts +0 -23
  218. package/src/context/window-manager.ts +5 -7
  219. package/src/credential-execution/executable-discovery.ts +16 -0
  220. package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +6 -0
  221. package/src/daemon/__tests__/inference-profile-notification.test.ts +153 -0
  222. package/src/daemon/__tests__/native-web-search-metadata.test.ts +10 -8
  223. package/src/daemon/assistant-attachments.ts +1 -1
  224. package/src/daemon/config-watcher.ts +2 -2
  225. package/src/daemon/context-overflow-reducer.ts +0 -1
  226. package/src/daemon/conversation-agent-loop-handlers.ts +594 -153
  227. package/src/daemon/conversation-agent-loop.ts +301 -997
  228. package/src/daemon/conversation-history.ts +5 -4
  229. package/src/daemon/conversation-lifecycle.ts +3 -4
  230. package/src/daemon/conversation-messaging.ts +7 -6
  231. package/src/daemon/conversation-process.ts +11 -16
  232. package/src/daemon/conversation-registry.ts +159 -0
  233. package/src/daemon/conversation-runtime-assembly.ts +218 -398
  234. package/src/daemon/conversation-slash.ts +6 -25
  235. package/src/daemon/conversation-store.ts +9 -90
  236. package/src/daemon/conversation-surfaces.ts +222 -4
  237. package/src/daemon/conversation-tool-setup.ts +2 -29
  238. package/src/daemon/conversation-workspace.ts +17 -0
  239. package/src/daemon/conversation.ts +32 -20
  240. package/src/daemon/external-plugins-bootstrap.ts +17 -18
  241. package/src/daemon/handlers/config-a2a.ts +51 -36
  242. package/src/daemon/handlers/config-slack-channel.ts +20 -14
  243. package/src/daemon/handlers/config-telegram.ts +16 -2
  244. package/src/daemon/handlers/conversations.ts +3 -1
  245. package/src/daemon/handlers/shared.ts +156 -84
  246. package/src/daemon/handlers/skills.ts +42 -10
  247. package/src/daemon/lifecycle.ts +25 -0
  248. package/src/daemon/message-types/apps.ts +1 -29
  249. package/src/daemon/message-types/messages.ts +9 -57
  250. package/src/daemon/message-types/skills.ts +2 -0
  251. package/src/daemon/message-types/surfaces.ts +136 -3
  252. package/src/daemon/now-scratchpad.ts +21 -0
  253. package/src/daemon/orphan-reaper.test.ts +210 -0
  254. package/src/daemon/orphan-reaper.ts +240 -0
  255. package/src/daemon/overflow-reduction-loop.ts +230 -0
  256. package/src/daemon/persist-unsendable-image.ts +117 -0
  257. package/src/daemon/process-message.ts +1 -3
  258. package/src/daemon/server.ts +2 -0
  259. package/src/daemon/trace-emitter.ts +6 -4
  260. package/src/daemon/trust-context.ts +19 -0
  261. package/src/daemon/wake-target-adapter.ts +3 -1
  262. package/src/heartbeat/__tests__/heartbeat-service.test.ts +3 -0
  263. package/src/heartbeat/heartbeat-run-store.ts +23 -1
  264. package/src/heartbeat/heartbeat-service.ts +26 -0
  265. package/src/home/home-greeting-cache.ts +24 -1
  266. package/src/ipc/__tests__/browser-ipc.test.ts +1 -1
  267. package/src/ipc/__tests__/ui-request-route.test.ts +3 -3
  268. package/src/ipc/gateway-client.test.ts +2 -2
  269. package/src/ipc/gateway-client.ts +3 -3
  270. package/src/ipc/skill-routes/__tests__/memory.test.ts +15 -0
  271. package/src/ipc/skill-routes/memory.ts +4 -2
  272. package/src/media/gemini-image-service.ts +15 -0
  273. package/src/media/openai-image-service.ts +14 -0
  274. package/src/media/types.ts +34 -0
  275. package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +56 -0
  276. package/src/memory/auth-fallback-events-store.ts +94 -0
  277. package/src/memory/conversation-starter-checkpoints.ts +1 -0
  278. package/src/memory/conversation-title-service.ts +65 -41
  279. package/src/memory/db-init.ts +6 -0
  280. package/src/memory/graph/__tests__/conversation-graph-memory-registry.test.ts +119 -0
  281. package/src/memory/graph/conversation-graph-memory.ts +65 -0
  282. package/src/memory/job-handlers/conversation-starters.ts +13 -2
  283. package/src/memory/jobs-store.ts +33 -0
  284. package/src/memory/jobs-worker.ts +32 -5
  285. package/src/memory/llm-usage-store.ts +224 -50
  286. package/src/memory/migrations/222-strip-placeholder-sentinels-from-messages.ts +6 -5
  287. package/src/memory/migrations/270-schedule-source-conversation.ts +13 -0
  288. package/src/memory/migrations/271-create-auth-fallback-events.ts +21 -0
  289. package/src/memory/migrations/272-acp-session-history-cwd.ts +36 -0
  290. package/src/memory/migrations/index.ts +3 -0
  291. package/src/memory/pkb/autoinject.ts +61 -0
  292. package/src/memory/pkb/context.ts +50 -0
  293. package/src/memory/pkb/types.ts +14 -0
  294. package/src/memory/schedule-attribution-sql.ts +104 -0
  295. package/src/memory/schema/acp.ts +4 -0
  296. package/src/memory/schema/infrastructure.ts +16 -0
  297. package/src/memory/usage-grouped-buckets.ts +6 -1
  298. package/src/memory/v2/__tests__/consolidation-job.test.ts +4 -4
  299. package/src/memory/v2/consolidation-job.ts +14 -5
  300. package/src/notifications/conversation-pairing.ts +8 -15
  301. package/src/notifications/decision-engine.ts +6 -3
  302. package/src/notifications/home-feed-side-effect.ts +12 -1
  303. package/src/permissions/prompter.ts +4 -0
  304. package/src/plugin-api/constants.ts +4 -0
  305. package/src/plugin-api/index.ts +7 -5
  306. package/src/plugin-api/types.ts +151 -1
  307. package/src/plugins/defaults/compaction/compact.ts +59 -0
  308. package/src/plugins/defaults/compaction/package.json +1 -1
  309. package/src/plugins/defaults/compaction/register.ts +8 -19
  310. package/src/plugins/defaults/empty-response/hooks/stop.ts +126 -0
  311. package/src/plugins/defaults/empty-response/register.ts +8 -13
  312. package/src/plugins/defaults/index.ts +2 -18
  313. package/src/plugins/defaults/memory-retrieval/hooks/post-compact.ts +95 -0
  314. package/src/plugins/defaults/memory-retrieval/hooks/user-prompt-submit-temp.ts +216 -0
  315. package/src/plugins/defaults/memory-retrieval/injector-chain.ts +35 -0
  316. package/src/plugins/defaults/{injectors/register.ts → memory-retrieval/injectors.ts} +288 -81
  317. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/assign.test.ts +4 -4
  318. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/health.test.ts +16 -0
  319. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/live-integration.test.ts +4 -4
  320. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/maintain-job.test.ts +5 -5
  321. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/orchestrate.test.ts +48 -12
  322. package/src/plugins/defaults/memory-v3-shadow/__tests__/provider-blocks.test.ts +13 -0
  323. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/reconcile.test.ts +2 -2
  324. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/render-injection.test.ts +1 -1
  325. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/router.test.ts +104 -32
  326. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/selection-log-store.test.ts +8 -8
  327. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/selector.test.ts +96 -30
  328. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/shadow-plugin.test.ts +34 -16
  329. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/assign.ts +5 -5
  330. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/capabilities.ts +2 -2
  331. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/health.ts +0 -0
  332. package/src/plugins/defaults/memory-v3-shadow/hooks/post-compact.ts +14 -0
  333. package/src/plugins/defaults/memory-v3-shadow/hooks/user-prompt-submit.ts +19 -0
  334. package/src/plugins/defaults/memory-v3-shadow/injector.ts +75 -0
  335. package/src/plugins/defaults/memory-v3-shadow/llm-retry.ts +32 -0
  336. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/maintain-job.ts +8 -8
  337. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/orchestrate.ts +26 -14
  338. package/src/plugins/defaults/{llm-call → memory-v3-shadow}/package.json +2 -2
  339. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/page-content.ts +2 -2
  340. package/src/plugins/defaults/memory-v3-shadow/provider-blocks.ts +26 -0
  341. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/reconcile.ts +3 -3
  342. package/src/plugins/defaults/memory-v3-shadow/register.ts +26 -0
  343. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/render-injection.ts +1 -1
  344. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/router.ts +51 -45
  345. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/selection-log-store.ts +4 -4
  346. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/selector.ts +61 -46
  347. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/shadow-plugin.ts +69 -99
  348. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/tree.ts +1 -1
  349. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/types.ts +8 -0
  350. package/src/plugins/defaults/title-generate/hooks/stop.ts +75 -0
  351. package/src/plugins/defaults/title-generate/hooks/user-prompt-submit.ts +35 -0
  352. package/src/plugins/defaults/title-generate/package.json +1 -1
  353. package/src/plugins/defaults/title-generate/register.ts +18 -18
  354. package/src/plugins/defaults/tool-error/hooks/post-tool-use.ts +118 -0
  355. package/src/plugins/defaults/tool-error/package.json +1 -1
  356. package/src/plugins/defaults/tool-error/register.ts +9 -21
  357. package/src/plugins/defaults/tool-result-truncate/hooks/post-tool-use.ts +32 -0
  358. package/src/plugins/defaults/tool-result-truncate/register.ts +10 -21
  359. package/src/plugins/defaults/tool-result-truncate/terminal.ts +37 -18
  360. package/src/plugins/external-api.ts +2 -2
  361. package/src/plugins/pipeline.ts +6 -305
  362. package/src/plugins/registry.ts +10 -55
  363. package/src/plugins/types.ts +62 -797
  364. package/src/plugins/user-loader.ts +30 -127
  365. package/src/proactive-artifact/aux-message-injector.ts +4 -4
  366. package/src/proactive-artifact/job.test.ts +8 -13
  367. package/src/prompts/__tests__/system-prompt.test.ts +42 -0
  368. package/src/prompts/templates/BOOTSTRAP-ACTIVATION-RAIL.md +64 -0
  369. package/src/prompts/templates/BOOTSTRAP.md +2 -2
  370. package/src/prompts/templates/system-sections.ts +15 -0
  371. package/src/providers/anthropic/client.ts +37 -29
  372. package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +112 -0
  373. package/src/providers/openai/chat-completions-provider.ts +44 -0
  374. package/src/providers/openrouter/client.ts +1 -0
  375. package/src/providers/placeholder-sentinels.ts +35 -0
  376. package/src/runtime/__tests__/agent-wake.test.ts +10 -6
  377. package/src/runtime/__tests__/interactive-ui.test.ts +1 -1
  378. package/src/runtime/agent-wake.ts +2 -5
  379. package/src/runtime/assistant-event-hub.ts +37 -7
  380. package/src/runtime/{conversation-stream-state.ts → assistant-stream-state.ts} +132 -58
  381. package/src/runtime/channel-approvals.ts +1 -1
  382. package/src/runtime/http-router.ts +16 -21
  383. package/src/runtime/http-types.ts +16 -70
  384. package/src/runtime/interactive-ui.ts +1 -1
  385. package/src/runtime/pending-interactions.ts +1 -0
  386. package/src/runtime/routes/__tests__/acp-routes.test.ts +283 -55
  387. package/src/runtime/routes/__tests__/consolidation-routes.test.ts +265 -2
  388. package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +1 -1
  389. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +31 -1
  390. package/src/runtime/routes/__tests__/memory-v2-routes.test.ts +6 -2
  391. package/src/runtime/routes/__tests__/surface-action-routes.test.ts +5 -4
  392. package/src/runtime/routes/__tests__/surface-content-routes.test.ts +4 -1
  393. package/src/runtime/routes/__tests__/tts-routes.test.ts +6 -2
  394. package/src/runtime/routes/acp-routes.test.ts +89 -25
  395. package/src/runtime/routes/acp-routes.ts +81 -29
  396. package/src/runtime/routes/app-management-routes.ts +6 -117
  397. package/src/runtime/routes/app-routes.ts +13 -15
  398. package/src/runtime/routes/approval-routes.ts +1 -1
  399. package/src/runtime/routes/attachment-routes.ts +26 -15
  400. package/src/runtime/routes/avatar-routes.ts +26 -0
  401. package/src/runtime/routes/browser-routes.ts +1 -1
  402. package/src/runtime/routes/browser-tabs-routes.ts +6 -10
  403. package/src/runtime/routes/btw-routes.ts +29 -23
  404. package/src/runtime/routes/consolidation-routes.ts +120 -20
  405. package/src/runtime/routes/conversation-cli-routes.ts +1 -1
  406. package/src/runtime/routes/conversation-list-routes.ts +1 -1
  407. package/src/runtime/routes/conversation-query-routes.ts +3 -1
  408. package/src/runtime/routes/conversation-routes.ts +372 -185
  409. package/src/runtime/routes/conversation-starter-routes.ts +13 -7
  410. package/src/runtime/routes/conversations-import-routes.ts +24 -7
  411. package/src/runtime/routes/documents-routes.ts +4 -0
  412. package/src/runtime/routes/domain-routes.ts +51 -37
  413. package/src/runtime/routes/epoch-millis-range.ts +34 -0
  414. package/src/runtime/routes/events-routes.ts +28 -34
  415. package/src/runtime/routes/gateway-log-routes.ts +26 -4
  416. package/src/runtime/routes/heartbeat-routes.ts +32 -12
  417. package/src/runtime/routes/host-app-control-routes.ts +1 -1
  418. package/src/runtime/routes/host-cu-routes.ts +1 -1
  419. package/src/runtime/routes/identity-intro-cache.ts +11 -34
  420. package/src/runtime/routes/identity-routes.ts +224 -18
  421. package/src/runtime/routes/image-generation-routes.ts +40 -2
  422. package/src/runtime/routes/inbound-message-handler.ts +1 -1
  423. package/src/runtime/routes/index.ts +2 -0
  424. package/src/runtime/routes/integrations/a2a.ts +12 -10
  425. package/src/runtime/routes/integrations/slack/__tests__/channel.test.ts +16 -0
  426. package/src/runtime/routes/integrations/slack/channel.ts +4 -0
  427. package/src/runtime/routes/integrations/slack/share.ts +27 -6
  428. package/src/runtime/routes/integrations/telegram.ts +6 -0
  429. package/src/runtime/routes/integrations/twilio.ts +42 -0
  430. package/src/runtime/routes/internal-telemetry-routes.ts +88 -0
  431. package/src/runtime/routes/log-export-routes.ts +8 -0
  432. package/src/runtime/routes/memory-v2-routes.ts +15 -8
  433. package/src/runtime/routes/memory-v3-routes.ts +66 -34
  434. package/src/runtime/routes/oauth-apps.ts +66 -12
  435. package/src/runtime/routes/oauth-providers.ts +44 -5
  436. package/src/runtime/routes/platform-routes.ts +81 -5
  437. package/src/runtime/routes/playground/__tests__/force-compact.test.ts +6 -4
  438. package/src/runtime/routes/playground/force-compact.ts +1 -1
  439. package/src/runtime/routes/playground/helpers.ts +1 -1
  440. package/src/runtime/routes/rename-conversation-routes.ts +5 -0
  441. package/src/runtime/routes/schedule-routes.ts +152 -42
  442. package/src/runtime/routes/secret-routes.ts +14 -2
  443. package/src/runtime/routes/skills-routes.ts +43 -14
  444. package/src/runtime/routes/surface-conversation-resolver.ts +4 -3
  445. package/src/runtime/routes/tool-call-confirmation-enrichment.test.ts +161 -0
  446. package/src/runtime/routes/tool-call-confirmation-enrichment.ts +107 -0
  447. package/src/runtime/routes/trust-rules-routes.ts +26 -2
  448. package/src/runtime/routes/tts-routes.ts +35 -0
  449. package/src/runtime/routes/types.ts +66 -8
  450. package/src/runtime/routes/usage-routes.ts +47 -39
  451. package/src/runtime/routes/webhook-routes.ts +41 -2
  452. package/src/runtime/routes/work-items-routes.ts +2 -4
  453. package/src/runtime/routes/workspace-routes.ts +4 -0
  454. package/src/runtime/services/__tests__/analyze-conversation.test.ts +6 -0
  455. package/src/runtime/services/analyze-conversation.ts +2 -2
  456. package/src/runtime/services/conversation-serializer.ts +1 -1
  457. package/src/schedule/schedule-store.ts +20 -1
  458. package/src/schedule/schedule-usage-store.ts +83 -0
  459. package/src/schedule/scheduler.ts +12 -5
  460. package/src/signals/cancel.ts +2 -4
  461. package/src/skills/catalog-files.ts +2 -2
  462. package/src/skills/catalog-install.ts +3 -0
  463. package/src/skills/categories-cache.ts +118 -0
  464. package/src/skills/clawhub-files.ts +1 -2
  465. package/src/skills/skillssh-files.ts +1 -2
  466. package/src/subagent/manager.ts +17 -5
  467. package/src/telemetry/types.ts +29 -1
  468. package/src/telemetry/usage-telemetry-reporter.test.ts +112 -3
  469. package/src/telemetry/usage-telemetry-reporter.ts +57 -2
  470. package/src/tools/acp/context.ts +20 -0
  471. package/src/tools/acp/list-agents.test.ts +7 -1
  472. package/src/tools/acp/spawn.test.ts +158 -55
  473. package/src/tools/acp/spawn.ts +47 -72
  474. package/src/tools/acp/steer.test.ts +105 -8
  475. package/src/tools/acp/steer.ts +48 -17
  476. package/src/tools/apps/executors.ts +13 -8
  477. package/src/tools/executor.ts +1 -53
  478. package/src/tools/filesystem/write.ts +34 -0
  479. package/src/tools/network/__tests__/web-search-metadata.test.ts +7 -1
  480. package/src/tools/network/__tests__/web-search.test.ts +11 -3
  481. package/src/tools/network/web-search-error.test.ts +248 -0
  482. package/src/tools/network/web-search-error.ts +267 -0
  483. package/src/tools/network/web-search.ts +207 -48
  484. package/src/tools/schedule/create.ts +2 -0
  485. package/src/tools/subagent/spawn.ts +2 -4
  486. package/src/tools/terminal/safe-env.ts +10 -1
  487. package/src/tools/ui-surface/definitions.ts +34 -5
  488. package/src/tts/__tests__/provider-catalog-consistency.test.ts +85 -1
  489. package/src/tts/provider-catalog.ts +76 -1
  490. package/src/util/mutex.ts +47 -0
  491. package/src/workspace/git-service.ts +1 -42
  492. package/src/workspace/migrations/051-seed-conversation-summarization-callsite.ts +4 -5
  493. package/src/workspace/migrations/095-bump-heartbeat-interval-30m-to-60m.ts +51 -0
  494. package/src/workspace/migrations/096-reduce-quality-profile-effort.ts +72 -0
  495. package/src/workspace/migrations/097-enable-adaptive-thinking-managed-profiles.ts +117 -0
  496. package/src/workspace/migrations/registry.ts +6 -0
  497. package/docs/plugins.md +0 -836
  498. package/examples/plugins/echo/register.ts +0 -184
  499. package/src/__tests__/bootstrap-turn-cleanup.test.ts +0 -44
  500. package/src/__tests__/circuit-breaker-pipeline.test.ts +0 -405
  501. package/src/__tests__/compaction-pipeline.test.ts +0 -210
  502. package/src/__tests__/compaction-timeout-recovery.test.ts +0 -251
  503. package/src/__tests__/empty-response-pipeline.test.ts +0 -423
  504. package/src/__tests__/llm-call-pipeline.test.ts +0 -287
  505. package/src/__tests__/memory-retrieval-pipeline.test.ts +0 -418
  506. package/src/__tests__/persistence-pipeline.test.ts +0 -503
  507. package/src/__tests__/pipeline-runner.test.ts +0 -564
  508. package/src/__tests__/title-generate-pipeline.test.ts +0 -211
  509. package/src/__tests__/token-estimate-pipeline.test.ts +0 -479
  510. package/src/__tests__/tool-error-pipeline.test.ts +0 -241
  511. package/src/__tests__/tool-execute-pipeline.test.ts +0 -417
  512. package/src/__tests__/tool-result-truncate-pipeline.test.ts +0 -341
  513. package/src/daemon/bootstrap-turn-cleanup.ts +0 -45
  514. package/src/gallery/default-gallery.ts +0 -1359
  515. package/src/gallery/gallery-manifest.ts +0 -28
  516. package/src/home/feature-gate.ts +0 -22
  517. package/src/memory/v3/provider-blocks.ts +0 -16
  518. package/src/plugins/defaults/circuit-breaker/middlewares/circuitBreaker.ts +0 -93
  519. package/src/plugins/defaults/circuit-breaker/package.json +0 -15
  520. package/src/plugins/defaults/circuit-breaker/register.ts +0 -39
  521. package/src/plugins/defaults/compaction/middlewares/compaction.ts +0 -25
  522. package/src/plugins/defaults/compaction/terminal.ts +0 -73
  523. package/src/plugins/defaults/empty-response/middlewares/emptyResponse.ts +0 -22
  524. package/src/plugins/defaults/empty-response/terminal.ts +0 -106
  525. package/src/plugins/defaults/injectors/package.json +0 -15
  526. package/src/plugins/defaults/llm-call/middlewares/llmCall.ts +0 -17
  527. package/src/plugins/defaults/llm-call/register.ts +0 -45
  528. package/src/plugins/defaults/memory-retrieval/middlewares/memoryRetrieval.ts +0 -17
  529. package/src/plugins/defaults/memory-retrieval/package.json +0 -15
  530. package/src/plugins/defaults/memory-retrieval/register.ts +0 -181
  531. package/src/plugins/defaults/overflow-reduce/middlewares/overflowReduce.ts +0 -126
  532. package/src/plugins/defaults/overflow-reduce/package.json +0 -15
  533. package/src/plugins/defaults/overflow-reduce/register.ts +0 -42
  534. package/src/plugins/defaults/persistence/middlewares/persistence.ts +0 -19
  535. package/src/plugins/defaults/persistence/package.json +0 -15
  536. package/src/plugins/defaults/persistence/register.ts +0 -38
  537. package/src/plugins/defaults/persistence/terminal.ts +0 -83
  538. package/src/plugins/defaults/title-generate/terminal.ts +0 -31
  539. package/src/plugins/defaults/token-estimate/middlewares/tokenEstimate.ts +0 -23
  540. package/src/plugins/defaults/token-estimate/package.json +0 -15
  541. package/src/plugins/defaults/token-estimate/register.ts +0 -34
  542. package/src/plugins/defaults/token-estimate/terminal.ts +0 -40
  543. package/src/plugins/defaults/tool-error/middlewares/toolError.ts +0 -21
  544. package/src/plugins/defaults/tool-error/terminal.ts +0 -47
  545. package/src/plugins/defaults/tool-execute/middlewares/toolExecute.ts +0 -23
  546. package/src/plugins/defaults/tool-execute/package.json +0 -15
  547. package/src/plugins/defaults/tool-execute/register.ts +0 -49
  548. package/src/plugins/defaults/tool-result-truncate/middlewares/toolResultTruncate.ts +0 -23
  549. package/src/plugins/defaults/tool-result-truncate/types.ts +0 -22
  550. package/src/skills/category-inference.ts +0 -111
  551. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/capabilities.test.ts +0 -0
  552. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/core.test.ts +0 -0
  553. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/fixtures/eval-turns.json +0 -0
  554. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/fixtures/live-turns.json +0 -0
  555. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/needle.test.ts +0 -0
  556. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/snapshot.test.ts +0 -0
  557. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/tree.test.ts +0 -0
  558. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/types.test.ts +0 -0
  559. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/working-set-eviction.test.ts +0 -0
  560. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/working-set-skeleton.test.ts +0 -0
  561. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/core.ts +0 -0
  562. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/README.md +0 -0
  563. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/assignments.json +0 -0
  564. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/core.json +0 -0
  565. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/leaves/domain-a/topic-x.md +0 -0
  566. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/leaves/domain-a/topic-y.md +0 -0
  567. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/leaves/domain-b/topic-z.md +0 -0
  568. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/needle.ts +0 -0
  569. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/snapshot.ts +0 -0
  570. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/working-set.ts +0 -0
@@ -3,38 +3,33 @@
3
3
  *
4
4
  * Greetings are sourced from (in priority order):
5
5
  * 1. A `## Greetings` section in SOUL.md (user-defined bullet list)
6
- * 2. A cached greetings array (populated by the BTW side-chain LLM call)
7
- * 3. Fallback: the assistant name from IDENTITY.md
6
+ * 2. A cached greetings array (populated by the empty-state greeting callsite)
7
+ * 3. A generic fallback when generation is unavailable
8
8
  *
9
- * Cache uses TTL + content-hash invalidation: when IDENTITY.md, SOUL.md, or
10
- * the guardian persona change, the cache is busted.
9
+ * Cache invalidation is intentionally TTL-only. User-authored SOUL.md
10
+ * greetings are read before cache, so manual overrides still take priority
11
+ * without coupling cache validity to prompt-file edits.
11
12
  *
12
13
  * Storage uses the existing `memory_checkpoints` table (simple key-value store).
13
14
  */
14
15
 
15
- import { createHash } from "node:crypto";
16
16
  import { existsSync, readFileSync } from "node:fs";
17
17
 
18
18
  import {
19
19
  getMemoryCheckpoint,
20
20
  setMemoryCheckpoint,
21
21
  } from "../../memory/checkpoints.js";
22
- import { resolveGuardianPersona } from "../../prompts/persona-resolver.js";
23
22
  import { getWorkspacePromptPath } from "../../util/platform.js";
24
23
 
25
24
  // ---------------------------------------------------------------------------
26
25
  // Constants
27
26
  // ---------------------------------------------------------------------------
28
27
 
29
- const CACHE_TTL_MS = 4 * 60 * 60 * 1000; // 4 hours
28
+ const CACHE_TTL_MS = 2 * 24 * 60 * 60 * 1000; // 2 days
30
29
 
31
30
  const CHECKPOINT_KEY_GREETINGS = "identity:intro:greetings";
32
- const CHECKPOINT_KEY_HASH = "identity:intro:content_hash";
33
31
  const CHECKPOINT_KEY_TIMESTAMP = "identity:intro:cached_at";
34
32
 
35
- /** Workspace files whose content influences the identity intro. */
36
- const IDENTITY_FILES = ["IDENTITY.md", "SOUL.md"] as const;
37
-
38
33
  // ---------------------------------------------------------------------------
39
34
  // Helpers
40
35
  // ---------------------------------------------------------------------------
@@ -125,14 +120,6 @@ export function readWorkspaceGreetings(): string[] | null {
125
120
  return parseGreetingsSection(soulContent);
126
121
  }
127
122
 
128
- /** Compute a SHA-256 hex hash of the concatenated identity file contents. */
129
- export function computeIdentityContentHash(): string {
130
- const staticFiles = IDENTITY_FILES.map(readWorkspaceFile).join("\n---\n");
131
- const guardianPersona = resolveGuardianPersona() ?? "";
132
- const combined = staticFiles + "\n---\n" + guardianPersona;
133
- return createHash("sha256").update(combined).digest("hex");
134
- }
135
-
136
123
  // ---------------------------------------------------------------------------
137
124
  // Public API
138
125
  // ---------------------------------------------------------------------------
@@ -142,27 +129,22 @@ export interface CachedIntro {
142
129
  }
143
130
 
144
131
  /**
145
- * Retrieve the cached greetings array if it exists, is within the TTL window,
146
- * and the identity files have not changed since it was generated.
132
+ * Retrieve the cached greetings array if it exists and is within the TTL
133
+ * window.
147
134
  *
148
- * Returns `null` when the cache is missing, expired, or invalidated.
135
+ * Returns `null` when the cache is missing or expired.
149
136
  */
150
137
  export function getCachedIntro(): CachedIntro | null {
151
138
  try {
152
139
  const raw = getMemoryCheckpoint(CHECKPOINT_KEY_GREETINGS);
153
- const hash = getMemoryCheckpoint(CHECKPOINT_KEY_HASH);
154
140
  const timestampStr = getMemoryCheckpoint(CHECKPOINT_KEY_TIMESTAMP);
155
141
 
156
- if (!raw || !hash || !timestampStr) return null;
142
+ if (!raw || !timestampStr) return null;
157
143
 
158
144
  // TTL check
159
145
  const cachedAt = Number(timestampStr);
160
146
  if (isNaN(cachedAt) || Date.now() - cachedAt > CACHE_TTL_MS) return null;
161
147
 
162
- // Content-hash check — bust cache when identity files change
163
- const currentHash = computeIdentityContentHash();
164
- if (currentHash !== hash) return null;
165
-
166
148
  // Parse stored value — handles both JSON array and legacy single string
167
149
  let greetings: string[];
168
150
  try {
@@ -178,16 +160,11 @@ export function getCachedIntro(): CachedIntro | null {
178
160
  }
179
161
  }
180
162
 
181
- /**
182
- * Store a greetings array in the cache along with the current content hash
183
- * and timestamp.
184
- */
163
+ /** Store a greetings array in the cache along with the current timestamp. */
185
164
  export function setCachedIntro(greetings: string[]): void {
186
165
  try {
187
- const hash = computeIdentityContentHash();
188
166
  const now = String(Date.now());
189
167
  setMemoryCheckpoint(CHECKPOINT_KEY_GREETINGS, JSON.stringify(greetings));
190
- setMemoryCheckpoint(CHECKPOINT_KEY_HASH, hash);
191
168
  setMemoryCheckpoint(CHECKPOINT_KEY_TIMESTAMP, now);
192
169
  } catch {
193
170
  // Cache write failure is non-fatal — next request will regenerate.
@@ -7,10 +7,15 @@ import { availableParallelism, cpus, totalmem } from "node:os";
7
7
 
8
8
  import { z } from "zod";
9
9
 
10
+ import { isAssistantFeatureFlagEnabled } from "../../config/assistant-feature-flags.js";
10
11
  import { getCpuLimit, getIsPlatform } from "../../config/env-registry.js";
12
+ import { resolveCallSiteConfig } from "../../config/llm-resolver.js";
13
+ import { getConfig } from "../../config/loader.js";
11
14
  import { parseIdentityFields } from "../../daemon/handlers/identity.js";
12
15
  import { getProfilerRuntimeStatus } from "../../daemon/profiler-run-store.js";
13
16
  import { getMaxMigrationVersion } from "../../memory/migrations/registry.js";
17
+ import { buildSystemPrompt } from "../../prompts/system-prompt.js";
18
+ import { getConfiguredProvider } from "../../providers/provider-send-message.js";
14
19
  import { getCesClient } from "../../security/secure-keys.js";
15
20
  import {
16
21
  getDiskUsageInfo,
@@ -23,10 +28,13 @@ import { resolveHatchedAtReadOnly } from "../../workspace/hatched-date.js";
23
28
  import { WORKSPACE_MIGRATIONS } from "../../workspace/migrations/registry.js";
24
29
  import { getLastWorkspaceMigrationId } from "../../workspace/migrations/runner.js";
25
30
  import { ACTOR_PRINCIPALS } from "../auth/route-policy.js";
31
+ import { runBtwSidechain } from "../btw-sidechain.js";
26
32
  import { NotFoundError } from "./errors.js";
27
33
  import {
28
34
  getCachedIntro,
29
35
  readWorkspaceGreetings,
36
+ readWorkspaceIdentityIntro,
37
+ setCachedIntro,
30
38
  } from "./identity-intro-cache.js";
31
39
  import type { RouteDefinition } from "./types.js";
32
40
 
@@ -402,31 +410,204 @@ const FALLBACK_GREETINGS = [
402
410
  "Ready when you are.",
403
411
  ];
404
412
 
405
- function getIdentityIntro() {
413
+ const GENERATED_GREETING_LIMIT = 4;
414
+ const GREETING_GENERATION_TIMEOUT_MS = 10_000;
415
+ const GREETING_GENERATION_FAILURE_COOLDOWN_MS = 60_000;
416
+ const EMPTY_STATE_GREETING_CALLSITE = "emptyStateGreeting" as const;
417
+ const EMPTY_STATE_DYNAMIC_GREETINGS_FLAG =
418
+ "empty-state-dynamic-greetings" as const;
419
+
420
+ type IdentityIntroSource = "workspace" | "cache" | "fallback";
421
+
422
+ interface IdentityIntroResponse {
423
+ greetings: string[];
424
+ text: string;
425
+ source: IdentityIntroSource;
426
+ refreshing: boolean;
427
+ }
428
+
429
+ let greetingGenerationInFlight: Promise<void> | null = null;
430
+ let lastGreetingGenerationFailureAt = 0;
431
+
432
+ function identityIntroResponse(
433
+ greetings: string[],
434
+ source: IdentityIntroSource,
435
+ refreshing = false,
436
+ ): IdentityIntroResponse {
437
+ return {
438
+ greetings,
439
+ text: greetings[0] ?? "",
440
+ source,
441
+ refreshing,
442
+ };
443
+ }
444
+
445
+ function getIdentityIntro(): IdentityIntroResponse {
406
446
  // 1. User-defined greetings from SOUL.md `## Greetings`
407
447
  const workspaceGreetings = readWorkspaceGreetings();
408
448
  if (workspaceGreetings) {
409
- return { greetings: workspaceGreetings, text: workspaceGreetings[0] };
449
+ return identityIntroResponse(workspaceGreetings, "workspace");
450
+ }
451
+
452
+ const config = getConfig();
453
+ if (
454
+ !isAssistantFeatureFlagEnabled(EMPTY_STATE_DYNAMIC_GREETINGS_FLAG, config)
455
+ ) {
456
+ return identityIntroResponse(FALLBACK_GREETINGS, "fallback");
410
457
  }
411
458
 
412
- // 2. Cached LLM-generated greetings
459
+ // 2. Cached LLM-generated greetings (populated by background refresh)
413
460
  const cached = getCachedIntro();
414
461
  if (cached) {
415
- return { greetings: cached.greetings, text: cached.greetings[0] };
462
+ return identityIntroResponse(cached.greetings, "cache");
416
463
  }
417
464
 
418
- // 3. Fallback: name-based greeting + static defaults
419
- const identityPath = getWorkspacePromptPath("IDENTITY.md");
420
- if (existsSync(identityPath)) {
421
- const content = readFileSync(identityPath, "utf-8");
422
- const fields = parseIdentityFields(content);
423
- if (fields.name) {
424
- const greetings = [`Hi, I'm ${fields.name}!`, ...FALLBACK_GREETINGS];
425
- return { greetings, text: greetings[0] };
465
+ // 3. Identity intro tagline from `## Identity Intro` in IDENTITY.md
466
+ // (written during onboarding by BOOTSTRAP.md instructions)
467
+ const identityIntro = readWorkspaceIdentityIntro();
468
+ if (identityIntro) {
469
+ // Still trigger background generation so the next request gets
470
+ // LLM-generated greetings instead of the static tagline.
471
+ const refreshing = triggerEmptyStateGreetingGeneration();
472
+ return identityIntroResponse(
473
+ [identityIntro, ...FALLBACK_GREETINGS],
474
+ "workspace",
475
+ refreshing,
476
+ );
477
+ }
478
+
479
+ // 4. Trigger fresh generation without blocking the empty-state UI.
480
+ const refreshing = triggerEmptyStateGreetingGeneration();
481
+
482
+ // 5. Generic fallback only when generation is unavailable.
483
+ return identityIntroResponse(FALLBACK_GREETINGS, "fallback", refreshing);
484
+ }
485
+
486
+ function triggerEmptyStateGreetingGeneration(): boolean {
487
+ if (greetingGenerationInFlight) {
488
+ return true;
489
+ }
490
+
491
+ if (
492
+ lastGreetingGenerationFailureAt > 0 &&
493
+ Date.now() - lastGreetingGenerationFailureAt <
494
+ GREETING_GENERATION_FAILURE_COOLDOWN_MS
495
+ ) {
496
+ return false;
497
+ }
498
+
499
+ greetingGenerationInFlight = new Promise<void>((resolve) => {
500
+ queueMicrotask(() => {
501
+ void generateEmptyStateGreetings()
502
+ .then((greetings) => {
503
+ lastGreetingGenerationFailureAt = greetings === null ? Date.now() : 0;
504
+ })
505
+ .finally(() => {
506
+ greetingGenerationInFlight = null;
507
+ resolve();
508
+ });
509
+ });
510
+ });
511
+
512
+ return true;
513
+ }
514
+
515
+ async function generateEmptyStateGreetings(): Promise<string[] | null> {
516
+ try {
517
+ const provider = await getConfiguredProvider(EMPTY_STATE_GREETING_CALLSITE);
518
+ if (!provider) {
519
+ return null;
426
520
  }
521
+
522
+ const resolved = resolveCallSiteConfig(
523
+ EMPTY_STATE_GREETING_CALLSITE,
524
+ getConfig().llm,
525
+ );
526
+ const systemPrompt = buildSystemPrompt({
527
+ excludeBootstrap: true,
528
+ excludeCustomPrefix: true,
529
+ });
530
+ const result = await runBtwSidechain({
531
+ content:
532
+ `Generate ${GENERATED_GREETING_LIMIT} short first-person greeting options for the empty new-chat screen. ` +
533
+ "Use the assistant identity, voice, and relationship guidance from IDENTITY.md and SOUL.md. " +
534
+ "Each greeting should feel personal and inviting, not like a generic assistant introduction. " +
535
+ "Return only a JSON array of strings. No markdown, keys, or explanation.",
536
+ provider,
537
+ systemPrompt,
538
+ messages: [],
539
+ tools: [],
540
+ callSite: EMPTY_STATE_GREETING_CALLSITE,
541
+ maxTokens: resolved.maxTokens,
542
+ timeoutMs: GREETING_GENERATION_TIMEOUT_MS,
543
+ });
544
+
545
+ const greetings = parseGeneratedGreetings(result.text);
546
+ if (greetings.length === 0) {
547
+ return null;
548
+ }
549
+
550
+ setCachedIntro(greetings);
551
+ return greetings;
552
+ } catch (err) {
553
+ getLogger("identity").warn(
554
+ { err },
555
+ "Failed to generate empty-state greetings",
556
+ );
557
+ return null;
427
558
  }
559
+ }
560
+
561
+ function parseGeneratedGreetings(text: string): string[] {
562
+ const cleaned = text
563
+ .trim()
564
+ .replace(/^```(?:json)?\s*/i, "")
565
+ .replace(/\s*```$/i, "")
566
+ .trim();
428
567
 
429
- return { greetings: FALLBACK_GREETINGS, text: FALLBACK_GREETINGS[0] };
568
+ try {
569
+ const parsed = JSON.parse(cleaned) as unknown;
570
+ if (Array.isArray(parsed)) {
571
+ return normalizeGeneratedGreetings(parsed);
572
+ }
573
+ if (
574
+ parsed &&
575
+ typeof parsed === "object" &&
576
+ Array.isArray((parsed as { greetings?: unknown }).greetings)
577
+ ) {
578
+ return normalizeGeneratedGreetings(
579
+ (parsed as { greetings: unknown[] }).greetings,
580
+ );
581
+ }
582
+ } catch {
583
+ // Fall through to line parsing for non-JSON model output.
584
+ }
585
+
586
+ return normalizeGeneratedGreetings(cleaned.split("\n"));
587
+ }
588
+
589
+ function normalizeGeneratedGreetings(values: unknown[]): string[] {
590
+ const greetings: string[] = [];
591
+ const seen = new Set<string>();
592
+
593
+ for (const value of values) {
594
+ if (typeof value !== "string") continue;
595
+ const greeting = value
596
+ .trim()
597
+ .replace(/^(?:[-*+]\s+|\d+[.)]\s+)/, "")
598
+ .replace(/^["'`]+|["'`]+$/g, "")
599
+ .trim();
600
+ if (!greeting) continue;
601
+
602
+ const key = greeting.toLowerCase();
603
+ if (seen.has(key)) continue;
604
+ seen.add(key);
605
+ greetings.push(greeting);
606
+
607
+ if (greetings.length >= GENERATED_GREETING_LIMIT) break;
608
+ }
609
+
610
+ return greetings;
430
611
  }
431
612
 
432
613
  // ---------------------------------------------------------------------------
@@ -464,14 +645,37 @@ const cesHealthSchema = z.object({
464
645
  connected: z.boolean(),
465
646
  });
466
647
 
648
+ const healthDiskSchema = z.object({
649
+ path: z.string(),
650
+ totalMb: z.number(),
651
+ usedMb: z.number(),
652
+ freeMb: z.number(),
653
+ });
654
+
655
+ const healthMemorySchema = z.object({
656
+ currentMb: z.number(),
657
+ maxMb: z.number(),
658
+ });
659
+
660
+ const healthCpuSchema = z.object({
661
+ currentPercent: z.number(),
662
+ maxCores: z.number(),
663
+ });
664
+
665
+ const healthMigrationsSchema = z.object({
666
+ dbVersion: z.number(),
667
+ lastWorkspaceMigrationId: z.string().nullable(),
668
+ });
669
+
467
670
  const detailedHealthSchema = z.object({
468
671
  status: z.string(),
469
672
  timestamp: z.string(),
470
673
  version: z.string(),
471
- disk: z.object({}).passthrough(),
472
- memory: z.object({}).passthrough(),
473
- cpu: z.object({}).passthrough(),
474
- migrations: z.object({}).passthrough(),
674
+ // `getDiskUsageInfo()` returns null when usage can't be measured.
675
+ disk: healthDiskSchema.nullable(),
676
+ memory: healthMemorySchema,
677
+ cpu: healthCpuSchema,
678
+ migrations: healthMigrationsSchema,
475
679
  ces: cesHealthSchema,
476
680
  profiler: profilerStatusSchema.optional(),
477
681
  });
@@ -544,11 +748,13 @@ export const ROUTES: RouteDefinition[] = [
544
748
  handler: getIdentityIntro,
545
749
  summary: "Get identity greetings",
546
750
  description:
547
- "Returns an array of greetings sourced from SOUL.md, LLM cache, or static fallbacks.",
751
+ "Returns greetings sourced from SOUL.md, the generated cache, or generic fallbacks while background generation refreshes the cache.",
548
752
  tags: ["identity"],
549
753
  responseBody: z.object({
550
754
  greetings: z.array(z.string()),
551
755
  text: z.string(),
756
+ source: z.enum(["workspace", "cache", "fallback"]),
757
+ refreshing: z.boolean(),
552
758
  }),
553
759
  },
554
760
  ];
@@ -1,3 +1,5 @@
1
+ import { z } from "zod";
2
+
1
3
  import { getConfig } from "../../config/loader.js";
2
4
  import { resolveImageGenCredentials } from "../../media/image-credentials.js";
3
5
  import {
@@ -6,16 +8,50 @@ import {
6
8
  providerForModel,
7
9
  } from "../../media/image-service.js";
8
10
  import { ACTOR_PRINCIPALS } from "../auth/route-policy.js";
9
- import { BadRequestError, InternalError, UnprocessableEntityError } from "./errors.js";
11
+ import {
12
+ BadRequestError,
13
+ InternalError,
14
+ UnprocessableEntityError,
15
+ } from "./errors.js";
10
16
  import type { RouteDefinition, RouteHandlerArgs } from "./types.js";
11
17
 
18
+ // ---------------------------------------------------------------------------
19
+ // Schemas
20
+ // ---------------------------------------------------------------------------
21
+
22
+ const SourceImageSchema = z.object({
23
+ mimeType: z.string(),
24
+ dataBase64: z.string(),
25
+ });
26
+
27
+ const ImageGenerationRequestSchema = z.object({
28
+ prompt: z.string(),
29
+ mode: z.enum(["generate", "edit"]).optional(),
30
+ sourceImages: z.array(SourceImageSchema).optional(),
31
+ model: z.string().optional(),
32
+ variants: z.number().optional(),
33
+ });
34
+
35
+ const GeneratedImageSchema = z.object({
36
+ mimeType: z.string(),
37
+ dataBase64: z.string(),
38
+ title: z.string().optional(),
39
+ });
40
+
41
+ const ImageGenerationResponseSchema = z.object({
42
+ images: z.array(GeneratedImageSchema),
43
+ text: z.string().optional(),
44
+ resolvedModel: z.string(),
45
+ });
46
+ type ImageGenerationResponse = z.infer<typeof ImageGenerationResponseSchema>;
47
+
12
48
  // ---------------------------------------------------------------------------
13
49
  // Handler
14
50
  // ---------------------------------------------------------------------------
15
51
 
16
52
  async function handleImageGenerationGenerate(
17
53
  args: RouteHandlerArgs,
18
- ): Promise<unknown> {
54
+ ): Promise<ImageGenerationResponse> {
19
55
  const { prompt, mode, sourceImages, model, variants } = args.body ?? {};
20
56
 
21
57
  // Validate prompt
@@ -99,6 +135,8 @@ export const ROUTES: RouteDefinition[] = [
99
135
  description:
100
136
  "Calls the configured image-generation provider (Gemini or OpenAI) to produce one or more images.",
101
137
  tags: ["image-generation"],
138
+ requestBody: ImageGenerationRequestSchema,
139
+ responseBody: ImageGenerationResponseSchema,
102
140
  handler: handleImageGenerationGenerate,
103
141
  },
104
142
  ];
@@ -20,7 +20,7 @@ import {
20
20
  createApprovalConversationGenerator,
21
21
  createApprovalCopyGenerator,
22
22
  } from "../../daemon/approval-generators.js";
23
- import { findConversation } from "../../daemon/conversation-store.js";
23
+ import { findConversation } from "../../daemon/conversation-registry.js";
24
24
  import {
25
25
  canonicalizeTimeZone,
26
26
  resolveTurnTimezoneContext,
@@ -85,6 +85,7 @@ import { ROUTES as TELEGRAM_ROUTES } from "./integrations/telegram.js";
85
85
  import { ROUTES as TWILIO_ROUTES } from "./integrations/twilio.js";
86
86
  import { ROUTES as VERCEL_ROUTES } from "./integrations/vercel.js";
87
87
  import { ROUTES as INTERNAL_OAUTH_ROUTES } from "./internal-oauth-routes.js";
88
+ import { ROUTES as INTERNAL_TELEMETRY_ROUTES } from "./internal-telemetry-routes.js";
88
89
  import { ROUTES as INTERNAL_TWILIO_ROUTES } from "./internal-twilio-routes.js";
89
90
  import { ROUTES as LLM_CALL_SITES_ROUTES } from "./llm-call-sites-routes.js";
90
91
  import { ROUTES as LOG_EXPORT_ROUTES } from "./log-export-routes.js";
@@ -212,6 +213,7 @@ export const ROUTES: RouteDefinition[] = [
212
213
  ...INFERENCE_PROVIDER_CONNECTION_ROUTES,
213
214
  ...INFERENCE_SEND_ROUTES,
214
215
  ...INTERNAL_OAUTH_ROUTES,
216
+ ...INTERNAL_TELEMETRY_ROUTES,
215
217
  ...MCP_AUTH_ROUTES,
216
218
  ...OAUTH_CONNECT_ROUTES,
217
219
  ...INTERNAL_TWILIO_ROUTES,
@@ -10,17 +10,20 @@
10
10
  * POST /v1/integrations/a2a/invite/accept — self-hosted broker: orchestrate complete + redeem
11
11
  */
12
12
 
13
- import { z } from "zod";
14
-
15
13
  import { isA2AEnabled } from "../../../a2a/feature-gate.js";
16
14
  import { getConfig } from "../../../config/loader.js";
17
15
  import {
16
+ A2AConfigResultSchema,
18
17
  acceptA2AInvite,
18
+ AcceptA2AInviteResultSchema,
19
19
  clearA2AConfig,
20
20
  completeA2AInvite,
21
+ CompleteA2AInviteResultSchema,
21
22
  createA2AInvite,
23
+ CreateA2AInviteResultSchema,
22
24
  getA2AConfig,
23
25
  redeemA2AInvite,
26
+ RedeemA2AInviteResultSchema,
24
27
  setA2AConfig,
25
28
  } from "../../../daemon/handlers/config-a2a.js";
26
29
  import {
@@ -232,6 +235,7 @@ export const ROUTES: RouteDefinition[] = [
232
235
  description: "Check current A2A channel configuration status.",
233
236
  tags: ["integrations"],
234
237
  handler: () => handleGetA2AConfig(),
238
+ responseBody: A2AConfigResultSchema,
235
239
  },
236
240
  {
237
241
  operationId: "integrations_a2a_config_post",
@@ -242,6 +246,7 @@ export const ROUTES: RouteDefinition[] = [
242
246
  description: "Enable the A2A channel for inter-assistant communication.",
243
247
  tags: ["integrations"],
244
248
  handler: () => handleSetA2AConfig(),
249
+ responseBody: A2AConfigResultSchema,
245
250
  },
246
251
  {
247
252
  operationId: "integrations_a2a_config_delete",
@@ -252,6 +257,7 @@ export const ROUTES: RouteDefinition[] = [
252
257
  description: "Disable the A2A channel.",
253
258
  tags: ["integrations"],
254
259
  handler: () => handleClearA2AConfig(),
260
+ responseBody: A2AConfigResultSchema,
255
261
  },
256
262
  {
257
263
  operationId: "integrations_a2a_invite_post",
@@ -266,14 +272,7 @@ export const ROUTES: RouteDefinition[] = [
266
272
  "Create a shareable A2A invite token for link-based contact creation.",
267
273
  tags: ["integrations"],
268
274
  handler: handleCreateA2AInvite,
269
- responseBody: z.object({
270
- success: z.boolean(),
271
- inviteId: z.string().optional(),
272
- token: z.string().optional(),
273
- expiresAt: z.number().optional(),
274
- senderGatewayUrl: z.string().optional(),
275
- error: z.string().optional(),
276
- }),
275
+ responseBody: CreateA2AInviteResultSchema,
277
276
  },
278
277
  {
279
278
  operationId: "integrations_a2a_invite_complete_post",
@@ -288,6 +287,7 @@ export const ROUTES: RouteDefinition[] = [
288
287
  "Called by the platform to finalize the sender side of a link-based A2A connection.",
289
288
  tags: ["integrations"],
290
289
  handler: handleCompleteA2AInvite,
290
+ responseBody: CompleteA2AInviteResultSchema,
291
291
  },
292
292
  {
293
293
  operationId: "integrations_a2a_invite_redeem_post",
@@ -302,6 +302,7 @@ export const ROUTES: RouteDefinition[] = [
302
302
  "Called by the platform to create a trusted contact on the receiver side of a link-based A2A connection.",
303
303
  tags: ["integrations"],
304
304
  handler: handleRedeemA2AInvite,
305
+ responseBody: RedeemA2AInviteResultSchema,
305
306
  },
306
307
  {
307
308
  operationId: "integrations_a2a_invite_accept_post",
@@ -313,5 +314,6 @@ export const ROUTES: RouteDefinition[] = [
313
314
  "Orchestrate cross-daemon invite acceptance for self-hosted deployments. Calls the sender's invite/complete, then creates a local contact via invite/redeem.",
314
315
  tags: ["integrations"],
315
316
  handler: handleAcceptA2AInvite,
317
+ responseBody: AcceptA2AInviteResultSchema,
316
318
  },
317
319
  ];
@@ -7,6 +7,8 @@
7
7
 
8
8
  import { afterEach, describe, expect, mock, test } from "bun:test";
9
9
 
10
+ import { z } from "zod";
11
+
10
12
  import type { SlackChannelConfigResult } from "../../../../../daemon/handlers/config-slack-channel.js";
11
13
 
12
14
  // ---------------------------------------------------------------------------
@@ -29,6 +31,20 @@ let mockSetConfigResult: SlackChannelConfigResult = {
29
31
  };
30
32
 
31
33
  mock.module("../../../../../daemon/handlers/config-slack-channel.js", () => ({
34
+ SlackChannelConfigResultSchema: z.object({
35
+ success: z.boolean(),
36
+ hasBotToken: z.boolean(),
37
+ hasAppToken: z.boolean(),
38
+ hasUserToken: z.boolean(),
39
+ connected: z.boolean(),
40
+ teamId: z.string().optional(),
41
+ teamName: z.string().optional(),
42
+ teamUrl: z.string().optional(),
43
+ botUserId: z.string().optional(),
44
+ botUsername: z.string().optional(),
45
+ error: z.string().optional(),
46
+ warning: z.string().optional(),
47
+ }),
32
48
  setSlackChannelConfig: async (
33
49
  botToken?: string,
34
50
  appToken?: string,
@@ -12,6 +12,7 @@ import {
12
12
  clearSlackChannelConfig,
13
13
  getSlackChannelConfig,
14
14
  setSlackChannelConfig,
15
+ SlackChannelConfigResultSchema,
15
16
  } from "../../../../daemon/handlers/config-slack-channel.js";
16
17
  import { ACTOR_PRINCIPALS } from "../../../auth/route-policy.js";
17
18
  import { BadRequestError } from "../../errors.js";
@@ -62,6 +63,7 @@ export const ROUTES: RouteDefinition[] = [
62
63
  summary: "Get Slack channel config",
63
64
  description: "Check current Slack channel configuration status.",
64
65
  tags: ["integrations"],
66
+ responseBody: SlackChannelConfigResultSchema,
65
67
  handler: () => handleGetSlackChannelConfig(),
66
68
  },
67
69
  {
@@ -80,6 +82,7 @@ export const ROUTES: RouteDefinition[] = [
80
82
  botToken: z.string().describe("Slack bot token"),
81
83
  appToken: z.string().describe("Slack app-level token"),
82
84
  }),
85
+ responseBody: SlackChannelConfigResultSchema,
83
86
  },
84
87
  {
85
88
  operationId: "integrations_slack_channel_config_delete",
@@ -92,6 +95,7 @@ export const ROUTES: RouteDefinition[] = [
92
95
  summary: "Clear Slack channel config",
93
96
  description: "Clear stored Slack channel credentials.",
94
97
  tags: ["integrations"],
98
+ responseBody: SlackChannelConfigResultSchema,
95
99
  handler: () => handleClearSlackChannelConfig(),
96
100
  },
97
101
  ];