nodal-agents 0.7.9 → 0.7.95

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 (224) hide show
  1. package/README.md +6 -5
  2. package/cli.js +38 -2
  3. package/migrations/0066_schedule_notify_channel.sql +19 -0
  4. package/migrations/0067_webhook_notify_channel.sql +12 -0
  5. package/migrations/meta/_journal.json +14 -0
  6. package/package.json +1 -1
  7. package/runner.js +277 -154
  8. package/web/.next/BUILD_ID +1 -1
  9. package/web/.next/app-path-routes-manifest.json +11 -11
  10. package/web/.next/build-manifest.json +2 -2
  11. package/web/.next/prerender-manifest.json +3 -3
  12. package/web/.next/required-server-files.json +1 -0
  13. package/web/.next/server/app/(dashboard)/agents/[id]/channels/page.js +2 -2
  14. package/web/.next/server/app/(dashboard)/agents/[id]/channels/page.js.nft.json +1 -1
  15. package/web/.next/server/app/(dashboard)/agents/[id]/channels/page_client-reference-manifest.js +1 -1
  16. package/web/.next/server/app/(dashboard)/agents/[id]/edit/page.js +5 -5
  17. package/web/.next/server/app/(dashboard)/agents/[id]/edit/page.js.nft.json +1 -1
  18. package/web/.next/server/app/(dashboard)/agents/[id]/edit/page_client-reference-manifest.js +1 -1
  19. package/web/.next/server/app/(dashboard)/agents/[id]/telegram/page.js +1 -1
  20. package/web/.next/server/app/(dashboard)/agents/[id]/telegram/page.js.nft.json +1 -1
  21. package/web/.next/server/app/(dashboard)/agents/[id]/telegram/page_client-reference-manifest.js +1 -1
  22. package/web/.next/server/app/(dashboard)/agents/page.js +2 -2
  23. package/web/.next/server/app/(dashboard)/agents/page.js.nft.json +1 -1
  24. package/web/.next/server/app/(dashboard)/agents/page_client-reference-manifest.js +1 -1
  25. package/web/.next/server/app/(dashboard)/approvals/page.js +2 -2
  26. package/web/.next/server/app/(dashboard)/approvals/page.js.nft.json +1 -1
  27. package/web/.next/server/app/(dashboard)/approvals/page_client-reference-manifest.js +1 -1
  28. package/web/.next/server/app/(dashboard)/automations/page.js +2 -2
  29. package/web/.next/server/app/(dashboard)/automations/page.js.nft.json +1 -1
  30. package/web/.next/server/app/(dashboard)/automations/page_client-reference-manifest.js +1 -1
  31. package/web/.next/server/app/(dashboard)/chat/page.js +2 -2
  32. package/web/.next/server/app/(dashboard)/chat/page.js.nft.json +1 -1
  33. package/web/.next/server/app/(dashboard)/chat/page_client-reference-manifest.js +1 -1
  34. package/web/.next/server/app/(dashboard)/connectors/page.js +2 -2
  35. package/web/.next/server/app/(dashboard)/connectors/page.js.nft.json +1 -1
  36. package/web/.next/server/app/(dashboard)/connectors/page_client-reference-manifest.js +1 -1
  37. package/web/.next/server/app/(dashboard)/credentials/page.js +2 -2
  38. package/web/.next/server/app/(dashboard)/credentials/page.js.nft.json +1 -1
  39. package/web/.next/server/app/(dashboard)/credentials/page_client-reference-manifest.js +1 -1
  40. package/web/.next/server/app/(dashboard)/jobs/[id]/page.js +2 -2
  41. package/web/.next/server/app/(dashboard)/jobs/[id]/page.js.nft.json +1 -1
  42. package/web/.next/server/app/(dashboard)/jobs/[id]/page_client-reference-manifest.js +1 -1
  43. package/web/.next/server/app/(dashboard)/jobs/page.js +2 -2
  44. package/web/.next/server/app/(dashboard)/jobs/page.js.nft.json +1 -1
  45. package/web/.next/server/app/(dashboard)/jobs/page_client-reference-manifest.js +1 -1
  46. package/web/.next/server/app/(dashboard)/learned-skills/page.js +2 -2
  47. package/web/.next/server/app/(dashboard)/learned-skills/page.js.nft.json +1 -1
  48. package/web/.next/server/app/(dashboard)/learned-skills/page_client-reference-manifest.js +1 -1
  49. package/web/.next/server/app/(dashboard)/llm-providers/page.js +2 -2
  50. package/web/.next/server/app/(dashboard)/llm-providers/page.js.nft.json +1 -1
  51. package/web/.next/server/app/(dashboard)/llm-providers/page_client-reference-manifest.js +1 -1
  52. package/web/.next/server/app/(dashboard)/logs/page.js +2 -2
  53. package/web/.next/server/app/(dashboard)/logs/page.js.nft.json +1 -1
  54. package/web/.next/server/app/(dashboard)/logs/page_client-reference-manifest.js +1 -1
  55. package/web/.next/server/app/(dashboard)/mcp/page.js +2 -2
  56. package/web/.next/server/app/(dashboard)/mcp/page.js.nft.json +1 -1
  57. package/web/.next/server/app/(dashboard)/mcp/page_client-reference-manifest.js +1 -1
  58. package/web/.next/server/app/(dashboard)/memories/page.js +2 -2
  59. package/web/.next/server/app/(dashboard)/memories/page.js.nft.json +1 -1
  60. package/web/.next/server/app/(dashboard)/memories/page_client-reference-manifest.js +1 -1
  61. package/web/.next/server/app/(dashboard)/page.js +4 -4
  62. package/web/.next/server/app/(dashboard)/page.js.nft.json +1 -1
  63. package/web/.next/server/app/(dashboard)/page_client-reference-manifest.js +1 -1
  64. package/web/.next/server/app/(dashboard)/settings/page.js +2 -2
  65. package/web/.next/server/app/(dashboard)/settings/page.js.nft.json +1 -1
  66. package/web/.next/server/app/(dashboard)/settings/page_client-reference-manifest.js +1 -1
  67. package/web/.next/server/app/(dashboard)/settings/root-context/page.js +1 -1
  68. package/web/.next/server/app/(dashboard)/settings/root-context/page.js.nft.json +1 -1
  69. package/web/.next/server/app/(dashboard)/settings/root-context/page_client-reference-manifest.js +1 -1
  70. package/web/.next/server/app/(dashboard)/skills/[id]/edit/page.js +2 -2
  71. package/web/.next/server/app/(dashboard)/skills/[id]/edit/page.js.nft.json +1 -1
  72. package/web/.next/server/app/(dashboard)/skills/[id]/edit/page_client-reference-manifest.js +1 -1
  73. package/web/.next/server/app/(dashboard)/skills/new/page.js +1 -1
  74. package/web/.next/server/app/(dashboard)/skills/new/page.js.nft.json +1 -1
  75. package/web/.next/server/app/(dashboard)/skills/new/page_client-reference-manifest.js +1 -1
  76. package/web/.next/server/app/(dashboard)/skills/page.js +2 -2
  77. package/web/.next/server/app/(dashboard)/skills/page.js.nft.json +1 -1
  78. package/web/.next/server/app/(dashboard)/skills/page_client-reference-manifest.js +1 -1
  79. package/web/.next/server/app/_global-error/page.js +2 -2
  80. package/web/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  81. package/web/.next/server/app/_global-error.html +1 -1
  82. package/web/.next/server/app/_global-error.rsc +3 -3
  83. package/web/.next/server/app/_global-error.segments/_full.segment.rsc +3 -3
  84. package/web/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  85. package/web/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  86. package/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  87. package/web/.next/server/app/_global-error.segments/_index.segment.rsc +3 -3
  88. package/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  89. package/web/.next/server/app/_not-found/page.js +1 -1
  90. package/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  91. package/web/.next/server/app/_not-found.html +1 -1
  92. package/web/.next/server/app/_not-found.rsc +4 -4
  93. package/web/.next/server/app/_not-found.segments/_full.segment.rsc +4 -4
  94. package/web/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  95. package/web/.next/server/app/_not-found.segments/_index.segment.rsc +4 -4
  96. package/web/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -2
  97. package/web/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  98. package/web/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  99. package/web/.next/server/app/login/page.js +2 -2
  100. package/web/.next/server/app/login/page_client-reference-manifest.js +1 -1
  101. package/web/.next/server/app/onboarding/page.js +165 -165
  102. package/web/.next/server/app/onboarding/page_client-reference-manifest.js +1 -1
  103. package/web/.next/server/app-paths-manifest.json +11 -11
  104. package/web/.next/server/chunks/1466.js +1 -0
  105. package/web/.next/server/chunks/1767.js +1 -0
  106. package/web/.next/server/chunks/3308.js +1 -0
  107. package/web/.next/server/chunks/4574.js +1 -1
  108. package/web/.next/server/chunks/5300.js +1 -0
  109. package/web/.next/server/chunks/6184.js +1 -0
  110. package/web/.next/server/chunks/6539.js +1 -0
  111. package/web/.next/server/chunks/7124.js +20 -20
  112. package/web/.next/server/chunks/8380.js +1 -0
  113. package/web/.next/server/chunks/9137.js +1 -0
  114. package/web/.next/server/chunks/{3847.js → 9507.js} +7 -7
  115. package/web/.next/server/chunks/9982.js +1 -0
  116. package/web/.next/server/middleware-build-manifest.js +1 -1
  117. package/web/.next/server/pages/404.html +1 -1
  118. package/web/.next/server/pages/500.html +1 -1
  119. package/web/.next/server/server-reference-manifest.js +1 -1
  120. package/web/.next/server/server-reference-manifest.json +1 -1
  121. package/web/.next/static/chunks/{7357-df6d26fbdbae296b.js → 1498-d0d434749bb18cd2.js} +1 -1
  122. package/web/.next/static/chunks/{7536-169aab9ed2feeab6.js → 2491-b14243a2db419dd9.js} +1 -1
  123. package/web/.next/static/chunks/4095-f76de40c53ae3d47.js +1 -0
  124. package/web/.next/static/chunks/4766-d80c537321cca448.js +1 -0
  125. package/web/.next/static/chunks/5876-4423499f49214575.js +1 -0
  126. package/web/.next/static/chunks/5953-54a29fc1e2d84c0c.js +1 -0
  127. package/web/.next/static/chunks/7829-78f753c50b408cde.js +1 -0
  128. package/web/.next/static/chunks/8542-ba178b7c68e14cf3.js +1 -0
  129. package/web/.next/static/chunks/9387-f5283e69fe4d4e83.js +1 -0
  130. package/web/.next/static/chunks/9567-db1512a42580d07c.js +1 -0
  131. package/web/.next/static/chunks/{8097-bad68cd78aa59a10.js → 9583-f93faba69d4c1f57.js} +1 -1
  132. package/web/.next/static/chunks/app/(dashboard)/agents/[id]/channels/page-d40d5db150472c4f.js +1 -0
  133. package/web/.next/static/chunks/app/(dashboard)/agents/[id]/edit/page-74934ff99c3b1261.js +6 -0
  134. package/web/.next/static/chunks/app/(dashboard)/agents/[id]/telegram/page-d40d5db150472c4f.js +1 -0
  135. package/web/.next/static/chunks/app/(dashboard)/agents/page-8ec50d6f48425813.js +1 -0
  136. package/web/.next/static/chunks/app/(dashboard)/approvals/page-d907a7c12917ab8a.js +1 -0
  137. package/web/.next/static/chunks/app/(dashboard)/automations/page-dd20cb7f04d22cca.js +1 -0
  138. package/web/.next/static/chunks/app/(dashboard)/chat/page-e9ffd3d09a46ad38.js +1 -0
  139. package/web/.next/static/chunks/app/(dashboard)/connectors/page-52828e317e7a63e6.js +1 -0
  140. package/web/.next/static/chunks/app/(dashboard)/credentials/page-f84a3f991cf69228.js +1 -0
  141. package/web/.next/static/chunks/app/(dashboard)/jobs/[id]/page-a0866da7952de417.js +1 -0
  142. package/web/.next/static/chunks/app/(dashboard)/jobs/page-aade90b389efb824.js +1 -0
  143. package/web/.next/static/chunks/app/(dashboard)/layout-10486dd8640fb6a0.js +1 -0
  144. package/web/.next/static/chunks/app/(dashboard)/learned-skills/page-e22d1e586ac8579c.js +1 -0
  145. package/web/.next/static/chunks/app/(dashboard)/llm-providers/page-46858f7d737ee49b.js +1 -0
  146. package/web/.next/static/chunks/app/(dashboard)/logs/page-17dd2080f6196b01.js +1 -0
  147. package/web/.next/static/chunks/app/(dashboard)/mcp/page-81e83a08c7b65719.js +1 -0
  148. package/web/.next/static/chunks/app/(dashboard)/memories/page-0336ba541b5ab006.js +1 -0
  149. package/web/.next/static/chunks/app/(dashboard)/page-3bf3a72ec95863d8.js +1 -0
  150. package/web/.next/static/chunks/app/(dashboard)/settings/page-0ee25e256bc3097f.js +1 -0
  151. package/web/.next/static/chunks/app/(dashboard)/settings/root-context/page-76653439bca06d8c.js +1 -0
  152. package/web/.next/static/chunks/app/(dashboard)/skills/[id]/edit/page-de1bf934a2c5e8b2.js +1 -0
  153. package/web/.next/static/chunks/app/(dashboard)/skills/new/page-a9640274b845190a.js +1 -0
  154. package/web/.next/static/chunks/app/(dashboard)/skills/page-928b6f005ba4dafb.js +1 -0
  155. package/web/.next/static/chunks/app/_global-error/page-d40d5db150472c4f.js +1 -0
  156. package/web/.next/static/chunks/app/_not-found/page-d40d5db150472c4f.js +1 -0
  157. package/web/.next/static/chunks/app/api/auth/[...all]/route-d40d5db150472c4f.js +1 -0
  158. package/web/.next/static/chunks/app/api/health/route-d40d5db150472c4f.js +1 -0
  159. package/web/.next/static/chunks/app/api/oauth/[provider]/callback/route-d40d5db150472c4f.js +1 -0
  160. package/web/.next/static/chunks/app/api/oauth/[provider]/start/route-d40d5db150472c4f.js +1 -0
  161. package/web/.next/static/chunks/app/auth/callback/route-d40d5db150472c4f.js +1 -0
  162. package/web/.next/static/chunks/app/error-ec052ef28a67f9b0.js +1 -0
  163. package/web/.next/static/chunks/app/login/{page-1063bbdf158045cf.js → page-97a658fa01e36c3f.js} +1 -1
  164. package/web/.next/static/chunks/app/onboarding/page-d7c5a220f9244b45.js +26 -0
  165. package/web/.next/static/chunks/next/dist/client/components/builtin/app-error-d40d5db150472c4f.js +1 -0
  166. package/web/.next/static/chunks/next/dist/client/components/builtin/forbidden-d40d5db150472c4f.js +1 -0
  167. package/web/.next/static/chunks/next/dist/client/components/builtin/unauthorized-d40d5db150472c4f.js +1 -0
  168. package/web/.next/static/css/0f40c037c3aa9ff2.css +3 -0
  169. package/web/server.js +1 -1
  170. package/web/.next/server/chunks/1957.js +0 -1
  171. package/web/.next/server/chunks/2313.js +0 -1
  172. package/web/.next/server/chunks/2314.js +0 -1
  173. package/web/.next/server/chunks/2747.js +0 -1
  174. package/web/.next/server/chunks/3422.js +0 -1
  175. package/web/.next/server/chunks/4761.js +0 -1
  176. package/web/.next/server/chunks/5128.js +0 -1
  177. package/web/.next/server/chunks/6128.js +0 -1
  178. package/web/.next/server/chunks/9857.js +0 -1
  179. package/web/.next/static/chunks/2281-928529ce483ceb72.js +0 -1
  180. package/web/.next/static/chunks/3114-d846062bc8434b58.js +0 -1
  181. package/web/.next/static/chunks/3763-2fa54c0e83122050.js +0 -1
  182. package/web/.next/static/chunks/4766-0433c4d93110e059.js +0 -1
  183. package/web/.next/static/chunks/7831-b5f0e41f306942cc.js +0 -1
  184. package/web/.next/static/chunks/8447-ec639f4e1d42d912.js +0 -1
  185. package/web/.next/static/chunks/8943-8619f44ee3282119.js +0 -1
  186. package/web/.next/static/chunks/8992-1b711ff6a77d023a.js +0 -1
  187. package/web/.next/static/chunks/app/(dashboard)/agents/[id]/channels/page-5c6067025edafbc0.js +0 -1
  188. package/web/.next/static/chunks/app/(dashboard)/agents/[id]/edit/page-fc4002bde145810b.js +0 -6
  189. package/web/.next/static/chunks/app/(dashboard)/agents/[id]/telegram/page-9397b9b7fccbb444.js +0 -1
  190. package/web/.next/static/chunks/app/(dashboard)/agents/page-be616beb457238ca.js +0 -1
  191. package/web/.next/static/chunks/app/(dashboard)/approvals/page-ca87808aaa42a079.js +0 -1
  192. package/web/.next/static/chunks/app/(dashboard)/automations/page-88c5b2061235936a.js +0 -1
  193. package/web/.next/static/chunks/app/(dashboard)/chat/page-197ee8afc4ef48b2.js +0 -1
  194. package/web/.next/static/chunks/app/(dashboard)/connectors/page-7bee350e3c9d4682.js +0 -1
  195. package/web/.next/static/chunks/app/(dashboard)/credentials/page-567d0e2e3c255976.js +0 -1
  196. package/web/.next/static/chunks/app/(dashboard)/jobs/[id]/page-2a5d3e0fd5248864.js +0 -1
  197. package/web/.next/static/chunks/app/(dashboard)/jobs/page-0d50850f43cb7ccb.js +0 -1
  198. package/web/.next/static/chunks/app/(dashboard)/layout-7f9bdb14405ef107.js +0 -1
  199. package/web/.next/static/chunks/app/(dashboard)/learned-skills/page-17878b5d662400b2.js +0 -1
  200. package/web/.next/static/chunks/app/(dashboard)/llm-providers/page-e38d2642e44278b1.js +0 -1
  201. package/web/.next/static/chunks/app/(dashboard)/logs/page-7ac6dbdcd9cf7042.js +0 -1
  202. package/web/.next/static/chunks/app/(dashboard)/mcp/page-a5b036571bb575b8.js +0 -1
  203. package/web/.next/static/chunks/app/(dashboard)/memories/page-1d7007962535c0db.js +0 -1
  204. package/web/.next/static/chunks/app/(dashboard)/page-55efec02eb59c413.js +0 -1
  205. package/web/.next/static/chunks/app/(dashboard)/settings/page-db76b2ad9934ead0.js +0 -1
  206. package/web/.next/static/chunks/app/(dashboard)/settings/root-context/page-5ffdba723e59a369.js +0 -1
  207. package/web/.next/static/chunks/app/(dashboard)/skills/[id]/edit/page-eaa016de6c6d8b02.js +0 -1
  208. package/web/.next/static/chunks/app/(dashboard)/skills/new/page-07669c2c3c9e3b0e.js +0 -1
  209. package/web/.next/static/chunks/app/(dashboard)/skills/page-393ec6f04d00e50f.js +0 -1
  210. package/web/.next/static/chunks/app/_global-error/page-9397b9b7fccbb444.js +0 -1
  211. package/web/.next/static/chunks/app/_not-found/page-9397b9b7fccbb444.js +0 -1
  212. package/web/.next/static/chunks/app/api/auth/[...all]/route-9397b9b7fccbb444.js +0 -1
  213. package/web/.next/static/chunks/app/api/health/route-9397b9b7fccbb444.js +0 -1
  214. package/web/.next/static/chunks/app/api/oauth/[provider]/callback/route-9397b9b7fccbb444.js +0 -1
  215. package/web/.next/static/chunks/app/api/oauth/[provider]/start/route-9397b9b7fccbb444.js +0 -1
  216. package/web/.next/static/chunks/app/auth/callback/route-9397b9b7fccbb444.js +0 -1
  217. package/web/.next/static/chunks/app/error-5e6b38c936ae1a78.js +0 -1
  218. package/web/.next/static/chunks/app/onboarding/page-799f8658aea94b41.js +0 -26
  219. package/web/.next/static/chunks/next/dist/client/components/builtin/app-error-9397b9b7fccbb444.js +0 -1
  220. package/web/.next/static/chunks/next/dist/client/components/builtin/forbidden-9397b9b7fccbb444.js +0 -1
  221. package/web/.next/static/chunks/next/dist/client/components/builtin/unauthorized-9397b9b7fccbb444.js +0 -1
  222. package/web/.next/static/css/110d6e5ec0dc635f.css +0 -3
  223. /package/web/.next/static/{xZ_yeD2bqK-_EOEqMMFYk → TWzSfBwiIIU81SgNxXcIw}/_buildManifest.js +0 -0
  224. /package/web/.next/static/{xZ_yeD2bqK-_EOEqMMFYk → TWzSfBwiIIU81SgNxXcIw}/_ssgManifest.js +0 -0
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  > **Your AI agents. Your data. Your machine.**
4
4
 
