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
@@ -238,7 +238,7 @@ export declare const ChatMessageSchema: z.ZodObject<{
238
238
  id: string;
239
239
  timestamp: string;
240
240
  content: string;
241
- role: "user" | "system" | "assistant" | "tool";
241
+ role: "user" | "system" | "tool" | "assistant";
242
242
  name?: string | undefined;
243
243
  tokensUsed?: number | undefined;
244
244
  toolCallId?: string | undefined;
@@ -247,7 +247,7 @@ export declare const ChatMessageSchema: z.ZodObject<{
247
247
  id: string;
248
248
  timestamp: string;
249
249
  content: string;
250
- role: "user" | "system" | "assistant" | "tool";
250
+ role: "user" | "system" | "tool" | "assistant";
251
251
  name?: string | undefined;
252
252
  tokensUsed?: number | undefined;
253
253
  toolCallId?: string | undefined;
@@ -270,7 +270,7 @@ export declare const ChatCompletionRequestSchema: z.ZodObject<{
270
270
  id: string;
271
271
  timestamp: string;
272
272
  content: string;
273
- role: "user" | "system" | "assistant" | "tool";
273
+ role: "user" | "system" | "tool" | "assistant";
274
274
  name?: string | undefined;
275
275
  tokensUsed?: number | undefined;
276
276
  toolCallId?: string | undefined;
@@ -279,7 +279,7 @@ export declare const ChatCompletionRequestSchema: z.ZodObject<{
279
279
  id: string;
280
280
  timestamp: string;
281
281
  content: string;
282
- role: "user" | "system" | "assistant" | "tool";
282
+ role: "user" | "system" | "tool" | "assistant";
283
283
  name?: string | undefined;
284
284
  tokensUsed?: number | undefined;
285
285
  toolCallId?: string | undefined;
@@ -311,7 +311,7 @@ export declare const ChatCompletionRequestSchema: z.ZodObject<{
311
311
  id: string;
312
312
  timestamp: string;
313
313
  content: string;
314
- role: "user" | "system" | "assistant" | "tool";
314
+ role: "user" | "system" | "tool" | "assistant";
315
315
  name?: string | undefined;
316
316
  tokensUsed?: number | undefined;
317
317
  toolCallId?: string | undefined;
@@ -328,14 +328,14 @@ export declare const ChatCompletionRequestSchema: z.ZodObject<{
328
328
  description: string;
329
329
  parameters: Record<string, unknown>;
330
330
  }[] | undefined;
331
- systemPrompt?: string | undefined;
332
331
  maxTokens?: number | undefined;
332
+ systemPrompt?: string | undefined;
333
333
  }, {
334
334
  messages: {
335
335
  id: string;
336
336
  timestamp: string;
337
337
  content: string;
338
- role: "user" | "system" | "assistant" | "tool";
338
+ role: "user" | "system" | "tool" | "assistant";
339
339
  name?: string | undefined;
340
340
  tokensUsed?: number | undefined;
341
341
  toolCallId?: string | undefined;
@@ -352,9 +352,9 @@ export declare const ChatCompletionRequestSchema: z.ZodObject<{
352
352
  description: string;
353
353
  parameters: Record<string, unknown>;
354
354
  }[] | undefined;
355
+ maxTokens?: number | undefined;
355
356
  systemPrompt?: string | undefined;
356
357
  temperature?: number | undefined;
357
- maxTokens?: number | undefined;
358
358
  }>;
359
359
  export type ChatCompletionRequest = z.infer<typeof ChatCompletionRequestSchema>;
360
360
  export declare const ChatCompletionResponseSchema: z.ZodObject<{
@@ -374,7 +374,7 @@ export declare const ChatCompletionResponseSchema: z.ZodObject<{
374
374
  id: string;
375
375
  timestamp: string;
376
376
  content: string;
377
- role: "user" | "system" | "assistant" | "tool";
377
+ role: "user" | "system" | "tool" | "assistant";
378
378
  name?: string | undefined;
379
379
  tokensUsed?: number | undefined;
380
380
  toolCallId?: string | undefined;
@@ -383,7 +383,7 @@ export declare const ChatCompletionResponseSchema: z.ZodObject<{
383
383
  id: string;
384
384
  timestamp: string;
385
385
  content: string;
386
- role: "user" | "system" | "assistant" | "tool";
386
+ role: "user" | "system" | "tool" | "assistant";
387
387
  name?: string | undefined;
388
388
  tokensUsed?: number | undefined;
389
389
  toolCallId?: string | undefined;
@@ -425,7 +425,7 @@ export declare const ChatCompletionResponseSchema: z.ZodObject<{
425
425
  id: string;
426
426
  timestamp: string;
427
427
  content: string;
428
- role: "user" | "system" | "assistant" | "tool";
428
+ role: "user" | "system" | "tool" | "assistant";
429
429
  name?: string | undefined;
430
430
  tokensUsed?: number | undefined;
431
431
  toolCallId?: string | undefined;
@@ -452,7 +452,7 @@ export declare const ChatCompletionResponseSchema: z.ZodObject<{
452
452
  id: string;
453
453
  timestamp: string;
454
454
  content: string;
455
- role: "user" | "system" | "assistant" | "tool";
455
+ role: "user" | "system" | "tool" | "assistant";
456
456
  name?: string | undefined;
457
457
  tokensUsed?: number | undefined;
458
458
  toolCallId?: string | undefined;
@@ -494,7 +494,7 @@ export declare const ConversationSchema: z.ZodObject<{
494
494
  id: string;
495
495
  timestamp: string;
496
496
  content: string;
497
- role: "user" | "system" | "assistant" | "tool";
497
+ role: "user" | "system" | "tool" | "assistant";
498
498
  name?: string | undefined;
499
499
  tokensUsed?: number | undefined;
500
500
  toolCallId?: string | undefined;
@@ -503,7 +503,7 @@ export declare const ConversationSchema: z.ZodObject<{
503
503
  id: string;
504
504
  timestamp: string;
505
505
  content: string;
506
- role: "user" | "system" | "assistant" | "tool";
506
+ role: "user" | "system" | "tool" | "assistant";
507
507
  name?: string | undefined;
508
508
  tokensUsed?: number | undefined;
509
509
  toolCallId?: string | undefined;
@@ -530,7 +530,7 @@ export declare const ConversationSchema: z.ZodObject<{
530
530
  id: string;
531
531
  timestamp: string;
532
532
  content: string;
533
- role: "user" | "system" | "assistant" | "tool";
533
+ role: "user" | "system" | "tool" | "assistant";
534
534
  name?: string | undefined;
535
535
  tokensUsed?: number | undefined;
536
536
  toolCallId?: string | undefined;
@@ -552,7 +552,7 @@ export declare const ConversationSchema: z.ZodObject<{
552
552
  id: string;
553
553
  timestamp: string;
554
554
  content: string;
555
- role: "user" | "system" | "assistant" | "tool";
555
+ role: "user" | "system" | "tool" | "assistant";
556
556
  name?: string | undefined;
557
557
  tokensUsed?: number | undefined;
558
558
  toolCallId?: string | undefined;
@@ -43,5 +43,55 @@ agents.get('/types', (c) => {
43
43
  types: registry.getAdapterTypes(),
44
44
  });
45
45
  });
46
+ // --- Multi-Agent Orchestration ---
47
+ import { z } from 'zod';
48
+ import { orchestrate, cancelOrchestration, listActiveOrchestrations } from '../agents/orchestrator.js';
49
+ const subAgentSchema = z.object({
50
+ id: z.string().optional(),
51
+ name: z.string(),
52
+ prompt: z.string(),
53
+ systemPrompt: z.string().optional(),
54
+ model: z.string().optional(),
55
+ maxTokens: z.number().optional(),
56
+ timeoutMs: z.number().optional(),
57
+ allowedTools: z.array(z.string()).optional(),
58
+ effort: z.enum(['low', 'medium', 'high']).optional(),
59
+ });
60
+ const orchestrateSchema = z.object({
61
+ name: z.string().min(1).max(200),
62
+ pattern: z.enum(['fan_out', 'pipeline', 'debate', 'custom']),
63
+ agents: z.array(subAgentSchema).min(1).max(10),
64
+ synthesizerPrompt: z.string().optional(),
65
+ judgePrompt: z.string().optional(),
66
+ timeoutMs: z.number().optional(),
67
+ failFast: z.boolean().optional(),
68
+ });
69
+ /** Execute a multi-agent orchestration */
70
+ agents.post('/orchestrate', async (c) => {
71
+ const body = await c.req.json();
72
+ const parsed = orchestrateSchema.safeParse(body);
73
+ if (!parsed.success) {
74
+ return c.json({ success: false, error: { code: 'VALIDATION_ERROR', message: parsed.error.message } }, 400);
75
+ }
76
+ const config = {
77
+ id: crypto.randomUUID(),
78
+ ...parsed.data,
79
+ agents: parsed.data.agents.map((a, i) => ({
80
+ ...a,
81
+ id: a.id || `agent-${i}`,
82
+ })),
83
+ };
84
+ const result = await orchestrate(config);
85
+ return c.json({ success: result.success, data: result });
86
+ });
87
+ /** Cancel a running orchestration */
88
+ agents.post('/orchestrate/:id/cancel', (c) => {
89
+ const cancelled = cancelOrchestration(c.req.param('id'));
90
+ return c.json({ success: cancelled });
91
+ });
92
+ /** List active orchestrations */
93
+ agents.get('/orchestrate/active', (c) => {
94
+ return c.json({ success: true, data: listActiveOrchestrations() });
95
+ });
46
96
  export { agents as agentsRoutes };
47
97
  //# sourceMappingURL=agents.js.map
@@ -99,8 +99,15 @@ authRoutes.post('/signup', signupLimiter, async (c) => {
99
99
  // Check registration mode
100
100
  const settings = await getSettingsRaw();
101
101
  const mode = settings.system.registrationMode;
102
+ // Allow first user signup without invite code (bootstrap admin)
103
+ const db = getDb();
104
+ let isFirstUser = false;
105
+ if (db) {
106
+ const existingUsers = await db.select({ id: users.id }).from(users).limit(1);
107
+ isFirstUser = existingUsers.length === 0;
108
+ }
102
109
  let inviteRecord;
103
- if (mode === 'invite') {
110
+ if (mode === 'invite' && !isFirstUser) {
104
111
  if (!inviteCode) {
105
112
  return c.json({ error: 'Registration requires an invite code' }, 403);
106
113
  }
@@ -9,8 +9,18 @@ import { streamText } from "hono/streaming";
9
9
  import { zValidator } from "@hono/zod-validator";
10
10
  import { z } from "zod";
11
11
  import { randomUUID } from "node:crypto";
12
+ import { routeQuery, recordRoutingDecision, isSmartRouterEnabled, getCostComparison, } from "../providers/smart-router.js";
12
13
  import { logger } from "../utils/logger.js";
14
+ import { rateLimit } from "../middleware/rate-limit.js";
15
+ import { contentFilter } from "../middleware/content-filter.js";
13
16
  const chatRoutes = new Hono();
17
+ // Per-IP sliding-window rate limiter for chat send endpoints
18
+ const chatMaxRequests = parseInt(process.env['CHAT_RATE_LIMIT'] ?? '20', 10);
19
+ const chatRateLimiter = rateLimit({
20
+ maxRequests: chatMaxRequests,
21
+ windowMs: 60_000,
22
+ message: `Chat rate limit exceeded. Maximum ${chatMaxRequests} messages per minute.`,
23
+ });
14
24
  let chatRuntimePromise = null;
15
25
  let ProviderTypeSchema;
16
26
  let aiProvider;
@@ -26,6 +36,7 @@ let listConversations;
26
36
  let deleteConversation;
27
37
  let addMessage;
28
38
  let getConversationMessages;
39
+ let deleteMessage;
29
40
  let getRecentConversationsWithPreview;
30
41
  let compactMessages;
31
42
  let getMemoryStats;
@@ -65,6 +76,7 @@ async function ensureChatRuntime() {
65
76
  deleteConversation = chatModule.deleteConversation;
66
77
  addMessage = chatModule.addMessage;
67
78
  getConversationMessages = chatModule.getConversationMessages;
79
+ deleteMessage = chatModule.deleteMessage;
68
80
  getRecentConversationsWithPreview =
69
81
  chatModule.getRecentConversationsWithPreview;
70
82
  compactMessages = chatModule.compactMessages;
@@ -168,6 +180,84 @@ chatRoutes.get("/model-capability", async (c) => {
168
180
  const resolved = MODEL_ALIASES[model.toLowerCase()]?.model ?? model;
169
181
  return c.json(getModelRouting(resolved));
170
182
  });
183
+ /**
184
+ * POST /api/chat/send
185
+ * Simple one-shot chat - send a message and get a response
186
+ */
187
+ chatRoutes.post("/send", chatRateLimiter, contentFilter(), zValidator("json", z.object({
188
+ message: z.string(),
189
+ model: z.string().optional(),
190
+ systemPrompt: z.string().optional(),
191
+ temperature: z.number().min(0).max(2).optional(),
192
+ maxTokens: z.number().positive().optional(),
193
+ })), async (c) => {
194
+ const body = c.req.valid("json");
195
+ try {
196
+ const messages = [
197
+ {
198
+ id: randomUUID(),
199
+ role: "user",
200
+ content: body.message,
201
+ timestamp: new Date().toISOString(),
202
+ },
203
+ ];
204
+ // Smart routing: auto-select model if none specified
205
+ let routing;
206
+ let modelToUse = body.model;
207
+ if (!body.model && isSmartRouterEnabled()) {
208
+ const providers = new Set(aiProvider.getConfiguredProviders());
209
+ routing = routeQuery(body.message, providers);
210
+ modelToUse = routing.selectedModel.id;
211
+ recordRoutingDecision(routing);
212
+ }
213
+ const response = await aiProvider.chat({
214
+ messages,
215
+ model: modelToUse,
216
+ systemPrompt: body.systemPrompt,
217
+ temperature: body.temperature,
218
+ maxTokens: body.maxTokens,
219
+ });
220
+ // Track token usage for cost dashboard
221
+ if (response.usage?.totalTokens && response.model) {
222
+ await ensureChatRuntime();
223
+ trackChatUsage(response.model, response.usage.totalTokens, response.usage.promptTokens, response.usage.completionTokens);
224
+ }
225
+ return c.json({
226
+ id: response.id,
227
+ provider: response.provider,
228
+ model: response.model,
229
+ reply: response.content,
230
+ finishReason: response.finishReason,
231
+ usage: response.usage,
232
+ duration: response.duration,
233
+ ...(routing && {
234
+ routing: {
235
+ smartRouted: true,
236
+ complexity: routing.complexity.tier,
237
+ confidence: Math.round(routing.complexity.confidence * 100),
238
+ reasoning: routing.complexity.reasoning,
239
+ savings: `${routing.savingsPercent}%`,
240
+ estimatedCost: `$${routing.estimatedCost.toFixed(4)}`,
241
+ summary: getCostComparison(routing),
242
+ ...(routing.missingProviderHint && {
243
+ tip: {
244
+ addProvider: routing.missingProviderHint.provider,
245
+ reason: routing.missingProviderHint.reason,
246
+ savings: routing.missingProviderHint.estimatedSavings,
247
+ signupUrl: routing.missingProviderHint.signupUrl,
248
+ },
249
+ }),
250
+ },
251
+ }),
252
+ });
253
+ }
254
+ catch (error) {
255
+ logger.error("[Chat] Send error:", error instanceof Error ? error : undefined);
256
+ return c.json({
257
+ error: error instanceof Error ? error.message : "Chat send failed",
258
+ }, 500);
259
+ }
260
+ });
171
261
  /**
172
262
  * POST /api/chat/completions
173
263
  * Generate a chat completion
@@ -183,11 +273,37 @@ chatRoutes.post("/completions", zValidator("json", ChatCompletionSchema), async
183
273
  }));
184
274
  // Handle streaming
185
275
  if (body.stream) {
276
+ // Smart route for streaming too
277
+ let streamRouting;
278
+ let streamModel = body.model;
279
+ if (!body.model && isSmartRouterEnabled()) {
280
+ const lastUserMsg = [...body.messages].reverse().find((m) => m.role === "user");
281
+ if (lastUserMsg) {
282
+ const providers = new Set(aiProvider.getConfiguredProviders());
283
+ streamRouting = routeQuery(lastUserMsg.content, providers, {
284
+ conversationLength: body.messages.length,
285
+ });
286
+ streamModel = streamRouting.selectedModel.id;
287
+ recordRoutingDecision(streamRouting);
288
+ }
289
+ }
186
290
  return streamText(c, async (stream) => {
187
291
  try {
292
+ // Send routing info as first event in stream
293
+ if (streamRouting) {
294
+ await stream.write(`data: ${JSON.stringify({
295
+ routing: {
296
+ smartRouted: true,
297
+ complexity: streamRouting.complexity.tier,
298
+ savings: `${streamRouting.savingsPercent}%`,
299
+ model: streamRouting.selectedModel.id,
300
+ provider: streamRouting.selectedModel.provider,
301
+ },
302
+ })}\n\n`);
303
+ }
188
304
  const response = await aiProvider.chatStream({
189
305
  messages,
190
- model: body.model,
306
+ model: streamModel,
191
307
  systemPrompt: body.systemPrompt,
192
308
  temperature: body.temperature,
193
309
  maxTokens: body.maxTokens,
@@ -216,9 +332,23 @@ chatRoutes.post("/completions", zValidator("json", ChatCompletionSchema), async
216
332
  }
217
333
  // Non-streaming
218
334
  try {
335
+ // Smart routing for completions
336
+ let routing;
337
+ let modelToUse = body.model;
338
+ if (!body.model && isSmartRouterEnabled()) {
339
+ const lastUserMsg = [...body.messages].reverse().find((m) => m.role === "user");
340
+ if (lastUserMsg) {
341
+ const providers = new Set(aiProvider.getConfiguredProviders());
342
+ routing = routeQuery(lastUserMsg.content, providers, {
343
+ conversationLength: body.messages.length,
344
+ });
345
+ modelToUse = routing.selectedModel.id;
346
+ recordRoutingDecision(routing);
347
+ }
348
+ }
219
349
  const response = await aiProvider.chat({
220
350
  messages,
221
- model: body.model,
351
+ model: modelToUse,
222
352
  systemPrompt: body.systemPrompt,
223
353
  temperature: body.temperature,
224
354
  maxTokens: body.maxTokens,
@@ -234,6 +364,15 @@ chatRoutes.post("/completions", zValidator("json", ChatCompletionSchema), async
234
364
  finishReason: response.finishReason,
235
365
  usage: response.usage,
236
366
  duration: response.duration,
367
+ ...(routing && {
368
+ routing: {
369
+ smartRouted: true,
370
+ complexity: routing.complexity.tier,
371
+ savings: `${routing.savingsPercent}%`,
372
+ estimatedCost: `$${routing.estimatedCost.toFixed(4)}`,
373
+ summary: getCostComparison(routing),
374
+ },
375
+ }),
237
376
  });
238
377
  }
239
378
  catch (error) {
@@ -751,14 +890,62 @@ chatRoutes.post("/conversations/:id/compact", async (c) => {
751
890
  return c.json({ error: "Failed to compact conversation" }, 500);
752
891
  }
753
892
  });
893
+ /**
894
+ * DELETE /api/chat/conversations/:id/messages/:messageId
895
+ * Delete a single message from a conversation
896
+ */
897
+ chatRoutes.delete("/conversations/:id/messages/:messageId", async (c) => {
898
+ const conversationId = c.req.param("id");
899
+ const messageId = c.req.param("messageId");
900
+ try {
901
+ const conversation = await getConversation(conversationId);
902
+ if (!conversation) {
903
+ return c.json({ error: "Conversation not found" }, 404);
904
+ }
905
+ await deleteMessage(conversationId, messageId);
906
+ return c.json({ success: true });
907
+ }
908
+ catch (error) {
909
+ logger.error("[Chat] Delete message error:", error instanceof Error ? error : undefined);
910
+ return c.json({ error: "Failed to delete message" }, 500);
911
+ }
912
+ });
913
+ /**
914
+ * GET /api/chat/conversations/:id/export
915
+ * Export a conversation as JSON
916
+ */
917
+ chatRoutes.get("/conversations/:id/export", async (c) => {
918
+ const conversationId = c.req.param("id");
919
+ try {
920
+ const conversation = await getConversation(conversationId);
921
+ if (!conversation) {
922
+ return c.json({ error: "Conversation not found" }, 404);
923
+ }
924
+ const messages = await getConversationMessages(conversationId);
925
+ return c.json({
926
+ conversation: {
927
+ id: conversation.id,
928
+ title: conversation.title,
929
+ createdAt: conversation.createdAt,
930
+ },
931
+ messages,
932
+ exportedAt: new Date().toISOString(),
933
+ });
934
+ }
935
+ catch (error) {
936
+ logger.error("[Chat] Export conversation error:", error instanceof Error ? error : undefined);
937
+ return c.json({ error: "Failed to export conversation" }, 500);
938
+ }
939
+ });
754
940
  /**
755
941
  * POST /api/chat/conversations/:id/messages
756
942
  * Send a message in a conversation (with context and history)
757
943
  */
758
- chatRoutes.post("/conversations/:id/messages", zValidator("json", z.object({
944
+ chatRoutes.post("/conversations/:id/messages", chatRateLimiter, contentFilter(), zValidator("json", z.object({
759
945
  content: z.string(),
760
946
  model: z.string().optional(),
761
947
  temperature: z.number().min(0).max(2).optional(),
948
+ stream: z.boolean().optional(),
762
949
  })), async (c) => {
763
950
  const conversationId = c.req.param("id");
764
951
  const body = c.req.valid("json");
@@ -870,7 +1057,56 @@ chatRoutes.post("/conversations/:id/messages", zValidator("json", z.object({
870
1057
  content: m.content,
871
1058
  timestamp: m.createdAt,
872
1059
  }));
873
- // Send to AI
1060
+ // Streaming branch
1061
+ if (body.stream) {
1062
+ return streamText(c, async (stream) => {
1063
+ try {
1064
+ let fullContent = "";
1065
+ const response = await aiProvider.chatStream({
1066
+ messages: chatMessages,
1067
+ model: body.model,
1068
+ systemPrompt,
1069
+ temperature: body.temperature,
1070
+ }, (chunk) => {
1071
+ fullContent += chunk;
1072
+ stream
1073
+ .write(`data: ${JSON.stringify({ content: chunk })}\n\n`)
1074
+ .catch((err) => {
1075
+ logger.error("[Chat] Stream write error:", err instanceof Error ? err : undefined);
1076
+ });
1077
+ });
1078
+ // Save assistant response after streaming completes
1079
+ const assistantMessage = await addMessage({
1080
+ conversationId,
1081
+ role: "assistant",
1082
+ content: fullContent || response.content,
1083
+ model: response.model,
1084
+ provider: response.provider,
1085
+ tokenUsage: response.usage
1086
+ ? {
1087
+ prompt: response.usage.promptTokens,
1088
+ completion: response.usage.completionTokens,
1089
+ total: response.usage.totalTokens,
1090
+ }
1091
+ : undefined,
1092
+ cost: response.usage?.cost,
1093
+ });
1094
+ await stream.write(`data: ${JSON.stringify({
1095
+ done: true,
1096
+ usage: response.usage,
1097
+ messageId: assistantMessage.id,
1098
+ compaction: compactionInfo,
1099
+ })}\n\n`);
1100
+ }
1101
+ catch (error) {
1102
+ logger.error("[Chat] Conversation stream error:", error instanceof Error ? error : undefined);
1103
+ await stream.write(`data: ${JSON.stringify({
1104
+ error: error instanceof Error ? error.message : "Failed to send message",
1105
+ })}\n\n`);
1106
+ }
1107
+ });
1108
+ }
1109
+ // Send to AI (non-streaming)
874
1110
  const response = await aiProvider.chat({
875
1111
  messages: chatMessages,
876
1112
  model: body.model,
@@ -915,7 +1151,7 @@ chatRoutes.post("/conversations/:id/messages", zValidator("json", z.object({
915
1151
  * POST /api/chat/conversations/:id/messages/with-tools
916
1152
  * Send a message in a conversation with native tool calling enabled
917
1153
  */
918
- chatRoutes.post("/conversations/:id/messages/with-tools", zValidator("json", z.object({
1154
+ chatRoutes.post("/conversations/:id/messages/with-tools", chatRateLimiter, contentFilter(), zValidator("json", z.object({
919
1155
  content: z.string(),
920
1156
  model: z.string().optional(),
921
1157
  temperature: z.number().min(0).max(2).optional(),
@@ -993,6 +1229,10 @@ chatRoutes.post("/conversations/:id/messages/with-tools", zValidator("json", z.o
993
1229
  const tools = enableTools
994
1230
  ? getChatToolsForModel(modelId, { conversationId })
995
1231
  : [];
1232
+ logger.info(`[Chat] Tools for ${modelId}: ${tools.length} (enableTools=${enableTools})`, {
1233
+ component: 'Chat',
1234
+ toolNames: tools.map(t => t.name).join(', '),
1235
+ });
996
1236
  // Build system prompt with context and tool mode
997
1237
  const systemPrompt = await buildSystemPrompt(conversation.presetId, context, {
998
1238
  enableTools: enableTools && tools.length > 0,
@@ -1322,7 +1562,7 @@ chatRoutes.post("/with-tools", zValidator("json", z.object({
1322
1562
  * - complete - Session complete
1323
1563
  * - error - Error occurred
1324
1564
  */
1325
- chatRoutes.post("/conversations/:id/messages/agentic", zValidator("json", z.object({
1565
+ chatRoutes.post("/conversations/:id/messages/agentic", chatRateLimiter, contentFilter(), zValidator("json", z.object({
1326
1566
  content: z.string(),
1327
1567
  model: z.string().optional(),
1328
1568
  provider: z.string().optional(),
@@ -1385,8 +1625,6 @@ chatRoutes.post("/conversations/:id/messages/agentic", zValidator("json", z.obje
1385
1625
  conversationId,
1386
1626
  sessionOverride,
1387
1627
  };
1388
- // Get tools - agentic mode uses model-aware filtering
1389
- const tools = getChatToolsForModel(resolvedRef.model, { conversationId, includeAll: true });
1390
1628
  // Build system prompt with agent mode (uses AGENT_MODE_SUFFIX)
1391
1629
  const systemPrompt = await buildSystemPrompt(conversation.presetId, context, {
1392
1630
  agentMode: true,
@@ -1429,11 +1667,14 @@ chatRoutes.post("/conversations/:id/messages/agentic", zValidator("json", z.obje
1429
1667
  content: m.content,
1430
1668
  timestamp: m.createdAt,
1431
1669
  }));
1432
- // Create tool handler
1670
+ // Create tool handler (triggers tool registration if first call)
1433
1671
  const toolHandler = await createChatToolHandler({
1434
1672
  conversationId,
1435
1673
  securityMode: "full", // Full access in agentic mode (tools are pre-approved)
1436
1674
  });
1675
+ // Get tools AFTER handler init (registry is now populated)
1676
+ const tools = getChatToolsForModel(resolvedRef.model, { conversationId });
1677
+ logger.info(`[Chat/Agentic] Tools for model ${resolvedRef.model}: ${tools.length}`);
1437
1678
  // Set up SSE streaming response
1438
1679
  c.header("Content-Type", "text/event-stream");
1439
1680
  c.header("Cache-Control", "no-cache");
@@ -1491,11 +1732,15 @@ chatRoutes.post("/conversations/:id/messages/agentic", zValidator("json", z.obje
1491
1732
  provider: body.provider,
1492
1733
  temperature: body.temperature,
1493
1734
  toolHandler,
1494
- tools: tools.map((t) => ({
1495
- name: t.name,
1496
- description: t.description,
1497
- parameters: t.parameters,
1498
- })),
1735
+ tools: (() => {
1736
+ const mapped = tools.map((t) => ({
1737
+ name: t.name,
1738
+ description: t.description,
1739
+ parameters: t.parameters,
1740
+ }));
1741
+ logger.info(`[Chat/Agentic] Sending ${mapped.length} tools: [${mapped.map(t => t.name).join(', ')}]`);
1742
+ return mapped;
1743
+ })(),
1499
1744
  showThinking: body.showThinking,
1500
1745
  maxSteps: body.maxSteps,
1501
1746
  maxBudget: body.maxBudget,
@@ -2,6 +2,7 @@ import { Hono } from 'hono';
2
2
  import { getUsageSummary } from '../costs/token-tracker.js';
3
3
  import { getBudgetStatus } from '../costs/budget.js';
4
4
  import { getStorage } from '../storage/index.js';
5
+ import { getRoutingStats, getCostOptimizationAdvice } from '../providers/smart-router.js';
5
6
  const costs = new Hono();
6
7
  // Get usage summary
7
8
  costs.get('/summary', (c) => {
@@ -19,6 +20,37 @@ costs.get('/analytics', async (c) => {
19
20
  const analytics = await storage.getCostAnalytics();
20
21
  return c.json(analytics);
21
22
  });
23
+ // Get smart routing stats (savings from auto-routing)
24
+ costs.get('/routing', (_c) => {
25
+ const stats = getRoutingStats();
26
+ return _c.json({
27
+ success: true,
28
+ data: {
29
+ ...stats,
30
+ totalSaved: `$${stats.totalSaved.toFixed(4)}`,
31
+ avgSavingsPercent: `${Math.round(stats.avgSavingsPercent)}%`,
32
+ message: stats.totalRouted > 0
33
+ ? `Smart routing saved $${stats.totalSaved.toFixed(2)} across ${stats.totalRouted} requests (avg ${Math.round(stats.avgSavingsPercent)}% savings)`
34
+ : 'No queries routed yet. Smart routing will show savings as you use profClaw.',
35
+ },
36
+ });
37
+ });
38
+ // Get cost optimization advice
39
+ costs.get('/optimize', async (c) => {
40
+ // Get configured providers dynamically
41
+ const { aiProvider } = await import('../providers/ai-sdk.js');
42
+ const providers = new Set(aiProvider.getConfiguredProviders());
43
+ const advice = getCostOptimizationAdvice(providers);
44
+ return c.json({
45
+ success: true,
46
+ data: {
47
+ configuredProviders: [...providers],
48
+ providerCount: providers.size,
49
+ recommendations: advice,
50
+ optimalSetup: advice.some(a => a.action.includes('cost-optimal')),
51
+ },
52
+ });
53
+ });
22
54
  // Export cost report as CSV
23
55
  costs.get('/export', async (c) => {
24
56
  const format = c.req.query('format') || 'csv';