profclaw 2.0.0 → 2.3.0

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 (477) hide show
  1. package/.env.example +14 -2
  2. package/CHANGELOG.md +37 -0
  3. package/CONTRIBUTING.md +20 -0
  4. package/Dockerfile +39 -23
  5. package/README.md +174 -40
  6. package/dist/agents/agent-summary.d.ts +44 -0
  7. package/dist/agents/agent-summary.js +176 -0
  8. package/dist/agents/auto-memory.d.ts +59 -0
  9. package/dist/agents/auto-memory.js +310 -0
  10. package/dist/agents/checkpoint-manager.d.ts +76 -0
  11. package/dist/agents/checkpoint-manager.js +156 -0
  12. package/dist/agents/circuit-breaker.d.ts +54 -0
  13. package/dist/agents/circuit-breaker.js +153 -0
  14. package/dist/agents/context-compactor.d.ts +70 -0
  15. package/dist/agents/context-compactor.js +361 -0
  16. package/dist/agents/conversation-branch.d.ts +55 -0
  17. package/dist/agents/conversation-branch.js +115 -0
  18. package/dist/agents/error-recovery.d.ts +44 -0
  19. package/dist/agents/error-recovery.js +197 -0
  20. package/dist/agents/events.d.ts +76 -0
  21. package/dist/agents/events.js +8 -0
  22. package/dist/agents/executor.d.ts +35 -1
  23. package/dist/agents/executor.js +573 -124
  24. package/dist/agents/file-snapshots.d.ts +72 -0
  25. package/dist/agents/file-snapshots.js +182 -0
  26. package/dist/agents/index.d.ts +2 -0
  27. package/dist/agents/orchestrator.d.ts +183 -0
  28. package/dist/agents/orchestrator.js +495 -0
  29. package/dist/agents/permissions.d.ts +63 -0
  30. package/dist/agents/permissions.js +138 -0
  31. package/dist/agents/plan-mode.d.ts +71 -0
  32. package/dist/agents/plan-mode.js +186 -0
  33. package/dist/agents/prompt-suggestions.d.ts +33 -0
  34. package/dist/agents/prompt-suggestions.js +208 -0
  35. package/dist/agents/rate-limit-monitor.d.ts +56 -0
  36. package/dist/agents/rate-limit-monitor.js +224 -0
  37. package/dist/agents/result-store.d.ts +37 -0
  38. package/dist/agents/result-store.js +104 -0
  39. package/dist/agents/session-diff.d.ts +43 -0
  40. package/dist/agents/session-diff.js +258 -0
  41. package/dist/agents/tool-loader.d.ts +65 -0
  42. package/dist/agents/tool-loader.js +273 -0
  43. package/dist/agents/transcript.d.ts +96 -0
  44. package/dist/agents/transcript.js +267 -0
  45. package/dist/agents/worktree-manager.d.ts +80 -0
  46. package/dist/agents/worktree-manager.js +203 -0
  47. package/dist/auth/middleware.js +14 -0
  48. package/dist/chat/agentic-executor.d.ts +7 -0
  49. package/dist/chat/agentic-executor.js +253 -30
  50. package/dist/chat/conversations.d.ts +2 -0
  51. package/dist/chat/conversations.js +8 -0
  52. package/dist/chat/execution/executor.d.ts +8 -0
  53. package/dist/chat/execution/executor.js +157 -103
  54. package/dist/chat/execution/index.js +5 -1
  55. package/dist/chat/execution/tool-router.js +40 -14
  56. package/dist/chat/execution/tools/canvas.d.ts +2 -2
  57. package/dist/chat/execution/tools/code-tools.d.ts +66 -0
  58. package/dist/chat/execution/tools/code-tools.js +353 -0
  59. package/dist/chat/execution/tools/complete-task.d.ts +2 -2
  60. package/dist/chat/execution/tools/cron-tool.d.ts +26 -10
  61. package/dist/chat/execution/tools/cron-tool.js +48 -3
  62. package/dist/chat/execution/tools/decompose-task.d.ts +58 -0
  63. package/dist/chat/execution/tools/decompose-task.js +166 -0
  64. package/dist/chat/execution/tools/exec.d.ts +5 -2
  65. package/dist/chat/execution/tools/exec.js +294 -155
  66. package/dist/chat/execution/tools/feed-tools.d.ts +77 -0
  67. package/dist/chat/execution/tools/feed-tools.js +142 -0
  68. package/dist/chat/execution/tools/file-ops.d.ts +1 -1
  69. package/dist/chat/execution/tools/github.d.ts +2 -2
  70. package/dist/chat/execution/tools/index.d.ts +14 -2
  71. package/dist/chat/execution/tools/index.js +86 -12
  72. package/dist/chat/execution/tools/integrations.d.ts +8 -8
  73. package/dist/chat/execution/tools/multi-patch.d.ts +53 -0
  74. package/dist/chat/execution/tools/multi-patch.js +373 -0
  75. package/dist/chat/execution/tools/openai-image-gen.d.ts +2 -2
  76. package/dist/chat/execution/tools/plan-tools.d.ts +80 -0
  77. package/dist/chat/execution/tools/plan-tools.js +134 -0
  78. package/dist/chat/execution/tools/profclaw-ops.d.ts +6 -6
  79. package/dist/chat/execution/tools/repl-tool.d.ts +46 -0
  80. package/dist/chat/execution/tools/repl-tool.js +207 -0
  81. package/dist/chat/execution/tools/sessions-send.d.ts +2 -2
  82. package/dist/chat/execution/tools/slack-actions.d.ts +2 -2
  83. package/dist/chat/execution/tools/system.d.ts +4 -4
  84. package/dist/chat/execution/tools/todo-tool.d.ts +72 -0
  85. package/dist/chat/execution/tools/todo-tool.js +152 -0
  86. package/dist/chat/execution/tools/tool-search.d.ts +50 -0
  87. package/dist/chat/execution/tools/tool-search.js +155 -0
  88. package/dist/chat/execution/types.d.ts +21 -14
  89. package/dist/chat/execution/workflows/executor.d.ts +11 -0
  90. package/dist/chat/execution/workflows/executor.js +99 -1
  91. package/dist/chat/execution/workflows/types.d.ts +35 -2
  92. package/dist/chat/format/index.d.ts +1 -0
  93. package/dist/chat/format/index.js +1 -0
  94. package/dist/chat/format/markdown-convert.d.ts +23 -0
  95. package/dist/chat/format/markdown-convert.js +149 -0
  96. package/dist/chat/index.d.ts +1 -1
  97. package/dist/chat/index.js +1 -1
  98. package/dist/chat/message-handler.js +58 -6
  99. package/dist/chat/proactive/index.d.ts +62 -0
  100. package/dist/chat/proactive/index.js +147 -0
  101. package/dist/chat/prompt-adapter.js +2 -0
  102. package/dist/chat/providers/irc/index.d.ts +2 -2
  103. package/dist/chat/providers/telegram/index.d.ts +2 -0
  104. package/dist/chat/providers/telegram/index.js +21 -2
  105. package/dist/chat/system-prompts.d.ts +3 -3
  106. package/dist/chat/system-prompts.js +116 -61
  107. package/dist/chat/tools.d.ts +6 -6
  108. package/dist/cli/commands/auth.js +64 -1
  109. package/dist/cli/commands/chat.js +1327 -138
  110. package/dist/cli/commands/doctor.js +222 -16
  111. package/dist/cli/commands/history.d.ts +3 -0
  112. package/dist/cli/commands/history.js +138 -0
  113. package/dist/cli/commands/import.d.ts +44 -0
  114. package/dist/cli/commands/import.js +526 -0
  115. package/dist/cli/commands/init.d.ts +13 -0
  116. package/dist/cli/commands/init.js +381 -0
  117. package/dist/cli/commands/onboard.js +210 -30
  118. package/dist/cli/commands/plan.d.ts +13 -0
  119. package/dist/cli/commands/plan.js +184 -0
  120. package/dist/cli/commands/serve.d.ts +7 -0
  121. package/dist/cli/commands/serve.js +77 -18
  122. package/dist/cli/commands/setup.js +84 -3
  123. package/dist/cli/commands/status.js +54 -0
  124. package/dist/cli/commands/tools.js +13 -13
  125. package/dist/cli/commands/tui.js +26 -1
  126. package/dist/cli/index.js +19 -0
  127. package/dist/cli/ink/App.d.ts +13 -0
  128. package/dist/cli/ink/App.js +6 -0
  129. package/dist/cli/ink/ChatApp.d.ts +60 -0
  130. package/dist/cli/ink/ChatApp.js +325 -0
  131. package/dist/cli/ink/DashboardApp.d.ts +3 -0
  132. package/dist/cli/ink/DashboardApp.js +143 -0
  133. package/dist/cli/ink/components/AgentStatus.d.ts +17 -0
  134. package/dist/cli/ink/components/AgentStatus.js +33 -0
  135. package/dist/cli/ink/components/ChannelList.d.ts +17 -0
  136. package/dist/cli/ink/components/ChannelList.js +33 -0
  137. package/dist/cli/ink/components/ConnectionStatus.d.ts +19 -0
  138. package/dist/cli/ink/components/ConnectionStatus.js +50 -0
  139. package/dist/cli/ink/components/CostBar.d.ts +19 -0
  140. package/dist/cli/ink/components/CostBar.js +35 -0
  141. package/dist/cli/ink/components/HookStatus.d.ts +15 -0
  142. package/dist/cli/ink/components/HookStatus.js +7 -0
  143. package/dist/cli/ink/components/PermissionPrompt.d.ts +21 -0
  144. package/dist/cli/ink/components/PermissionPrompt.js +51 -0
  145. package/dist/cli/ink/components/PlanView.d.ts +23 -0
  146. package/dist/cli/ink/components/PlanView.js +26 -0
  147. package/dist/cli/ink/components/ProviderList.d.ts +16 -0
  148. package/dist/cli/ink/components/ProviderList.js +16 -0
  149. package/dist/cli/ink/components/SessionHeader.d.ts +15 -0
  150. package/dist/cli/ink/components/SessionHeader.js +15 -0
  151. package/dist/cli/ink/components/StreamingMessage.d.ts +20 -0
  152. package/dist/cli/ink/components/StreamingMessage.js +27 -0
  153. package/dist/cli/ink/components/SuggestionBar.d.ts +15 -0
  154. package/dist/cli/ink/components/SuggestionBar.js +28 -0
  155. package/dist/cli/ink/components/SystemHealth.d.ts +20 -0
  156. package/dist/cli/ink/components/SystemHealth.js +39 -0
  157. package/dist/cli/ink/components/TaskList.d.ts +17 -0
  158. package/dist/cli/ink/components/TaskList.js +59 -0
  159. package/dist/cli/ink/components/ToolCall.d.ts +17 -0
  160. package/dist/cli/ink/components/ToolCall.js +43 -0
  161. package/dist/cli/ink/index.d.ts +23 -0
  162. package/dist/cli/ink/index.js +15 -0
  163. package/dist/cli/ink/keybindings.d.ts +35 -0
  164. package/dist/cli/ink/keybindings.js +105 -0
  165. package/dist/cli/ink/markdown-renderer.d.ts +47 -0
  166. package/dist/cli/ink/markdown-renderer.js +380 -0
  167. package/dist/cli/ink/output-styles.d.ts +39 -0
  168. package/dist/cli/ink/output-styles.js +119 -0
  169. package/dist/cli/interactive/auto-serve.d.ts +38 -0
  170. package/dist/cli/interactive/auto-serve.js +209 -0
  171. package/dist/cli/interactive/index.d.ts +25 -0
  172. package/dist/cli/interactive/index.js +23 -0
  173. package/dist/cli/interactive/picker.d.ts +28 -0
  174. package/dist/cli/interactive/picker.js +153 -0
  175. package/dist/cli/interactive/renderer.d.ts +26 -0
  176. package/dist/cli/interactive/renderer.js +555 -0
  177. package/dist/cli/interactive/repl.d.ts +14 -0
  178. package/dist/cli/interactive/repl.js +1516 -0
  179. package/dist/cli/interactive/stream-client.d.ts +59 -0
  180. package/dist/cli/interactive/stream-client.js +506 -0
  181. package/dist/cli/interactive/types.d.ts +121 -0
  182. package/dist/cli/interactive/types.js +10 -0
  183. package/dist/cli/utils/api.d.ts +9 -0
  184. package/dist/cli/utils/api.js +58 -2
  185. package/dist/cron/natural-language.d.ts +54 -0
  186. package/dist/cron/natural-language.js +569 -0
  187. package/dist/cron/scheduler.d.ts +34 -4
  188. package/dist/cron/scheduler.js +141 -9
  189. package/dist/cron/templates.d.ts +1 -1
  190. package/dist/cron/templates.js +219 -0
  191. package/dist/feeds/feed-engine.d.ts +149 -0
  192. package/dist/feeds/feed-engine.js +600 -0
  193. package/dist/feeds/index.d.ts +9 -0
  194. package/dist/feeds/index.js +8 -0
  195. package/dist/gateway/router.js +6 -1
  196. package/dist/hooks/built-in/audit-log.d.ts +11 -0
  197. package/dist/hooks/built-in/audit-log.js +84 -0
  198. package/dist/hooks/built-in/cost-warning.d.ts +10 -0
  199. package/dist/hooks/built-in/cost-warning.js +59 -0
  200. package/dist/hooks/built-in/dangerous-tool.d.ts +32 -0
  201. package/dist/hooks/built-in/dangerous-tool.js +80 -0
  202. package/dist/hooks/built-in/index.d.ts +14 -0
  203. package/dist/hooks/built-in/index.js +20 -0
  204. package/dist/hooks/index.d.ts +3 -0
  205. package/dist/hooks/index.js +6 -0
  206. package/dist/hooks/loader.d.ts +17 -0
  207. package/dist/hooks/loader.js +142 -0
  208. package/dist/hooks/registry.d.ts +62 -0
  209. package/dist/hooks/registry.js +127 -0
  210. package/dist/integrations/web-search.js +6 -3
  211. package/dist/memory/index.d.ts +1 -0
  212. package/dist/memory/index.js +2 -0
  213. package/dist/memory/memory-service.js +14 -13
  214. package/dist/memory/observational.d.ts +62 -0
  215. package/dist/memory/observational.js +396 -0
  216. package/dist/middleware/content-filter.d.ts +22 -0
  217. package/dist/middleware/content-filter.js +69 -0
  218. package/dist/middleware/request-validator.d.ts +159 -0
  219. package/dist/middleware/request-validator.js +93 -0
  220. package/dist/plugins/sdk.d.ts +22 -0
  221. package/dist/plugins/sdk.js +17 -1
  222. package/dist/projects/types.d.ts +10 -10
  223. package/dist/providers/ai-sdk.d.ts +11 -0
  224. package/dist/providers/ai-sdk.js +78 -19
  225. package/dist/providers/core/models.js +67 -1
  226. package/dist/providers/core/types.d.ts +3 -0
  227. package/dist/providers/index.d.ts +1 -0
  228. package/dist/providers/index.js +1 -0
  229. package/dist/providers/smart-router.d.ts +118 -0
  230. package/dist/providers/smart-router.js +685 -0
  231. package/dist/providers/types.d.ts +16 -16
  232. package/dist/routes/agents.js +50 -0
  233. package/dist/routes/auth.js +8 -1
  234. package/dist/routes/chat.js +259 -14
  235. package/dist/routes/costs.js +32 -0
  236. package/dist/routes/cron.js +80 -5
  237. package/dist/routes/feeds.d.ts +10 -0
  238. package/dist/routes/feeds.js +168 -0
  239. package/dist/routes/mcp.js +21 -0
  240. package/dist/routes/memory.js +130 -0
  241. package/dist/routes/skills.js +129 -0
  242. package/dist/routes/teams.d.ts +9 -0
  243. package/dist/routes/teams.js +210 -0
  244. package/dist/routes/tools.js +14 -0
  245. package/dist/routes/users.js +2 -0
  246. package/dist/server/route-loader.js +3 -1
  247. package/dist/server/stream-bridge.d.ts +19 -0
  248. package/dist/server/stream-bridge.js +38 -0
  249. package/dist/server.js +310 -36
  250. package/dist/skills/marketplace.d.ts +87 -0
  251. package/dist/skills/marketplace.js +268 -0
  252. package/dist/storage/index.d.ts +14 -0
  253. package/dist/storage/index.js +64 -3
  254. package/dist/storage/schema.d.ts +4 -4
  255. package/dist/storage/schema.js +1 -1
  256. package/dist/teams/index.d.ts +110 -0
  257. package/dist/teams/index.js +365 -0
  258. package/dist/tickets/types.d.ts +39 -39
  259. package/dist/types/summary.d.ts +5 -5
  260. package/dist/utils/auto-update.d.ts +23 -0
  261. package/dist/utils/auto-update.js +157 -0
  262. package/dist/utils/offline-detect.d.ts +55 -0
  263. package/dist/utils/offline-detect.js +121 -0
  264. package/dist/utils/pid-file.d.ts +36 -0
  265. package/dist/utils/pid-file.js +125 -0
  266. package/dist/utils/prevent-sleep.d.ts +27 -0
  267. package/dist/utils/prevent-sleep.js +95 -0
  268. package/dist/utils/sanitizer.d.ts +57 -0
  269. package/dist/utils/sanitizer.js +174 -0
  270. package/docker-compose.yml +13 -137
  271. package/package.json +31 -6
  272. package/skills/deploy-cloudflare/SKILL.md +62 -0
  273. package/skills/deploy-vercel/SKILL.md +67 -0
  274. package/skills/docker-deploy/SKILL.md +158 -0
  275. package/skills/full-stack-builder/SKILL.md +92 -0
  276. package/skills/humanizer/SKILL.md +488 -0
  277. package/skills/profclaw-assistant/SKILL.md +85 -56
  278. package/ui/dist/assets/ActivityView-Da6HQ8ws.js +1 -0
  279. package/ui/dist/assets/AgentList-H58R0kX3.js +1 -0
  280. package/ui/dist/assets/AnalyticsDashboard-B28AeRsc.js +1 -0
  281. package/ui/dist/assets/AreaChart-DwLzeAQ8.js +1 -0
  282. package/ui/dist/assets/CartesianChart-piKQsTAR.js +36 -0
  283. package/ui/dist/assets/ChatView-Dbj8rxU5.js +10 -0
  284. package/ui/dist/assets/CostsDashboard-C6F5df0F.js +1 -0
  285. package/ui/dist/assets/EstimateSelect-wga0rUKX.js +1 -0
  286. package/ui/dist/assets/FeedDashboard-Ef6FEzEf.js +1 -0
  287. package/ui/dist/assets/FloatingChatbot-0yhkUeCq.js +2 -0
  288. package/ui/dist/assets/InviteCodeManagement-tUXfx4Bc.js +2 -0
  289. package/ui/dist/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
  290. package/ui/dist/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
  291. package/ui/dist/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
  292. package/ui/dist/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
  293. package/ui/dist/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
  294. package/ui/dist/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
  295. package/ui/dist/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
  296. package/ui/dist/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
  297. package/ui/dist/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
  298. package/ui/dist/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
  299. package/ui/dist/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
  300. package/ui/dist/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
  301. package/ui/dist/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
  302. package/ui/dist/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
  303. package/ui/dist/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
  304. package/ui/dist/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
  305. package/ui/dist/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
  306. package/ui/dist/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
  307. package/ui/dist/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
  308. package/ui/dist/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
  309. package/ui/dist/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
  310. package/ui/dist/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
  311. package/ui/dist/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
  312. package/ui/dist/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
  313. package/ui/dist/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
  314. package/ui/dist/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
  315. package/ui/dist/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
  316. package/ui/dist/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
  317. package/ui/dist/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
  318. package/ui/dist/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
  319. package/ui/dist/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
  320. package/ui/dist/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
  321. package/ui/dist/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
  322. package/ui/dist/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
  323. package/ui/dist/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
  324. package/ui/dist/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
  325. package/ui/dist/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
  326. package/ui/dist/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
  327. package/ui/dist/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
  328. package/ui/dist/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
  329. package/ui/dist/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
  330. package/ui/dist/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
  331. package/ui/dist/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
  332. package/ui/dist/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
  333. package/ui/dist/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
  334. package/ui/dist/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
  335. package/ui/dist/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
  336. package/ui/dist/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
  337. package/ui/dist/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
  338. package/ui/dist/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
  339. package/ui/dist/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
  340. package/ui/dist/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
  341. package/ui/dist/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
  342. package/ui/dist/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
  343. package/ui/dist/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
  344. package/ui/dist/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
  345. package/ui/dist/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
  346. package/ui/dist/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
  347. package/ui/dist/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
  348. package/ui/dist/assets/MarketplacePage-DGrLtolR.js +1 -0
  349. package/ui/dist/assets/{ProjectDetail--gPfvATB.js → ProjectDetail-BgWvA6UP.js} +2 -2
  350. package/ui/dist/assets/ProjectIcon-TDuliqwg.js +1 -0
  351. package/ui/dist/assets/ProjectList-DXgM4187.js +1 -0
  352. package/ui/dist/assets/{Settings-1kaf7VHE.js → Settings-xA8Zhi3p.js} +3 -3
  353. package/ui/dist/assets/StatusIndicator-B8vfFAxg.js +1 -0
  354. package/ui/dist/assets/{SummaryDetail-DV3AmONk.js → SummaryDetail-eedRfTtF.js} +2 -2
  355. package/ui/dist/assets/SummaryList-CLNX2P84.js +1 -0
  356. package/ui/dist/assets/TaskDetail-BtWclNiR.js +1 -0
  357. package/ui/dist/assets/TaskList-JjODAgSc.js +1 -0
  358. package/ui/dist/assets/TeamsPage-CBK5iAyx.js +1 -0
  359. package/ui/dist/assets/TicketBoard-C9aJNNYp.js +1 -0
  360. package/ui/dist/assets/TicketDetail-CV5JmL31.js +1 -0
  361. package/ui/dist/assets/TicketList-68V4lzUz.js +1 -0
  362. package/ui/dist/assets/UserManagement-DKTb6UpE.js +2 -0
  363. package/ui/dist/assets/ViewSwitcher-BvdQht2Y.js +1 -0
  364. package/ui/dist/assets/alert-dialog-O6qBOv_f.js +1 -0
  365. package/ui/dist/assets/{archive-BsLa7brF.js → archive-CX7UvZpf.js} +1 -1
  366. package/ui/dist/assets/badge-BbfnwDJP.js +1 -0
  367. package/ui/dist/assets/{bug-CmZI7jqM.js → bug-3WX0394-.js} +1 -1
  368. package/ui/dist/assets/{calendar-Bf0t2B82.js → calendar-buq77TaS.js} +1 -1
  369. package/ui/dist/assets/{chevron-up-CoUsOvZj.js → chevron-up-4ymsBJRo.js} +1 -1
  370. package/ui/dist/assets/{circle-x-Dgw11LgT.js → circle-x-ByXtwR6Y.js} +1 -1
  371. package/ui/dist/assets/constants-CVdDh7p0.js +1 -0
  372. package/ui/dist/assets/{cpu-DiPMQICV.js → cpu-CiuoCeDY.js} +1 -1
  373. package/ui/dist/assets/{database-BwTfupDi.js → database-BWXSBg5a.js} +1 -1
  374. package/ui/dist/assets/dialog-lDg4NvMV.js +1 -0
  375. package/ui/dist/assets/dollar-sign-Dmijd6DP.js +1 -0
  376. package/ui/dist/assets/{ellipsis-UJx4Xnf6.js → ellipsis-vT-5SVIp.js} +1 -1
  377. package/ui/dist/assets/{ellipsis-vertical-DoULYEKn.js → ellipsis-vertical-B4tAX_bL.js} +1 -1
  378. package/ui/dist/assets/feature-markdown-DBo5Q7uq.js +289 -0
  379. package/ui/dist/assets/{file-code-B2UrJLwi.js → file-code-ChOWdKXf.js} +1 -1
  380. package/ui/dist/assets/{folder-open-BJi577JH.js → folder-open-CkOUbIiP.js} +1 -1
  381. package/ui/dist/assets/{funnel-PkaD_HSR.js → funnel-uZkoSPP-.js} +1 -1
  382. package/ui/dist/assets/{git-branch-C_K30am0.js → git-branch-CwvUxj7C.js} +1 -1
  383. package/ui/dist/assets/{git-commit-horizontal-IT6ecxWQ.js → git-commit-horizontal-lxPzCvhD.js} +1 -1
  384. package/ui/dist/assets/{globe-f-jjCa_g.js → globe-D_WpJdsj.js} +1 -1
  385. package/ui/dist/assets/{hash-DNEv8Elo.js → hash-CA0hJ7vh.js} +1 -1
  386. package/ui/dist/assets/{history-BQSBo_1Q.js → history-CEWMLELs.js} +1 -1
  387. package/ui/dist/assets/inbox-ehtOptTV.js +1 -0
  388. package/ui/dist/assets/{index-nS3EErDg.js → index-C1rhbml4.js} +3 -3
  389. package/ui/dist/assets/index-CR8gfCHv.js +1 -0
  390. package/ui/dist/assets/index-DVXMpWai.js +1 -0
  391. package/ui/dist/assets/index-DaDJMM2v.js +1 -0
  392. package/ui/dist/assets/index-Djdq_0xu.js +1 -0
  393. package/ui/dist/assets/index-M46Gcb8K.css +1 -0
  394. package/ui/dist/assets/index-sEBN7w8J.js +109 -0
  395. package/ui/dist/assets/layers-C6Mhf8Nk.js +1 -0
  396. package/ui/dist/assets/{layout-dashboard-CcKt1hXw.js → layout-dashboard-BRUM0kpT.js} +1 -1
  397. package/ui/dist/assets/{lightbulb-Jhp7FvbU.js → lightbulb-CN2q1O5l.js} +1 -1
  398. package/ui/dist/assets/{link-2-DdO7ostF.js → link-2-CC4E28yJ.js} +1 -1
  399. package/ui/dist/assets/markdown-renderer-C6ENbB0u.js +10 -0
  400. package/ui/dist/assets/markdown-renderer-CfVKi3_s.css +1 -0
  401. package/ui/dist/assets/{message-square-CBgH65X7.js → message-square-Bbb241am.js} +1 -1
  402. package/ui/dist/assets/package-CwT3IzFx.js +1 -0
  403. package/ui/dist/assets/{pencil-CYXCEPQh.js → pencil-CDmiHzoj.js} +1 -1
  404. package/ui/dist/assets/{play-d1ONaH0-.js → play-tjy5jMQX.js} +1 -1
  405. package/ui/dist/assets/popover-CFHZf3pE.js +1 -0
  406. package/ui/dist/assets/progress-BboUHuLf.js +1 -0
  407. package/ui/dist/assets/{rocket-DhvUetsk.js → rocket--8ZHgdXJ.js} +1 -1
  408. package/ui/dist/assets/select-n108rXny.js +1 -0
  409. package/ui/dist/assets/{send-P0r5D7td.js → send-Cu7MR2Qh.js} +1 -1
  410. package/ui/dist/assets/server-DmodxZp-.js +1 -0
  411. package/ui/dist/assets/{settings-2-ocj5uHGx.js → settings-2-CkRNqkxj.js} +1 -1
  412. package/ui/dist/assets/sheet-7aUJkyzU.js +1 -0
  413. package/ui/dist/assets/{shield-check-DfVdE34l.js → shield-check-ViI3nMKE.js} +1 -1
  414. package/ui/dist/assets/{shield-off-8l0J6R-8.js → shield-off-DN3tagkn.js} +1 -1
  415. package/ui/dist/assets/skeleton-C0E1Nfro.js +1 -0
  416. package/ui/dist/assets/{smartphone-77_g3SQn.js → smartphone-5FghiXpA.js} +1 -1
  417. package/ui/dist/assets/{square-Ckzsr3Rn.js → square-DiNSx8K7.js} +1 -1
  418. package/ui/dist/assets/star-DhdFVidS.js +1 -0
  419. package/ui/dist/assets/switch-CIgVbZqQ.js +1 -0
  420. package/ui/dist/assets/table-BC56FVMV.js +1 -0
  421. package/ui/dist/assets/{tag-C35mgoEv.js → tag-CH_vQliw.js} +1 -1
  422. package/ui/dist/assets/textarea-CxDiKFXZ.js +1 -0
  423. package/ui/dist/assets/{timer-DHJBS2w1.js → timer-CdGVTb60.js} +1 -1
  424. package/ui/dist/assets/tooltip-BuW9A5UO.js +1 -0
  425. package/ui/dist/assets/{trash-2-keO5tKPE.js → trash-2-CucZJL0N.js} +1 -1
  426. package/ui/dist/assets/trending-down-BCezC1z2.js +1 -0
  427. package/ui/dist/assets/{trending-up-BBv8KbrY.js → trending-up-C5OYX2k2.js} +1 -1
  428. package/ui/dist/assets/vendor-query-C0p7b53x.js +4 -0
  429. package/ui/dist/assets/vendor-react-Mc5_kfYG.js +12 -0
  430. package/ui/dist/assets/vendor-ui-CXPAUBFv.js +51 -0
  431. package/ui/dist/assets/{wand-sparkles-BusQ52ZK.js → wand-sparkles-BaH6pJnc.js} +1 -1
  432. package/ui/dist/assets/{wrench-02YaOSiK.js → wrench-CjxjP6ok.js} +1 -1
  433. package/ui/dist/index.html +5 -2
  434. package/ui/dist/assets/ActivityView-BeshZXmE.js +0 -1
  435. package/ui/dist/assets/AgentList-QVHeldPi.js +0 -1
  436. package/ui/dist/assets/AnalyticsDashboard-C9R97dXE.js +0 -1
  437. package/ui/dist/assets/AreaChart-B73gaiVQ.js +0 -1
  438. package/ui/dist/assets/CartesianChart-CXYL2R-A.js +0 -36
  439. package/ui/dist/assets/ChatView-qjZErlrp.js +0 -10
  440. package/ui/dist/assets/CostsDashboard-O4DCLy1i.js +0 -1
  441. package/ui/dist/assets/EstimateSelect-1hQf4Osk.js +0 -1
  442. package/ui/dist/assets/FloatingChatbot-BZBzrJxd.js +0 -2
  443. package/ui/dist/assets/InviteCodeManagement-LEoGqYeA.js +0 -2
  444. package/ui/dist/assets/ProjectIcon-Chd_ofsw.js +0 -1
  445. package/ui/dist/assets/ProjectList-BvUfVB6c.js +0 -4
  446. package/ui/dist/assets/StatusIndicator-pRfkNcdV.js +0 -1
  447. package/ui/dist/assets/SummaryList-B6kXiTxL.js +0 -1
  448. package/ui/dist/assets/TaskDetail-CV6CzbOS.js +0 -1
  449. package/ui/dist/assets/TaskList-DL7brQKd.js +0 -1
  450. package/ui/dist/assets/TicketBoard-CrkkFj7C.js +0 -1
  451. package/ui/dist/assets/TicketDetail-hnnYclpD.js +0 -1
  452. package/ui/dist/assets/TicketList-CsDAyQCL.js +0 -1
  453. package/ui/dist/assets/UserManagement-BGFQyTSr.js +0 -2
  454. package/ui/dist/assets/ViewSwitcher-CnL0OqA8.js +0 -1
  455. package/ui/dist/assets/alert-dialog-SKM6Gjz4.js +0 -7
  456. package/ui/dist/assets/badge-CVHH1a-v.js +0 -1
  457. package/ui/dist/assets/brain-6o_RHVpe.js +0 -1
  458. package/ui/dist/assets/constants-Q5Zivl-a.js +0 -1
  459. package/ui/dist/assets/dialog-BUqN9Psj.js +0 -1
  460. package/ui/dist/assets/index-BUmnwPQr.js +0 -1
  461. package/ui/dist/assets/index-BfF5G4Cw.js +0 -1
  462. package/ui/dist/assets/index-C8N375c2.js +0 -1
  463. package/ui/dist/assets/index-CuxnqVVz.css +0 -1
  464. package/ui/dist/assets/index-CzMM3QOk.js +0 -1
  465. package/ui/dist/assets/index-lJlNPFVJ.js +0 -67
  466. package/ui/dist/assets/layers-jFqVrWMD.js +0 -1
  467. package/ui/dist/assets/markdown-renderer-n1ToC4XQ.js +0 -36
  468. package/ui/dist/assets/popover-CrmZgoWu.js +0 -1
  469. package/ui/dist/assets/progress-uv4SPkL5.js +0 -1
  470. package/ui/dist/assets/select-CeQ8AHGy.js +0 -1
  471. package/ui/dist/assets/server-CVHTZB72.js +0 -1
  472. package/ui/dist/assets/sheet-DuQExSho.js +0 -1
  473. package/ui/dist/assets/skeleton-TFiFJ3nB.js +0 -1
  474. package/ui/dist/assets/switch-CAePkd6k.js +0 -1
  475. package/ui/dist/assets/table-ZjAZ7hkt.js +0 -1
  476. package/ui/dist/assets/textarea-DsVPnSgR.js +0 -1
  477. package/ui/dist/assets/tooltip-BYmQ331W.js +0 -1
