profclaw 0.0.1-beta.1

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 (942) hide show
  1. package/.env.example +215 -0
  2. package/CHANGELOG.md +49 -0
  3. package/CONTRIBUTING.md +119 -0
  4. package/Dockerfile +107 -0
  5. package/LICENSE +661 -0
  6. package/README.md +196 -0
  7. package/config/agents.yml +55 -0
  8. package/config/budget.yml +15 -0
  9. package/config/pricing.yml +46 -0
  10. package/config/settings.yml +168 -0
  11. package/dist/adapters/claude-code.d.ts +46 -0
  12. package/dist/adapters/claude-code.js +215 -0
  13. package/dist/adapters/index.d.ts +4 -0
  14. package/dist/adapters/index.js +4 -0
  15. package/dist/adapters/ollama.d.ts +45 -0
  16. package/dist/adapters/ollama.js +277 -0
  17. package/dist/adapters/openclaw.d.ts +60 -0
  18. package/dist/adapters/openclaw.js +289 -0
  19. package/dist/adapters/registry.d.ts +56 -0
  20. package/dist/adapters/registry.js +163 -0
  21. package/dist/agents/executor.d.ts +78 -0
  22. package/dist/agents/executor.js +657 -0
  23. package/dist/agents/index.d.ts +10 -0
  24. package/dist/agents/index.js +27 -0
  25. package/dist/agents/stop-conditions.d.ts +108 -0
  26. package/dist/agents/stop-conditions.js +299 -0
  27. package/dist/agents/types.d.ts +185 -0
  28. package/dist/agents/types.js +14 -0
  29. package/dist/ai/embedding-service.d.ts +96 -0
  30. package/dist/ai/embedding-service.js +333 -0
  31. package/dist/auth/api-tokens.d.ts +71 -0
  32. package/dist/auth/api-tokens.js +235 -0
  33. package/dist/auth/auth-service.d.ts +75 -0
  34. package/dist/auth/auth-service.js +557 -0
  35. package/dist/auth/device-identity.d.ts +96 -0
  36. package/dist/auth/device-identity.js +250 -0
  37. package/dist/auth/github-oauth.d.ts +20 -0
  38. package/dist/auth/github-oauth.js +59 -0
  39. package/dist/auth/jira-oauth.d.ts +25 -0
  40. package/dist/auth/jira-oauth.js +75 -0
  41. package/dist/auth/linear-oauth.d.ts +21 -0
  42. package/dist/auth/linear-oauth.js +59 -0
  43. package/dist/auth/middleware.d.ts +44 -0
  44. package/dist/auth/middleware.js +190 -0
  45. package/dist/auth/pairing-codes.d.ts +109 -0
  46. package/dist/auth/pairing-codes.js +274 -0
  47. package/dist/auth/password.d.ts +53 -0
  48. package/dist/auth/password.js +126 -0
  49. package/dist/auth/qr-pairing.d.ts +36 -0
  50. package/dist/auth/qr-pairing.js +138 -0
  51. package/dist/auth/slack-oauth.d.ts +31 -0
  52. package/dist/auth/slack-oauth.js +80 -0
  53. package/dist/backup/index.d.ts +50 -0
  54. package/dist/backup/index.js +184 -0
  55. package/dist/browser/adapters.d.ts +25 -0
  56. package/dist/browser/adapters.js +32 -0
  57. package/dist/browser/cli.d.ts +19 -0
  58. package/dist/browser/cli.js +277 -0
  59. package/dist/browser/compression.d.ts +32 -0
  60. package/dist/browser/compression.js +269 -0
  61. package/dist/browser/extensions.d.ts +144 -0
  62. package/dist/browser/extensions.js +251 -0
  63. package/dist/browser/index.d.ts +37 -0
  64. package/dist/browser/index.js +43 -0
  65. package/dist/browser/refs.d.ts +46 -0
  66. package/dist/browser/refs.js +120 -0
  67. package/dist/browser/search.d.ts +36 -0
  68. package/dist/browser/search.js +193 -0
  69. package/dist/browser/service.d.ts +94 -0
  70. package/dist/browser/service.js +358 -0
  71. package/dist/browser/snapshot.d.ts +19 -0
  72. package/dist/browser/snapshot.js +250 -0
  73. package/dist/browser/tools.d.ts +259 -0
  74. package/dist/browser/tools.js +463 -0
  75. package/dist/browser/types.d.ts +134 -0
  76. package/dist/browser/types.js +17 -0
  77. package/dist/chat/agentic-executor.d.ts +108 -0
  78. package/dist/chat/agentic-executor.js +739 -0
  79. package/dist/chat/api-key-detector.d.ts +41 -0
  80. package/dist/chat/api-key-detector.js +290 -0
  81. package/dist/chat/auto-reply.d.ts +90 -0
  82. package/dist/chat/auto-reply.js +272 -0
  83. package/dist/chat/conversations.d.ts +91 -0
  84. package/dist/chat/conversations.js +297 -0
  85. package/dist/chat/execution/audit.d.ts +192 -0
  86. package/dist/chat/execution/audit.js +323 -0
  87. package/dist/chat/execution/executor.d.ts +56 -0
  88. package/dist/chat/execution/executor.js +654 -0
  89. package/dist/chat/execution/guardrails.d.ts +98 -0
  90. package/dist/chat/execution/guardrails.js +571 -0
  91. package/dist/chat/execution/index.d.ts +61 -0
  92. package/dist/chat/execution/index.js +129 -0
  93. package/dist/chat/execution/model-capability.d.ts +34 -0
  94. package/dist/chat/execution/model-capability.js +96 -0
  95. package/dist/chat/execution/process-pool.d.ts +110 -0
  96. package/dist/chat/execution/process-pool.js +290 -0
  97. package/dist/chat/execution/pty.d.ts +92 -0
  98. package/dist/chat/execution/pty.js +285 -0
  99. package/dist/chat/execution/rate-limiter.d.ts +87 -0
  100. package/dist/chat/execution/rate-limiter.js +305 -0
  101. package/dist/chat/execution/registry.d.ts +54 -0
  102. package/dist/chat/execution/registry.js +220 -0
  103. package/dist/chat/execution/sandbox.d.ts +109 -0
  104. package/dist/chat/execution/sandbox.js +684 -0
  105. package/dist/chat/execution/secrets.d.ts +45 -0
  106. package/dist/chat/execution/secrets.js +338 -0
  107. package/dist/chat/execution/security.d.ts +179 -0
  108. package/dist/chat/execution/security.js +739 -0
  109. package/dist/chat/execution/self-correction.d.ts +162 -0
  110. package/dist/chat/execution/self-correction.js +557 -0
  111. package/dist/chat/execution/session-manager.d.ts +79 -0
  112. package/dist/chat/execution/session-manager.js +356 -0
  113. package/dist/chat/execution/session-spawn/config.d.ts +37 -0
  114. package/dist/chat/execution/session-spawn/config.js +83 -0
  115. package/dist/chat/execution/session-spawn/index.d.ts +10 -0
  116. package/dist/chat/execution/session-spawn/index.js +10 -0
  117. package/dist/chat/execution/session-spawn/manager.d.ts +35 -0
  118. package/dist/chat/execution/session-spawn/manager.js +418 -0
  119. package/dist/chat/execution/session-spawn/types.d.ts +117 -0
  120. package/dist/chat/execution/session-spawn/types.js +16 -0
  121. package/dist/chat/execution/smart-prompts.d.ts +34 -0
  122. package/dist/chat/execution/smart-prompts.js +151 -0
  123. package/dist/chat/execution/stream-results.d.ts +65 -0
  124. package/dist/chat/execution/stream-results.js +156 -0
  125. package/dist/chat/execution/tool-router.d.ts +76 -0
  126. package/dist/chat/execution/tool-router.js +296 -0
  127. package/dist/chat/execution/tools/agents-list.d.ts +49 -0
  128. package/dist/chat/execution/tools/agents-list.js +165 -0
  129. package/dist/chat/execution/tools/browser.d.ts +12 -0
  130. package/dist/chat/execution/tools/browser.js +14 -0
  131. package/dist/chat/execution/tools/canvas.d.ts +61 -0
  132. package/dist/chat/execution/tools/canvas.js +150 -0
  133. package/dist/chat/execution/tools/complete-task.d.ts +72 -0
  134. package/dist/chat/execution/tools/complete-task.js +104 -0
  135. package/dist/chat/execution/tools/cron-tool.d.ts +204 -0
  136. package/dist/chat/execution/tools/cron-tool.js +680 -0
  137. package/dist/chat/execution/tools/discord-actions.d.ts +120 -0
  138. package/dist/chat/execution/tools/discord-actions.js +361 -0
  139. package/dist/chat/execution/tools/exec.d.ts +43 -0
  140. package/dist/chat/execution/tools/exec.js +223 -0
  141. package/dist/chat/execution/tools/file-ops.d.ts +175 -0
  142. package/dist/chat/execution/tools/file-ops.js +723 -0
  143. package/dist/chat/execution/tools/git.d.ts +143 -0
  144. package/dist/chat/execution/tools/git.js +395 -0
  145. package/dist/chat/execution/tools/github.d.ts +42 -0
  146. package/dist/chat/execution/tools/github.js +184 -0
  147. package/dist/chat/execution/tools/glinr-ops.d.ts +202 -0
  148. package/dist/chat/execution/tools/glinr-ops.js +694 -0
  149. package/dist/chat/execution/tools/image-analyze.d.ts +29 -0
  150. package/dist/chat/execution/tools/image-analyze.js +127 -0
  151. package/dist/chat/execution/tools/index.d.ts +64 -0
  152. package/dist/chat/execution/tools/index.js +245 -0
  153. package/dist/chat/execution/tools/integrations.d.ts +109 -0
  154. package/dist/chat/execution/tools/integrations.js +237 -0
  155. package/dist/chat/execution/tools/link-understand.d.ts +34 -0
  156. package/dist/chat/execution/tools/link-understand.js +307 -0
  157. package/dist/chat/execution/tools/maintenance.d.ts +29 -0
  158. package/dist/chat/execution/tools/maintenance.js +105 -0
  159. package/dist/chat/execution/tools/memory-tools.d.ts +76 -0
  160. package/dist/chat/execution/tools/memory-tools.js +278 -0
  161. package/dist/chat/execution/tools/openai-image-gen.d.ts +51 -0
  162. package/dist/chat/execution/tools/openai-image-gen.js +212 -0
  163. package/dist/chat/execution/tools/profclaw-ops.d.ts +204 -0
  164. package/dist/chat/execution/tools/profclaw-ops.js +665 -0
  165. package/dist/chat/execution/tools/session-spawn.d.ts +146 -0
  166. package/dist/chat/execution/tools/session-spawn.js +544 -0
  167. package/dist/chat/execution/tools/session-status.d.ts +38 -0
  168. package/dist/chat/execution/tools/session-status.js +185 -0
  169. package/dist/chat/execution/tools/sessions-list.d.ts +49 -0
  170. package/dist/chat/execution/tools/sessions-list.js +153 -0
  171. package/dist/chat/execution/tools/sessions-send.d.ts +48 -0
  172. package/dist/chat/execution/tools/sessions-send.js +207 -0
  173. package/dist/chat/execution/tools/sessions-spawn.d.ts +51 -0
  174. package/dist/chat/execution/tools/sessions-spawn.js +137 -0
  175. package/dist/chat/execution/tools/slack-actions.d.ts +90 -0
  176. package/dist/chat/execution/tools/slack-actions.js +272 -0
  177. package/dist/chat/execution/tools/subagent-orchestrate.d.ts +66 -0
  178. package/dist/chat/execution/tools/subagent-orchestrate.js +313 -0
  179. package/dist/chat/execution/tools/system.d.ts +121 -0
  180. package/dist/chat/execution/tools/system.js +415 -0
  181. package/dist/chat/execution/tools/telegram-actions.d.ts +126 -0
  182. package/dist/chat/execution/tools/telegram-actions.js +339 -0
  183. package/dist/chat/execution/tools/test-run.d.ts +43 -0
  184. package/dist/chat/execution/tools/test-run.js +391 -0
  185. package/dist/chat/execution/tools/tts-speak.d.ts +39 -0
  186. package/dist/chat/execution/tools/tts-speak.js +199 -0
  187. package/dist/chat/execution/tools/web-fetch.d.ts +42 -0
  188. package/dist/chat/execution/tools/web-fetch.js +247 -0
  189. package/dist/chat/execution/tools/web-search.d.ts +53 -0
  190. package/dist/chat/execution/tools/web-search.js +130 -0
  191. package/dist/chat/execution/types.d.ts +337 -0
  192. package/dist/chat/execution/types.js +8 -0
  193. package/dist/chat/execution/workflows/built-in.d.ts +10 -0
  194. package/dist/chat/execution/workflows/built-in.js +249 -0
  195. package/dist/chat/execution/workflows/executor.d.ts +13 -0
  196. package/dist/chat/execution/workflows/executor.js +259 -0
  197. package/dist/chat/execution/workflows/index.d.ts +5 -0
  198. package/dist/chat/execution/workflows/index.js +5 -0
  199. package/dist/chat/execution/workflows/trigger.d.ts +15 -0
  200. package/dist/chat/execution/workflows/trigger.js +111 -0
  201. package/dist/chat/execution/workflows/types.d.ts +80 -0
  202. package/dist/chat/execution/workflows/types.js +2 -0
  203. package/dist/chat/failover/error.d.ts +73 -0
  204. package/dist/chat/failover/error.js +412 -0
  205. package/dist/chat/failover/index.d.ts +10 -0
  206. package/dist/chat/failover/index.js +11 -0
  207. package/dist/chat/failover/model-fallback.d.ts +97 -0
  208. package/dist/chat/failover/model-fallback.js +328 -0
  209. package/dist/chat/failover/types.d.ts +47 -0
  210. package/dist/chat/failover/types.js +8 -0
  211. package/dist/chat/format/chunk.d.ts +59 -0
  212. package/dist/chat/format/chunk.js +253 -0
  213. package/dist/chat/format/index.d.ts +7 -0
  214. package/dist/chat/format/index.js +7 -0
  215. package/dist/chat/format/tool-result-formatter.d.ts +30 -0
  216. package/dist/chat/format/tool-result-formatter.js +177 -0
  217. package/dist/chat/group.d.ts +232 -0
  218. package/dist/chat/group.js +311 -0
  219. package/dist/chat/index.d.ts +21 -0
  220. package/dist/chat/index.js +30 -0
  221. package/dist/chat/memory.d.ts +108 -0
  222. package/dist/chat/memory.js +343 -0
  223. package/dist/chat/message-handler.d.ts +38 -0
  224. package/dist/chat/message-handler.js +274 -0
  225. package/dist/chat/proactive/index.d.ts +167 -0
  226. package/dist/chat/proactive/index.js +721 -0
  227. package/dist/chat/prompt-adapter.d.ts +52 -0
  228. package/dist/chat/prompt-adapter.js +245 -0
  229. package/dist/chat/providers/dingtalk/index.d.ts +69 -0
  230. package/dist/chat/providers/dingtalk/index.js +225 -0
  231. package/dist/chat/providers/discord/index.d.ts +264 -0
  232. package/dist/chat/providers/discord/index.js +657 -0
  233. package/dist/chat/providers/feishu/index.d.ts +97 -0
  234. package/dist/chat/providers/feishu/index.js +362 -0
  235. package/dist/chat/providers/googlechat/index.d.ts +269 -0
  236. package/dist/chat/providers/googlechat/index.js +634 -0
  237. package/dist/chat/providers/imessage/index.d.ts +61 -0
  238. package/dist/chat/providers/imessage/index.js +166 -0
  239. package/dist/chat/providers/index.d.ts +76 -0
  240. package/dist/chat/providers/index.js +430 -0
  241. package/dist/chat/providers/irc/index.d.ts +101 -0
  242. package/dist/chat/providers/irc/index.js +557 -0
  243. package/dist/chat/providers/line/index.d.ts +113 -0
  244. package/dist/chat/providers/line/index.js +434 -0
  245. package/dist/chat/providers/matrix/index.d.ts +161 -0
  246. package/dist/chat/providers/matrix/index.js +559 -0
  247. package/dist/chat/providers/mattermost/index.d.ts +106 -0
  248. package/dist/chat/providers/mattermost/index.js +425 -0
  249. package/dist/chat/providers/msteams/index.d.ts +198 -0
  250. package/dist/chat/providers/msteams/index.js +694 -0
  251. package/dist/chat/providers/nextcloud/index.d.ts +52 -0
  252. package/dist/chat/providers/nextcloud/index.js +156 -0
  253. package/dist/chat/providers/nostr/index.d.ts +60 -0
  254. package/dist/chat/providers/nostr/index.js +200 -0
  255. package/dist/chat/providers/qq/index.d.ts +57 -0
  256. package/dist/chat/providers/qq/index.js +260 -0
  257. package/dist/chat/providers/registry.d.ts +89 -0
  258. package/dist/chat/providers/registry.js +213 -0
  259. package/dist/chat/providers/signal/index.d.ts +88 -0
  260. package/dist/chat/providers/signal/index.js +357 -0
  261. package/dist/chat/providers/slack/index.d.ts +52 -0
  262. package/dist/chat/providers/slack/index.js +477 -0
  263. package/dist/chat/providers/synology/index.d.ts +50 -0
  264. package/dist/chat/providers/synology/index.js +138 -0
  265. package/dist/chat/providers/telegram/index.d.ts +148 -0
  266. package/dist/chat/providers/telegram/index.js +492 -0
  267. package/dist/chat/providers/tlon/index.d.ts +44 -0
  268. package/dist/chat/providers/tlon/index.js +243 -0
  269. package/dist/chat/providers/twitch/index.d.ts +79 -0
  270. package/dist/chat/providers/twitch/index.js +349 -0
  271. package/dist/chat/providers/types.d.ts +437 -0
  272. package/dist/chat/providers/types.js +14 -0
  273. package/dist/chat/providers/webchat/index.d.ts +38 -0
  274. package/dist/chat/providers/webchat/index.js +214 -0
  275. package/dist/chat/providers/wecom/index.d.ts +62 -0
  276. package/dist/chat/providers/wecom/index.js +228 -0
  277. package/dist/chat/providers/whatsapp/index.d.ts +147 -0
  278. package/dist/chat/providers/whatsapp/index.js +396 -0
  279. package/dist/chat/providers/zalo/index.d.ts +54 -0
  280. package/dist/chat/providers/zalo/index.js +158 -0
  281. package/dist/chat/providers/zalo-personal/index.d.ts +53 -0
  282. package/dist/chat/providers/zalo-personal/index.js +212 -0
  283. package/dist/chat/skills.d.ts +82 -0
  284. package/dist/chat/skills.js +410 -0
  285. package/dist/chat/system-prompts.d.ts +76 -0
  286. package/dist/chat/system-prompts.js +407 -0
  287. package/dist/chat/tool-handler.d.ts +57 -0
  288. package/dist/chat/tool-handler.js +336 -0
  289. package/dist/chat/tools.d.ts +373 -0
  290. package/dist/chat/tools.js +512 -0
  291. package/dist/cli/commands/agent.d.ts +3 -0
  292. package/dist/cli/commands/agent.js +108 -0
  293. package/dist/cli/commands/auth.d.ts +12 -0
  294. package/dist/cli/commands/auth.js +301 -0
  295. package/dist/cli/commands/browser.d.ts +3 -0
  296. package/dist/cli/commands/browser.js +138 -0
  297. package/dist/cli/commands/canvas.d.ts +3 -0
  298. package/dist/cli/commands/canvas.js +155 -0
  299. package/dist/cli/commands/channels.d.ts +3 -0
  300. package/dist/cli/commands/channels.js +167 -0
  301. package/dist/cli/commands/chat.d.ts +9 -0
  302. package/dist/cli/commands/chat.js +360 -0
  303. package/dist/cli/commands/completion.d.ts +3 -0
  304. package/dist/cli/commands/completion.js +170 -0
  305. package/dist/cli/commands/config.d.ts +3 -0
  306. package/dist/cli/commands/config.js +193 -0
  307. package/dist/cli/commands/cost.d.ts +3 -0
  308. package/dist/cli/commands/cost.js +134 -0
  309. package/dist/cli/commands/daemon.d.ts +3 -0
  310. package/dist/cli/commands/daemon.js +381 -0
  311. package/dist/cli/commands/devices.d.ts +3 -0
  312. package/dist/cli/commands/devices.js +150 -0
  313. package/dist/cli/commands/doctor.d.ts +3 -0
  314. package/dist/cli/commands/doctor.js +295 -0
  315. package/dist/cli/commands/logs.d.ts +3 -0
  316. package/dist/cli/commands/logs.js +139 -0
  317. package/dist/cli/commands/mcp.d.ts +15 -0
  318. package/dist/cli/commands/mcp.js +157 -0
  319. package/dist/cli/commands/memory.d.ts +3 -0
  320. package/dist/cli/commands/memory.js +170 -0
  321. package/dist/cli/commands/models.d.ts +3 -0
  322. package/dist/cli/commands/models.js +197 -0
  323. package/dist/cli/commands/nodes.d.ts +3 -0
  324. package/dist/cli/commands/nodes.js +193 -0
  325. package/dist/cli/commands/onboard.d.ts +13 -0
  326. package/dist/cli/commands/onboard.js +360 -0
  327. package/dist/cli/commands/plugin.d.ts +15 -0
  328. package/dist/cli/commands/plugin.js +226 -0
  329. package/dist/cli/commands/provider.d.ts +16 -0
  330. package/dist/cli/commands/provider.js +320 -0
  331. package/dist/cli/commands/security.d.ts +3 -0
  332. package/dist/cli/commands/security.js +180 -0
  333. package/dist/cli/commands/serve.d.ts +3 -0
  334. package/dist/cli/commands/serve.js +179 -0
  335. package/dist/cli/commands/session.d.ts +3 -0
  336. package/dist/cli/commands/session.js +172 -0
  337. package/dist/cli/commands/setup.d.ts +13 -0
  338. package/dist/cli/commands/setup.js +636 -0
  339. package/dist/cli/commands/skill.d.ts +15 -0
  340. package/dist/cli/commands/skill.js +191 -0
  341. package/dist/cli/commands/status.d.ts +3 -0
  342. package/dist/cli/commands/status.js +71 -0
  343. package/dist/cli/commands/summary.d.ts +3 -0
  344. package/dist/cli/commands/summary.js +160 -0
  345. package/dist/cli/commands/task.d.ts +3 -0
  346. package/dist/cli/commands/task.js +170 -0
  347. package/dist/cli/commands/ticket.d.ts +3 -0
  348. package/dist/cli/commands/ticket.js +421 -0
  349. package/dist/cli/commands/tools.d.ts +9 -0
  350. package/dist/cli/commands/tools.js +508 -0
  351. package/dist/cli/commands/tui.d.ts +3 -0
  352. package/dist/cli/commands/tui.js +158 -0
  353. package/dist/cli/commands/tunnel.d.ts +3 -0
  354. package/dist/cli/commands/tunnel.js +135 -0
  355. package/dist/cli/commands/webhooks.d.ts +3 -0
  356. package/dist/cli/commands/webhooks.js +191 -0
  357. package/dist/cli/index.d.ts +3 -0
  358. package/dist/cli/index.js +127 -0
  359. package/dist/cli/utils/api.d.ts +17 -0
  360. package/dist/cli/utils/api.js +63 -0
  361. package/dist/cli/utils/config.d.ts +31 -0
  362. package/dist/cli/utils/config.js +81 -0
  363. package/dist/cli/utils/output.d.ts +58 -0
  364. package/dist/cli/utils/output.js +148 -0
  365. package/dist/core/deployment.d.ts +30 -0
  366. package/dist/core/deployment.js +114 -0
  367. package/dist/core/sandbox-config.d.ts +63 -0
  368. package/dist/core/sandbox-config.js +148 -0
  369. package/dist/costs/budget.d.ts +28 -0
  370. package/dist/costs/budget.js +57 -0
  371. package/dist/costs/persistence.d.ts +77 -0
  372. package/dist/costs/persistence.js +210 -0
  373. package/dist/costs/pricing.d.ts +16 -0
  374. package/dist/costs/pricing.js +39 -0
  375. package/dist/costs/token-tracker.d.ts +34 -0
  376. package/dist/costs/token-tracker.js +141 -0
  377. package/dist/cron/heartbeat.d.ts +23 -0
  378. package/dist/cron/heartbeat.js +109 -0
  379. package/dist/cron/index.d.ts +22 -0
  380. package/dist/cron/index.js +37 -0
  381. package/dist/cron/issue-poller.d.ts +15 -0
  382. package/dist/cron/issue-poller.js +174 -0
  383. package/dist/cron/scheduler.d.ts +315 -0
  384. package/dist/cron/scheduler.js +1008 -0
  385. package/dist/cron/stale-checker.d.ts +16 -0
  386. package/dist/cron/stale-checker.js +61 -0
  387. package/dist/cron/templates.d.ts +107 -0
  388. package/dist/cron/templates.js +395 -0
  389. package/dist/diagnostics/exporters.d.ts +21 -0
  390. package/dist/diagnostics/exporters.js +138 -0
  391. package/dist/diagnostics/index.d.ts +10 -0
  392. package/dist/diagnostics/index.js +9 -0
  393. package/dist/diagnostics/middleware.d.ts +12 -0
  394. package/dist/diagnostics/middleware.js +58 -0
  395. package/dist/diagnostics/tracer.d.ts +133 -0
  396. package/dist/diagnostics/tracer.js +257 -0
  397. package/dist/discovery/index.d.ts +8 -0
  398. package/dist/discovery/index.js +7 -0
  399. package/dist/discovery/mdns.d.ts +40 -0
  400. package/dist/discovery/mdns.js +249 -0
  401. package/dist/gateway/index.d.ts +35 -0
  402. package/dist/gateway/index.js +36 -0
  403. package/dist/gateway/router.d.ts +110 -0
  404. package/dist/gateway/router.js +649 -0
  405. package/dist/gateway/types.d.ts +275 -0
  406. package/dist/gateway/types.js +2 -0
  407. package/dist/gateway/workflows.d.ts +37 -0
  408. package/dist/gateway/workflows.js +748 -0
  409. package/dist/hooks/agent-webhook.d.ts +277 -0
  410. package/dist/hooks/agent-webhook.js +197 -0
  411. package/dist/hooks/index.d.ts +13 -0
  412. package/dist/hooks/index.js +15 -0
  413. package/dist/hooks/prompt-submit.d.ts +45 -0
  414. package/dist/hooks/prompt-submit.js +111 -0
  415. package/dist/hooks/schemas.d.ts +563 -0
  416. package/dist/hooks/schemas.js +108 -0
  417. package/dist/hooks/session-end.d.ts +25 -0
  418. package/dist/hooks/session-end.js +153 -0
  419. package/dist/hooks/tool-use.d.ts +41 -0
  420. package/dist/hooks/tool-use.js +201 -0
  421. package/dist/hooks/types.d.ts +76 -0
  422. package/dist/hooks/types.js +7 -0
  423. package/dist/integrations/cloudflare-tunnel.d.ts +78 -0
  424. package/dist/integrations/cloudflare-tunnel.js +268 -0
  425. package/dist/integrations/github-client.d.ts +27 -0
  426. package/dist/integrations/github-client.js +79 -0
  427. package/dist/integrations/github-projects.d.ts +97 -0
  428. package/dist/integrations/github-projects.js +433 -0
  429. package/dist/integrations/github-ticket-sync.d.ts +82 -0
  430. package/dist/integrations/github-ticket-sync.js +352 -0
  431. package/dist/integrations/github.d.ts +11 -0
  432. package/dist/integrations/github.js +241 -0
  433. package/dist/integrations/jira-client.d.ts +30 -0
  434. package/dist/integrations/jira-client.js +67 -0
  435. package/dist/integrations/jira.d.ts +13 -0
  436. package/dist/integrations/jira.js +108 -0
  437. package/dist/integrations/linear-client.d.ts +23 -0
  438. package/dist/integrations/linear-client.js +52 -0
  439. package/dist/integrations/linear.d.ts +15 -0
  440. package/dist/integrations/linear.js +312 -0
  441. package/dist/integrations/tailscale.d.ts +68 -0
  442. package/dist/integrations/tailscale.js +173 -0
  443. package/dist/integrations/web-search.d.ts +112 -0
  444. package/dist/integrations/web-search.js +287 -0
  445. package/dist/intelligence/index.d.ts +8 -0
  446. package/dist/intelligence/index.js +8 -0
  447. package/dist/intelligence/ollama.d.ts +50 -0
  448. package/dist/intelligence/ollama.js +213 -0
  449. package/dist/intelligence/rules.d.ts +39 -0
  450. package/dist/intelligence/rules.js +308 -0
  451. package/dist/labels/index.d.ts +93 -0
  452. package/dist/labels/index.js +248 -0
  453. package/dist/mcp/browser-tools.d.ts +10 -0
  454. package/dist/mcp/browser-tools.js +16 -0
  455. package/dist/mcp/client.d.ts +54 -0
  456. package/dist/mcp/client.js +153 -0
  457. package/dist/mcp/index.d.ts +12 -0
  458. package/dist/mcp/index.js +13 -0
  459. package/dist/mcp/server.d.ts +40 -0
  460. package/dist/mcp/server.js +826 -0
  461. package/dist/mcp/tool-adapter.d.ts +49 -0
  462. package/dist/mcp/tool-adapter.js +193 -0
  463. package/dist/memory/experience-store.d.ts +121 -0
  464. package/dist/memory/experience-store.js +439 -0
  465. package/dist/memory/index.d.ts +8 -0
  466. package/dist/memory/index.js +25 -0
  467. package/dist/memory/memory-service.d.ts +312 -0
  468. package/dist/memory/memory-service.js +1172 -0
  469. package/dist/memory/memory-watcher.d.ts +116 -0
  470. package/dist/memory/memory-watcher.js +239 -0
  471. package/dist/middleware/logging.d.ts +34 -0
  472. package/dist/middleware/logging.js +184 -0
  473. package/dist/middleware/rate-limit.d.ts +29 -0
  474. package/dist/middleware/rate-limit.js +91 -0
  475. package/dist/notifications/in-app.d.ts +28 -0
  476. package/dist/notifications/in-app.js +53 -0
  477. package/dist/notifications/index.d.ts +3 -0
  478. package/dist/notifications/index.js +3 -0
  479. package/dist/notifications/push.d.ts +74 -0
  480. package/dist/notifications/push.js +175 -0
  481. package/dist/notifications/slack.d.ts +32 -0
  482. package/dist/notifications/slack.js +157 -0
  483. package/dist/plugins/clawhub.d.ts +70 -0
  484. package/dist/plugins/clawhub.js +260 -0
  485. package/dist/plugins/loader.d.ts +23 -0
  486. package/dist/plugins/loader.js +140 -0
  487. package/dist/plugins/marketplace.d.ts +77 -0
  488. package/dist/plugins/marketplace.js +275 -0
  489. package/dist/plugins/registry.d.ts +122 -0
  490. package/dist/plugins/registry.js +352 -0
  491. package/dist/plugins/sandbox.d.ts +77 -0
  492. package/dist/plugins/sandbox.js +287 -0
  493. package/dist/plugins/scaffolder.d.ts +28 -0
  494. package/dist/plugins/scaffolder.js +409 -0
  495. package/dist/plugins/sdk.d.ts +35 -0
  496. package/dist/plugins/sdk.js +8 -0
  497. package/dist/plugins/search/brave.d.ts +9 -0
  498. package/dist/plugins/search/brave.js +157 -0
  499. package/dist/plugins/search/duckduckgo.d.ts +9 -0
  500. package/dist/plugins/search/duckduckgo.js +171 -0
  501. package/dist/plugins/search/index.d.ts +13 -0
  502. package/dist/plugins/search/index.js +23 -0
  503. package/dist/plugins/search/searxng.d.ts +9 -0
  504. package/dist/plugins/search/searxng.js +170 -0
  505. package/dist/plugins/search/serper.d.ts +9 -0
  506. package/dist/plugins/search/serper.js +135 -0
  507. package/dist/plugins/search/tavily.d.ts +9 -0
  508. package/dist/plugins/search/tavily.js +146 -0
  509. package/dist/plugins/types.d.ts +174 -0
  510. package/dist/plugins/types.js +8 -0
  511. package/dist/projects/index.d.ts +133 -0
  512. package/dist/projects/index.js +897 -0
  513. package/dist/projects/types.d.ts +444 -0
  514. package/dist/projects/types.js +207 -0
  515. package/dist/providers/adapters/anthropic.d.ts +26 -0
  516. package/dist/providers/adapters/anthropic.js +306 -0
  517. package/dist/providers/adapters/base.d.ts +53 -0
  518. package/dist/providers/adapters/base.js +99 -0
  519. package/dist/providers/adapters/ollama.d.ts +30 -0
  520. package/dist/providers/adapters/ollama.js +292 -0
  521. package/dist/providers/ai-sdk.d.ts +178 -0
  522. package/dist/providers/ai-sdk.js +1552 -0
  523. package/dist/providers/core/index.d.ts +8 -0
  524. package/dist/providers/core/index.js +10 -0
  525. package/dist/providers/core/models.d.ts +31 -0
  526. package/dist/providers/core/models.js +949 -0
  527. package/dist/providers/core/types.d.ts +117 -0
  528. package/dist/providers/core/types.js +83 -0
  529. package/dist/providers/index.d.ts +7 -0
  530. package/dist/providers/index.js +7 -0
  531. package/dist/providers/registry.d.ts +93 -0
  532. package/dist/providers/registry.js +228 -0
  533. package/dist/providers/schema-utils.d.ts +23 -0
  534. package/dist/providers/schema-utils.js +545 -0
  535. package/dist/providers/types.d.ts +609 -0
  536. package/dist/providers/types.js +279 -0
  537. package/dist/queue/failure-handler.d.ts +93 -0
  538. package/dist/queue/failure-handler.js +379 -0
  539. package/dist/queue/index.d.ts +23 -0
  540. package/dist/queue/index.js +86 -0
  541. package/dist/queue/memory-queue.d.ts +30 -0
  542. package/dist/queue/memory-queue.js +429 -0
  543. package/dist/queue/notifications.d.ts +6 -0
  544. package/dist/queue/notifications.js +128 -0
  545. package/dist/queue/task-queue.d.ts +55 -0
  546. package/dist/queue/task-queue.js +518 -0
  547. package/dist/queue/webhook-queue.d.ts +47 -0
  548. package/dist/queue/webhook-queue.js +158 -0
  549. package/dist/routes/agents.d.ts +4 -0
  550. package/dist/routes/agents.js +45 -0
  551. package/dist/routes/auth.d.ts +19 -0
  552. package/dist/routes/auth.js +492 -0
  553. package/dist/routes/backup.d.ts +6 -0
  554. package/dist/routes/backup.js +71 -0
  555. package/dist/routes/chat.d.ts +10 -0
  556. package/dist/routes/chat.js +1678 -0
  557. package/dist/routes/clawhub.d.ts +8 -0
  558. package/dist/routes/clawhub.js +89 -0
  559. package/dist/routes/costs.d.ts +4 -0
  560. package/dist/routes/costs.js +78 -0
  561. package/dist/routes/cron.d.ts +11 -0
  562. package/dist/routes/cron.js +708 -0
  563. package/dist/routes/devices.d.ts +9 -0
  564. package/dist/routes/devices.js +490 -0
  565. package/dist/routes/discord.d.ts +15 -0
  566. package/dist/routes/discord.js +524 -0
  567. package/dist/routes/dlq.d.ts +4 -0
  568. package/dist/routes/dlq.js +64 -0
  569. package/dist/routes/gateway.d.ts +4 -0
  570. package/dist/routes/gateway.js +253 -0
  571. package/dist/routes/health.d.ts +29 -0
  572. package/dist/routes/health.js +296 -0
  573. package/dist/routes/hooks.d.ts +4 -0
  574. package/dist/routes/hooks.js +170 -0
  575. package/dist/routes/import.d.ts +9 -0
  576. package/dist/routes/import.js +540 -0
  577. package/dist/routes/index.d.ts +38 -0
  578. package/dist/routes/index.js +39 -0
  579. package/dist/routes/integrations.d.ts +10 -0
  580. package/dist/routes/integrations.js +200 -0
  581. package/dist/routes/labels.d.ts +8 -0
  582. package/dist/routes/labels.js +240 -0
  583. package/dist/routes/mcp.d.ts +14 -0
  584. package/dist/routes/mcp.js +125 -0
  585. package/dist/routes/memory.d.ts +10 -0
  586. package/dist/routes/memory.js +622 -0
  587. package/dist/routes/notifications.d.ts +9 -0
  588. package/dist/routes/notifications.js +154 -0
  589. package/dist/routes/oobe.d.ts +10 -0
  590. package/dist/routes/oobe.js +405 -0
  591. package/dist/routes/openapi.d.ts +9 -0
  592. package/dist/routes/openapi.js +537 -0
  593. package/dist/routes/plugins.d.ts +8 -0
  594. package/dist/routes/plugins.js +108 -0
  595. package/dist/routes/projects.d.ts +8 -0
  596. package/dist/routes/projects.js +592 -0
  597. package/dist/routes/push.d.ts +8 -0
  598. package/dist/routes/push.js +75 -0
  599. package/dist/routes/search.d.ts +4 -0
  600. package/dist/routes/search.js +189 -0
  601. package/dist/routes/security.d.ts +10 -0
  602. package/dist/routes/security.js +189 -0
  603. package/dist/routes/settings.d.ts +4 -0
  604. package/dist/routes/settings.js +119 -0
  605. package/dist/routes/setup.d.ts +11 -0
  606. package/dist/routes/setup.js +525 -0
  607. package/dist/routes/skills.d.ts +13 -0
  608. package/dist/routes/skills.js +152 -0
  609. package/dist/routes/slack.d.ts +12 -0
  610. package/dist/routes/slack.js +999 -0
  611. package/dist/routes/states.d.ts +8 -0
  612. package/dist/routes/states.js +123 -0
  613. package/dist/routes/stats.d.ts +6 -0
  614. package/dist/routes/stats.js +369 -0
  615. package/dist/routes/summaries.d.ts +4 -0
  616. package/dist/routes/summaries.js +344 -0
  617. package/dist/routes/sync.d.ts +13 -0
  618. package/dist/routes/sync.js +268 -0
  619. package/dist/routes/tasks.d.ts +4 -0
  620. package/dist/routes/tasks.js +473 -0
  621. package/dist/routes/telegram.d.ts +14 -0
  622. package/dist/routes/telegram.js +420 -0
  623. package/dist/routes/tickets.d.ts +4 -0
  624. package/dist/routes/tickets.js +1090 -0
  625. package/dist/routes/tokens.d.ts +4 -0
  626. package/dist/routes/tokens.js +83 -0
  627. package/dist/routes/tools.d.ts +14 -0
  628. package/dist/routes/tools.js +790 -0
  629. package/dist/routes/tunnels.d.ts +8 -0
  630. package/dist/routes/tunnels.js +145 -0
  631. package/dist/routes/users.d.ts +15 -0
  632. package/dist/routes/users.js +998 -0
  633. package/dist/routes/voice.d.ts +8 -0
  634. package/dist/routes/voice.js +127 -0
  635. package/dist/routes/webchat.d.ts +11 -0
  636. package/dist/routes/webchat.js +173 -0
  637. package/dist/routes/webhook-dedup.d.ts +11 -0
  638. package/dist/routes/webhook-dedup.js +49 -0
  639. package/dist/routes/webhooks.d.ts +4 -0
  640. package/dist/routes/webhooks.js +71 -0
  641. package/dist/routes/whatsapp.d.ts +14 -0
  642. package/dist/routes/whatsapp.js +391 -0
  643. package/dist/security/audit-scanner.d.ts +32 -0
  644. package/dist/security/audit-scanner.js +217 -0
  645. package/dist/security/fs-guard.d.ts +41 -0
  646. package/dist/security/fs-guard.js +206 -0
  647. package/dist/security/prompt-guard.d.ts +47 -0
  648. package/dist/security/prompt-guard.js +198 -0
  649. package/dist/security/ssrf-guard.d.ts +38 -0
  650. package/dist/security/ssrf-guard.js +266 -0
  651. package/dist/security/types.d.ts +92 -0
  652. package/dist/security/types.js +8 -0
  653. package/dist/server/route-loader.d.ts +15 -0
  654. package/dist/server/route-loader.js +135 -0
  655. package/dist/server.d.ts +5 -0
  656. package/dist/server.js +835 -0
  657. package/dist/settings/index.d.ts +841 -0
  658. package/dist/settings/index.js +451 -0
  659. package/dist/skills/compiler.d.ts +83 -0
  660. package/dist/skills/compiler.js +358 -0
  661. package/dist/skills/frontmatter.d.ts +33 -0
  662. package/dist/skills/frontmatter.js +175 -0
  663. package/dist/skills/index.d.ts +19 -0
  664. package/dist/skills/index.js +24 -0
  665. package/dist/skills/installer.d.ts +22 -0
  666. package/dist/skills/installer.js +220 -0
  667. package/dist/skills/loader.d.ts +72 -0
  668. package/dist/skills/loader.js +484 -0
  669. package/dist/skills/prompt-builder.d.ts +48 -0
  670. package/dist/skills/prompt-builder.js +135 -0
  671. package/dist/skills/registry.d.ts +115 -0
  672. package/dist/skills/registry.js +225 -0
  673. package/dist/skills/types.d.ts +202 -0
  674. package/dist/skills/types.js +24 -0
  675. package/dist/states/index.d.ts +64 -0
  676. package/dist/states/index.js +142 -0
  677. package/dist/storage/adapter.d.ts +146 -0
  678. package/dist/storage/adapter.js +2 -0
  679. package/dist/storage/index.d.ts +48 -0
  680. package/dist/storage/index.js +135 -0
  681. package/dist/storage/libsql.d.ts +99 -0
  682. package/dist/storage/libsql.js +1873 -0
  683. package/dist/storage/migrations.d.ts +65 -0
  684. package/dist/storage/migrations.js +289 -0
  685. package/dist/storage/schema.d.ts +10185 -0
  686. package/dist/storage/schema.js +1113 -0
  687. package/dist/summaries/extractor.d.ts +56 -0
  688. package/dist/summaries/extractor.js +377 -0
  689. package/dist/summaries/index.d.ts +13 -0
  690. package/dist/summaries/index.js +14 -0
  691. package/dist/summaries/storage.d.ts +51 -0
  692. package/dist/summaries/storage.js +101 -0
  693. package/dist/summaries/templates.d.ts +68 -0
  694. package/dist/summaries/templates.js +245 -0
  695. package/dist/sync/adapters/base.d.ts +42 -0
  696. package/dist/sync/adapters/base.js +142 -0
  697. package/dist/sync/adapters/github.d.ts +45 -0
  698. package/dist/sync/adapters/github.js +445 -0
  699. package/dist/sync/adapters/linear.d.ts +40 -0
  700. package/dist/sync/adapters/linear.js +434 -0
  701. package/dist/sync/config.d.ts +388 -0
  702. package/dist/sync/config.js +281 -0
  703. package/dist/sync/engine.d.ts +112 -0
  704. package/dist/sync/engine.js +623 -0
  705. package/dist/sync/index.d.ts +31 -0
  706. package/dist/sync/index.js +34 -0
  707. package/dist/sync/integration.d.ts +53 -0
  708. package/dist/sync/integration.js +231 -0
  709. package/dist/sync/types.d.ts +249 -0
  710. package/dist/sync/types.js +30 -0
  711. package/dist/tickets/index.d.ts +139 -0
  712. package/dist/tickets/index.js +1406 -0
  713. package/dist/tickets/types.d.ts +817 -0
  714. package/dist/tickets/types.js +310 -0
  715. package/dist/tools/adapters.d.ts +56 -0
  716. package/dist/tools/adapters.js +183 -0
  717. package/dist/tools/index.d.ts +66 -0
  718. package/dist/tools/index.js +105 -0
  719. package/dist/tools/types.d.ts +117 -0
  720. package/dist/tools/types.js +20 -0
  721. package/dist/types/agent.d.ts +101 -0
  722. package/dist/types/agent.js +2 -0
  723. package/dist/types/errors.d.ts +150 -0
  724. package/dist/types/errors.js +338 -0
  725. package/dist/types/index.d.ts +3 -0
  726. package/dist/types/index.js +3 -0
  727. package/dist/types/summary.d.ts +638 -0
  728. package/dist/types/summary.js +137 -0
  729. package/dist/types/task.d.ts +123 -0
  730. package/dist/types/task.js +46 -0
  731. package/dist/utils/ai-cache.d.ts +72 -0
  732. package/dist/utils/ai-cache.js +204 -0
  733. package/dist/utils/ai-inference.d.ts +57 -0
  734. package/dist/utils/ai-inference.js +190 -0
  735. package/dist/utils/ai-responder.d.ts +44 -0
  736. package/dist/utils/ai-responder.js +272 -0
  737. package/dist/utils/circuit-breaker.d.ts +139 -0
  738. package/dist/utils/circuit-breaker.js +281 -0
  739. package/dist/utils/config-loader.d.ts +12 -0
  740. package/dist/utils/config-loader.js +44 -0
  741. package/dist/utils/crypto.d.ts +10 -0
  742. package/dist/utils/crypto.js +59 -0
  743. package/dist/utils/env-validator.d.ts +44 -0
  744. package/dist/utils/env-validator.js +236 -0
  745. package/dist/utils/file-lock.d.ts +85 -0
  746. package/dist/utils/file-lock.js +204 -0
  747. package/dist/utils/logger.d.ts +153 -0
  748. package/dist/utils/logger.js +282 -0
  749. package/dist/utils/metrics.d.ts +183 -0
  750. package/dist/utils/metrics.js +345 -0
  751. package/dist/utils/security.d.ts +90 -0
  752. package/dist/utils/security.js +347 -0
  753. package/dist/voice/index.d.ts +79 -0
  754. package/dist/voice/index.js +144 -0
  755. package/dist/voice/stt/whisper.d.ts +13 -0
  756. package/dist/voice/stt/whisper.js +116 -0
  757. package/dist/voice/tts/elevenlabs.d.ts +18 -0
  758. package/dist/voice/tts/elevenlabs.js +178 -0
  759. package/dist/voice/tts/openai-tts.d.ts +19 -0
  760. package/dist/voice/tts/openai-tts.js +127 -0
  761. package/dist/voice/tts/system.d.ts +26 -0
  762. package/dist/voice/tts/system.js +146 -0
  763. package/dist/voice/wake-word.d.ts +44 -0
  764. package/dist/voice/wake-word.js +145 -0
  765. package/docker-compose.yml +222 -0
  766. package/package.json +154 -0
  767. package/profclaw.mjs +24 -0
  768. package/skills/1password/SKILL.md +155 -0
  769. package/skills/api-tester/SKILL.md +177 -0
  770. package/skills/apple-notes/SKILL.md +167 -0
  771. package/skills/apple-reminders/SKILL.md +178 -0
  772. package/skills/bear-notes/SKILL.md +166 -0
  773. package/skills/blogwatcher/SKILL.md +177 -0
  774. package/skills/camsnap/SKILL.md +130 -0
  775. package/skills/code-generation/SKILL.md +139 -0
  776. package/skills/code-review/SKILL.md +116 -0
  777. package/skills/coding-agent/SKILL.md +184 -0
  778. package/skills/cron-manager/SKILL.md +141 -0
  779. package/skills/debug-helper/SKILL.md +134 -0
  780. package/skills/docker-ops/SKILL.md +246 -0
  781. package/skills/file-manager/SKILL.md +160 -0
  782. package/skills/git-workflow/SKILL.md +171 -0
  783. package/skills/github-issues/SKILL.md +244 -0
  784. package/skills/gog/SKILL.md +191 -0
  785. package/skills/goplaces/SKILL.md +156 -0
  786. package/skills/healthcheck/SKILL.md +270 -0
  787. package/skills/himalaya/SKILL.md +165 -0
  788. package/skills/mcp-discovery/SKILL.md +109 -0
  789. package/skills/memory-manager/SKILL.md +151 -0
  790. package/skills/model-usage/SKILL.md +177 -0
  791. package/skills/nano-banana-pro/SKILL.md +214 -0
  792. package/skills/nano-pdf/SKILL.md +165 -0
  793. package/skills/notion/SKILL.md +147 -0
  794. package/skills/obsidian/SKILL.md +163 -0
  795. package/skills/openai-image-gen/SKILL.md +194 -0
  796. package/skills/openai-whisper/SKILL.md +98 -0
  797. package/skills/openai-whisper-api/SKILL.md +130 -0
  798. package/skills/openhue/SKILL.md +203 -0
  799. package/skills/oracle/SKILL.md +236 -0
  800. package/skills/phone-control/SKILL.md +201 -0
  801. package/skills/profclaw-assistant/SKILL.md +81 -0
  802. package/skills/profclaw-projects/SKILL.md +68 -0
  803. package/skills/profclaw-tickets/SKILL.md +91 -0
  804. package/skills/session-logs/SKILL.md +216 -0
  805. package/skills/sherpa-onnx-tts/SKILL.md +134 -0
  806. package/skills/skill-creator/SKILL.md +183 -0
  807. package/skills/songsee/SKILL.md +170 -0
  808. package/skills/spotify-player/SKILL.md +254 -0
  809. package/skills/summarize/SKILL.md +155 -0
  810. package/skills/system-admin/SKILL.md +179 -0
  811. package/skills/things-mac/SKILL.md +179 -0
  812. package/skills/tmux/SKILL.md +170 -0
  813. package/skills/trello/SKILL.md +154 -0
  814. package/skills/video-frames/SKILL.md +127 -0
  815. package/skills/weather/SKILL.md +186 -0
  816. package/skills/web-research/SKILL.md +128 -0
  817. package/skills/xurl/SKILL.md +198 -0
  818. package/ui/README.md +73 -0
  819. package/ui/dist/assets/ActivityView-CkPgKhwm.js +1 -0
  820. package/ui/dist/assets/AgentList-C3SVdeEz.js +1 -0
  821. package/ui/dist/assets/AnalyticsDashboard-DVU--vlP.js +1 -0
  822. package/ui/dist/assets/AreaChart-B5qMEGWj.js +1 -0
  823. package/ui/dist/assets/CartesianChart-B50bcUJi.js +36 -0
  824. package/ui/dist/assets/ChatView-BZFJs7w_.js +10 -0
  825. package/ui/dist/assets/CostsDashboard-ChfH8BlG.js +1 -0
  826. package/ui/dist/assets/EstimateSelect-CLpB4NQO.js +1 -0
  827. package/ui/dist/assets/FloatingChatbot-CBzBY9a0.js +2 -0
  828. package/ui/dist/assets/InviteCodeManagement-DsbdPa6W.js +2 -0
  829. package/ui/dist/assets/ProjectDetail-BEM3tFXg.js +2 -0
  830. package/ui/dist/assets/ProjectDetail-D1-0B2xV.css +1 -0
  831. package/ui/dist/assets/ProjectIcon-CN1FmFAk.js +1 -0
  832. package/ui/dist/assets/ProjectList-DSDaNhxQ.js +4 -0
  833. package/ui/dist/assets/Settings-dPVcqC_d.js +6 -0
  834. package/ui/dist/assets/StatusIndicator-DA3NAo_b.js +1 -0
  835. package/ui/dist/assets/SummaryDetail-Bjnf9lT8.js +27 -0
  836. package/ui/dist/assets/SummaryList-ENwKDBKW.js +1 -0
  837. package/ui/dist/assets/TaskDetail-DnwG6MzB.js +1 -0
  838. package/ui/dist/assets/TaskList-D9Ug_HiV.js +1 -0
  839. package/ui/dist/assets/TicketBoard-CviH1571.js +1 -0
  840. package/ui/dist/assets/TicketDetail-8Jk8O-33.js +1 -0
  841. package/ui/dist/assets/TicketList-B-iV4rRA.js +1 -0
  842. package/ui/dist/assets/UserManagement-CPZ8s7s2.js +2 -0
  843. package/ui/dist/assets/ViewSwitcher-BUyOOWDI.js +1 -0
  844. package/ui/dist/assets/alert-dialog-BOmnTkN-.js +7 -0
  845. package/ui/dist/assets/archive-D5my9zOG.js +1 -0
  846. package/ui/dist/assets/badge-B4ov81_m.js +1 -0
  847. package/ui/dist/assets/brain-C53ElFLD.js +1 -0
  848. package/ui/dist/assets/bug-D0TJoCYn.js +1 -0
  849. package/ui/dist/assets/calendar-BkWIhKa1.js +1 -0
  850. package/ui/dist/assets/chevron-up-BRTtndUZ.js +1 -0
  851. package/ui/dist/assets/circle-x-BN89YhbS.js +1 -0
  852. package/ui/dist/assets/constants-fc7TFI7u.js +1 -0
  853. package/ui/dist/assets/cpu-B41x1-vV.js +1 -0
  854. package/ui/dist/assets/database-D9Cnfmzj.js +1 -0
  855. package/ui/dist/assets/defineProperty-CoXUr7_6.js +2 -0
  856. package/ui/dist/assets/dialog-DrWB4EYD.js +1 -0
  857. package/ui/dist/assets/element-adapter-DL0DQilL.js +4 -0
  858. package/ui/dist/assets/ellipsis-NuUWekvu.js +1 -0
  859. package/ui/dist/assets/ellipsis-vertical-BueMfuCw.js +1 -0
  860. package/ui/dist/assets/file-code-HR9829Jc.js +1 -0
  861. package/ui/dist/assets/folder-open-C_7oYEqe.js +1 -0
  862. package/ui/dist/assets/funnel-B5gmNXGf.js +1 -0
  863. package/ui/dist/assets/git-branch-BRMiJmV3.js +1 -0
  864. package/ui/dist/assets/git-commit-horizontal-CXOUQeJI.js +1 -0
  865. package/ui/dist/assets/globe-CCspjvus.js +1 -0
  866. package/ui/dist/assets/hash-g3102kPC.js +1 -0
  867. package/ui/dist/assets/history-CNqcBBrV.js +1 -0
  868. package/ui/dist/assets/index-27mTPKuh.js +1 -0
  869. package/ui/dist/assets/index-BMx3fH-e.js +1 -0
  870. package/ui/dist/assets/index-C9jNQXzL.js +1 -0
  871. package/ui/dist/assets/index-CEZ6R2Uw.js +7 -0
  872. package/ui/dist/assets/index-DURTouJI.js +1 -0
  873. package/ui/dist/assets/index-WclMPci1.css +1 -0
  874. package/ui/dist/assets/index-kb4AJXUB.js +67 -0
  875. package/ui/dist/assets/layers-CLXiHN6o.js +1 -0
  876. package/ui/dist/assets/layout-dashboard-B07MFhBs.js +1 -0
  877. package/ui/dist/assets/lightbulb-B2dgG5ks.js +1 -0
  878. package/ui/dist/assets/link-2-BxNmr9hL.js +1 -0
  879. package/ui/dist/assets/markdown-renderer-CjU6hBcW.js +36 -0
  880. package/ui/dist/assets/message-square-Bf2-CVbt.js +1 -0
  881. package/ui/dist/assets/pencil-D096Ey62.js +1 -0
  882. package/ui/dist/assets/play-DfdcSI3x.js +1 -0
  883. package/ui/dist/assets/popover-BV0QJDQq.js +1 -0
  884. package/ui/dist/assets/progress-DjPEDJfI.js +1 -0
  885. package/ui/dist/assets/rocket-CPsTc-5G.js +1 -0
  886. package/ui/dist/assets/select-LsO16slr.js +1 -0
  887. package/ui/dist/assets/send-BDYBZDUZ.js +1 -0
  888. package/ui/dist/assets/server-B3k6noce.js +1 -0
  889. package/ui/dist/assets/settings-2-Cu4xTjhG.js +1 -0
  890. package/ui/dist/assets/sheet-BScLnPKX.js +1 -0
  891. package/ui/dist/assets/shield-check-CQqkwufI.js +1 -0
  892. package/ui/dist/assets/shield-off-ZFruH9KO.js +1 -0
  893. package/ui/dist/assets/skeleton-CtkIA_MU.js +1 -0
  894. package/ui/dist/assets/smartphone-DnoksVkc.js +1 -0
  895. package/ui/dist/assets/square-uD9ZHMfW.js +1 -0
  896. package/ui/dist/assets/switch-MQPnwGJK.js +1 -0
  897. package/ui/dist/assets/table-B8cqlywA.js +1 -0
  898. package/ui/dist/assets/tag-wEJQRWlV.js +1 -0
  899. package/ui/dist/assets/textarea-D5LJCOGl.js +1 -0
  900. package/ui/dist/assets/timer-mbGHegmr.js +1 -0
  901. package/ui/dist/assets/tooltip-Df1CunSp.js +1 -0
  902. package/ui/dist/assets/trash-2-B4oAXsX-.js +1 -0
  903. package/ui/dist/assets/trending-up-BGWxvlmZ.js +1 -0
  904. package/ui/dist/assets/wand-sparkles-CZy4xvL3.js +1 -0
  905. package/ui/dist/assets/wrench-ByZkjO6m.js +1 -0
  906. package/ui/dist/audio-worklets/vad-processor.js +132 -0
  907. package/ui/dist/brand/profclaw-appicon-192.png +0 -0
  908. package/ui/dist/brand/profclaw-appicon-512.png +0 -0
  909. package/ui/dist/brand/profclaw-appicon-shadow.svg +51 -0
  910. package/ui/dist/brand/profclaw-appicon.svg +50 -0
  911. package/ui/dist/brand/profclaw-favicon-coral-bg-128.png +0 -0
  912. package/ui/dist/brand/profclaw-favicon-coral-bg-64.png +0 -0
  913. package/ui/dist/brand/profclaw-favicon-coral-bg.svg +52 -0
  914. package/ui/dist/brand/profclaw-favicon-coral-body-128.png +0 -0
  915. package/ui/dist/brand/profclaw-favicon-coral-body.svg +41 -0
  916. package/ui/dist/brand/profclaw-favicon-shadow-128.png +0 -0
  917. package/ui/dist/brand/profclaw-favicon-shadow-64.png +0 -0
  918. package/ui/dist/brand/profclaw-favicon-shadow.svg +51 -0
  919. package/ui/dist/brand/profclaw-mark-coral-256.png +0 -0
  920. package/ui/dist/brand/profclaw-mark-coral-64.png +0 -0
  921. package/ui/dist/brand/profclaw-mark-coral.svg +31 -0
  922. package/ui/dist/brand/profclaw-mono-white.svg +18 -0
  923. package/ui/dist/brand/profclaw-text-dark.svg +18 -0
  924. package/ui/dist/brand/profclaw-text-light.svg +18 -0
  925. package/ui/dist/brand/profclaw-wordmark-dark.svg +48 -0
  926. package/ui/dist/brand/profclaw-wordmark-light.svg +48 -0
  927. package/ui/dist/brand/safari-pinned-tab.svg +15 -0
  928. package/ui/dist/favicon/android-chrome-192x192.png +0 -0
  929. package/ui/dist/favicon/android-chrome-384x384.png +0 -0
  930. package/ui/dist/favicon/android-chrome-512x512.png +0 -0
  931. package/ui/dist/favicon/apple-touch-icon.png +0 -0
  932. package/ui/dist/favicon/browserconfig.xml +9 -0
  933. package/ui/dist/favicon/favicon-16x16.png +0 -0
  934. package/ui/dist/favicon/favicon-32x32.png +0 -0
  935. package/ui/dist/favicon/favicon.ico +0 -0
  936. package/ui/dist/favicon/mstile-150x150.png +0 -0
  937. package/ui/dist/favicon/safari-pinned-tab.svg +46 -0
  938. package/ui/dist/favicon/site.webmanifest +22 -0
  939. package/ui/dist/index.html +32 -0
  940. package/ui/dist/manifest.json +49 -0
  941. package/ui/dist/sw.js +124 -0
  942. package/ui/dist/vite.svg +1 -0