5
- A self-hosted platform for building and orchestrating a **team of AI agents** on your own hardware — each with its own personality, tools, memory, and model. Talk to them in the dashboard or on Telegram; they research, write files, call your connectors, and delegate to each other to get the job done.
5
+ A self-hosted platform for building and orchestrating a **team of AI agents** on your own hardware — each with its own personality, tools, memory, and model. Talk to them in the dashboard, or on Telegram, Discord, Slack, and WhatsApp; they research, write files, call your connectors, and delegate to each other to get the job done.
6
6
 
7
7
  **No SaaS lock-in. No per-token markup. No cloud roundtrip.** Two commands to install, runs on any machine with Node 22+ (Mac, Windows, Linux), and works with **any LLM** — frontier or local, paid or free.
8
8
 
@@ -70,18 +70,20 @@ Every agent runs on the model **you** choose, with the tools **you** grant, in a
70
70
 
71
71
  ## Available now
72
72
 
73
- **Models** — Anthropic · OpenAI · Google · Groq · Mistral · OpenRouter · **native DeepSeek** (`api.deepseek.com`) · **native MiniMax** (`api.minimax.io`) · any local model (LM Studio, Ollama). One key per provider; each agent picks its own model.
73
+ **Models** — Anthropic · OpenAI · Google · Groq · Mistral · OpenRouter · **native DeepSeek** (`api.deepseek.com`) · **native MiniMax** (`api.minimax.io`) · **native Moonshot / Kimi** (`api.moonshot.ai`) · any local model (LM Studio, Ollama). One key per provider; each agent picks its own model.
74
74
 