@@ -0,0 +1,600 @@
1
+ /**
2
+ * RSS/Atom Feed Engine
3
+ *
4
+ * Fetches, parses, and stores articles from RSS/Atom feeds.
5
+ * Provides deduplication, categorization, and AI summarization integration.
6
+ *
7
+ * Fully dynamic - categories, sources, and bundles can be extended at runtime.
8
+ * No hardcoded limitations on feed types, categories, or article counts.
9
+ *
10
+ * Used by cron jobs to power "morning AI news digest" and similar automations.
11
+ */
12
+ import { getClient } from '../storage/index.js';
13
+ import { createContextualLogger } from '../utils/logger.js';
14
+ const log = createContextualLogger('FeedEngine');
15
+ // Pre-configured feed bundles (starter packs - users and agents can add more at runtime)
16
+ export const FEED_BUNDLES = {
17
+ 'ai-news': [
18
+ { name: 'OpenAI Blog', url: 'https://openai.com/blog/rss.xml', category: 'ai' },
19
+ { name: 'Anthropic News', url: 'https://www.anthropic.com/rss.xml', category: 'ai' },
20
+ { name: 'Hugging Face Blog', url: 'https://huggingface.co/blog/feed.xml', category: 'ai' },
21
+ { name: 'TechCrunch AI', url: 'https://techcrunch.com/category/artificial-intelligence/feed/', category: 'ai' },
22
+ { name: 'The Verge AI', url: 'https://www.theverge.com/rss/ai-artificial-intelligence/index.xml', category: 'ai' },
23
+ { name: 'MIT Tech Review', url: 'https://www.technologyreview.com/feed/', category: 'ai' },
24
+ ],
25
+ 'dev-news': [
26
+ { name: 'Hacker News (Best)', url: 'https://hnrss.org/best', category: 'dev' },
27
+ { name: 'Lobsters', url: 'https://lobste.rs/rss', category: 'dev' },
28
+ { name: 'Dev.to Top', url: 'https://dev.to/feed', category: 'dev' },
29
+ ],
30
+ 'security': [
31
+ { name: 'Krebs on Security', url: 'https://krebsonsecurity.com/feed/', category: 'security' },
32
+ { name: 'The Hacker News', url: 'https://feeds.feedburner.com/TheHackersNews', category: 'security' },
33
+ { name: 'Schneier on Security', url: 'https://www.schneier.com/feed/', category: 'security' },
34
+ ],
35
+ };
36
+ /**
37
+ * Register a custom feed bundle at runtime.
38
+ * Agents and users can call this to extend the available bundles.
39
+ */
40
+ export function registerFeedBundle(name, feeds) {
41
+ FEED_BUNDLES[name] = feeds;
42
+ log.info(`Registered feed bundle: ${name} (${feeds.length} feeds)`);
43
+ }
44
+ // Database initialization
45
+ const FEEDS_TABLE = `
46
+ CREATE TABLE IF NOT EXISTS feed_sources (
47
+ id TEXT PRIMARY KEY,
48
+ name TEXT NOT NULL,
49
+ url TEXT NOT NULL UNIQUE,
50
+ category TEXT NOT NULL DEFAULT 'general',
51
+ tags TEXT NOT NULL DEFAULT '[]',
52
+ enabled INTEGER NOT NULL DEFAULT 1,
53
+ poll_interval_ms INTEGER NOT NULL DEFAULT 3600000,
54
+ last_polled_at TEXT,
55
+ last_error TEXT,
56
+ article_count INTEGER NOT NULL DEFAULT 0,
57
+ metadata TEXT NOT NULL DEFAULT '{}',
58
+ user_id TEXT,
59
+ created_at TEXT NOT NULL DEFAULT (datetime('now')),
60
+ updated_at TEXT NOT NULL DEFAULT (datetime('now'))
61
+ )`;
62
+ const ARTICLES_TABLE = `
63
+ CREATE TABLE IF NOT EXISTS feed_articles (
64
+ id TEXT PRIMARY KEY,
65
+ feed_id TEXT NOT NULL REFERENCES feed_sources(id) ON DELETE CASCADE,
66
+ title TEXT NOT NULL,
67
+ url TEXT NOT NULL,
68
+ summary TEXT,
69
+ content TEXT,
70
+ author TEXT,
71
+ published_at TEXT,
72
+ fetched_at TEXT NOT NULL DEFAULT (datetime('now')),
73
+ ai_summary TEXT,
74
+ digested_at TEXT,
75
+ content_hash TEXT NOT NULL,
76
+ UNIQUE(feed_id, content_hash)
77
+ )`;
78
+ const ARTICLES_INDEX = `CREATE INDEX IF NOT EXISTS idx_articles_feed_date ON feed_articles(feed_id, fetched_at DESC)`;
79
+ const ARTICLES_URL_INDEX = `CREATE INDEX IF NOT EXISTS idx_articles_url ON feed_articles(url)`;
80
+ let tablesInitialized = false;
81
+ async function ensureTables() {
82
+ if (tablesInitialized)
83
+ return;
84
+ const client = getClient();
85
+ await client.execute(FEEDS_TABLE);
86
+ await client.execute(ARTICLES_TABLE);
87
+ await client.execute(ARTICLES_INDEX);
88
+ await client.execute(ARTICLES_URL_INDEX);
89
+ tablesInitialized = true;
90
+ }
91
+ // Feed CRUD
92
+ export async function addFeed(params) {
93
+ await ensureTables();
94
+ const client = getClient();
95
+ const id = crypto.randomUUID();
96
+ const now = new Date().toISOString();
97
+ await client.execute({
98
+ sql: `INSERT INTO feed_sources (id, name, url, category, tags, poll_interval_ms, metadata, user_id, created_at, updated_at)
99
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
100
+ args: [
101
+ id, params.name, params.url,
102
+ params.category || 'general',
103
+ JSON.stringify(params.tags || []),
104
+ params.pollIntervalMs || 3600000,
105
+ JSON.stringify(params.metadata || {}),
106
+ params.userId || null,
107
+ now, now,
108
+ ],
109
+ });
110
+ log.info(`Added feed: ${params.name} (${params.url})`);
111
+ return {
112
+ id,
113
+ name: params.name,
114
+ url: params.url,
115
+ category: params.category || 'general',
116
+ tags: params.tags || [],
117
+ enabled: true,
118
+ pollIntervalMs: params.pollIntervalMs || 3600000,
119
+ articleCount: 0,
120
+ metadata: params.metadata || {},
121
+ userId: params.userId,
122
+ createdAt: new Date(now),
123
+ updatedAt: new Date(now),
124
+ };
125
+ }
126
+ export async function addFeedBundle(bundleName, userId) {
127
+ const bundle = FEED_BUNDLES[bundleName];
128
+ if (!bundle) {
129
+ throw new Error(`Unknown feed bundle: ${bundleName}. Available: ${Object.keys(FEED_BUNDLES).join(', ')}`);
130
+ }
131
+ const results = [];
132
+ for (const feed of bundle) {
133
+ try {
134
+ const source = await addFeed({ ...feed, userId });
135
+ results.push(source);
136
+ }
137
+ catch (error) {
138
+ // Skip duplicates silently
139
+ if (error instanceof Error && error.message.includes('UNIQUE')) {
140
+ log.debug(`Feed already exists: ${feed.url}`);
141
+ }
142
+ else {
143
+ log.error(`Failed to add feed ${feed.name}:`, error instanceof Error ? error : new Error(String(error)));
144
+ }
145
+ }
146
+ }
147
+ return results;
148
+ }
149
+ export async function listFeeds(filters) {
150
+ await ensureTables();
151
+ const client = getClient();
152
+ let sql = 'SELECT * FROM feed_sources WHERE 1=1';
153
+ const args = [];
154
+ if (filters?.category) {
155
+ sql += ' AND category = ?';
156
+ args.push(filters.category);
157
+ }
158
+ if (filters?.tag) {
159
+ // Search within JSON array
160
+ sql += ' AND tags LIKE ?';
161
+ args.push(`%"${filters.tag}"%`);
162
+ }
163
+ if (filters?.enabled !== undefined) {
164
+ sql += ' AND enabled = ?';
165
+ args.push(filters.enabled ? 1 : 0);
166
+ }
167
+ if (filters?.userId) {
168
+ sql += ' AND user_id = ?';
169
+ args.push(filters.userId);
170
+ }
171
+ sql += ' ORDER BY name ASC';
172
+ const result = await client.execute({ sql, args });
173
+ return result.rows.map(mapFeedRow);
174
+ }
175
+ export async function getFeed(id) {
176
+ await ensureTables();
177
+ const client = getClient();
178
+ const result = await client.execute({ sql: 'SELECT * FROM feed_sources WHERE id = ?', args: [id] });
179
+ return result.rows.length > 0 ? mapFeedRow(result.rows[0]) : null;
180
+ }
181
+ export async function updateFeed(id, updates) {
182
+ await ensureTables();
183
+ const client = getClient();
184
+ const sets = [];
185
+ const args = [];
186
+ if (updates.name !== undefined) {
187
+ sets.push('name = ?');
188
+ args.push(updates.name);
189
+ }
190
+ if (updates.category !== undefined) {
191
+ sets.push('category = ?');
192
+ args.push(updates.category);
193
+ }
194
+ if (updates.tags !== undefined) {
195
+ sets.push('tags = ?');
196
+ args.push(JSON.stringify(updates.tags));
197
+ }
198
+ if (updates.pollIntervalMs !== undefined) {
199
+ sets.push('poll_interval_ms = ?');
200
+ args.push(updates.pollIntervalMs);
201
+ }
202
+ if (updates.metadata !== undefined) {
203
+ sets.push('metadata = ?');
204
+ args.push(JSON.stringify(updates.metadata));
205
+ }
206
+ if (sets.length === 0)
207
+ return;
208
+ sets.push('updated_at = datetime("now")');
209
+ args.push(id);
210
+ await client.execute({
211
+ sql: `UPDATE feed_sources SET ${sets.join(', ')} WHERE id = ?`,
212
+ args,
213
+ });
214
+ }
215
+ export async function removeFeed(id) {
216
+ await ensureTables();
217
+ const client = getClient();
218
+ const result = await client.execute({ sql: 'DELETE FROM feed_sources WHERE id = ?', args: [id] });
219
+ return result.rowsAffected > 0;
220
+ }
221
+ export async function toggleFeed(id, enabled) {
222
+ await ensureTables();
223
+ const client = getClient();
224
+ await client.execute({
225
+ sql: 'UPDATE feed_sources SET enabled = ?, updated_at = datetime("now") WHERE id = ?',
226
+ args: [enabled ? 1 : 0, id],
227
+ });
228
+ }
229
+ // Feed polling and parsing
230
+ /**
231
+ * Parse an RSS/Atom XML feed into articles.
232
+ * Lightweight regex-based parser - no external dependencies needed.
233
+ */
234
+ export function parseFeedXml(xml) {
235
+ const articles = [];
236
+ const isAtom = xml.includes('<feed') && xml.includes('xmlns="http://www.w3.org/2005/Atom"');
237
+ if (isAtom) {
238
+ const entryRegex = /<entry>([\s\S]*?)<\/entry>/gi;
239
+ let match;
240
+ while ((match = entryRegex.exec(xml)) !== null) {
241
+ const entry = match[1];
242
+ const title = extractTag(entry, 'title');
243
+ const link = extractAtomLink(entry);
244
+ const summary = extractTag(entry, 'summary') || extractTag(entry, 'content');
245
+ const author = extractTag(entry, 'name');
246
+ const published = extractTag(entry, 'published') || extractTag(entry, 'updated');
247
+ if (title && link) {
248
+ articles.push({
249
+ title: decodeHtmlEntities(title),
250
+ url: link,
251
+ summary: summary ? decodeHtmlEntities(stripHtml(summary)).slice(0, 500) : undefined,
252
+ author: author ? decodeHtmlEntities(author) : undefined,
253
+ publishedAt: published || undefined,
254
+ });
255
+ }
256
+ }
257
+ }
258
+ else {
259
+ const itemRegex = /<item>([\s\S]*?)<\/item>/gi;
260
+ let match;
261
+ while ((match = itemRegex.exec(xml)) !== null) {
262
+ const item = match[1];
263
+ const title = extractTag(item, 'title');
264
+ const link = extractTag(item, 'link');
265
+ const description = extractTag(item, 'description');
266
+ const contentEncoded = extractTag(item, 'content:encoded');
267
+ const author = extractTag(item, 'dc:creator') || extractTag(item, 'author');
268
+ const pubDate = extractTag(item, 'pubDate');
269
+ if (title && link) {
270
+ articles.push({
271
+ title: decodeHtmlEntities(title),
272
+ url: link.trim(),
273
+ summary: description ? decodeHtmlEntities(stripHtml(description)).slice(0, 500) : undefined,
274
+ content: contentEncoded ? decodeHtmlEntities(stripHtml(contentEncoded)).slice(0, 2000) : undefined,
275
+ author: author ? decodeHtmlEntities(author) : undefined,
276
+ publishedAt: pubDate || undefined,
277
+ });
278
+ }
279
+ }
280
+ }
281
+ return articles;
282
+ }
283
+ /**
284
+ * Poll a single feed source and store new articles.
285
+ */
286
+ export async function pollFeed(feedId) {
287
+ await ensureTables();
288
+ const client = getClient();
289
+ const feedResult = await client.execute({ sql: 'SELECT * FROM feed_sources WHERE id = ?', args: [feedId] });
290
+ if (feedResult.rows.length === 0) {
291
+ return { newArticles: 0, errors: 'Feed not found' };
292
+ }
293
+ const feed = mapFeedRow(feedResult.rows[0]);
294
+ let newArticles = 0;
295
+ try {
296
+ const response = await fetch(feed.url, {
297
+ headers: {
298
+ 'User-Agent': 'profClaw/2.0 Feed Reader',
299
+ 'Accept': 'application/rss+xml, application/atom+xml, application/xml, text/xml',
300
+ },
301
+ signal: AbortSignal.timeout(15000),
302
+ });
303
+ if (!response.ok) {
304
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
305
+ }
306
+ const xml = await response.text();
307
+ const parsed = parseFeedXml(xml);
308
+ for (const article of parsed) {
309
+ const contentHash = hashString(`${feed.id}:${article.url}:${article.title}`);
310
+ try {
311
+ await client.execute({
312
+ sql: `INSERT OR IGNORE INTO feed_articles
313
+ (id, feed_id, title, url, summary, content, author, published_at, fetched_at, content_hash)
314
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, datetime('now'), ?)`,
315
+ args: [
316
+ crypto.randomUUID(),
317
+ feedId,
318
+ article.title,
319
+ article.url,
320
+ article.summary || null,
321
+ article.content || null,
322
+ article.author || null,
323
+ article.publishedAt || null,
324
+ contentHash,
325
+ ],
326
+ });
327
+ newArticles++;
328
+ }
329
+ catch {
330
+ // Duplicate - skip
331
+ }
332
+ }
333
+ await client.execute({
334
+ sql: `UPDATE feed_sources SET
335
+ last_polled_at = datetime('now'),
336
+ last_error = NULL,
337
+ article_count = article_count + ?,
338
+ updated_at = datetime('now')
339
+ WHERE id = ?`,
340
+ args: [newArticles, feedId],
341
+ });
342
+ log.info(`Polled ${feed.name}: ${newArticles} new articles from ${parsed.length} total`);
343
+ }
344
+ catch (error) {
345
+ const errMsg = error instanceof Error ? error.message : String(error);
346
+ await client.execute({
347
+ sql: `UPDATE feed_sources SET last_polled_at = datetime('now'), last_error = ?, updated_at = datetime('now') WHERE id = ?`,
348
+ args: [errMsg, feedId],
349
+ });
350
+ log.error(`Feed poll failed for ${feed.name}:`, error instanceof Error ? error : new Error(errMsg));
351
+ return { newArticles: 0, errors: errMsg };
352
+ }
353
+ return { newArticles };
354
+ }
355
+ /**
356
+ * Poll all enabled feeds that are due for polling.
357
+ */
358
+ export async function pollAllFeeds() {
359
+ const feeds = await listFeeds({ enabled: true });
360
+ let total = 0;
361
+ let newArticles = 0;
362
+ let errors = 0;
363
+ for (const feed of feeds) {
364
+ if (feed.lastPolledAt) {
365
+ const timeSincePoll = Date.now() - feed.lastPolledAt.getTime();
366
+ if (timeSincePoll < feed.pollIntervalMs)
367
+ continue;
368
+ }
369
+ total++;
370
+ const result = await pollFeed(feed.id);
371
+ newArticles += result.newArticles;
372
+ if (result.errors)
373
+ errors++;
374
+ // Small delay between feeds to be nice to servers
375
+ await new Promise((resolve) => setTimeout(resolve, 500));
376
+ }
377
+ log.info(`Feed poll complete: ${total} feeds polled, ${newArticles} new articles, ${errors} errors`);
378
+ return { total, newArticles, errors };
379
+ }
380
+ /**
381
+ * Get recent articles for a digest.
382
+ * All filters are optional - the engine imposes no limits by default.
383
+ */
384
+ export async function getDigestArticles(options) {
385
+ await ensureTables();
386
+ const client = getClient();
387
+ const since = options?.since || new Date(Date.now() - 24 * 60 * 60 * 1000);
388
+ const limit = options?.limit || 50;
389
+ let sql = `
390
+ SELECT a.*
391
+ FROM feed_articles a
392
+ JOIN feed_sources f ON a.feed_id = f.id
393
+ WHERE a.fetched_at >= ?
394
+ `;
395
+ const args = [since.toISOString()];
396
+ if (options?.category) {
397
+ sql += ' AND f.category = ?';
398
+ args.push(options.category);
399
+ }
400
+ if (options?.tag) {
401
+ sql += ' AND f.tags LIKE ?';
402
+ args.push(`%"${options.tag}"%`);
403
+ }
404
+ if (options?.feedId) {
405
+ sql += ' AND a.feed_id = ?';
406
+ args.push(options.feedId);
407
+ }
408
+ if (options?.undigestedOnly) {
409
+ sql += ' AND a.digested_at IS NULL';
410
+ }
411
+ sql += ' ORDER BY a.fetched_at DESC LIMIT ?';
412
+ args.push(limit);
413
+ const result = await client.execute({ sql, args });
414
+ return result.rows.map(mapArticleRow);
415
+ }
416
+ /**
417
+ * Mark articles as digested (included in a delivered digest).
418
+ */
419
+ export async function markAsDigested(articleIds) {
420
+ if (articleIds.length === 0)
421
+ return;
422
+ await ensureTables();
423
+ const client = getClient();
424
+ // Batch in groups of 100 for safety
425
+ for (let i = 0; i < articleIds.length; i += 100) {
426
+ const batch = articleIds.slice(i, i + 100);
427
+ const placeholders = batch.map(() => '?').join(',');
428
+ await client.execute({
429
+ sql: `UPDATE feed_articles SET digested_at = datetime('now') WHERE id IN (${placeholders})`,
430
+ args: batch,
431
+ });
432
+ }
433
+ }
434
+ /**
435
+ * Get feed statistics.
436
+ */
437
+ export async function getFeedStats() {
438
+ await ensureTables();
439
+ const client = getClient();
440
+ const total = await client.execute('SELECT COUNT(*) as count FROM feed_sources');
441
+ const enabled = await client.execute('SELECT COUNT(*) as count FROM feed_sources WHERE enabled = 1');
442
+ const articles = await client.execute('SELECT COUNT(*) as count FROM feed_articles');
443
+ const today = await client.execute(`SELECT COUNT(*) as count FROM feed_articles WHERE fetched_at >= datetime('now', '-1 day')`);
444
+ const catResult = await client.execute('SELECT category, COUNT(*) as count FROM feed_sources GROUP BY category');
445
+ const byCategory = {};
446
+ for (const row of catResult.rows) {
447
+ byCategory[row.category] = row.count;
448
+ }
449
+ return {
450
+ totalFeeds: total.rows[0].count,
451
+ enabledFeeds: enabled.rows[0].count,
452
+ totalArticles: articles.rows[0].count,
453
+ articlesToday: today.rows[0].count,
454
+ byCategory,
455
+ };
456
+ }
457
+ /**
458
+ * List all distinct categories currently in use.
459
+ */
460
+ export async function listCategories() {
461
+ await ensureTables();
462
+ const client = getClient();
463
+ const result = await client.execute('SELECT DISTINCT category FROM feed_sources ORDER BY category');
464
+ return result.rows.map((r) => r.category);
465
+ }
466
+ /**
467
+ * Auto-discover feed URL from a website.
468
+ * Fetches the page and looks for RSS/Atom link tags.
469
+ */
470
+ export async function discoverFeedUrl(websiteUrl) {
471
+ try {
472
+ const response = await fetch(websiteUrl, {
473
+ headers: { 'User-Agent': 'profClaw/2.0 Feed Discovery' },
474
+ signal: AbortSignal.timeout(10000),
475
+ });
476
+ if (!response.ok)
477
+ return null;
478
+ const html = await response.text();
479
+ // Look for <link rel="alternate" type="application/rss+xml" href="..." />
480
+ const rssMatch = html.match(/<link[^>]*type="application\/(?:rss|atom)\+xml"[^>]*href="([^"]+)"/i);
481
+ if (rssMatch) {
482
+ const href = rssMatch[1];
483
+ // Resolve relative URLs
484
+ if (href.startsWith('http'))
485
+ return href;
486
+ const base = new URL(websiteUrl);
487
+ return new URL(href, base).toString();
488
+ }
489
+ // Fallback: try common feed paths
490
+ const commonPaths = ['/feed', '/rss', '/rss.xml', '/feed.xml', '/atom.xml', '/blog/rss.xml'];
491
+ for (const path of commonPaths) {
492
+ try {
493
+ const feedUrl = new URL(path, websiteUrl).toString();
494
+ const feedResp = await fetch(feedUrl, {
495
+ method: 'HEAD',
496
+ signal: AbortSignal.timeout(5000),
497
+ });
498
+ if (feedResp.ok)
499
+ return feedUrl;
500
+ }
501
+ catch {
502
+ // Try next
503
+ }
504
+ }
505
+ return null;
506
+ }
507
+ catch {
508
+ return null;
509
+ }
510
+ }
511
+ // Helper functions
512
+ function extractTag(xml, tagName) {
513
+ const cdataRegex = new RegExp(`<${tagName}[^>]*>\\s*<!\\[CDATA\\[([\\s\\S]*?)\\]\\]>\\s*<\\/${tagName}>`, 'i');
514
+ const cdataMatch = cdataRegex.exec(xml);
515
+ if (cdataMatch)
516
+ return cdataMatch[1].trim();
517
+ const regex = new RegExp(`<${tagName}[^>]*>([\\s\\S]*?)<\\/${tagName}>`, 'i');
518
+ const match = regex.exec(xml);
519
+ return match ? match[1].trim() : null;
520
+ }
521
+ function extractAtomLink(entry) {
522
+ const linkRegex = /<link[^>]*href="([^"]*)"[^>]*(?:rel="alternate")?[^>]*\/?>/gi;
523
+ let match;
524
+ let bestLink = null;
525
+ while ((match = linkRegex.exec(entry)) !== null) {
526
+ const fullTag = match[0];
527
+ const href = match[1];
528
+ if (fullTag.includes('rel="alternate"') || !bestLink) {
529
+ bestLink = href;
530
+ }
531
+ }
532
+ return bestLink;
533
+ }
534
+ function stripHtml(html) {
535
+ return html.replace(/<[^>]+>/g, '').replace(/\s+/g, ' ').trim();
536
+ }
537
+ function decodeHtmlEntities(text) {
538
+ return text
539
+ .replace(/&amp;/g, '&')
540
+ .replace(/&lt;/g, '<')
541
+ .replace(/&gt;/g, '>')
542
+ .replace(/&quot;/g, '"')
543
+ .replace(/&#39;/g, "'")
544
+ .replace(/&#x27;/g, "'")
545
+ .replace(/&#(\d+);/g, (_, code) => String.fromCharCode(parseInt(code)));
546
+ }
547
+ function hashString(input) {
548
+ let hash = 0;
549
+ for (let i = 0; i < input.length; i++) {
550
+ const char = input.charCodeAt(i);
551
+ hash = ((hash << 5) - hash) + char;
552
+ hash = hash & hash;
553
+ }
554
+ return Math.abs(hash).toString(36);
555
+ }
556
+ function mapFeedRow(row) {
557
+ let tags = [];
558
+ try {
559
+ tags = JSON.parse(row.tags || '[]');
560
+ }
561
+ catch { /* empty */ }
562
+ let metadata = {};
563
+ try {
564
+ metadata = JSON.parse(row.metadata || '{}');
565
+ }
566
+ catch { /* empty */ }
567
+ return {
568
+ id: row.id,
569
+ name: row.name,
570
+ url: row.url,
571
+ category: row.category || 'general',
572
+ tags,
573
+ enabled: row.enabled === 1,
574
+ pollIntervalMs: row.poll_interval_ms || 3600000,
575
+ lastPolledAt: row.last_polled_at ? new Date(row.last_polled_at) : undefined,
576
+ lastError: row.last_error,
577
+ articleCount: row.article_count || 0,
578
+ metadata,
579
+ userId: row.user_id,
580
+ createdAt: new Date(row.created_at),
581
+ updatedAt: new Date(row.updated_at),
582
+ };
583
+ }
584
+ function mapArticleRow(row) {
585
+ return {
586
+ id: row.id,
587
+ feedId: row.feed_id,
588
+ title: row.title,
589
+ url: row.url,
590
+ summary: row.summary,
591
+ content: row.content,
592
+ author: row.author,
593
+ publishedAt: row.published_at ? new Date(row.published_at) : undefined,
594
+ fetchedAt: new Date(row.fetched_at),
595
+ aiSummary: row.ai_summary,
596
+ digestedAt: row.digested_at ? new Date(row.digested_at) : undefined,
597
+ contentHash: row.content_hash,
598
+ };
599
+ }
600
+ //# sourceMappingURL=feed-engine.js.map
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Feed Engine - Public API
3
+ *
4
+ * Fully dynamic feed system - no hardcoded limitations.
5
+ * Categories, sources, and bundles can all be extended at runtime.
6
+ */
7
+ export { addFeed, addFeedBundle, listFeeds, getFeed, updateFeed, removeFeed, toggleFeed, pollFeed, pollAllFeeds, getDigestArticles, markAsDigested, getFeedStats, listCategories, discoverFeedUrl, parseFeedXml, registerFeedBundle, FEED_BUNDLES, } from './feed-engine.js';
8
+ export type { FeedSource, FeedArticle, FeedDigest, FeedBundleEntry, CreateFeedParams, } from './feed-engine.js';
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Feed Engine - Public API
3
+ *
4
+ * Fully dynamic feed system - no hardcoded limitations.
5
+ * Categories, sources, and bundles can all be extended at runtime.
6
+ */
7
+ export { addFeed, addFeedBundle, listFeeds, getFeed, updateFeed, removeFeed, toggleFeed, pollFeed, pollAllFeeds, getDigestArticles, markAsDigested, getFeedStats, listCategories, discoverFeedUrl, parseFeedXml, registerFeedBundle, FEED_BUNDLES, } from './feed-engine.js';
8
+ //# sourceMappingURL=index.js.map
@@ -606,7 +606,12 @@ export class GatewayRouter {
606
606
  return getAgentRegistry().getActiveAdapters();
607
607
  }
608
608
  async getAgentHealth(agentId) {
609
- const adapter = getAgentRegistry().getAdapter(agentId);
609
+ const registry = getAgentRegistry();
610
+ // Look up by ID first, then fall back to matching by type
611
+ let adapter = registry.getAdapter(agentId);
612
+ if (!adapter) {
613
+ adapter = registry.getActiveAdapters().find(a => a.type === agentId);
614
+ }
610
615
  if (!adapter) {
611
616
  return {
612
617
  healthy: false,
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Built-in Hook: Audit Log
3
+ *
4
+ * Logs all tool executions after they complete (`afterToolCall`).
5
+ * Records: timestamp, sessionId, toolName, sanitized args, success/failure,
6
+ * and duration (if startedAt is provided via metadata).
7
+ */
8
+ import type { Hook } from '../registry.js';
9
+ export declare const auditLogHook: Hook;
10
+ export default auditLogHook;
11
+ //# sourceMappingURL=audit-log.d.ts.map