@@ -0,0 +1,1678 @@
1
+ /**
2
+ * Chat API Routes
3
+ *
4
+ * REST API for AI chat functionality with profClaw intelligence.
5
+ * Supports multiple providers, conversation history, and context-aware prompts.
6
+ */
7
+ import { Hono } from "hono";
8
+ import { streamText } from "hono/streaming";
9
+ import { zValidator } from "@hono/zod-validator";
10
+ import { z } from "zod";
11
+ import { randomUUID } from "node:crypto";
12
+ import { logger } from "../utils/logger.js";
13
+ const chatRoutes = new Hono();
14
+ let chatRuntimePromise = null;
15
+ let ProviderTypeSchema;
16
+ let aiProvider;
17
+ let MODEL_ALIASES;
18
+ let saveProviderConfig;
19
+ let getClient;
20
+ let CHAT_PRESETS;
21
+ let QUICK_ACTIONS;
22
+ let buildSystemPrompt;
23
+ let createConversation;
24
+ let getConversation;
25
+ let listConversations;
26
+ let deleteConversation;
27
+ let addMessage;
28
+ let getConversationMessages;
29
+ let getRecentConversationsWithPreview;
30
+ let compactMessages;
31
+ let getMemoryStats;
32
+ let needsCompaction;
33
+ let CHAT_SKILLS;
34
+ let MODEL_TIERS;
35
+ let detectIntent;
36
+ let selectModel;
37
+ let createChatToolHandler;
38
+ let getDefaultChatTools;
39
+ let getAllChatTools;
40
+ let getChatToolsForModel;
41
+ let getSessionModel;
42
+ let streamAgenticChat;
43
+ let getGroupChatManager;
44
+ let trackChatUsage;
45
+ async function ensureChatRuntime() {
46
+ if (!chatRuntimePromise) {
47
+ chatRuntimePromise = Promise.all([
48
+ import("../providers/index.js"),
49
+ import("../storage/index.js"),
50
+ import("../chat/index.js"),
51
+ import("../costs/token-tracker.js"),
52
+ ])
53
+ .then(([providersModule, storageModule, chatModule, costsModule]) => {
54
+ ProviderTypeSchema = providersModule.ProviderType;
55
+ aiProvider = providersModule.aiProvider;
56
+ MODEL_ALIASES = providersModule.MODEL_ALIASES;
57
+ saveProviderConfig = storageModule.saveProviderConfig;
58
+ getClient = storageModule.getClient;
59
+ CHAT_PRESETS = chatModule.CHAT_PRESETS;
60
+ QUICK_ACTIONS = chatModule.QUICK_ACTIONS;
61
+ buildSystemPrompt = chatModule.buildSystemPrompt;
62
+ createConversation = chatModule.createConversation;
63
+ getConversation = chatModule.getConversation;
64
+ listConversations = chatModule.listConversations;
65
+ deleteConversation = chatModule.deleteConversation;
66
+ addMessage = chatModule.addMessage;
67
+ getConversationMessages = chatModule.getConversationMessages;
68
+ getRecentConversationsWithPreview =
69
+ chatModule.getRecentConversationsWithPreview;
70
+ compactMessages = chatModule.compactMessages;
71
+ getMemoryStats = chatModule.getMemoryStats;
72
+ needsCompaction = chatModule.needsCompaction;
73
+ CHAT_SKILLS = chatModule.CHAT_SKILLS;
74
+ MODEL_TIERS = chatModule.MODEL_TIERS;
75
+ detectIntent = chatModule.detectIntent;
76
+ selectModel = chatModule.selectModel;
77
+ createChatToolHandler = chatModule.createChatToolHandler;
78
+ getDefaultChatTools = chatModule.getDefaultChatTools;
79
+ getAllChatTools = chatModule.getAllChatTools;
80
+ getChatToolsForModel = chatModule.getChatToolsForModel;
81
+ getSessionModel = chatModule.getSessionModel;
82
+ streamAgenticChat = chatModule.streamAgenticChat;
83
+ getGroupChatManager = chatModule.getGroupChatManager;
84
+ trackChatUsage = costsModule.trackChatUsage;
85
+ })
86
+ .catch((error) => {
87
+ chatRuntimePromise = null;
88
+ throw error;
89
+ });
90
+ }
91
+ await chatRuntimePromise;
92
+ }
93
+ function parseProviderType(value) {
94
+ const parsed = ProviderTypeSchema.safeParse(value);
95
+ return parsed.success ? parsed.data : null;
96
+ }
97
+ chatRoutes.use("*", async (c, next) => {
98
+ try {
99
+ await ensureChatRuntime();
100
+ }
101
+ catch (error) {
102
+ logger.error("[Chat] Failed to initialize runtime", error instanceof Error ? error : undefined);
103
+ return c.json({
104
+ error: error instanceof Error
105
+ ? error.message
106
+ : "Chat runtime unavailable",
107
+ }, 500);
108
+ }
109
+ await next();
110
+ });
111
+ // === Schemas ===
112
+ const ChatMessageSchema = z.object({
113
+ role: z.enum(["user", "assistant", "system"]),
114
+ content: z.string(),
115
+ });
116
+ const ChatCompletionSchema = z.object({
117
+ messages: z.array(ChatMessageSchema),
118
+ model: z.string().optional(),
119
+ systemPrompt: z.string().optional(),
120
+ temperature: z.number().min(0).max(2).optional(),
121
+ maxTokens: z.number().positive().optional(),
122
+ stream: z.boolean().optional(),
123
+ // Context linking
124
+ conversationId: z.string().optional(),
125
+ ticketId: z.string().optional(),
126
+ taskId: z.string().optional(),
127
+ });
128
+ const ProviderConfigSchema = z.object({
129
+ type: z.enum([
130
+ "anthropic",
131
+ "openai",
132
+ "azure",
133
+ "google",
134
+ "ollama",
135
+ "openrouter",
136
+ "groq",
137
+ "xai",
138
+ "mistral",
139
+ "cohere",
140
+ "perplexity",
141
+ "deepseek",
142
+ "together",
143
+ "cerebras",
144
+ "fireworks",
145
+ ]),
146
+ apiKey: z.string().optional(),
147
+ baseUrl: z.string().optional(),
148
+ // Azure-specific fields
149
+ resourceName: z.string().optional(),
150
+ deploymentName: z.string().optional(),
151
+ apiVersion: z.string().optional(),
152
+ defaultModel: z.string().optional(),
153
+ enabled: z.boolean().optional(),
154
+ });
155
+ // === Routes ===
156
+ /**
157
+ * GET /api/chat/model-capability
158
+ * Returns capability tier and tool access level for a given model ID
159
+ */
160
+ chatRoutes.get("/model-capability", async (c) => {
161
+ const model = c.req.query("model");
162
+ if (!model) {
163
+ return c.json({ capability: "reasoning", tier: "full", maxSchemaTokens: 20000 });
164
+ }
165
+ const { getModelRouting } = await import("../chat/execution/model-capability.js");
166
+ // Resolve alias to full model ID (e.g. "gemini" -> "gemini-1.5-pro")
167
+ const { MODEL_ALIASES } = await import("../providers/core/models.js");
168
+ const resolved = MODEL_ALIASES[model.toLowerCase()]?.model ?? model;
169
+ return c.json(getModelRouting(resolved));
170
+ });
171
+ /**
172
+ * POST /api/chat/completions
173
+ * Generate a chat completion
174
+ */
175
+ chatRoutes.post("/completions", zValidator("json", ChatCompletionSchema), async (c) => {
176
+ const body = c.req.valid("json");
177
+ // Convert to ChatMessage format
178
+ const messages = body.messages.map((msg) => ({
179
+ id: randomUUID(),
180
+ role: msg.role,
181
+ content: msg.content,
182
+ timestamp: new Date().toISOString(),
183
+ }));
184
+ // Handle streaming
185
+ if (body.stream) {
186
+ return streamText(c, async (stream) => {
187
+ try {
188
+ const response = await aiProvider.chatStream({
189
+ messages,
190
+ model: body.model,
191
+ systemPrompt: body.systemPrompt,
192
+ temperature: body.temperature,
193
+ maxTokens: body.maxTokens,
194
+ }, (chunk) => {
195
+ // Non-blocking write - fire and forget for speed
196
+ stream
197
+ .write(`data: ${JSON.stringify({ content: chunk })}\n\n`)
198
+ .catch((err) => {
199
+ logger.error("[Chat] Stream write error:", err instanceof Error ? err : undefined);
200
+ });
201
+ });
202
+ // Send final message with usage (this one we await to ensure delivery)
203
+ await stream.write(`data: ${JSON.stringify({
204
+ done: true,
205
+ usage: response.usage,
206
+ finishReason: response.finishReason,
207
+ })}\n\n`);
208
+ }
209
+ catch (error) {
210
+ logger.error("[Chat] Stream error:", error instanceof Error ? error : undefined);
211
+ await stream.write(`data: ${JSON.stringify({
212
+ error: error instanceof Error ? error.message : "Chat failed",
213
+ })}\n\n`);
214
+ }
215
+ });
216
+ }
217
+ // Non-streaming
218
+ try {
219
+ const response = await aiProvider.chat({
220
+ messages,
221
+ model: body.model,
222
+ systemPrompt: body.systemPrompt,
223
+ temperature: body.temperature,
224
+ maxTokens: body.maxTokens,
225
+ });
226
+ return c.json({
227
+ id: response.id,
228
+ provider: response.provider,
229
+ model: response.model,
230
+ message: {
231
+ role: "assistant",
232
+ content: response.content,
233
+ },
234
+ finishReason: response.finishReason,
235
+ usage: response.usage,
236
+ duration: response.duration,
237
+ });
238
+ }
239
+ catch (error) {
240
+ logger.error("[Chat] Completion error:", error instanceof Error ? error : undefined);
241
+ return c.json({
242
+ error: error instanceof Error ? error.message : "Chat completion failed",
243
+ }, 500);
244
+ }
245
+ });
246
+ /**
247
+ * GET /api/chat/models
248
+ * List available models
249
+ */
250
+ chatRoutes.get("/models", async (c) => {
251
+ const provider = c.req.query("provider");
252
+ let models;
253
+ if (provider) {
254
+ const providerType = parseProviderType(provider);
255
+ if (!providerType) {
256
+ return c.json({ error: "Invalid provider" }, 400);
257
+ }
258
+ models = aiProvider.getModelsForProvider(providerType);
259
+ }
260
+ else {
261
+ models = aiProvider.getAllModels();
262
+ }
263
+ // Convert MODEL_ALIASES to API format dynamically
264
+ const aliases = Object.entries(MODEL_ALIASES).map(([alias, config]) => ({
265
+ alias,
266
+ provider: config.provider,
267
+ model: config.model,
268
+ }));
269
+ return c.json({
270
+ models,
271
+ aliases,
272
+ });
273
+ });
274
+ /**
275
+ * GET /api/chat/providers
276
+ * List configured providers and their status
277
+ */
278
+ chatRoutes.get("/providers", async (c) => {
279
+ const configured = aiProvider.getConfiguredProviders();
280
+ const health = await aiProvider.healthCheck();
281
+ return c.json({
282
+ default: aiProvider.getDefaultProvider(),
283
+ providers: configured.map((p) => {
284
+ const h = health.find((h) => h.provider === p);
285
+ return {
286
+ type: p,
287
+ enabled: true,
288
+ healthy: h?.healthy ?? false,
289
+ message: h?.message,
290
+ latencyMs: h?.latencyMs,
291
+ };
292
+ }),
293
+ });
294
+ });
295
+ /**
296
+ * POST /api/chat/providers/:type/configure
297
+ * Configure a provider (persists to database)
298
+ */
299
+ chatRoutes.post("/providers/:type/configure", zValidator("json", ProviderConfigSchema), async (c) => {
300
+ const type = parseProviderType(c.req.param("type"));
301
+ const config = c.req.valid("json");
302
+ if (!type) {
303
+ return c.json({ error: "Invalid provider" }, 400);
304
+ }
305
+ try {
306
+ // Build provider config (include Azure-specific fields)
307
+ const providerConfig = {
308
+ type,
309
+ apiKey: config.apiKey,
310
+ baseUrl: config.baseUrl,
311
+ resourceName: config.resourceName,
312
+ deploymentName: config.deploymentName,
313
+ apiVersion: config.apiVersion,
314
+ defaultModel: config.defaultModel,
315
+ enabled: config.enabled ?? true,
316
+ };
317
+ // Configure in memory
318
+ aiProvider.configure(type, providerConfig);
319
+ // Persist to database (only if we have an API key or baseUrl)
320
+ if (config.apiKey || config.baseUrl) {
321
+ await saveProviderConfig({
322
+ type,
323
+ apiKey: config.apiKey,
324
+ baseUrl: config.baseUrl,
325
+ resourceName: config.resourceName,
326
+ deploymentName: config.deploymentName,
327
+ apiVersion: config.apiVersion,
328
+ defaultModel: config.defaultModel,
329
+ enabled: config.enabled ?? true,
330
+ });
331
+ logger.info(`[Chat] Provider ${type} config saved to database`);
332
+ }
333
+ return c.json({ success: true, message: `${type} configured` });
334
+ }
335
+ catch (error) {
336
+ logger.error(`[Chat] Failed to configure provider ${type}:`, error instanceof Error ? error : undefined);
337
+ return c.json({
338
+ error: error instanceof Error ? error.message : "Configuration failed",
339
+ }, 400);
340
+ }
341
+ });
342
+ /**
343
+ * POST /api/chat/providers/:type/health
344
+ * Check provider health
345
+ */
346
+ chatRoutes.post("/providers/:type/health", async (c) => {
347
+ const type = parseProviderType(c.req.param("type"));
348
+ if (!type) {
349
+ return c.json({ error: "Invalid provider" }, 400);
350
+ }
351
+ const results = await aiProvider.healthCheck(type);
352
+ const result = results[0];
353
+ if (!result) {
354
+ return c.json({ error: "Provider not found" }, 404);
355
+ }
356
+ return c.json(result);
357
+ });
358
+ /**
359
+ * POST /api/chat/providers/default
360
+ * Set default provider
361
+ */
362
+ chatRoutes.post("/providers/default", zValidator("json", z.object({ provider: ProviderConfigSchema.shape.type })), async (c) => {
363
+ const { provider } = c.req.valid("json");
364
+ try {
365
+ aiProvider.setDefaultProvider(provider);
366
+ return c.json({ success: true, default: provider });
367
+ }
368
+ catch (error) {
369
+ return c.json({
370
+ error: error instanceof Error ? error.message : "Failed to set default",
371
+ }, 400);
372
+ }
373
+ });
374
+ /**
375
+ * GET /api/chat/providers/:type/models
376
+ * Fetch available models from a provider (dynamic discovery)
377
+ */
378
+ chatRoutes.get("/providers/:type/models", async (c) => {
379
+ const type = c.req.param("type");
380
+ try {
381
+ // For Ollama, fetch from the local API
382
+ if (type === "ollama") {
383
+ const baseUrl = process.env.OLLAMA_BASE_URL || "http://localhost:11434";
384
+ const response = await fetch(`${baseUrl}/api/tags`);
385
+ if (!response.ok) {
386
+ throw new Error("Failed to fetch Ollama models");
387
+ }
388
+ const data = (await response.json());
389
+ return c.json({
390
+ provider: type,
391
+ models: (data.models || []).map((m) => ({
392
+ id: m.name,
393
+ name: m.name,
394
+ size: m.size,
395
+ modifiedAt: m.modified_at,
396
+ })),
397
+ });
398
+ }
399
+ // For OpenRouter, fetch from their API
400
+ if (type === "openrouter") {
401
+ const apiKey = process.env.OPENROUTER_API_KEY;
402
+ if (!apiKey) {
403
+ return c.json({ error: "OpenRouter not configured" }, 400);
404
+ }
405
+ const response = await fetch("https://openrouter.ai/api/v1/models", {
406
+ headers: { Authorization: `Bearer ${apiKey}` },
407
+ });
408
+ if (!response.ok) {
409
+ throw new Error("Failed to fetch OpenRouter models");
410
+ }
411
+ const data = (await response.json());
412
+ return c.json({
413
+ provider: type,
414
+ models: (data.data || []).map((m) => ({
415
+ id: m.id,
416
+ name: m.name || m.id,
417
+ pricing: m.pricing,
418
+ })),
419
+ });
420
+ }
421
+ // For other providers, return static catalog
422
+ const providerType = parseProviderType(type);
423
+ if (!providerType) {
424
+ return c.json({ error: "Invalid provider" }, 400);
425
+ }
426
+ const models = aiProvider.getModelsForProvider(providerType);
427
+ return c.json({ provider: type, models });
428
+ }
429
+ catch (error) {
430
+ logger.error(`[Chat] Failed to fetch models for ${type}:`, error instanceof Error ? error : undefined);
431
+ return c.json({
432
+ error: error instanceof Error ? error.message : "Failed to fetch models",
433
+ }, 500);
434
+ }
435
+ });
436
+ /**
437
+ * POST /api/chat/quick
438
+ * Quick chat endpoint for simple requests
439
+ */
440
+ chatRoutes.post("/quick", zValidator("json", z.object({
441
+ prompt: z.string(),
442
+ model: z.string().optional(),
443
+ systemPrompt: z.string().optional(),
444
+ temperature: z.number().optional(),
445
+ })), async (c) => {
446
+ const { prompt, model, systemPrompt, temperature } = c.req.valid("json");
447
+ try {
448
+ const response = await aiProvider.chat({
449
+ messages: [
450
+ {
451
+ id: randomUUID(),
452
+ role: "user",
453
+ content: prompt,
454
+ timestamp: new Date().toISOString(),
455
+ },
456
+ ],
457
+ model,
458
+ systemPrompt,
459
+ temperature,
460
+ });
461
+ return c.json({
462
+ content: response.content,
463
+ model: response.model,
464
+ provider: response.provider,
465
+ usage: response.usage,
466
+ });
467
+ }
468
+ catch (error) {
469
+ logger.error("[Chat] Quick chat error:", error instanceof Error ? error : undefined);
470
+ return c.json({
471
+ error: error instanceof Error ? error.message : "Quick chat failed",
472
+ }, 500);
473
+ }
474
+ });
475
+ // === Preset & Context Routes ===
476
+ /**
477
+ * GET /api/chat/presets
478
+ * List available chat presets
479
+ */
480
+ chatRoutes.get("/presets", async (c) => {
481
+ return c.json({
482
+ presets: CHAT_PRESETS.map((p) => ({
483
+ id: p.id,
484
+ name: p.name,
485
+ description: p.description,
486
+ icon: p.icon,
487
+ examples: p.examples,
488
+ })),
489
+ default: "profclaw-assistant",
490
+ });
491
+ });
492
+ /**
493
+ * GET /api/chat/quick-actions
494
+ * List quick action suggestions
495
+ */
496
+ chatRoutes.get("/quick-actions", async (c) => {
497
+ return c.json({ actions: QUICK_ACTIONS });
498
+ });
499
+ // === Skills Routes ===
500
+ /**
501
+ * GET /api/chat/skills
502
+ * List available chat skills
503
+ */
504
+ chatRoutes.get("/skills", async (c) => {
505
+ return c.json({
506
+ skills: CHAT_SKILLS.map((s) => ({
507
+ id: s.id,
508
+ name: s.name,
509
+ description: s.description,
510
+ icon: s.icon,
511
+ capabilities: s.capabilities,
512
+ preferredModel: s.preferredModel,
513
+ examples: s.examples,
514
+ })),
515
+ modelTiers: MODEL_TIERS.map((t) => ({
516
+ tier: t.tier,
517
+ description: t.description,
518
+ costMultiplier: t.costMultiplier,
519
+ })),
520
+ });
521
+ });
522
+ /**
523
+ * POST /api/chat/skills/detect
524
+ * Detect intent and match skills for a message
525
+ */
526
+ chatRoutes.post("/skills/detect", zValidator("json", z.object({
527
+ message: z.string(),
528
+ hasTask: z.boolean().optional(),
529
+ hasTicket: z.boolean().optional(),
530
+ hasCode: z.boolean().optional(),
531
+ })), async (c) => {
532
+ const { message, hasTask, hasTicket, hasCode } = c.req.valid("json");
533
+ const matches = detectIntent(message, { hasTask, hasTicket, hasCode });
534
+ return c.json({
535
+ matches: matches.slice(0, 3).map((m) => ({
536
+ skillId: m.skill.id,
537
+ skillName: m.skill.name,
538
+ confidence: m.confidence,
539
+ matchedPattern: m.matchedPattern,
540
+ extractedVars: m.extractedVars,
541
+ preferredModel: m.skill.preferredModel,
542
+ })),
543
+ recommendedSkill: matches[0]
544
+ ? {
545
+ id: matches[0].skill.id,
546
+ name: matches[0].skill.name,
547
+ confidence: matches[0].confidence,
548
+ }
549
+ : null,
550
+ });
551
+ });
552
+ /**
553
+ * POST /api/chat/skills/route
554
+ * Get recommended model and skill for a message
555
+ */
556
+ chatRoutes.post("/skills/route", zValidator("json", z.object({
557
+ message: z.string(),
558
+ availableModels: z.array(z.string()).optional(),
559
+ hasTask: z.boolean().optional(),
560
+ hasTicket: z.boolean().optional(),
561
+ hasCode: z.boolean().optional(),
562
+ })), async (c) => {
563
+ const { message, availableModels, hasTask, hasTicket, hasCode } = c.req.valid("json");
564
+ // Get available models from providers if not specified
565
+ let models = availableModels;
566
+ if (!models || models.length === 0) {
567
+ const allModels = aiProvider.getAllModels();
568
+ models = allModels.map((m) => m.id);
569
+ }
570
+ // Detect intent
571
+ const matches = detectIntent(message, { hasTask, hasTicket, hasCode });
572
+ const bestMatch = matches[0];
573
+ if (!bestMatch) {
574
+ return c.json({
575
+ error: "Could not detect intent",
576
+ fallback: { model: models[0], tier: "balanced" },
577
+ });
578
+ }
579
+ // Select model based on skill and message
580
+ const selection = selectModel(bestMatch, message, models);
581
+ return c.json({
582
+ skill: {
583
+ id: bestMatch.skill.id,
584
+ name: bestMatch.skill.name,
585
+ confidence: bestMatch.confidence,
586
+ },
587
+ model: {
588
+ selected: selection.model,
589
+ tier: selection.tier.tier,
590
+ reason: selection.reason,
591
+ costMultiplier: selection.tier.costMultiplier,
592
+ },
593
+ routing: {
594
+ method: bestMatch.matchedPattern ? "pattern_match" : "fallback",
595
+ pattern: bestMatch.matchedPattern,
596
+ },
597
+ });
598
+ });
599
+ // === Conversation Routes ===
600
+ /**
601
+ * GET /api/chat/conversations
602
+ * List conversations with optional filtering
603
+ */
604
+ chatRoutes.get("/conversations", async (c) => {
605
+ const limit = Number(c.req.query("limit")) || 20;
606
+ const offset = Number(c.req.query("offset")) || 0;
607
+ const taskId = c.req.query("taskId");
608
+ const ticketId = c.req.query("ticketId");
609
+ try {
610
+ const result = await listConversations({ limit, offset, taskId, ticketId });
611
+ return c.json(result);
612
+ }
613
+ catch (error) {
614
+ logger.error("[Chat] List conversations error:", error instanceof Error ? error : undefined);
615
+ return c.json({ error: "Failed to list conversations" }, 500);
616
+ }
617
+ });
618
+ /**
619
+ * GET /api/chat/conversations/recent
620
+ * Get recent conversations with preview
621
+ */
622
+ chatRoutes.get("/conversations/recent", async (c) => {
623
+ const limit = Number(c.req.query("limit")) || 10;
624
+ try {
625
+ const conversations = await getRecentConversationsWithPreview(limit);
626
+ return c.json({ conversations });
627
+ }
628
+ catch (error) {
629
+ logger.error("[Chat] Recent conversations error:", error instanceof Error ? error : undefined);
630
+ return c.json({ error: "Failed to get recent conversations" }, 500);
631
+ }
632
+ });
633
+ /**
634
+ * POST /api/chat/conversations
635
+ * Create a new conversation
636
+ */
637
+ chatRoutes.post("/conversations", zValidator("json", z.object({
638
+ title: z.string().optional(),
639
+ presetId: z.string().optional(),
640
+ taskId: z.string().optional(),
641
+ ticketId: z.string().optional(),
642
+ projectId: z.string().optional(),
643
+ })), async (c) => {
644
+ const body = c.req.valid("json");
645
+ try {
646
+ const conversation = await createConversation(body);
647
+ return c.json({ conversation }, 201);
648
+ }
649
+ catch (error) {
650
+ logger.error("[Chat] Create conversation error:", error instanceof Error ? error : undefined);
651
+ return c.json({ error: "Failed to create conversation" }, 500);
652
+ }
653
+ });
654
+ /**
655
+ * GET /api/chat/conversations/:id
656
+ * Get a conversation with messages
657
+ */
658
+ chatRoutes.get("/conversations/:id", async (c) => {
659
+ const id = c.req.param("id");
660
+ try {
661
+ const conversation = await getConversation(id);
662
+ if (!conversation) {
663
+ return c.json({ error: "Conversation not found" }, 404);
664
+ }
665
+ const messages = await getConversationMessages(id);
666
+ return c.json({ conversation, messages });
667
+ }
668
+ catch (error) {
669
+ logger.error("[Chat] Get conversation error:", error instanceof Error ? error : undefined);
670
+ return c.json({ error: "Failed to get conversation" }, 500);
671
+ }
672
+ });
673
+ /**
674
+ * DELETE /api/chat/conversations/:id
675
+ * Delete a conversation
676
+ */
677
+ chatRoutes.delete("/conversations/:id", async (c) => {
678
+ const id = c.req.param("id");
679
+ try {
680
+ await deleteConversation(id);
681
+ return c.json({ message: "Conversation deleted" });
682
+ }
683
+ catch (error) {
684
+ logger.error("[Chat] Delete conversation error:", error instanceof Error ? error : undefined);
685
+ return c.json({ error: "Failed to delete conversation" }, 500);
686
+ }
687
+ });
688
+ /**
689
+ * GET /api/chat/conversations/:id/memory
690
+ * Get memory stats for a conversation
691
+ */
692
+ chatRoutes.get("/conversations/:id/memory", async (c) => {
693
+ const id = c.req.param("id");
694
+ const model = c.req.query("model");
695
+ try {
696
+ const conversation = await getConversation(id);
697
+ if (!conversation) {
698
+ return c.json({ error: "Conversation not found" }, 404);
699
+ }
700
+ const messages = await getConversationMessages(id);
701
+ const stats = getMemoryStats(messages, model);
702
+ return c.json({
703
+ conversationId: id,
704
+ stats,
705
+ recommendation: stats.needsCompaction
706
+ ? "Conversation will be automatically compacted on next message"
707
+ : stats.usagePercentage > 50
708
+ ? "Approaching context limit, consider starting a new conversation for long discussions"
709
+ : "Memory usage healthy",
710
+ });
711
+ }
712
+ catch (error) {
713
+ logger.error("[Chat] Memory stats error:", error instanceof Error ? error : undefined);
714
+ return c.json({ error: "Failed to get memory stats" }, 500);
715
+ }
716
+ });
717
+ /**
718
+ * POST /api/chat/conversations/:id/compact
719
+ * Manually trigger compaction for a conversation
720
+ */
721
+ chatRoutes.post("/conversations/:id/compact", async (c) => {
722
+ const id = c.req.param("id");
723
+ const model = c.req.query("model");
724
+ try {
725
+ const conversation = await getConversation(id);
726
+ if (!conversation) {
727
+ return c.json({ error: "Conversation not found" }, 404);
728
+ }
729
+ const messages = await getConversationMessages(id);
730
+ const result = await compactMessages(messages, model);
731
+ if (!result.wasCompacted) {
732
+ return c.json({
733
+ compacted: false,
734
+ message: "Conversation does not need compaction yet",
735
+ stats: getMemoryStats(messages, model),
736
+ });
737
+ }
738
+ // Note: In a full implementation, we'd save the compacted messages
739
+ // For now, we just return what the compaction would produce
740
+ return c.json({
741
+ compacted: true,
742
+ originalCount: result.originalCount,
743
+ compactedCount: result.compactedCount,
744
+ tokensReduced: result.tokensReduced,
745
+ summary: result.summary,
746
+ stats: getMemoryStats(result.messages, model),
747
+ });
748
+ }
749
+ catch (error) {
750
+ logger.error("[Chat] Manual compaction error:", error instanceof Error ? error : undefined);
751
+ return c.json({ error: "Failed to compact conversation" }, 500);
752
+ }
753
+ });
754
+ /**
755
+ * POST /api/chat/conversations/:id/messages
756
+ * Send a message in a conversation (with context and history)
757
+ */
758
+ chatRoutes.post("/conversations/:id/messages", zValidator("json", z.object({
759
+ content: z.string(),
760
+ model: z.string().optional(),
761
+ temperature: z.number().min(0).max(2).optional(),
762
+ })), async (c) => {
763
+ const conversationId = c.req.param("id");
764
+ const body = c.req.valid("json");
765
+ try {
766
+ // Get conversation and build context
767
+ const conversation = await getConversation(conversationId);
768
+ if (!conversation) {
769
+ return c.json({ error: "Conversation not found" }, 404);
770
+ }
771
+ // Build context from linked entities
772
+ const context = {};
773
+ const client = getClient();
774
+ if (conversation.taskId) {
775
+ const taskResult = await client.execute({
776
+ sql: `SELECT id, description, status, assigned_agent as agent FROM tasks WHERE id = ?`,
777
+ args: [conversation.taskId],
778
+ });
779
+ if (taskResult.rows.length > 0) {
780
+ const t = taskResult.rows[0];
781
+ context.task = {
782
+ id: t.id,
783
+ title: (t.description || "").slice(0, 100),
784
+ description: t.description,
785
+ status: t.status,
786
+ agent: t.agent,
787
+ };
788
+ }
789
+ }
790
+ if (conversation.ticketId) {
791
+ const ticketResult = await client.execute({
792
+ sql: `SELECT id, title, description, status FROM tickets WHERE id = ?`,
793
+ args: [conversation.ticketId],
794
+ });
795
+ if (ticketResult.rows.length > 0) {
796
+ const t = ticketResult.rows[0];
797
+ context.ticket = {
798
+ id: t.id,
799
+ title: t.title,
800
+ description: t.description,
801
+ status: t.status,
802
+ };
803
+ }
804
+ }
805
+ // Get recent activity for context
806
+ const statsResult = await client.execute(`
807
+ SELECT
808
+ (SELECT COUNT(*) FROM tasks WHERE status = 'completed') as completed,
809
+ (SELECT COUNT(*) FROM tasks WHERE status = 'pending') as pending
810
+ `);
811
+ const stats = statsResult.rows[0];
812
+ context.recentActivity = {
813
+ tasksCompleted: Number(stats.completed) || 0,
814
+ tasksPending: Number(stats.pending) || 0,
815
+ activeAgents: [],
816
+ };
817
+ // Add runtime info (model awareness like OpenClaw)
818
+ const sessionOverride = getSessionModel(conversationId);
819
+ // Use the auto-selected default provider when no model specified
820
+ const defaultProvider = aiProvider.getDefaultProvider();
821
+ const resolvedRef = aiProvider.resolveModel(sessionOverride || body.model || defaultProvider);
822
+ context.runtime = {
823
+ model: `${resolvedRef.provider}/${resolvedRef.model}`,
824
+ provider: resolvedRef.provider,
825
+ defaultModel: `${defaultProvider}/${resolvedRef.model}`,
826
+ conversationId,
827
+ sessionOverride,
828
+ };
829
+ // Build system prompt with context
830
+ const systemPrompt = await buildSystemPrompt(conversation.presetId, context);
831
+ // Get existing messages
832
+ const existingMessages = await getConversationMessages(conversationId);
833
+ // Save user message first
834
+ const userMessage = await addMessage({
835
+ conversationId,
836
+ role: "user",
837
+ content: body.content,
838
+ });
839
+ // Add user message to list for compaction check
840
+ const allMessages = [
841
+ ...existingMessages,
842
+ {
843
+ id: userMessage.id,
844
+ conversationId,
845
+ role: "user",
846
+ content: body.content,
847
+ createdAt: userMessage.createdAt,
848
+ },
849
+ ];
850
+ // Check if compaction is needed and compact if necessary
851
+ let messagesToSend = allMessages;
852
+ let compactionInfo = null;
853
+ if (needsCompaction(allMessages, body.model)) {
854
+ logger.info(`[Chat] Compacting conversation ${conversationId} (${allMessages.length} messages)`);
855
+ const compactionResult = await compactMessages(allMessages, body.model);
856
+ if (compactionResult.wasCompacted) {
857
+ messagesToSend = compactionResult.messages;
858
+ compactionInfo = {
859
+ originalCount: compactionResult.originalCount,
860
+ compactedCount: compactionResult.compactedCount,
861
+ tokensReduced: compactionResult.tokensReduced,
862
+ };
863
+ logger.info(`[Chat] Compaction complete: ${compactionResult.originalCount} -> ${compactionResult.compactedCount} messages, ${compactionResult.tokensReduced} tokens saved`);
864
+ }
865
+ }
866
+ // Build chat messages array from (potentially compacted) messages
867
+ const chatMessages = messagesToSend.map((m) => ({
868
+ id: m.id,
869
+ role: m.role,
870
+ content: m.content,
871
+ timestamp: m.createdAt,
872
+ }));
873
+ // Send to AI
874
+ const response = await aiProvider.chat({
875
+ messages: chatMessages,
876
+ model: body.model,
877
+ systemPrompt,
878
+ temperature: body.temperature,
879
+ });
880
+ // Save assistant response
881
+ const assistantMessage = await addMessage({
882
+ conversationId,
883
+ role: "assistant",
884
+ content: response.content,
885
+ model: response.model,
886
+ provider: response.provider,
887
+ tokenUsage: response.usage
888
+ ? {
889
+ prompt: response.usage.promptTokens,
890
+ completion: response.usage.completionTokens,
891
+ total: response.usage.totalTokens,
892
+ }
893
+ : undefined,
894
+ cost: response.usage?.cost,
895
+ });
896
+ return c.json({
897
+ userMessage,
898
+ assistantMessage: {
899
+ ...assistantMessage,
900
+ model: response.model,
901
+ provider: response.provider,
902
+ },
903
+ usage: response.usage,
904
+ compaction: compactionInfo,
905
+ });
906
+ }
907
+ catch (error) {
908
+ logger.error("[Chat] Conversation message error:", error instanceof Error ? error : undefined);
909
+ return c.json({
910
+ error: error instanceof Error ? error.message : "Failed to send message",
911
+ }, 500);
912
+ }
913
+ });
914
+ /**
915
+ * POST /api/chat/conversations/:id/messages/with-tools
916
+ * Send a message in a conversation with native tool calling enabled
917
+ */
918
+ chatRoutes.post("/conversations/:id/messages/with-tools", zValidator("json", z.object({
919
+ content: z.string(),
920
+ model: z.string().optional(),
921
+ temperature: z.number().min(0).max(2).optional(),
922
+ enableTools: z.boolean().optional().default(true),
923
+ })), async (c) => {
924
+ const conversationId = c.req.param("id");
925
+ const body = c.req.valid("json");
926
+ try {
927
+ // Get conversation and build context
928
+ const conversation = await getConversation(conversationId);
929
+ if (!conversation) {
930
+ return c.json({ error: "Conversation not found" }, 404);
931
+ }
932
+ // Build context from linked entities
933
+ const context = {};
934
+ const client = getClient();
935
+ if (conversation.taskId) {
936
+ const taskResult = await client.execute({
937
+ sql: `SELECT id, description, status, assigned_agent as agent FROM tasks WHERE id = ?`,
938
+ args: [conversation.taskId],
939
+ });
940
+ if (taskResult.rows.length > 0) {
941
+ const t = taskResult.rows[0];
942
+ context.task = {
943
+ id: t.id,
944
+ title: (t.description || "").slice(0, 100),
945
+ description: t.description,
946
+ status: t.status,
947
+ agent: t.agent,
948
+ };
949
+ }
950
+ }
951
+ if (conversation.ticketId) {
952
+ const ticketResult = await client.execute({
953
+ sql: `SELECT id, title, description, status FROM tickets WHERE id = ?`,
954
+ args: [conversation.ticketId],
955
+ });
956
+ if (ticketResult.rows.length > 0) {
957
+ const t = ticketResult.rows[0];
958
+ context.ticket = {
959
+ id: t.id,
960
+ title: t.title,
961
+ description: t.description,
962
+ status: t.status,
963
+ };
964
+ }
965
+ }
966
+ // Get recent activity for context
967
+ const statsResult = await client.execute(`
968
+ SELECT
969
+ (SELECT COUNT(*) FROM tasks WHERE status = 'completed') as completed,
970
+ (SELECT COUNT(*) FROM tasks WHERE status = 'pending') as pending
971
+ `);
972
+ const stats = statsResult.rows[0];
973
+ context.recentActivity = {
974
+ tasksCompleted: Number(stats.completed) || 0,
975
+ tasksPending: Number(stats.pending) || 0,
976
+ activeAgents: [],
977
+ };
978
+ // Add runtime info (model awareness like OpenClaw)
979
+ const sessionOverride = getSessionModel(conversationId);
980
+ // Use the auto-selected default provider when no model specified
981
+ const defaultProvider = aiProvider.getDefaultProvider();
982
+ const resolvedRef = aiProvider.resolveModel(sessionOverride || body.model || defaultProvider);
983
+ context.runtime = {
984
+ model: `${resolvedRef.provider}/${resolvedRef.model}`,
985
+ provider: resolvedRef.provider,
986
+ defaultModel: `${defaultProvider}/${resolvedRef.model}`,
987
+ conversationId,
988
+ sessionOverride,
989
+ };
990
+ // Get available tools - model-aware when model ID is known
991
+ const enableTools = body.enableTools ?? true;
992
+ const modelId = resolvedRef.model;
993
+ const tools = enableTools
994
+ ? getChatToolsForModel(modelId, { conversationId })
995
+ : [];
996
+ // Build system prompt with context and tool mode
997
+ const systemPrompt = await buildSystemPrompt(conversation.presetId, context, {
998
+ enableTools: enableTools && tools.length > 0,
999
+ });
1000
+ // Get existing messages
1001
+ const existingMessages = await getConversationMessages(conversationId);
1002
+ // Save user message first
1003
+ const userMessage = await addMessage({
1004
+ conversationId,
1005
+ role: "user",
1006
+ content: body.content,
1007
+ });
1008
+ // Add user message to list for API call
1009
+ const allMessages = [
1010
+ ...existingMessages,
1011
+ {
1012
+ id: userMessage.id,
1013
+ conversationId,
1014
+ role: "user",
1015
+ content: body.content,
1016
+ createdAt: userMessage.createdAt,
1017
+ },
1018
+ ];
1019
+ // Check if compaction is needed
1020
+ let messagesToSend = allMessages;
1021
+ let compactionInfo = null;
1022
+ if (needsCompaction(allMessages, body.model)) {
1023
+ logger.info(`[Chat] Compacting conversation ${conversationId} (${allMessages.length} messages)`);
1024
+ const compactionResult = await compactMessages(allMessages, body.model);
1025
+ if (compactionResult.wasCompacted) {
1026
+ messagesToSend = compactionResult.messages;
1027
+ compactionInfo = {
1028
+ originalCount: compactionResult.originalCount,
1029
+ compactedCount: compactionResult.compactedCount,
1030
+ tokensReduced: compactionResult.tokensReduced,
1031
+ };
1032
+ }
1033
+ }
1034
+ // Build chat messages array
1035
+ const chatMessages = messagesToSend.map((m) => ({
1036
+ id: m.id,
1037
+ role: m.role,
1038
+ content: m.content,
1039
+ timestamp: m.createdAt,
1040
+ }));
1041
+ // Create tool handler for this conversation
1042
+ const toolHandler = await createChatToolHandler({
1043
+ conversationId,
1044
+ securityMode: "ask",
1045
+ });
1046
+ // Send to AI with native tool support
1047
+ const response = await aiProvider.chatWithNativeTools({
1048
+ messages: chatMessages,
1049
+ model: body.model,
1050
+ systemPrompt,
1051
+ temperature: body.temperature,
1052
+ tools,
1053
+ onToolCall: async (toolName, args, toolCallId) => {
1054
+ return toolHandler.executeTool(toolName, args, toolCallId);
1055
+ },
1056
+ maxToolRoundtrips: 5,
1057
+ });
1058
+ // Get any pending approvals
1059
+ const pendingApprovals = toolHandler.getPendingApprovals();
1060
+ const inferToolCallStatus = (result) => {
1061
+ if (!result || typeof result !== "object") {
1062
+ return "success";
1063
+ }
1064
+ const record = result;
1065
+ if (record.pending === true) {
1066
+ return "pending";
1067
+ }
1068
+ if (record.success === false || record.error) {
1069
+ return "error";
1070
+ }
1071
+ return "success";
1072
+ };
1073
+ // Build toolCalls array for storage
1074
+ const toolCallsForStorage = response.toolCalls?.map((tc) => {
1075
+ const toolResult = response.toolResults?.find((tr) => tr.toolCallId === tc.id)?.result;
1076
+ return {
1077
+ id: tc.id,
1078
+ name: tc.name,
1079
+ arguments: tc.arguments,
1080
+ result: toolResult,
1081
+ status: inferToolCallStatus(toolResult),
1082
+ };
1083
+ });
1084
+ // Save assistant response with toolCalls
1085
+ const assistantMessage = await addMessage({
1086
+ conversationId,
1087
+ role: "assistant",
1088
+ content: response.content,
1089
+ model: response.model,
1090
+ provider: response.provider,
1091
+ tokenUsage: response.usage
1092
+ ? {
1093
+ prompt: response.usage.promptTokens,
1094
+ completion: response.usage.completionTokens,
1095
+ total: response.usage.totalTokens,
1096
+ }
1097
+ : undefined,
1098
+ cost: response.usage?.cost,
1099
+ toolCalls: toolCallsForStorage,
1100
+ });
1101
+ return c.json({
1102
+ userMessage,
1103
+ assistantMessage: {
1104
+ ...assistantMessage,
1105
+ model: response.model,
1106
+ provider: response.provider,
1107
+ },
1108
+ usage: response.usage,
1109
+ compaction: compactionInfo,
1110
+ toolCalls: toolCallsForStorage,
1111
+ pendingApprovals: pendingApprovals.length > 0
1112
+ ? pendingApprovals.map((a) => ({
1113
+ id: a.id,
1114
+ toolName: a.toolName,
1115
+ params: a.params,
1116
+ securityLevel: "moderate",
1117
+ }))
1118
+ : undefined,
1119
+ // Tool support info for UI warnings
1120
+ toolSupport: response.toolSupport,
1121
+ });
1122
+ }
1123
+ catch (error) {
1124
+ logger.error("[Chat] Conversation message with tools error:", error instanceof Error ? error : undefined);
1125
+ return c.json({
1126
+ error: error instanceof Error ? error.message : "Failed to send message",
1127
+ }, 500);
1128
+ }
1129
+ });
1130
+ /**
1131
+ * POST /api/chat/smart
1132
+ * Smart chat with automatic context injection
1133
+ * (Simpler alternative to conversation-based chat)
1134
+ */
1135
+ chatRoutes.post("/smart", zValidator("json", z.object({
1136
+ messages: z.array(ChatMessageSchema),
1137
+ model: z.string().optional(),
1138
+ presetId: z.string().optional(),
1139
+ taskId: z.string().optional(),
1140
+ ticketId: z.string().optional(),
1141
+ temperature: z.number().min(0).max(2).optional(),
1142
+ })), async (c) => {
1143
+ const body = c.req.valid("json");
1144
+ try {
1145
+ // Build context
1146
+ const context = {};
1147
+ const client = getClient();
1148
+ if (body.taskId) {
1149
+ const taskResult = await client.execute({
1150
+ sql: `SELECT id, description, status, assigned_agent as agent FROM tasks WHERE id = ?`,
1151
+ args: [body.taskId],
1152
+ });
1153
+ if (taskResult.rows.length > 0) {
1154
+ const t = taskResult.rows[0];
1155
+ context.task = {
1156
+ id: t.id,
1157
+ title: (t.description || "").slice(0, 100),
1158
+ description: t.description,
1159
+ status: t.status,
1160
+ agent: t.agent,
1161
+ };
1162
+ }
1163
+ }
1164
+ if (body.ticketId) {
1165
+ const ticketResult = await client.execute({
1166
+ sql: `SELECT id, title, description, status FROM tickets WHERE id = ?`,
1167
+ args: [body.ticketId],
1168
+ });
1169
+ if (ticketResult.rows.length > 0) {
1170
+ const t = ticketResult.rows[0];
1171
+ context.ticket = {
1172
+ id: t.id,
1173
+ title: t.title,
1174
+ description: t.description,
1175
+ status: t.status,
1176
+ };
1177
+ }
1178
+ }
1179
+ // Build system prompt
1180
+ const systemPrompt = await buildSystemPrompt(body.presetId || "profclaw-assistant", context);
1181
+ // Convert messages
1182
+ const messages = body.messages.map((msg) => ({
1183
+ id: randomUUID(),
1184
+ role: msg.role,
1185
+ content: msg.content,
1186
+ timestamp: new Date().toISOString(),
1187
+ }));
1188
+ // Send to AI
1189
+ const response = await aiProvider.chat({
1190
+ messages,
1191
+ model: body.model,
1192
+ systemPrompt,
1193
+ temperature: body.temperature,
1194
+ });
1195
+ return c.json({
1196
+ id: response.id,
1197
+ provider: response.provider,
1198
+ model: response.model,
1199
+ message: {
1200
+ role: "assistant",
1201
+ content: response.content,
1202
+ },
1203
+ finishReason: response.finishReason,
1204
+ usage: response.usage,
1205
+ duration: response.duration,
1206
+ context: {
1207
+ presetId: body.presetId || "profclaw-assistant",
1208
+ taskId: body.taskId,
1209
+ ticketId: body.ticketId,
1210
+ },
1211
+ });
1212
+ }
1213
+ catch (error) {
1214
+ logger.error("[Chat] Smart chat error:", error instanceof Error ? error : undefined);
1215
+ return c.json({ error: error instanceof Error ? error.message : "Smart chat failed" }, 500);
1216
+ }
1217
+ });
1218
+ // Chat with Tools
1219
+ /**
1220
+ * POST /api/chat/with-tools
1221
+ * Chat with AI tools enabled (file operations, git, system info, etc.)
1222
+ */
1223
+ chatRoutes.post("/with-tools", zValidator("json", z.object({
1224
+ messages: z.array(ChatMessageSchema),
1225
+ conversationId: z.string().optional(),
1226
+ model: z.string().optional(),
1227
+ systemPrompt: z.string().optional(),
1228
+ presetId: z.string().optional(),
1229
+ temperature: z.number().min(0).max(2).optional(),
1230
+ enableAllTools: z.boolean().optional(), // Enable all tools vs safe subset
1231
+ securityMode: z
1232
+ .enum(["deny", "sandbox", "allowlist", "ask", "full"])
1233
+ .optional(),
1234
+ workdir: z.string().optional(),
1235
+ })), async (c) => {
1236
+ const body = c.req.valid("json");
1237
+ const conversationId = body.conversationId || randomUUID();
1238
+ try {
1239
+ // Create tool handler with security settings
1240
+ const toolHandler = await createChatToolHandler({
1241
+ conversationId,
1242
+ workdir: body.workdir,
1243
+ securityMode: body.securityMode || "ask",
1244
+ });
1245
+ // Get tools based on user preference
1246
+ const tools = body.enableAllTools
1247
+ ? getAllChatTools()
1248
+ : getDefaultChatTools();
1249
+ // Build system prompt with tools enabled (this endpoint always has tools)
1250
+ let systemPrompt = body.systemPrompt || "";
1251
+ if (body.presetId) {
1252
+ systemPrompt =
1253
+ (await buildSystemPrompt(body.presetId, {}, { enableTools: true })) +
1254
+ "\n\n" +
1255
+ systemPrompt;
1256
+ }
1257
+ else if (!systemPrompt) {
1258
+ // Even without preset, add tool-enabled system prompt
1259
+ systemPrompt = await buildSystemPrompt("profclaw-assistant", {}, { enableTools: true });
1260
+ }
1261
+ // Convert messages
1262
+ const messages = body.messages.map((msg) => ({
1263
+ id: randomUUID(),
1264
+ role: msg.role,
1265
+ content: msg.content,
1266
+ timestamp: new Date().toISOString(),
1267
+ }));
1268
+ // Call AI with native tool support
1269
+ const response = await aiProvider.chatWithNativeTools({
1270
+ messages,
1271
+ model: body.model,
1272
+ systemPrompt,
1273
+ temperature: body.temperature,
1274
+ tools,
1275
+ onToolCall: async (toolName, args, toolCallId) => {
1276
+ return toolHandler.executeTool(toolName, args, toolCallId);
1277
+ },
1278
+ maxToolRoundtrips: 5,
1279
+ });
1280
+ // Check for pending approvals
1281
+ const pendingApprovals = toolHandler.getPendingApprovals();
1282
+ return c.json({
1283
+ id: response.id,
1284
+ conversationId,
1285
+ provider: response.provider,
1286
+ model: response.model,
1287
+ message: {
1288
+ role: "assistant",
1289
+ content: response.content,
1290
+ },
1291
+ finishReason: response.finishReason,
1292
+ usage: response.usage,
1293
+ duration: response.duration,
1294
+ // Tool execution info
1295
+ toolCalls: response.toolCalls,
1296
+ toolResults: response.toolResults,
1297
+ pendingApprovals: pendingApprovals.length > 0 ? pendingApprovals : undefined,
1298
+ steps: response.steps,
1299
+ // Tool support info for UI warnings
1300
+ toolSupport: response.toolSupport,
1301
+ });
1302
+ }
1303
+ catch (error) {
1304
+ logger.error("[Chat] Chat with tools error:", error instanceof Error ? error : undefined);
1305
+ return c.json({
1306
+ error: error instanceof Error ? error.message : "Chat with tools failed",
1307
+ }, 500);
1308
+ }
1309
+ });
1310
+ /**
1311
+ * POST /api/chat/conversations/:id/messages/agentic
1312
+ * Send a message in agentic mode with SSE streaming for real-time updates.
1313
+ *
1314
+ * This endpoint runs the AI in autonomous mode, executing multiple tools
1315
+ * until the task is complete. Events are streamed via SSE including:
1316
+ * - session:start - Agent session started
1317
+ * - thinking:start/update/end - AI reasoning (if enabled)
1318
+ * - step:start/complete - Step progress
1319
+ * - tool:call - Tool being called
1320
+ * - tool:result - Tool execution result
1321
+ * - summary - Final task summary
1322
+ * - complete - Session complete
1323
+ * - error - Error occurred
1324
+ */
1325
+ chatRoutes.post("/conversations/:id/messages/agentic", zValidator("json", z.object({
1326
+ content: z.string(),
1327
+ model: z.string().optional(),
1328
+ provider: z.string().optional(),
1329
+ temperature: z.number().min(0).max(2).optional(),
1330
+ showThinking: z.boolean().optional().default(true),
1331
+ maxSteps: z.number().min(1).max(200).optional(),
1332
+ maxBudget: z.number().min(1000).optional(),
1333
+ effort: z.enum(['low', 'medium', 'high', 'max']).optional(),
1334
+ })), async (c) => {
1335
+ const conversationId = c.req.param("id");
1336
+ const body = c.req.valid("json");
1337
+ try {
1338
+ // Get conversation
1339
+ const conversation = await getConversation(conversationId);
1340
+ if (!conversation) {
1341
+ return c.json({ error: "Conversation not found" }, 404);
1342
+ }
1343
+ // Build context from linked entities
1344
+ const context = {};
1345
+ const client = getClient();
1346
+ if (conversation.taskId) {
1347
+ const taskResult = await client.execute({
1348
+ sql: `SELECT id, description, status, assigned_agent as agent FROM tasks WHERE id = ?`,
1349
+ args: [conversation.taskId],
1350
+ });
1351
+ if (taskResult.rows.length > 0) {
1352
+ const t = taskResult.rows[0];
1353
+ context.task = {
1354
+ id: t.id,
1355
+ title: (t.description || "").slice(0, 100),
1356
+ description: t.description,
1357
+ status: t.status,
1358
+ agent: t.agent,
1359
+ };
1360
+ }
1361
+ }
1362
+ if (conversation.ticketId) {
1363
+ const ticketResult = await client.execute({
1364
+ sql: `SELECT id, title, description, status FROM tickets WHERE id = ?`,
1365
+ args: [conversation.ticketId],
1366
+ });
1367
+ if (ticketResult.rows.length > 0) {
1368
+ const t = ticketResult.rows[0];
1369
+ context.ticket = {
1370
+ id: t.id,
1371
+ title: t.title,
1372
+ description: t.description,
1373
+ status: t.status,
1374
+ };
1375
+ }
1376
+ }
1377
+ // Add runtime info
1378
+ const sessionOverride = getSessionModel(conversationId);
1379
+ const defaultProvider = aiProvider.getDefaultProvider();
1380
+ const resolvedRef = aiProvider.resolveModel(sessionOverride || body.model || defaultProvider);
1381
+ context.runtime = {
1382
+ model: `${resolvedRef.provider}/${resolvedRef.model}`,
1383
+ provider: resolvedRef.provider,
1384
+ defaultModel: `${defaultProvider}/${resolvedRef.model}`,
1385
+ conversationId,
1386
+ sessionOverride,
1387
+ };
1388
+ // Get tools - agentic mode uses model-aware filtering
1389
+ const tools = getChatToolsForModel(resolvedRef.model, { conversationId, includeAll: true });
1390
+ // Build system prompt with agent mode (uses AGENT_MODE_SUFFIX)
1391
+ const systemPrompt = await buildSystemPrompt(conversation.presetId, context, {
1392
+ agentMode: true,
1393
+ });
1394
+ // Get existing messages
1395
+ const existingMessages = await getConversationMessages(conversationId);
1396
+ // Save user message first
1397
+ const userMessage = await addMessage({
1398
+ conversationId,
1399
+ role: "user",
1400
+ content: body.content,
1401
+ });
1402
+ // Build all messages for compaction check
1403
+ const allMessages = [
1404
+ ...existingMessages,
1405
+ {
1406
+ id: userMessage.id,
1407
+ conversationId,
1408
+ role: "user",
1409
+ content: body.content,
1410
+ createdAt: userMessage.createdAt,
1411
+ },
1412
+ ];
1413
+ // Apply context pruning if conversation is getting long
1414
+ let messagesToSend = allMessages;
1415
+ let compactionApplied = false;
1416
+ if (needsCompaction(allMessages, body.model)) {
1417
+ logger.info(`[Chat/Agentic] Compacting conversation ${conversationId} (${allMessages.length} messages)`);
1418
+ const compactionResult = await compactMessages(allMessages, body.model);
1419
+ if (compactionResult.wasCompacted) {
1420
+ messagesToSend = compactionResult.messages;
1421
+ compactionApplied = true;
1422
+ logger.info(`[Chat/Agentic] Compaction complete: ${compactionResult.originalCount} -> ${compactionResult.compactedCount} messages, ${compactionResult.tokensReduced} tokens saved`);
1423
+ }
1424
+ }
1425
+ // Build chat messages from (potentially compacted) messages
1426
+ const chatMessages = messagesToSend.map((m) => ({
1427
+ id: m.id,
1428
+ role: m.role,
1429
+ content: m.content,
1430
+ timestamp: m.createdAt,
1431
+ }));
1432
+ // Create tool handler
1433
+ const toolHandler = await createChatToolHandler({
1434
+ conversationId,
1435
+ securityMode: "full", // Full access in agentic mode (tools are pre-approved)
1436
+ });
1437
+ // Set up SSE streaming response
1438
+ c.header("Content-Type", "text/event-stream");
1439
+ c.header("Cache-Control", "no-cache");
1440
+ c.header("Connection", "keep-alive");
1441
+ c.header("X-Accel-Buffering", "no");
1442
+ return streamText(c, async (stream) => {
1443
+ // Overall timeout for the agentic session (3 minutes)
1444
+ const AGENTIC_TIMEOUT_MS = 3 * 60 * 1000;
1445
+ let timedOut = false;
1446
+ const timeoutId = setTimeout(async () => {
1447
+ timedOut = true;
1448
+ logger.warn("[Chat/Agentic] Session timed out", {
1449
+ conversationId,
1450
+ timeoutMs: AGENTIC_TIMEOUT_MS,
1451
+ });
1452
+ try {
1453
+ await stream.write(`data: ${JSON.stringify({
1454
+ type: "error",
1455
+ data: {
1456
+ message: "Agentic session timed out after 3 minutes. The task may be too complex — try breaking it into smaller steps.",
1457
+ code: "TIMEOUT",
1458
+ },
1459
+ timestamp: Date.now(),
1460
+ })}\n\n`);
1461
+ }
1462
+ catch {
1463
+ // Stream may already be closed
1464
+ }
1465
+ }, AGENTIC_TIMEOUT_MS);
1466
+ // Send initial event with user message and compaction info
1467
+ await stream.write(`data: ${JSON.stringify({
1468
+ type: "user_message",
1469
+ data: {
1470
+ id: userMessage.id,
1471
+ content: body.content,
1472
+ compactionApplied,
1473
+ messageCount: messagesToSend.length,
1474
+ },
1475
+ timestamp: Date.now(),
1476
+ })}\n\n`);
1477
+ let lastAssistantContent = "";
1478
+ let totalTokens = 0;
1479
+ let inputTokensTotal;
1480
+ let outputTokensTotal;
1481
+ let finalModel = "";
1482
+ let finalProvider = "";
1483
+ let collectedToolCalls = [];
1484
+ try {
1485
+ // Run the streaming agentic chat
1486
+ for await (const event of streamAgenticChat({
1487
+ conversationId,
1488
+ messages: chatMessages,
1489
+ systemPrompt,
1490
+ model: body.model,
1491
+ provider: body.provider,
1492
+ temperature: body.temperature,
1493
+ toolHandler,
1494
+ tools: tools.map((t) => ({
1495
+ name: t.name,
1496
+ description: t.description,
1497
+ parameters: t.parameters,
1498
+ })),
1499
+ showThinking: body.showThinking,
1500
+ maxSteps: body.maxSteps,
1501
+ maxBudget: body.maxBudget,
1502
+ effort: body.effort,
1503
+ })) {
1504
+ // Check if we've timed out
1505
+ if (timedOut)
1506
+ break;
1507
+ // Stream each event to the client
1508
+ await stream.write(`data: ${JSON.stringify(event)}\n\n`);
1509
+ // Track data for final message save
1510
+ if (event.type === "summary") {
1511
+ const summaryData = event.data;
1512
+ lastAssistantContent = summaryData.summary;
1513
+ }
1514
+ if (event.type === "complete") {
1515
+ const completeData = event.data;
1516
+ totalTokens = completeData.totalTokens;
1517
+ inputTokensTotal = completeData.inputTokens;
1518
+ outputTokensTotal = completeData.outputTokens;
1519
+ finalModel = completeData.model;
1520
+ finalProvider = completeData.provider;
1521
+ collectedToolCalls = completeData.toolCalls || [];
1522
+ }
1523
+ }
1524
+ // Clear the timeout - we completed normally
1525
+ clearTimeout(timeoutId);
1526
+ // Save assistant response after streaming completes
1527
+ if (lastAssistantContent) {
1528
+ const promptTokens = inputTokensTotal ?? Math.floor(totalTokens * 0.7);
1529
+ const completionTokens = outputTokensTotal ?? (totalTokens - promptTokens);
1530
+ const assistantMessage = await addMessage({
1531
+ conversationId,
1532
+ role: "assistant",
1533
+ content: lastAssistantContent,
1534
+ model: finalModel,
1535
+ provider: finalProvider,
1536
+ tokenUsage: totalTokens > 0
1537
+ ? {
1538
+ prompt: promptTokens,
1539
+ completion: completionTokens,
1540
+ total: totalTokens,
1541
+ }
1542
+ : undefined,
1543
+ toolCalls: collectedToolCalls.length > 0 ? collectedToolCalls : undefined,
1544
+ });
1545
+ // Track in-memory usage for cost dashboard
1546
+ if (totalTokens > 0 && finalModel) {
1547
+ trackChatUsage(finalModel, totalTokens, inputTokensTotal, outputTokensTotal);
1548
+ }
1549
+ // Send final saved message event
1550
+ await stream.write(`data: ${JSON.stringify({
1551
+ type: "message_saved",
1552
+ data: { id: assistantMessage.id },
1553
+ timestamp: Date.now(),
1554
+ })}\n\n`);
1555
+ }
1556
+ }
1557
+ catch (error) {
1558
+ clearTimeout(timeoutId);
1559
+ logger.error("[Chat] Agentic streaming error:", error instanceof Error ? error : undefined);
1560
+ await stream.write(`data: ${JSON.stringify({
1561
+ type: "error",
1562
+ data: {
1563
+ message: error instanceof Error
1564
+ ? error.message
1565
+ : "Agentic execution failed",
1566
+ },
1567
+ timestamp: Date.now(),
1568
+ })}\n\n`);
1569
+ }
1570
+ });
1571
+ }
1572
+ catch (error) {
1573
+ logger.error("[Chat] Agentic chat setup error:", error instanceof Error ? error : undefined);
1574
+ return c.json({
1575
+ error: error instanceof Error
1576
+ ? error.message
1577
+ : "Failed to start agentic chat",
1578
+ }, 500);
1579
+ }
1580
+ });
1581
+ /**
1582
+ * GET /api/chat/tools
1583
+ * List available tools for chat
1584
+ */
1585
+ chatRoutes.get("/tools", async (c) => {
1586
+ const allTools = c.req.query("all") === "true";
1587
+ const tools = allTools ? getAllChatTools() : getDefaultChatTools();
1588
+ return c.json({
1589
+ tools: tools.map((t) => ({
1590
+ name: t.name,
1591
+ description: t.description,
1592
+ })),
1593
+ total: tools.length,
1594
+ mode: allTools ? "all" : "default",
1595
+ });
1596
+ });
1597
+ /**
1598
+ * POST /api/chat/tools/approve
1599
+ * Approve a pending tool execution
1600
+ */
1601
+ chatRoutes.post("/tools/approve", zValidator("json", z.object({
1602
+ conversationId: z.string(),
1603
+ approvalId: z.string(),
1604
+ decision: z.enum(["allow-once", "allow-always", "deny"]),
1605
+ })), async (c) => {
1606
+ const { conversationId, approvalId, decision } = c.req.valid("json");
1607
+ try {
1608
+ // Create handler for this conversation to access approvals
1609
+ const toolHandler = await createChatToolHandler({ conversationId });
1610
+ const result = await toolHandler.handleApproval(approvalId, decision);
1611
+ if (!result) {
1612
+ return c.json({ error: "Approval not found or expired" }, 404);
1613
+ }
1614
+ return c.json({
1615
+ success: true,
1616
+ result: result.result,
1617
+ decision,
1618
+ });
1619
+ }
1620
+ catch (error) {
1621
+ logger.error("[Chat] Tool approval error:", error instanceof Error ? error : undefined);
1622
+ return c.json({ error: error instanceof Error ? error.message : "Approval failed" }, 500);
1623
+ }
1624
+ });
1625
+ // Group Chat Routes
1626
+ /**
1627
+ * GET /api/chat/group/config
1628
+ * Get group chat configuration and channel personalities
1629
+ */
1630
+ chatRoutes.get("/group/config", (c) => {
1631
+ const manager = getGroupChatManager();
1632
+ return c.json({
1633
+ mentionGating: true,
1634
+ threadingEnabled: true,
1635
+ rateLimiting: true,
1636
+ channelPersonalities: manager.getChannelPersonalities(),
1637
+ });
1638
+ });
1639
+ /**
1640
+ * POST /api/chat/group/personality
1641
+ * Set a channel-specific system prompt
1642
+ */
1643
+ chatRoutes.post("/group/personality", zValidator("json", z.object({
1644
+ channelId: z.string().min(1),
1645
+ systemPrompt: z.string().min(1),
1646
+ })), async (c) => {
1647
+ const { channelId, systemPrompt } = c.req.valid("json");
1648
+ try {
1649
+ const manager = getGroupChatManager();
1650
+ manager.setChannelPersonality(channelId, systemPrompt);
1651
+ return c.json({ success: true });
1652
+ }
1653
+ catch (error) {
1654
+ logger.error("[Chat/Group] Set personality error:", error instanceof Error ? error : undefined);
1655
+ return c.json({ error: error instanceof Error ? error.message : "Failed to set personality" }, 500);
1656
+ }
1657
+ });
1658
+ /**
1659
+ * POST /api/chat/group/rate-limit
1660
+ * Configure the per-minute rate limit for a channel
1661
+ */
1662
+ chatRoutes.post("/group/rate-limit", zValidator("json", z.object({
1663
+ channelId: z.string().min(1),
1664
+ maxPerMinute: z.number().int().positive(),
1665
+ })), async (c) => {
1666
+ const { channelId, maxPerMinute } = c.req.valid("json");
1667
+ try {
1668
+ const manager = getGroupChatManager();
1669
+ manager.setRateLimit(channelId, maxPerMinute);
1670
+ return c.json({ success: true });
1671
+ }
1672
+ catch (error) {
1673
+ logger.error("[Chat/Group] Set rate limit error:", error instanceof Error ? error : undefined);
1674
+ return c.json({ error: error instanceof Error ? error.message : "Failed to set rate limit" }, 500);
1675
+ }
1676
+ });
1677
+ export { chatRoutes };
1678
+ //# sourceMappingURL=chat.js.map