75
75
  **Connectors** — multi-instance (Gmail perso *and* boulot on one install), managed from the dashboard:
76
76
  - *OAuth* — Airtable · Calendar · Docs · Gmail · Google Drive · Notion · Sheets
77
- - *API key* — Airtable · Apify · Firecrawl · Notion · Tavily
77
+ - *API key* — Airtable · Apify · Firecrawl · Notion · Poyo · Tavily
78
78
 
79
79
  **MCP servers** — over Streamable HTTP *and* stdio, plus add/edit your own:
80
80
  Apify · Blender · Cogni Cortex · Composio · Fetch · Filesystem · Git · GitHub · KeyShot · Linear · n8n · Notion · Perplexity · Photoshop · Playwright · PostgreSQL · Sentry · Stripe · Supabase · Unity · Unreal Engine
81
81
 
82
82
  **Skills** — built-in: office editing (Excel/Word/PowerPoint), shell execution, Obsidian, Telegram etiquette, task planning, markdown output, citation discipline, research methodology, results delivery, language mirroring, HTML design. Plus **install any community `SKILL.md`** from GitHub / skills.sh / ClawHub — and agents can **write their own**.
83
83
 
84
- **Channels** — Telegram (long-poll, multi-agent routing via `/ask <slug>`, group-chat filters, conversation continuity) and the dashboard chat.
84
+ **Channels** — Telegram (long-poll, multi-agent routing via `/ask <slug>`, group-chat filters, conversation continuity) · Discord (bot gateway) · Slack (Socket Mode) · WhatsApp (QR pairing) — and the dashboard chat. Approvals, images, and files flow over every channel, with graceful fallbacks where a channel lacks buttons.
85
+
86
+ **Event triggers** — inbound **webhooks** (`POST /webhooks/<slug>/<secret>` starts a job from any external service) and **watchers** (recurring polls with a capped daily budget and overlap protection).
85
87
 
