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,998 @@
1
+ /**
2
+ * User Routes
3
+ *
4
+ * Handles user profile and preferences management.
5
+ */
6
+ import { Hono } from 'hono';
7
+ import { getCookie } from 'hono/cookie';
8
+ import { eq } from 'drizzle-orm';
9
+ import { randomUUID, randomBytes, createHash } from 'crypto';
10
+ import { getDb } from '../storage/index.js';
11
+ import { users, userPreferences, userApiKeys, sessions, oauthAccounts, inviteCodes } from '../storage/schema.js';
12
+ import { validateSession, getUserById, getUserConnectedAccounts } from '../auth/auth-service.js';
13
+ import { hashPassword, verifyPassword, validatePasswordStrength, generateRecoveryCodes, hashRecoveryCodes, generateInviteCode, hashInviteCode, } from '../auth/password.js';
14
+ import { getSettingsRaw, updateSettings } from '../settings/index.js';
15
+ export const userRoutes = new Hono();
16
+ // Middleware to require authentication
17
+ async function requireAuth(c, next) {
18
+ const token = getCookie(c, 'profclaw_session');
19
+ if (!token) {
20
+ return c.json({ error: 'Not authenticated' }, 401);
21
+ }
22
+ const user = await validateSession(token);
23
+ if (!user) {
24
+ return c.json({ error: 'Invalid session' }, 401);
25
+ }
26
+ c.set('user', user);
27
+ await next();
28
+ }
29
+ // Apply auth middleware to all routes
30
+ userRoutes.use('/*', requireAuth);
31
+ // PROFILE
32
+ /**
33
+ * GET /api/users/me/profile
34
+ * Get full user profile with preferences
35
+ */
36
+ userRoutes.get('/me/profile', async (c) => {
37
+ const user = c.get('user');
38
+ const db = getDb();
39
+ if (!db)
40
+ return c.json({ error: 'Database not initialized' }, 500);
41
+ // Get preferences
42
+ const prefs = await db
43
+ .select()
44
+ .from(userPreferences)
45
+ .where(eq(userPreferences.userId, user.id))
46
+ .limit(1);
47
+ // Get connected accounts
48
+ const connectedAccounts = await getUserConnectedAccounts(user.id);
49
+ // Get active sessions count
50
+ const sessionsResult = await db
51
+ .select()
52
+ .from(sessions)
53
+ .where(eq(sessions.userId, user.id));
54
+ return c.json({
55
+ user,
56
+ preferences: prefs[0] || null,
57
+ connectedAccounts,
58
+ activeSessions: sessionsResult.length,
59
+ });
60
+ });
61
+ /**
62
+ * PATCH /api/users/me/profile
63
+ * Update user profile
64
+ */
65
+ userRoutes.patch('/me/profile', async (c) => {
66
+ const user = c.get('user');
67
+ const db = getDb();
68
+ if (!db)
69
+ return c.json({ error: 'Database not initialized' }, 500);
70
+ const body = await c.req.json();
71
+ const { name, bio, timezone, locale } = body;
72
+ // Validate inputs
73
+ if (name !== undefined && (typeof name !== 'string' || name.length < 1)) {
74
+ return c.json({ error: 'Name must be at least 1 character' }, 400);
75
+ }
76
+ await db
77
+ .update(users)
78
+ .set({
79
+ ...(name !== undefined && { name }),
80
+ ...(bio !== undefined && { bio }),
81
+ ...(timezone !== undefined && { timezone }),
82
+ ...(locale !== undefined && { locale }),
83
+ updatedAt: new Date(),
84
+ })
85
+ .where(eq(users.id, user.id));
86
+ const updated = await getUserById(user.id);
87
+ return c.json({ user: updated });
88
+ });
89
+ /**
90
+ * PUT /api/users/me/email
91
+ * Change user email address
92
+ * Requires password verification for security
93
+ */
94
+ userRoutes.put('/me/email', async (c) => {
95
+ const user = c.get('user');
96
+ const db = getDb();
97
+ if (!db)
98
+ return c.json({ error: 'Database not initialized' }, 500);
99
+ const body = await c.req.json();
100
+ const { newEmail, currentPassword } = body;
101
+ // Validate inputs
102
+ if (!newEmail || typeof newEmail !== 'string') {
103
+ return c.json({ error: 'New email is required' }, 400);
104
+ }
105
+ // Basic email validation
106
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
107
+ if (!emailRegex.test(newEmail)) {
108
+ return c.json({ error: 'Invalid email format' }, 400);
109
+ }
110
+ // Get current user with password hash
111
+ const currentUser = await db
112
+ .select()
113
+ .from(users)
114
+ .where(eq(users.id, user.id))
115
+ .limit(1);
116
+ if (!currentUser.length) {
117
+ return c.json({ error: 'User not found' }, 404);
118
+ }
119
+ // If user has a password, verify it
120
+ if (currentUser[0].passwordHash) {
121
+ if (!currentPassword) {
122
+ return c.json({ error: 'Current password is required' }, 400);
123
+ }
124
+ const { valid } = verifyPassword(currentPassword, currentUser[0].passwordHash);
125
+ if (!valid) {
126
+ return c.json({ error: 'Current password is incorrect' }, 401);
127
+ }
128
+ }
129
+ // Check if email already exists
130
+ const existingEmail = await db
131
+ .select()
132
+ .from(users)
133
+ .where(eq(users.email, newEmail.toLowerCase()))
134
+ .limit(1);
135
+ if (existingEmail.length > 0 && existingEmail[0].id !== user.id) {
136
+ return c.json({ error: 'Email already in use' }, 409);
137
+ }
138
+ // Update email
139
+ await db
140
+ .update(users)
141
+ .set({
142
+ email: newEmail.toLowerCase(),
143
+ updatedAt: new Date(),
144
+ })
145
+ .where(eq(users.id, user.id));
146
+ const updated = await getUserById(user.id);
147
+ return c.json({ user: updated, message: 'Email updated successfully' });
148
+ });
149
+ /**
150
+ * PUT /api/users/me/password
151
+ * Change user password
152
+ * OAuth-only users can set a password to enable email+password login
153
+ */
154
+ userRoutes.put('/me/password', async (c) => {
155
+ const user = c.get('user');
156
+ const db = getDb();
157
+ if (!db)
158
+ return c.json({ error: 'Database not initialized' }, 500);
159
+ const body = await c.req.json();
160
+ const { currentPassword, newPassword } = body;
161
+ // Validate new password strength
162
+ if (!newPassword || typeof newPassword !== 'string') {
163
+ return c.json({ error: 'New password is required' }, 400);
164
+ }
165
+ const passwordError = validatePasswordStrength(newPassword);
166
+ if (passwordError) {
167
+ return c.json({ error: passwordError }, 400);
168
+ }
169
+ // Get current user with password hash
170
+ const currentUser = await db
171
+ .select()
172
+ .from(users)
173
+ .where(eq(users.id, user.id))
174
+ .limit(1);
175
+ if (!currentUser.length) {
176
+ return c.json({ error: 'User not found' }, 404);
177
+ }
178
+ // If user already has a password, verify current password
179
+ if (currentUser[0].passwordHash) {
180
+ if (!currentPassword) {
181
+ return c.json({ error: 'Current password is required' }, 400);
182
+ }
183
+ const { valid } = verifyPassword(currentPassword, currentUser[0].passwordHash);
184
+ if (!valid) {
185
+ return c.json({ error: 'Current password is incorrect' }, 401);
186
+ }
187
+ }
188
+ // Note: OAuth-only users (no passwordHash) can set a password without verification
189
+ // Hash new password with scrypt
190
+ const newPasswordHash = hashPassword(newPassword);
191
+ // Update password
192
+ await db
193
+ .update(users)
194
+ .set({
195
+ passwordHash: newPasswordHash,
196
+ updatedAt: new Date(),
197
+ })
198
+ .where(eq(users.id, user.id));
199
+ return c.json({ message: 'Password updated successfully' });
200
+ });
201
+ // CONNECTED ACCOUNTS (OAuth)
202
+ /**
203
+ * GET /api/users/me/connected-accounts
204
+ * List connected OAuth accounts
205
+ */
206
+ userRoutes.get('/me/connected-accounts', async (c) => {
207
+ const user = c.get('user');
208
+ const accounts = await getUserConnectedAccounts(user.id);
209
+ // Get user to check if they have a password set
210
+ const db = getDb();
211
+ if (!db)
212
+ return c.json({ error: 'Database not initialized' }, 500);
213
+ const currentUser = await db
214
+ .select({ passwordHash: users.passwordHash })
215
+ .from(users)
216
+ .where(eq(users.id, user.id))
217
+ .limit(1);
218
+ return c.json({
219
+ accounts,
220
+ hasPassword: Boolean(currentUser[0]?.passwordHash),
221
+ canDisconnect: Boolean(currentUser[0]?.passwordHash) || accounts.length > 1,
222
+ });
223
+ });
224
+ /**
225
+ * DELETE /api/users/me/connected-accounts/:provider
226
+ * Disconnect an OAuth account
227
+ * Requires either a password to be set, or another OAuth account to exist
228
+ */
229
+ userRoutes.delete('/me/connected-accounts/:provider', async (c) => {
230
+ const user = c.get('user');
231
+ const provider = c.req.param('provider').toLowerCase();
232
+ const db = getDb();
233
+ if (!db)
234
+ return c.json({ error: 'Database not initialized' }, 500);
235
+ // Get all connected accounts
236
+ const accounts = await db
237
+ .select()
238
+ .from(oauthAccounts)
239
+ .where(eq(oauthAccounts.userId, user.id));
240
+ const accountToRemove = accounts.find((a) => a.provider === provider);
241
+ if (!accountToRemove) {
242
+ return c.json({ error: 'Account not found' }, 404);
243
+ }
244
+ // Check if user has password or other OAuth accounts
245
+ const currentUser = await db
246
+ .select({ passwordHash: users.passwordHash })
247
+ .from(users)
248
+ .where(eq(users.id, user.id))
249
+ .limit(1);
250
+ const hasPassword = Boolean(currentUser[0]?.passwordHash);
251
+ const otherAccounts = accounts.filter((a) => a.provider !== provider);
252
+ if (!hasPassword && otherAccounts.length === 0) {
253
+ return c.json({
254
+ error: 'Cannot disconnect last authentication method. Please set a password first.',
255
+ requiresPassword: true,
256
+ }, 400);
257
+ }
258
+ // Delete the OAuth account
259
+ await db.delete(oauthAccounts).where(eq(oauthAccounts.id, accountToRemove.id));
260
+ return c.json({
261
+ message: `${provider} account disconnected successfully`,
262
+ remainingAccounts: otherAccounts.length,
263
+ });
264
+ });
265
+ /**
266
+ * PUT /api/users/me/primary-email
267
+ * Set which email is the primary (login) email
268
+ * Can choose from connected OAuth account emails or manually set email
269
+ */
270
+ userRoutes.put('/me/primary-email', async (c) => {
271
+ const user = c.get('user');
272
+ const db = getDb();
273
+ if (!db)
274
+ return c.json({ error: 'Database not initialized' }, 500);
275
+ const body = await c.req.json();
276
+ const { email, source } = body; // source: 'manual' | 'github' | 'google' etc
277
+ if (!email || typeof email !== 'string') {
278
+ return c.json({ error: 'Email is required' }, 400);
279
+ }
280
+ // Basic email validation
281
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
282
+ if (!emailRegex.test(email)) {
283
+ return c.json({ error: 'Invalid email format' }, 400);
284
+ }
285
+ // If source is an OAuth provider, verify the email belongs to that account
286
+ if (source && source !== 'manual') {
287
+ const accounts = await db
288
+ .select()
289
+ .from(oauthAccounts)
290
+ .where(eq(oauthAccounts.userId, user.id));
291
+ const providerAccount = accounts.find((a) => a.provider === source);
292
+ if (!providerAccount) {
293
+ return c.json({ error: `No ${source} account connected` }, 400);
294
+ }
295
+ // Verify email matches provider data (if available)
296
+ const providerData = providerAccount.providerData;
297
+ const providerEmail = typeof providerData?.email === 'string' ? providerData.email : undefined;
298
+ if (providerEmail && providerEmail.toLowerCase() !== email.toLowerCase()) {
299
+ return c.json({ error: 'Email does not match connected account' }, 400);
300
+ }
301
+ }
302
+ // Check if email already in use by another user
303
+ const existingUser = await db
304
+ .select()
305
+ .from(users)
306
+ .where(eq(users.email, email.toLowerCase()))
307
+ .limit(1);
308
+ if (existingUser.length > 0 && existingUser[0].id !== user.id) {
309
+ return c.json({ error: 'Email already in use by another account' }, 409);
310
+ }
311
+ // Update primary email
312
+ await db
313
+ .update(users)
314
+ .set({
315
+ email: email.toLowerCase(),
316
+ updatedAt: new Date(),
317
+ })
318
+ .where(eq(users.id, user.id));
319
+ const updated = await getUserById(user.id);
320
+ return c.json({
321
+ user: updated,
322
+ message: 'Primary email updated successfully',
323
+ });
324
+ });
325
+ // PREFERENCES
326
+ /**
327
+ * GET /api/users/me/preferences
328
+ * Get user preferences
329
+ */
330
+ userRoutes.get('/me/preferences', async (c) => {
331
+ const user = c.get('user');
332
+ const db = getDb();
333
+ if (!db)
334
+ return c.json({ error: 'Database not initialized' }, 500);
335
+ const prefs = await db
336
+ .select()
337
+ .from(userPreferences)
338
+ .where(eq(userPreferences.userId, user.id))
339
+ .limit(1);
340
+ if (!prefs.length) {
341
+ // Create default preferences
342
+ const id = randomUUID();
343
+ const now = new Date();
344
+ await db.insert(userPreferences).values({
345
+ id,
346
+ userId: user.id,
347
+ updatedAt: now,
348
+ });
349
+ const created = await db
350
+ .select()
351
+ .from(userPreferences)
352
+ .where(eq(userPreferences.id, id))
353
+ .limit(1);
354
+ return c.json({ preferences: created[0] });
355
+ }
356
+ return c.json({ preferences: prefs[0] });
357
+ });
358
+ /**
359
+ * PATCH /api/users/me/preferences
360
+ * Update user preferences
361
+ */
362
+ userRoutes.patch('/me/preferences', async (c) => {
363
+ const user = c.get('user');
364
+ const db = getDb();
365
+ if (!db)
366
+ return c.json({ error: 'Database not initialized' }, 500);
367
+ const body = await c.req.json();
368
+ const allowedFields = [
369
+ 'theme',
370
+ 'accentColor',
371
+ 'fontSize',
372
+ 'emailNotifications',
373
+ 'pushNotifications',
374
+ 'notifyOnMention',
375
+ 'notifyOnAssign',
376
+ 'notifyOnComment',
377
+ 'defaultAgent',
378
+ 'aiAutoSuggest',
379
+ 'aiResponseLength',
380
+ 'editorMode',
381
+ 'tabSize',
382
+ 'extraSettings',
383
+ ];
384
+ // Filter to allowed fields only
385
+ const updates = {};
386
+ for (const field of allowedFields) {
387
+ if (body[field] !== undefined) {
388
+ updates[field] = body[field];
389
+ }
390
+ }
391
+ updates.updatedAt = new Date();
392
+ // Ensure preferences exist
393
+ const existing = await db
394
+ .select()
395
+ .from(userPreferences)
396
+ .where(eq(userPreferences.userId, user.id))
397
+ .limit(1);
398
+ if (!existing.length) {
399
+ await db.insert(userPreferences).values({
400
+ id: randomUUID(),
401
+ userId: user.id,
402
+ ...updates,
403
+ });
404
+ }
405
+ else {
406
+ await db
407
+ .update(userPreferences)
408
+ .set(updates)
409
+ .where(eq(userPreferences.userId, user.id));
410
+ }
411
+ const updated = await db
412
+ .select()
413
+ .from(userPreferences)
414
+ .where(eq(userPreferences.userId, user.id))
415
+ .limit(1);
416
+ return c.json({ preferences: updated[0] });
417
+ });
418
+ // API KEYS
419
+ /**
420
+ * GET /api/users/me/api-keys
421
+ * List user's API keys (without the actual key values)
422
+ */
423
+ userRoutes.get('/me/api-keys', async (c) => {
424
+ const user = c.get('user');
425
+ const db = getDb();
426
+ if (!db)
427
+ return c.json({ error: 'Database not initialized' }, 500);
428
+ const keys = await db
429
+ .select({
430
+ id: userApiKeys.id,
431
+ name: userApiKeys.name,
432
+ keyPrefix: userApiKeys.keyPrefix,
433
+ scopes: userApiKeys.scopes,
434
+ lastUsedAt: userApiKeys.lastUsedAt,
435
+ usageCount: userApiKeys.usageCount,
436
+ expiresAt: userApiKeys.expiresAt,
437
+ createdAt: userApiKeys.createdAt,
438
+ revokedAt: userApiKeys.revokedAt,
439
+ })
440
+ .from(userApiKeys)
441
+ .where(eq(userApiKeys.userId, user.id));
442
+ return c.json({ apiKeys: keys });
443
+ });
444
+ /**
445
+ * POST /api/users/me/api-keys
446
+ * Create a new API key
447
+ */
448
+ userRoutes.post('/me/api-keys', async (c) => {
449
+ const user = c.get('user');
450
+ const db = getDb();
451
+ if (!db)
452
+ return c.json({ error: 'Database not initialized' }, 500);
453
+ const body = await c.req.json();
454
+ const { name, scopes = ['read'], expiresInDays } = body;
455
+ if (!name || typeof name !== 'string') {
456
+ return c.json({ error: 'Name is required' }, 400);
457
+ }
458
+ // Generate API key
459
+ const rawKey = `profclaw_${randomBytes(24).toString('hex')}`;
460
+ const keyPrefix = rawKey.slice(0, 14) + '...';
461
+ const keyHash = createHash('sha256').update(rawKey).digest('hex');
462
+ const id = randomUUID();
463
+ const now = new Date();
464
+ const expiresAt = expiresInDays
465
+ ? new Date(now.getTime() + expiresInDays * 24 * 60 * 60 * 1000)
466
+ : null;
467
+ await db.insert(userApiKeys).values({
468
+ id,
469
+ userId: user.id,
470
+ name,
471
+ keyHash,
472
+ keyPrefix,
473
+ scopes,
474
+ expiresAt,
475
+ createdAt: now,
476
+ });
477
+ // Return the full key ONLY on creation (it won't be retrievable later)
478
+ return c.json({
479
+ apiKey: {
480
+ id,
481
+ name,
482
+ key: rawKey, // Only returned once!
483
+ keyPrefix,
484
+ scopes,
485
+ expiresAt,
486
+ createdAt: now,
487
+ },
488
+ message: 'Save this key securely - it will not be shown again',
489
+ });
490
+ });
491
+ /**
492
+ * DELETE /api/users/me/api-keys/:keyId
493
+ * Revoke an API key
494
+ */
495
+ userRoutes.delete('/me/api-keys/:keyId', async (c) => {
496
+ const user = c.get('user');
497
+ const keyId = c.req.param('keyId');
498
+ const db = getDb();
499
+ if (!db)
500
+ return c.json({ error: 'Database not initialized' }, 500);
501
+ // Verify ownership
502
+ const key = await db
503
+ .select()
504
+ .from(userApiKeys)
505
+ .where(eq(userApiKeys.id, keyId))
506
+ .limit(1);
507
+ if (!key.length || key[0].userId !== user.id) {
508
+ return c.json({ error: 'API key not found' }, 404);
509
+ }
510
+ // Mark as revoked
511
+ await db
512
+ .update(userApiKeys)
513
+ .set({ revokedAt: new Date() })
514
+ .where(eq(userApiKeys.id, keyId));
515
+ return c.json({ message: 'API key revoked' });
516
+ });
517
+ // SESSIONS
518
+ /**
519
+ * GET /api/users/me/sessions
520
+ * List active sessions
521
+ */
522
+ userRoutes.get('/me/sessions', async (c) => {
523
+ const user = c.get('user');
524
+ const db = getDb();
525
+ if (!db)
526
+ return c.json({ error: 'Database not initialized' }, 500);
527
+ const currentToken = getCookie(c, 'profclaw_session');
528
+ const userSessions = await db
529
+ .select({
530
+ id: sessions.id,
531
+ userAgent: sessions.userAgent,
532
+ ipAddress: sessions.ipAddress,
533
+ deviceName: sessions.deviceName,
534
+ createdAt: sessions.createdAt,
535
+ lastActiveAt: sessions.lastActiveAt,
536
+ expiresAt: sessions.expiresAt,
537
+ token: sessions.token,
538
+ })
539
+ .from(sessions)
540
+ .where(eq(sessions.userId, user.id));
541
+ const sessionsWithCurrent = userSessions.map((s) => ({
542
+ id: s.id,
543
+ userAgent: s.userAgent,
544
+ ipAddress: s.ipAddress,
545
+ deviceName: s.deviceName,
546
+ createdAt: s.createdAt,
547
+ lastActiveAt: s.lastActiveAt,
548
+ expiresAt: s.expiresAt,
549
+ isCurrent: s.token === currentToken,
550
+ }));
551
+ return c.json({ sessions: sessionsWithCurrent });
552
+ });
553
+ /**
554
+ * DELETE /api/users/me/sessions/:sessionId
555
+ * Revoke a specific session
556
+ */
557
+ userRoutes.delete('/me/sessions/:sessionId', async (c) => {
558
+ const user = c.get('user');
559
+ const sessionId = c.req.param('sessionId');
560
+ const db = getDb();
561
+ if (!db)
562
+ return c.json({ error: 'Database not initialized' }, 500);
563
+ // Verify ownership
564
+ const session = await db
565
+ .select()
566
+ .from(sessions)
567
+ .where(eq(sessions.id, sessionId))
568
+ .limit(1);
569
+ if (!session.length || session[0].userId !== user.id) {
570
+ return c.json({ error: 'Session not found' }, 404);
571
+ }
572
+ await db.delete(sessions).where(eq(sessions.id, sessionId));
573
+ return c.json({ message: 'Session revoked' });
574
+ });
575
+ /**
576
+ * DELETE /api/users/me/sessions
577
+ * Revoke all sessions except current
578
+ */
579
+ userRoutes.delete('/me/sessions', async (c) => {
580
+ const user = c.get('user');
581
+ const currentToken = getCookie(c, 'profclaw_session');
582
+ const db = getDb();
583
+ if (!db)
584
+ return c.json({ error: 'Database not initialized' }, 500);
585
+ // Get all sessions except current
586
+ const userSessions = await db
587
+ .select()
588
+ .from(sessions)
589
+ .where(eq(sessions.userId, user.id));
590
+ let revokedCount = 0;
591
+ for (const session of userSessions) {
592
+ if (session.token !== currentToken) {
593
+ await db.delete(sessions).where(eq(sessions.id, session.id));
594
+ revokedCount++;
595
+ }
596
+ }
597
+ return c.json({ message: `Revoked ${revokedCount} sessions` });
598
+ });
599
+ // ONBOARDING
600
+ /**
601
+ * POST /api/users/me/complete-onboarding
602
+ * Mark onboarding as complete
603
+ */
604
+ userRoutes.post('/me/complete-onboarding', async (c) => {
605
+ const user = c.get('user');
606
+ const db = getDb();
607
+ if (!db)
608
+ return c.json({ error: 'Database not initialized' }, 500);
609
+ await db
610
+ .update(users)
611
+ .set({ onboardingCompleted: true, updatedAt: new Date() })
612
+ .where(eq(users.id, user.id));
613
+ return c.json({ message: 'Onboarding completed' });
614
+ });
615
+ // RECOVERY CODES
616
+ /**
617
+ * POST /api/users/me/recovery-codes/regenerate
618
+ * Regenerate recovery codes (invalidates all existing codes)
619
+ * Returns new codes ONLY ONCE - they cannot be retrieved again
620
+ */
621
+ userRoutes.post('/me/recovery-codes/regenerate', async (c) => {
622
+ const user = c.get('user');
623
+ const db = getDb();
624
+ if (!db)
625
+ return c.json({ error: 'Database not initialized' }, 500);
626
+ try {
627
+ // Generate new recovery codes
628
+ const recoveryCodes = generateRecoveryCodes(8);
629
+ const hashedRecoveryCodes = hashRecoveryCodes(recoveryCodes);
630
+ // Update user with new hashed codes (invalidates old ones)
631
+ await db
632
+ .update(users)
633
+ .set({
634
+ recoveryCodes: JSON.stringify(hashedRecoveryCodes),
635
+ updatedAt: new Date(),
636
+ })
637
+ .where(eq(users.id, user.id));
638
+ return c.json({
639
+ success: true,
640
+ recoveryCodes,
641
+ message: 'New recovery codes generated. Save these codes securely - they will not be shown again!',
642
+ });
643
+ }
644
+ catch (error) {
645
+ console.error('[Users] Recovery code regeneration error:', error);
646
+ return c.json({ error: 'Failed to regenerate recovery codes' }, 500);
647
+ }
648
+ });
649
+ /**
650
+ * GET /api/users/me/recovery-codes/count
651
+ * Get the count of remaining recovery codes (without exposing the codes)
652
+ */
653
+ userRoutes.get('/me/recovery-codes/count', async (c) => {
654
+ const user = c.get('user');
655
+ const db = getDb();
656
+ if (!db)
657
+ return c.json({ error: 'Database not initialized' }, 500);
658
+ try {
659
+ const result = await db
660
+ .select({ recoveryCodes: users.recoveryCodes })
661
+ .from(users)
662
+ .where(eq(users.id, user.id))
663
+ .limit(1);
664
+ if (!result.length) {
665
+ return c.json({ error: 'User not found' }, 404);
666
+ }
667
+ const storedCodes = result[0].recoveryCodes;
668
+ const count = storedCodes ? JSON.parse(storedCodes).length : 0;
669
+ return c.json({
670
+ remainingCodes: count,
671
+ hasRecoveryCodes: count > 0,
672
+ });
673
+ }
674
+ catch (error) {
675
+ console.error('[Users] Recovery code count error:', error);
676
+ return c.json({ error: 'Failed to get recovery code count' }, 500);
677
+ }
678
+ });
679
+ // ADMIN: USER MANAGEMENT
680
+ /**
681
+ * Middleware to require admin role
682
+ */
683
+ async function requireAdmin(c, next) {
684
+ const user = c.get('user');
685
+ if (user.role !== 'admin') {
686
+ return c.json({ error: 'Admin access required' }, 403);
687
+ }
688
+ await next();
689
+ }
690
+ /**
691
+ * GET /api/users/admin/list
692
+ * List all users (admin only)
693
+ */
694
+ userRoutes.get('/admin/list', requireAdmin, async (c) => {
695
+ const db = getDb();
696
+ if (!db)
697
+ return c.json({ error: 'Database not initialized' }, 500);
698
+ try {
699
+ const allUsers = await db
700
+ .select({
701
+ id: users.id,
702
+ email: users.email,
703
+ name: users.name,
704
+ role: users.role,
705
+ status: users.status,
706
+ avatarUrl: users.avatarUrl,
707
+ createdAt: users.createdAt,
708
+ updatedAt: users.updatedAt,
709
+ onboardingCompleted: users.onboardingCompleted,
710
+ })
711
+ .from(users)
712
+ .orderBy(users.createdAt);
713
+ return c.json({ users: allUsers, total: allUsers.length });
714
+ }
715
+ catch (error) {
716
+ console.error('[Admin] List users error:', error);
717
+ return c.json({ error: 'Failed to list users' }, 500);
718
+ }
719
+ });
720
+ // ADMIN: INVITE CODES (must be before /:userId to avoid route shadowing)
721
+ /**
722
+ * POST /api/users/admin/invites
723
+ * Generate invite code(s) (admin only)
724
+ */
725
+ userRoutes.post('/admin/invites', requireAdmin, async (c) => {
726
+ const user = c.get('user');
727
+ const db = getDb();
728
+ if (!db)
729
+ return c.json({ error: 'Database not initialized' }, 500);
730
+ try {
731
+ const body = await c.req.json();
732
+ const count = Math.min(Math.max(body.count || 1, 1), 50);
733
+ const label = body.label || null;
734
+ let expiresAt = null;
735
+ if (body.expiresInDays) {
736
+ expiresAt = new Date(Date.now() + body.expiresInDays * 24 * 60 * 60 * 1000);
737
+ }
738
+ const codes = [];
739
+ for (let i = 0; i < count; i++) {
740
+ const code = generateInviteCode();
741
+ const codeHash = hashInviteCode(code);
742
+ const id = randomUUID();
743
+ await db.insert(inviteCodes).values({
744
+ id,
745
+ codeHash,
746
+ createdBy: user.id,
747
+ expiresAt,
748
+ createdAt: new Date(),
749
+ label,
750
+ });
751
+ codes.push({ id, code, expiresAt });
752
+ }
753
+ return c.json({
754
+ codes,
755
+ message: `Generated ${count} invite code(s)`,
756
+ });
757
+ }
758
+ catch (err) {
759
+ console.error('[Admin] Generate invites error:', err);
760
+ return c.json({ error: 'Failed to generate invite codes' }, 500);
761
+ }
762
+ });
763
+ /**
764
+ * GET /api/users/admin/invites
765
+ * List invite codes (admin only)
766
+ */
767
+ userRoutes.get('/admin/invites', requireAdmin, async (c) => {
768
+ const db = getDb();
769
+ if (!db)
770
+ return c.json({ error: 'Database not initialized' }, 500);
771
+ try {
772
+ const allInvites = await db
773
+ .select({
774
+ id: inviteCodes.id,
775
+ createdBy: inviteCodes.createdBy,
776
+ usedBy: inviteCodes.usedBy,
777
+ usedAt: inviteCodes.usedAt,
778
+ expiresAt: inviteCodes.expiresAt,
779
+ createdAt: inviteCodes.createdAt,
780
+ label: inviteCodes.label,
781
+ })
782
+ .from(inviteCodes)
783
+ .orderBy(inviteCodes.createdAt);
784
+ return c.json({ invites: allInvites, total: allInvites.length });
785
+ }
786
+ catch (err) {
787
+ console.error('[Admin] List invites error:', err);
788
+ return c.json({ error: 'Failed to list invite codes' }, 500);
789
+ }
790
+ });
791
+ /**
792
+ * DELETE /api/users/admin/invites/:id
793
+ * Revoke/delete an invite code (admin only)
794
+ */
795
+ userRoutes.delete('/admin/invites/:id', requireAdmin, async (c) => {
796
+ const inviteId = c.req.param('id');
797
+ const db = getDb();
798
+ if (!db)
799
+ return c.json({ error: 'Database not initialized' }, 500);
800
+ try {
801
+ const existing = await db
802
+ .select()
803
+ .from(inviteCodes)
804
+ .where(eq(inviteCodes.id, inviteId))
805
+ .limit(1);
806
+ if (!existing.length) {
807
+ return c.json({ error: 'Invite code not found' }, 404);
808
+ }
809
+ await db.delete(inviteCodes).where(eq(inviteCodes.id, inviteId));
810
+ return c.json({ message: 'Invite code deleted' });
811
+ }
812
+ catch (err) {
813
+ console.error('[Admin] Delete invite error:', err);
814
+ return c.json({ error: 'Failed to delete invite code' }, 500);
815
+ }
816
+ });
817
+ // ADMIN: REGISTRATION MODE (must be before /:userId to avoid route shadowing)
818
+ /**
819
+ * GET /api/users/admin/registration-mode
820
+ * Get current registration mode (admin only)
821
+ */
822
+ userRoutes.get('/admin/registration-mode', requireAdmin, async (c) => {
823
+ try {
824
+ const settings = await getSettingsRaw();
825
+ return c.json({ mode: settings.system.registrationMode });
826
+ }
827
+ catch (err) {
828
+ console.error('[Admin] Get registration mode error:', err);
829
+ return c.json({ error: 'Failed to get registration mode' }, 500);
830
+ }
831
+ });
832
+ /**
833
+ * PATCH /api/users/admin/registration-mode
834
+ * Set registration mode (admin only)
835
+ */
836
+ userRoutes.patch('/admin/registration-mode', requireAdmin, async (c) => {
837
+ try {
838
+ const body = await c.req.json();
839
+ const { mode } = body;
840
+ if (mode !== 'open' && mode !== 'invite') {
841
+ return c.json({ error: 'Mode must be "open" or "invite"' }, 400);
842
+ }
843
+ await updateSettings({
844
+ system: { registrationMode: mode },
845
+ });
846
+ return c.json({ mode, message: `Registration mode set to ${mode}` });
847
+ }
848
+ catch (err) {
849
+ console.error('[Admin] Set registration mode error:', err);
850
+ return c.json({ error: 'Failed to set registration mode' }, 500);
851
+ }
852
+ });
853
+ // ADMIN: USER CRUD (/:userId wildcard routes - must be AFTER specific routes)
854
+ /**
855
+ * GET /api/users/admin/:userId
856
+ * Get user details (admin only)
857
+ */
858
+ userRoutes.get('/admin/:userId', requireAdmin, async (c) => {
859
+ const userId = c.req.param('userId');
860
+ const db = getDb();
861
+ if (!db)
862
+ return c.json({ error: 'Database not initialized' }, 500);
863
+ try {
864
+ const result = await db
865
+ .select({
866
+ id: users.id,
867
+ email: users.email,
868
+ name: users.name,
869
+ role: users.role,
870
+ status: users.status,
871
+ avatarUrl: users.avatarUrl,
872
+ createdAt: users.createdAt,
873
+ updatedAt: users.updatedAt,
874
+ onboardingCompleted: users.onboardingCompleted,
875
+ })
876
+ .from(users)
877
+ .where(eq(users.id, userId))
878
+ .limit(1);
879
+ if (!result.length) {
880
+ return c.json({ error: 'User not found' }, 404);
881
+ }
882
+ // Get session count
883
+ const userSessions = await db
884
+ .select()
885
+ .from(sessions)
886
+ .where(eq(sessions.userId, userId));
887
+ return c.json({ user: result[0], activeSessions: userSessions.length });
888
+ }
889
+ catch (error) {
890
+ console.error('[Admin] Get user error:', error);
891
+ return c.json({ error: 'Failed to get user' }, 500);
892
+ }
893
+ });
894
+ /**
895
+ * PATCH /api/users/admin/:userId
896
+ * Update user (admin only)
897
+ */
898
+ userRoutes.patch('/admin/:userId', requireAdmin, async (c) => {
899
+ const userId = c.req.param('userId');
900
+ const db = getDb();
901
+ if (!db)
902
+ return c.json({ error: 'Database not initialized' }, 500);
903
+ try {
904
+ const body = await c.req.json();
905
+ const { name, role, status } = body;
906
+ // Validate role if provided
907
+ if (role && !['admin', 'user'].includes(role)) {
908
+ return c.json({ error: 'Invalid role' }, 400);
909
+ }
910
+ // Validate status if provided
911
+ if (status && !['active', 'suspended', 'pending'].includes(status)) {
912
+ return c.json({ error: 'Invalid status' }, 400);
913
+ }
914
+ await db
915
+ .update(users)
916
+ .set({
917
+ ...(name !== undefined && { name }),
918
+ ...(role !== undefined && { role }),
919
+ ...(status !== undefined && { status }),
920
+ updatedAt: new Date(),
921
+ })
922
+ .where(eq(users.id, userId));
923
+ return c.json({ message: 'User updated' });
924
+ }
925
+ catch (error) {
926
+ console.error('[Admin] Update user error:', error);
927
+ return c.json({ error: 'Failed to update user' }, 500);
928
+ }
929
+ });
930
+ /**
931
+ * POST /api/users/admin/:userId/reset-password
932
+ * Reset user password (admin only) - generates temporary password
933
+ */
934
+ userRoutes.post('/admin/:userId/reset-password', requireAdmin, async (c) => {
935
+ const userId = c.req.param('userId');
936
+ const db = getDb();
937
+ if (!db)
938
+ return c.json({ error: 'Database not initialized' }, 500);
939
+ try {
940
+ // Generate a temporary password
941
+ const tempPassword = randomBytes(8).toString('hex');
942
+ const passwordHash = hashPassword(tempPassword);
943
+ // Generate new recovery codes
944
+ const recoveryCodes = generateRecoveryCodes(8);
945
+ const hashedRecoveryCodes = hashRecoveryCodes(recoveryCodes);
946
+ await db
947
+ .update(users)
948
+ .set({
949
+ passwordHash,
950
+ recoveryCodes: JSON.stringify(hashedRecoveryCodes),
951
+ updatedAt: new Date(),
952
+ })
953
+ .where(eq(users.id, userId));
954
+ // Invalidate all sessions for this user
955
+ await db.delete(sessions).where(eq(sessions.userId, userId));
956
+ return c.json({
957
+ message: 'Password reset successfully',
958
+ temporaryPassword: tempPassword,
959
+ recoveryCodes,
960
+ note: 'User must change password on next login. All sessions have been revoked.',
961
+ });
962
+ }
963
+ catch (error) {
964
+ console.error('[Admin] Reset password error:', error);
965
+ return c.json({ error: 'Failed to reset password' }, 500);
966
+ }
967
+ });
968
+ /**
969
+ * DELETE /api/users/admin/:userId
970
+ * Delete user (admin only)
971
+ */
972
+ userRoutes.delete('/admin/:userId', requireAdmin, async (c) => {
973
+ const adminUser = c.get('user');
974
+ const userId = c.req.param('userId');
975
+ const db = getDb();
976
+ if (!db)
977
+ return c.json({ error: 'Database not initialized' }, 500);
978
+ // Prevent self-deletion
979
+ if (userId === adminUser.id) {
980
+ return c.json({ error: 'Cannot delete your own account' }, 400);
981
+ }
982
+ try {
983
+ // Delete user sessions first
984
+ await db.delete(sessions).where(eq(sessions.userId, userId));
985
+ // Delete user preferences
986
+ await db.delete(userPreferences).where(eq(userPreferences.userId, userId));
987
+ // Delete user API keys
988
+ await db.delete(userApiKeys).where(eq(userApiKeys.userId, userId));
989
+ // Delete user
990
+ await db.delete(users).where(eq(users.id, userId));
991
+ return c.json({ message: 'User deleted' });
992
+ }
993
+ catch (error) {
994
+ console.error('[Admin] Delete user error:', error);
995
+ return c.json({ error: 'Failed to delete user' }, 500);
996
+ }
997
+ });
998
+ //# sourceMappingURL=users.js.map