86
88
  **Other** — shell execution (`run_command`, approval-gated), per-agent sandboxed filesystem folders, cron automations, tool-call audit log, full job transcripts.
87
89
 
@@ -172,7 +174,6 @@ Used daily by the maintainer; stable enough for personal production. **Pre-1.0**
172
174
  - **MCP OAuth** → unlocks Linear, Notion remote, GitHub remote, Atlassian, Sentry, and the rest of the SaaS-as-MCP ecosystem.
173
175
  - **Dry-run + test-workflow meta-tool** → preview what the ROOT would do before it runs.
174
176
  - **Bundled pgvector** → semantic memory search out of the box (today: keyword fallback).
175
- - **More channels** → Discord, Slack, and beyond Telegram.
176
177
 
177
178
  ---
178
179
 
package/cli.js CHANGED
@@ -12864,6 +12864,17 @@ var init_schedules = __esm({
12864
12864
  // forces the agent to send the user a success confirmation before finishing.
12865
12865
  // Default false → the cron runs silently (the user must opt in per schedule).
12866
12866
  notifyOnSuccess: boolean("notify_on_success").notNull().default(false),
12867
+ // Explicit notify channel choice (B1, notify-channel-choice plan). One of
12868
+ // 'telegram'|'discord'|'slack'|'whatsapp', or NULL = auto (the historical
12869
+ // behavior: first active channel by CHANNEL_PRIORITY — see run-schedules.ts).
12870
+ // Choosing a channel here LINKS chatId resolution to it: the owner
12871
+ // conversation resolved at fire time is the owner's conversation ON THIS
12872
+ // CHANNEL, not whichever channel happened to win priority. 'whatsapp' is
12873
+ // accepted at the DB layer for forward-compat but the UI does not offer it
12874
+ // yet — no outbound send tool exists for whatsapp (TOOL_ONLY_DELIVERY_CHANNELS,
12875
+ // execute.ts), so a whatsapp notify would only ever reach the user through
12876
+ // deliver-results.ts's adapter-direct path, never a mid-run agent send.
12877
+ notifyChannel: text("notify_channel"),
12867
12878
  // Per-schedule daily cost ceiling in USD (Event Triggers, Brique 3). Rolled
12868
12879
  // up against agent_jobs.total_cost_usd for this schedule since the start
12869
12880
  // of its local day — see runScheduleTick (apps/runner/src/cron/run-schedules.ts).
@@ -12879,7 +12890,11 @@ var init_schedules = __esm({
12879
12890
  check("agent_schedules_type_check", sql`${table.type} IN ('cron','heartbeat')`),
12880
12891
  check(
12881
12892
  "agent_schedules_last_status_check",
12882
- sql`${table.lastStatus} IN ('success','failed','no_action','budget_exhausted') OR ${table.lastStatus} IS NULL`
12893
+ sql`${table.lastStatus} IN ('success','failed','no_action','budget_exhausted','notify_unreachable') OR ${table.lastStatus} IS NULL`
12894
+ ),
12895
+ check(
12896
+ "agent_schedules_notify_channel_check",
12897
+ sql`${table.notifyChannel} IN ('telegram','discord','slack','whatsapp') OR ${table.notifyChannel} IS NULL`
12883
12898
  )
12884
12899
  ]
12885
12900
  );
@@ -13385,6 +13400,7 @@ var init_webhooks = __esm({
13385
13400
  "../../packages/db/src/schema/webhooks.ts"() {
13386
13401
  "use strict";
13387
13402
  init_pg_core();
13403
+ init_drizzle_orm();
13388
13404
  init_entities();
13389
13405
  init_agents();
13390
13406
  webhookTriggers = pgTable(
@@ -13401,10 +13417,30 @@ var init_webhooks = __esm({
13401
13417
  secret: text("secret"),
13402
13418
  lastTriggeredAt: timestamp("last_triggered_at", { withTimezone: true }),
13403
13419
  triggerCount: integer("trigger_count").default(0),
13420
+ // B2 (notify-channel-choice plan): same pair of columns as
13421
+ // agent_schedules (see schedules.ts), same mechanic — the schedules
13422
+ // brique (B1) established the pattern, this just closes the gap the plan
13423
+ // identified: webhooks had no notify at all, not by design, just because
13424
+ // the original webhooks brique scoped delivery to the HTTP caller (202 +
13425
+ // jobId) and never to the owner. Default false → firing stays silent
13426
+ // unless opted in per trigger.
13427
+ notifyOnSuccess: boolean("notify_on_success").notNull().default(false),
13428
+ // Explicit notify channel choice, NULL = auto (first active channel by
13429
+ // CHANNEL_PRIORITY — see routes/webhook.ts). Unlike agent_schedules,
13430
+ // there is no legacy webhook-notify behavior to preserve, so "auto" here
13431
+ // is a plain first-active-channel resolution from the start (no
13432
+ // telegram-only wrapper).
13433
+ notifyChannel: text("notify_channel"),
13404
13434
  createdAt: timestamp("created_at", { withTimezone: true }).defaultNow(),
13405
13435
  updatedAt: timestamp("updated_at", { withTimezone: true }).defaultNow()
13406
13436
  },
13407
- (table) => [index("idx_webhook_triggers_entity_id").on(table.entityId)]
13437
+ (table) => [
13438
+ index("idx_webhook_triggers_entity_id").on(table.entityId),
13439
+ check(
13440
+ "webhook_triggers_notify_channel_check",
13441
+ sql`${table.notifyChannel} IN ('telegram','discord','slack','whatsapp') OR ${table.notifyChannel} IS NULL`
13442
+ )
13443
+ ]
13408
13444
  );
13409
13445
  }
13410
13446
  });
@@ -0,0 +1,19 @@
1
+ -- Notify multi-canal pour les automations (B1). Today a schedule's success
2
+ -- confirmation always resolves the OWNER'S TELEGRAM chat (resolveOwnerChatId,
3
+ -- a hardcoded 'telegram' wrapper) and lets delivery-guard/deliver-results pick
4
+ -- whichever channel wins CHANNEL_PRIORITY — an agent bound to telegram+slack
5
+ -- notifies telegram today by priority coincidence, not by design.
6
+ --
7
+ -- notify_channel: explicit choice, NULL = auto (unchanged behavior: first
8
+ -- active channel by priority). Choosing a channel LINKS chatId resolution to
9
+ -- it — see run-schedules.ts's runScheduleTick.
10
+ ALTER TABLE "agent_schedules" ADD COLUMN "notify_channel" text;--> statement-breakpoint
11
+ ALTER TABLE "agent_schedules" ADD CONSTRAINT "agent_schedules_notify_channel_check" CHECK ("notify_channel" IN ('telegram','discord','slack','whatsapp') OR "notify_channel" IS NULL);--> statement-breakpoint
12
+
13
+ -- 'notify_unreachable' — fail-loud (invariant #4) status for when the chosen
14
+ -- channel has no owner conversation yet (never DMed the bot there): the cron
15
+ -- still fires the job (no silent fallback to another channel), just without
16
+ -- a chatId, and this status surfaces the problem in the UI instead of reading
17
+ -- as an ordinary 'failed'.
18
+ ALTER TABLE "agent_schedules" DROP CONSTRAINT IF EXISTS "agent_schedules_last_status_check";--> statement-breakpoint
19
+ ALTER TABLE "agent_schedules" ADD CONSTRAINT "agent_schedules_last_status_check" CHECK ("last_status" IN ('success','failed','no_action','budget_exhausted','notify_unreachable') OR "last_status" IS NULL);
@@ -0,0 +1,12 @@
1
+ -- Notify multi-canal pour les webhooks (B2, same plan as 0066's schedule
2
+ -- notify_channel). Webhooks never had a notify option at all — the original
3
+ -- webhooks brique scoped delivery to the HTTP caller (202 + jobId) and never
4
+ -- to the owner. Same pair of columns, same mechanic as agent_schedules.
5
+ --
6
+ -- notify_channel: explicit choice, NULL = auto (first active channel by
7
+ -- priority — no legacy telegram-only behavior to preserve here, unlike
8
+ -- schedules). Choosing a channel LINKS chatId resolution to it — see
9
+ -- routes/webhook.ts.
10
+ ALTER TABLE "webhook_triggers" ADD COLUMN "notify_on_success" boolean NOT NULL DEFAULT false;--> statement-breakpoint
11
+ ALTER TABLE "webhook_triggers" ADD COLUMN "notify_channel" text;--> statement-breakpoint
12
+ ALTER TABLE "webhook_triggers" ADD CONSTRAINT "webhook_triggers_notify_channel_check" CHECK ("notify_channel" IN ('telegram','discord','slack','whatsapp') OR "notify_channel" IS NULL);
@@ -456,6 +456,20 @@
456
456
  "when": 1784500000000,
457
457
  "tag": "0065_conversations_origin",
458
458
  "breakpoints": true
459
+ },
460
+ {
461
+ "idx": 66,
462
+ "version": "7",
463
+ "when": 1784600000000,
464
+ "tag": "0066_schedule_notify_channel",
465
+ "breakpoints": true
466
+ },
467
+ {
468
+ "idx": 67,
469
+ "version": "7",
470
+ "when": 1784700000000,
471
+ "tag": "0067_webhook_notify_channel",
472
+ "breakpoints": true
459
473
  }
460
474
  ]
461
475
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nodal-agents",
3
- "version": "0.7.9",
3
+ "version": "0.7.95",
4
4
  "description": "Local-first AI agent platform with a web dashboard — install in one command.",
5
5
  "license": "MIT",
6
6
  "repository": {