profclaw 2.0.0 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (477) hide show
  1. package/.env.example +14 -2
  2. package/CHANGELOG.md +37 -0
  3. package/CONTRIBUTING.md +20 -0
  4. package/Dockerfile +39 -23
  5. package/README.md +174 -40
  6. package/dist/agents/agent-summary.d.ts +44 -0
  7. package/dist/agents/agent-summary.js +176 -0
  8. package/dist/agents/auto-memory.d.ts +59 -0
  9. package/dist/agents/auto-memory.js +310 -0
  10. package/dist/agents/checkpoint-manager.d.ts +76 -0
  11. package/dist/agents/checkpoint-manager.js +156 -0
  12. package/dist/agents/circuit-breaker.d.ts +54 -0
  13. package/dist/agents/circuit-breaker.js +153 -0
  14. package/dist/agents/context-compactor.d.ts +70 -0
  15. package/dist/agents/context-compactor.js +361 -0
  16. package/dist/agents/conversation-branch.d.ts +55 -0
  17. package/dist/agents/conversation-branch.js +115 -0
  18. package/dist/agents/error-recovery.d.ts +44 -0
  19. package/dist/agents/error-recovery.js +197 -0
  20. package/dist/agents/events.d.ts +76 -0
  21. package/dist/agents/events.js +8 -0
  22. package/dist/agents/executor.d.ts +35 -1
  23. package/dist/agents/executor.js +573 -124
  24. package/dist/agents/file-snapshots.d.ts +72 -0
  25. package/dist/agents/file-snapshots.js +182 -0
  26. package/dist/agents/index.d.ts +2 -0
  27. package/dist/agents/orchestrator.d.ts +183 -0
  28. package/dist/agents/orchestrator.js +495 -0
  29. package/dist/agents/permissions.d.ts +63 -0
  30. package/dist/agents/permissions.js +138 -0
  31. package/dist/agents/plan-mode.d.ts +71 -0
  32. package/dist/agents/plan-mode.js +186 -0
  33. package/dist/agents/prompt-suggestions.d.ts +33 -0
  34. package/dist/agents/prompt-suggestions.js +208 -0
  35. package/dist/agents/rate-limit-monitor.d.ts +56 -0
  36. package/dist/agents/rate-limit-monitor.js +224 -0
  37. package/dist/agents/result-store.d.ts +37 -0
  38. package/dist/agents/result-store.js +104 -0
  39. package/dist/agents/session-diff.d.ts +43 -0
  40. package/dist/agents/session-diff.js +258 -0
  41. package/dist/agents/tool-loader.d.ts +65 -0
  42. package/dist/agents/tool-loader.js +273 -0
  43. package/dist/agents/transcript.d.ts +96 -0
  44. package/dist/agents/transcript.js +267 -0
  45. package/dist/agents/worktree-manager.d.ts +80 -0
  46. package/dist/agents/worktree-manager.js +203 -0
  47. package/dist/auth/middleware.js +14 -0
  48. package/dist/chat/agentic-executor.d.ts +7 -0
  49. package/dist/chat/agentic-executor.js +253 -30
  50. package/dist/chat/conversations.d.ts +2 -0
  51. package/dist/chat/conversations.js +8 -0
  52. package/dist/chat/execution/executor.d.ts +8 -0
  53. package/dist/chat/execution/executor.js +157 -103
  54. package/dist/chat/execution/index.js +5 -1
  55. package/dist/chat/execution/tool-router.js +40 -14
  56. package/dist/chat/execution/tools/canvas.d.ts +2 -2
  57. package/dist/chat/execution/tools/code-tools.d.ts +66 -0
  58. package/dist/chat/execution/tools/code-tools.js +353 -0
  59. package/dist/chat/execution/tools/complete-task.d.ts +2 -2
  60. package/dist/chat/execution/tools/cron-tool.d.ts +26 -10
  61. package/dist/chat/execution/tools/cron-tool.js +48 -3
  62. package/dist/chat/execution/tools/decompose-task.d.ts +58 -0
  63. package/dist/chat/execution/tools/decompose-task.js +166 -0
  64. package/dist/chat/execution/tools/exec.d.ts +5 -2
  65. package/dist/chat/execution/tools/exec.js +294 -155
  66. package/dist/chat/execution/tools/feed-tools.d.ts +77 -0
  67. package/dist/chat/execution/tools/feed-tools.js +142 -0
  68. package/dist/chat/execution/tools/file-ops.d.ts +1 -1
  69. package/dist/chat/execution/tools/github.d.ts +2 -2
  70. package/dist/chat/execution/tools/index.d.ts +14 -2
  71. package/dist/chat/execution/tools/index.js +86 -12
  72. package/dist/chat/execution/tools/integrations.d.ts +8 -8
  73. package/dist/chat/execution/tools/multi-patch.d.ts +53 -0
  74. package/dist/chat/execution/tools/multi-patch.js +373 -0
  75. package/dist/chat/execution/tools/openai-image-gen.d.ts +2 -2
  76. package/dist/chat/execution/tools/plan-tools.d.ts +80 -0
  77. package/dist/chat/execution/tools/plan-tools.js +134 -0
  78. package/dist/chat/execution/tools/profclaw-ops.d.ts +6 -6
  79. package/dist/chat/execution/tools/repl-tool.d.ts +46 -0
  80. package/dist/chat/execution/tools/repl-tool.js +207 -0
  81. package/dist/chat/execution/tools/sessions-send.d.ts +2 -2
  82. package/dist/chat/execution/tools/slack-actions.d.ts +2 -2
  83. package/dist/chat/execution/tools/system.d.ts +4 -4
  84. package/dist/chat/execution/tools/todo-tool.d.ts +72 -0
  85. package/dist/chat/execution/tools/todo-tool.js +152 -0
  86. package/dist/chat/execution/tools/tool-search.d.ts +50 -0
  87. package/dist/chat/execution/tools/tool-search.js +155 -0
  88. package/dist/chat/execution/types.d.ts +21 -14
  89. package/dist/chat/execution/workflows/executor.d.ts +11 -0
  90. package/dist/chat/execution/workflows/executor.js +99 -1
  91. package/dist/chat/execution/workflows/types.d.ts +35 -2
  92. package/dist/chat/format/index.d.ts +1 -0
  93. package/dist/chat/format/index.js +1 -0
  94. package/dist/chat/format/markdown-convert.d.ts +23 -0
  95. package/dist/chat/format/markdown-convert.js +149 -0
  96. package/dist/chat/index.d.ts +1 -1
  97. package/dist/chat/index.js +1 -1
  98. package/dist/chat/message-handler.js +58 -6
  99. package/dist/chat/proactive/index.d.ts +62 -0
  100. package/dist/chat/proactive/index.js +147 -0
  101. package/dist/chat/prompt-adapter.js +2 -0
  102. package/dist/chat/providers/irc/index.d.ts +2 -2
  103. package/dist/chat/providers/telegram/index.d.ts +2 -0
  104. package/dist/chat/providers/telegram/index.js +21 -2
  105. package/dist/chat/system-prompts.d.ts +3 -3
  106. package/dist/chat/system-prompts.js +116 -61
  107. package/dist/chat/tools.d.ts +6 -6
  108. package/dist/cli/commands/auth.js +64 -1
  109. package/dist/cli/commands/chat.js +1327 -138
  110. package/dist/cli/commands/doctor.js +222 -16
  111. package/dist/cli/commands/history.d.ts +3 -0
  112. package/dist/cli/commands/history.js +138 -0
  113. package/dist/cli/commands/import.d.ts +44 -0
  114. package/dist/cli/commands/import.js +526 -0
  115. package/dist/cli/commands/init.d.ts +13 -0
  116. package/dist/cli/commands/init.js +381 -0
  117. package/dist/cli/commands/onboard.js +210 -30
  118. package/dist/cli/commands/plan.d.ts +13 -0
  119. package/dist/cli/commands/plan.js +184 -0
  120. package/dist/cli/commands/serve.d.ts +7 -0
  121. package/dist/cli/commands/serve.js +77 -18
  122. package/dist/cli/commands/setup.js +84 -3
  123. package/dist/cli/commands/status.js +54 -0
  124. package/dist/cli/commands/tools.js +13 -13
  125. package/dist/cli/commands/tui.js +26 -1
  126. package/dist/cli/index.js +19 -0
  127. package/dist/cli/ink/App.d.ts +13 -0
  128. package/dist/cli/ink/App.js +6 -0
  129. package/dist/cli/ink/ChatApp.d.ts +60 -0
  130. package/dist/cli/ink/ChatApp.js +325 -0
  131. package/dist/cli/ink/DashboardApp.d.ts +3 -0
  132. package/dist/cli/ink/DashboardApp.js +143 -0
  133. package/dist/cli/ink/components/AgentStatus.d.ts +17 -0
  134. package/dist/cli/ink/components/AgentStatus.js +33 -0
  135. package/dist/cli/ink/components/ChannelList.d.ts +17 -0
  136. package/dist/cli/ink/components/ChannelList.js +33 -0
  137. package/dist/cli/ink/components/ConnectionStatus.d.ts +19 -0
  138. package/dist/cli/ink/components/ConnectionStatus.js +50 -0
  139. package/dist/cli/ink/components/CostBar.d.ts +19 -0
  140. package/dist/cli/ink/components/CostBar.js +35 -0
  141. package/dist/cli/ink/components/HookStatus.d.ts +15 -0
  142. package/dist/cli/ink/components/HookStatus.js +7 -0
  143. package/dist/cli/ink/components/PermissionPrompt.d.ts +21 -0
  144. package/dist/cli/ink/components/PermissionPrompt.js +51 -0
  145. package/dist/cli/ink/components/PlanView.d.ts +23 -0
  146. package/dist/cli/ink/components/PlanView.js +26 -0
  147. package/dist/cli/ink/components/ProviderList.d.ts +16 -0
  148. package/dist/cli/ink/components/ProviderList.js +16 -0
  149. package/dist/cli/ink/components/SessionHeader.d.ts +15 -0
  150. package/dist/cli/ink/components/SessionHeader.js +15 -0
  151. package/dist/cli/ink/components/StreamingMessage.d.ts +20 -0
  152. package/dist/cli/ink/components/StreamingMessage.js +27 -0
  153. package/dist/cli/ink/components/SuggestionBar.d.ts +15 -0
  154. package/dist/cli/ink/components/SuggestionBar.js +28 -0
  155. package/dist/cli/ink/components/SystemHealth.d.ts +20 -0
  156. package/dist/cli/ink/components/SystemHealth.js +39 -0
  157. package/dist/cli/ink/components/TaskList.d.ts +17 -0
  158. package/dist/cli/ink/components/TaskList.js +59 -0
  159. package/dist/cli/ink/components/ToolCall.d.ts +17 -0
  160. package/dist/cli/ink/components/ToolCall.js +43 -0
  161. package/dist/cli/ink/index.d.ts +23 -0
  162. package/dist/cli/ink/index.js +15 -0
  163. package/dist/cli/ink/keybindings.d.ts +35 -0
  164. package/dist/cli/ink/keybindings.js +105 -0
  165. package/dist/cli/ink/markdown-renderer.d.ts +47 -0
  166. package/dist/cli/ink/markdown-renderer.js +380 -0
  167. package/dist/cli/ink/output-styles.d.ts +39 -0
  168. package/dist/cli/ink/output-styles.js +119 -0
  169. package/dist/cli/interactive/auto-serve.d.ts +38 -0
  170. package/dist/cli/interactive/auto-serve.js +209 -0
  171. package/dist/cli/interactive/index.d.ts +25 -0
  172. package/dist/cli/interactive/index.js +23 -0
  173. package/dist/cli/interactive/picker.d.ts +28 -0
  174. package/dist/cli/interactive/picker.js +153 -0
  175. package/dist/cli/interactive/renderer.d.ts +26 -0
  176. package/dist/cli/interactive/renderer.js +555 -0
  177. package/dist/cli/interactive/repl.d.ts +14 -0
  178. package/dist/cli/interactive/repl.js +1516 -0
  179. package/dist/cli/interactive/stream-client.d.ts +59 -0
  180. package/dist/cli/interactive/stream-client.js +506 -0
  181. package/dist/cli/interactive/types.d.ts +121 -0
  182. package/dist/cli/interactive/types.js +10 -0
  183. package/dist/cli/utils/api.d.ts +9 -0
  184. package/dist/cli/utils/api.js +58 -2
  185. package/dist/cron/natural-language.d.ts +54 -0
  186. package/dist/cron/natural-language.js +569 -0
  187. package/dist/cron/scheduler.d.ts +34 -4
  188. package/dist/cron/scheduler.js +141 -9
  189. package/dist/cron/templates.d.ts +1 -1
  190. package/dist/cron/templates.js +219 -0
  191. package/dist/feeds/feed-engine.d.ts +149 -0
  192. package/dist/feeds/feed-engine.js +600 -0
  193. package/dist/feeds/index.d.ts +9 -0
  194. package/dist/feeds/index.js +8 -0
  195. package/dist/gateway/router.js +6 -1
  196. package/dist/hooks/built-in/audit-log.d.ts +11 -0
  197. package/dist/hooks/built-in/audit-log.js +84 -0
  198. package/dist/hooks/built-in/cost-warning.d.ts +10 -0
  199. package/dist/hooks/built-in/cost-warning.js +59 -0
  200. package/dist/hooks/built-in/dangerous-tool.d.ts +32 -0
  201. package/dist/hooks/built-in/dangerous-tool.js +80 -0
  202. package/dist/hooks/built-in/index.d.ts +14 -0
  203. package/dist/hooks/built-in/index.js +20 -0
  204. package/dist/hooks/index.d.ts +3 -0
  205. package/dist/hooks/index.js +6 -0
  206. package/dist/hooks/loader.d.ts +17 -0
  207. package/dist/hooks/loader.js +142 -0
  208. package/dist/hooks/registry.d.ts +62 -0
  209. package/dist/hooks/registry.js +127 -0
  210. package/dist/integrations/web-search.js +6 -3
  211. package/dist/memory/index.d.ts +1 -0
  212. package/dist/memory/index.js +2 -0
  213. package/dist/memory/memory-service.js +14 -13
  214. package/dist/memory/observational.d.ts +62 -0
  215. package/dist/memory/observational.js +396 -0
  216. package/dist/middleware/content-filter.d.ts +22 -0
  217. package/dist/middleware/content-filter.js +69 -0
  218. package/dist/middleware/request-validator.d.ts +159 -0
  219. package/dist/middleware/request-validator.js +93 -0
  220. package/dist/plugins/sdk.d.ts +22 -0
  221. package/dist/plugins/sdk.js +17 -1
  222. package/dist/projects/types.d.ts +10 -10
  223. package/dist/providers/ai-sdk.d.ts +11 -0
  224. package/dist/providers/ai-sdk.js +78 -19
  225. package/dist/providers/core/models.js +67 -1
  226. package/dist/providers/core/types.d.ts +3 -0
  227. package/dist/providers/index.d.ts +1 -0
  228. package/dist/providers/index.js +1 -0
  229. package/dist/providers/smart-router.d.ts +118 -0
  230. package/dist/providers/smart-router.js +685 -0
  231. package/dist/providers/types.d.ts +16 -16
  232. package/dist/routes/agents.js +50 -0
  233. package/dist/routes/auth.js +8 -1
  234. package/dist/routes/chat.js +259 -14
  235. package/dist/routes/costs.js +32 -0
  236. package/dist/routes/cron.js +80 -5
  237. package/dist/routes/feeds.d.ts +10 -0
  238. package/dist/routes/feeds.js +168 -0
  239. package/dist/routes/mcp.js +21 -0
  240. package/dist/routes/memory.js +130 -0
  241. package/dist/routes/skills.js +129 -0
  242. package/dist/routes/teams.d.ts +9 -0
  243. package/dist/routes/teams.js +210 -0
  244. package/dist/routes/tools.js +14 -0
  245. package/dist/routes/users.js +2 -0
  246. package/dist/server/route-loader.js +3 -1
  247. package/dist/server/stream-bridge.d.ts +19 -0
  248. package/dist/server/stream-bridge.js +38 -0
  249. package/dist/server.js +310 -36
  250. package/dist/skills/marketplace.d.ts +87 -0
  251. package/dist/skills/marketplace.js +268 -0
  252. package/dist/storage/index.d.ts +14 -0
  253. package/dist/storage/index.js +64 -3
  254. package/dist/storage/schema.d.ts +4 -4
  255. package/dist/storage/schema.js +1 -1
  256. package/dist/teams/index.d.ts +110 -0
  257. package/dist/teams/index.js +365 -0
  258. package/dist/tickets/types.d.ts +39 -39
  259. package/dist/types/summary.d.ts +5 -5
  260. package/dist/utils/auto-update.d.ts +23 -0
  261. package/dist/utils/auto-update.js +157 -0
  262. package/dist/utils/offline-detect.d.ts +55 -0
  263. package/dist/utils/offline-detect.js +121 -0
  264. package/dist/utils/pid-file.d.ts +36 -0
  265. package/dist/utils/pid-file.js +125 -0
  266. package/dist/utils/prevent-sleep.d.ts +27 -0
  267. package/dist/utils/prevent-sleep.js +95 -0
  268. package/dist/utils/sanitizer.d.ts +57 -0
  269. package/dist/utils/sanitizer.js +174 -0
  270. package/docker-compose.yml +13 -137
  271. package/package.json +31 -6
  272. package/skills/deploy-cloudflare/SKILL.md +62 -0
  273. package/skills/deploy-vercel/SKILL.md +67 -0
  274. package/skills/docker-deploy/SKILL.md +158 -0
  275. package/skills/full-stack-builder/SKILL.md +92 -0
  276. package/skills/humanizer/SKILL.md +488 -0
  277. package/skills/profclaw-assistant/SKILL.md +85 -56
  278. package/ui/dist/assets/ActivityView-Da6HQ8ws.js +1 -0
  279. package/ui/dist/assets/AgentList-H58R0kX3.js +1 -0
  280. package/ui/dist/assets/AnalyticsDashboard-B28AeRsc.js +1 -0
  281. package/ui/dist/assets/AreaChart-DwLzeAQ8.js +1 -0
  282. package/ui/dist/assets/CartesianChart-piKQsTAR.js +36 -0
  283. package/ui/dist/assets/ChatView-Dbj8rxU5.js +10 -0
  284. package/ui/dist/assets/CostsDashboard-C6F5df0F.js +1 -0
  285. package/ui/dist/assets/EstimateSelect-wga0rUKX.js +1 -0
  286. package/ui/dist/assets/FeedDashboard-Ef6FEzEf.js +1 -0
  287. package/ui/dist/assets/FloatingChatbot-0yhkUeCq.js +2 -0
  288. package/ui/dist/assets/InviteCodeManagement-tUXfx4Bc.js +2 -0
  289. package/ui/dist/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
  290. package/ui/dist/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
  291. package/ui/dist/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
  292. package/ui/dist/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
  293. package/ui/dist/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
  294. package/ui/dist/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
  295. package/ui/dist/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
  296. package/ui/dist/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
  297. package/ui/dist/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
  298. package/ui/dist/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
  299. package/ui/dist/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
  300. package/ui/dist/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
  301. package/ui/dist/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
  302. package/ui/dist/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
  303. package/ui/dist/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
  304. package/ui/dist/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
  305. package/ui/dist/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
  306. package/ui/dist/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
  307. package/ui/dist/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
  308. package/ui/dist/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
  309. package/ui/dist/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
  310. package/ui/dist/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
  311. package/ui/dist/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
  312. package/ui/dist/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
  313. package/ui/dist/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
  314. package/ui/dist/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
  315. package/ui/dist/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
  316. package/ui/dist/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
  317. package/ui/dist/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
  318. package/ui/dist/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
  319. package/ui/dist/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
  320. package/ui/dist/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
  321. package/ui/dist/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
  322. package/ui/dist/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
  323. package/ui/dist/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
  324. package/ui/dist/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
  325. package/ui/dist/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
  326. package/ui/dist/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
  327. package/ui/dist/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
  328. package/ui/dist/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
  329. package/ui/dist/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
  330. package/ui/dist/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
  331. package/ui/dist/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
  332. package/ui/dist/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
  333. package/ui/dist/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
  334. package/ui/dist/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
  335. package/ui/dist/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
  336. package/ui/dist/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
  337. package/ui/dist/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
  338. package/ui/dist/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
  339. package/ui/dist/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
  340. package/ui/dist/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
  341. package/ui/dist/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
  342. package/ui/dist/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
  343. package/ui/dist/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
  344. package/ui/dist/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
  345. package/ui/dist/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
  346. package/ui/dist/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
  347. package/ui/dist/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
  348. package/ui/dist/assets/MarketplacePage-DGrLtolR.js +1 -0
  349. package/ui/dist/assets/{ProjectDetail--gPfvATB.js → ProjectDetail-BgWvA6UP.js} +2 -2
  350. package/ui/dist/assets/ProjectIcon-TDuliqwg.js +1 -0
  351. package/ui/dist/assets/ProjectList-DXgM4187.js +1 -0
  352. package/ui/dist/assets/{Settings-1kaf7VHE.js → Settings-xA8Zhi3p.js} +3 -3
  353. package/ui/dist/assets/StatusIndicator-B8vfFAxg.js +1 -0
  354. package/ui/dist/assets/{SummaryDetail-DV3AmONk.js → SummaryDetail-eedRfTtF.js} +2 -2
  355. package/ui/dist/assets/SummaryList-CLNX2P84.js +1 -0
  356. package/ui/dist/assets/TaskDetail-BtWclNiR.js +1 -0
  357. package/ui/dist/assets/TaskList-JjODAgSc.js +1 -0
  358. package/ui/dist/assets/TeamsPage-CBK5iAyx.js +1 -0
  359. package/ui/dist/assets/TicketBoard-C9aJNNYp.js +1 -0
  360. package/ui/dist/assets/TicketDetail-CV5JmL31.js +1 -0
  361. package/ui/dist/assets/TicketList-68V4lzUz.js +1 -0
  362. package/ui/dist/assets/UserManagement-DKTb6UpE.js +2 -0
  363. package/ui/dist/assets/ViewSwitcher-BvdQht2Y.js +1 -0
  364. package/ui/dist/assets/alert-dialog-O6qBOv_f.js +1 -0
  365. package/ui/dist/assets/{archive-BsLa7brF.js → archive-CX7UvZpf.js} +1 -1
  366. package/ui/dist/assets/badge-BbfnwDJP.js +1 -0
  367. package/ui/dist/assets/{bug-CmZI7jqM.js → bug-3WX0394-.js} +1 -1
  368. package/ui/dist/assets/{calendar-Bf0t2B82.js → calendar-buq77TaS.js} +1 -1
  369. package/ui/dist/assets/{chevron-up-CoUsOvZj.js → chevron-up-4ymsBJRo.js} +1 -1
  370. package/ui/dist/assets/{circle-x-Dgw11LgT.js → circle-x-ByXtwR6Y.js} +1 -1
  371. package/ui/dist/assets/constants-CVdDh7p0.js +1 -0
  372. package/ui/dist/assets/{cpu-DiPMQICV.js → cpu-CiuoCeDY.js} +1 -1
  373. package/ui/dist/assets/{database-BwTfupDi.js → database-BWXSBg5a.js} +1 -1
  374. package/ui/dist/assets/dialog-lDg4NvMV.js +1 -0
  375. package/ui/dist/assets/dollar-sign-Dmijd6DP.js +1 -0
  376. package/ui/dist/assets/{ellipsis-UJx4Xnf6.js → ellipsis-vT-5SVIp.js} +1 -1
  377. package/ui/dist/assets/{ellipsis-vertical-DoULYEKn.js → ellipsis-vertical-B4tAX_bL.js} +1 -1
  378. package/ui/dist/assets/feature-markdown-DBo5Q7uq.js +289 -0
  379. package/ui/dist/assets/{file-code-B2UrJLwi.js → file-code-ChOWdKXf.js} +1 -1
  380. package/ui/dist/assets/{folder-open-BJi577JH.js → folder-open-CkOUbIiP.js} +1 -1
  381. package/ui/dist/assets/{funnel-PkaD_HSR.js → funnel-uZkoSPP-.js} +1 -1
  382. package/ui/dist/assets/{git-branch-C_K30am0.js → git-branch-CwvUxj7C.js} +1 -1
  383. package/ui/dist/assets/{git-commit-horizontal-IT6ecxWQ.js → git-commit-horizontal-lxPzCvhD.js} +1 -1
  384. package/ui/dist/assets/{globe-f-jjCa_g.js → globe-D_WpJdsj.js} +1 -1
  385. package/ui/dist/assets/{hash-DNEv8Elo.js → hash-CA0hJ7vh.js} +1 -1
  386. package/ui/dist/assets/{history-BQSBo_1Q.js → history-CEWMLELs.js} +1 -1
  387. package/ui/dist/assets/inbox-ehtOptTV.js +1 -0
  388. package/ui/dist/assets/{index-nS3EErDg.js → index-C1rhbml4.js} +3 -3
  389. package/ui/dist/assets/index-CR8gfCHv.js +1 -0
  390. package/ui/dist/assets/index-DVXMpWai.js +1 -0
  391. package/ui/dist/assets/index-DaDJMM2v.js +1 -0
  392. package/ui/dist/assets/index-Djdq_0xu.js +1 -0
  393. package/ui/dist/assets/index-M46Gcb8K.css +1 -0
  394. package/ui/dist/assets/index-sEBN7w8J.js +109 -0
  395. package/ui/dist/assets/layers-C6Mhf8Nk.js +1 -0
  396. package/ui/dist/assets/{layout-dashboard-CcKt1hXw.js → layout-dashboard-BRUM0kpT.js} +1 -1
  397. package/ui/dist/assets/{lightbulb-Jhp7FvbU.js → lightbulb-CN2q1O5l.js} +1 -1
  398. package/ui/dist/assets/{link-2-DdO7ostF.js → link-2-CC4E28yJ.js} +1 -1
  399. package/ui/dist/assets/markdown-renderer-C6ENbB0u.js +10 -0
  400. package/ui/dist/assets/markdown-renderer-CfVKi3_s.css +1 -0
  401. package/ui/dist/assets/{message-square-CBgH65X7.js → message-square-Bbb241am.js} +1 -1
  402. package/ui/dist/assets/package-CwT3IzFx.js +1 -0
  403. package/ui/dist/assets/{pencil-CYXCEPQh.js → pencil-CDmiHzoj.js} +1 -1
  404. package/ui/dist/assets/{play-d1ONaH0-.js → play-tjy5jMQX.js} +1 -1
  405. package/ui/dist/assets/popover-CFHZf3pE.js +1 -0
  406. package/ui/dist/assets/progress-BboUHuLf.js +1 -0
  407. package/ui/dist/assets/{rocket-DhvUetsk.js → rocket--8ZHgdXJ.js} +1 -1
  408. package/ui/dist/assets/select-n108rXny.js +1 -0
  409. package/ui/dist/assets/{send-P0r5D7td.js → send-Cu7MR2Qh.js} +1 -1
  410. package/ui/dist/assets/server-DmodxZp-.js +1 -0
  411. package/ui/dist/assets/{settings-2-ocj5uHGx.js → settings-2-CkRNqkxj.js} +1 -1
  412. package/ui/dist/assets/sheet-7aUJkyzU.js +1 -0
  413. package/ui/dist/assets/{shield-check-DfVdE34l.js → shield-check-ViI3nMKE.js} +1 -1
  414. package/ui/dist/assets/{shield-off-8l0J6R-8.js → shield-off-DN3tagkn.js} +1 -1
  415. package/ui/dist/assets/skeleton-C0E1Nfro.js +1 -0
  416. package/ui/dist/assets/{smartphone-77_g3SQn.js → smartphone-5FghiXpA.js} +1 -1
  417. package/ui/dist/assets/{square-Ckzsr3Rn.js → square-DiNSx8K7.js} +1 -1
  418. package/ui/dist/assets/star-DhdFVidS.js +1 -0
  419. package/ui/dist/assets/switch-CIgVbZqQ.js +1 -0
  420. package/ui/dist/assets/table-BC56FVMV.js +1 -0
  421. package/ui/dist/assets/{tag-C35mgoEv.js → tag-CH_vQliw.js} +1 -1
  422. package/ui/dist/assets/textarea-CxDiKFXZ.js +1 -0
  423. package/ui/dist/assets/{timer-DHJBS2w1.js → timer-CdGVTb60.js} +1 -1
  424. package/ui/dist/assets/tooltip-BuW9A5UO.js +1 -0
  425. package/ui/dist/assets/{trash-2-keO5tKPE.js → trash-2-CucZJL0N.js} +1 -1
  426. package/ui/dist/assets/trending-down-BCezC1z2.js +1 -0
  427. package/ui/dist/assets/{trending-up-BBv8KbrY.js → trending-up-C5OYX2k2.js} +1 -1
  428. package/ui/dist/assets/vendor-query-C0p7b53x.js +4 -0
  429. package/ui/dist/assets/vendor-react-Mc5_kfYG.js +12 -0
  430. package/ui/dist/assets/vendor-ui-CXPAUBFv.js +51 -0
  431. package/ui/dist/assets/{wand-sparkles-BusQ52ZK.js → wand-sparkles-BaH6pJnc.js} +1 -1
  432. package/ui/dist/assets/{wrench-02YaOSiK.js → wrench-CjxjP6ok.js} +1 -1
  433. package/ui/dist/index.html +5 -2
  434. package/ui/dist/assets/ActivityView-BeshZXmE.js +0 -1
  435. package/ui/dist/assets/AgentList-QVHeldPi.js +0 -1
  436. package/ui/dist/assets/AnalyticsDashboard-C9R97dXE.js +0 -1
  437. package/ui/dist/assets/AreaChart-B73gaiVQ.js +0 -1
  438. package/ui/dist/assets/CartesianChart-CXYL2R-A.js +0 -36
  439. package/ui/dist/assets/ChatView-qjZErlrp.js +0 -10
  440. package/ui/dist/assets/CostsDashboard-O4DCLy1i.js +0 -1
  441. package/ui/dist/assets/EstimateSelect-1hQf4Osk.js +0 -1
  442. package/ui/dist/assets/FloatingChatbot-BZBzrJxd.js +0 -2
  443. package/ui/dist/assets/InviteCodeManagement-LEoGqYeA.js +0 -2
  444. package/ui/dist/assets/ProjectIcon-Chd_ofsw.js +0 -1
  445. package/ui/dist/assets/ProjectList-BvUfVB6c.js +0 -4
  446. package/ui/dist/assets/StatusIndicator-pRfkNcdV.js +0 -1
  447. package/ui/dist/assets/SummaryList-B6kXiTxL.js +0 -1
  448. package/ui/dist/assets/TaskDetail-CV6CzbOS.js +0 -1
  449. package/ui/dist/assets/TaskList-DL7brQKd.js +0 -1
  450. package/ui/dist/assets/TicketBoard-CrkkFj7C.js +0 -1
  451. package/ui/dist/assets/TicketDetail-hnnYclpD.js +0 -1
  452. package/ui/dist/assets/TicketList-CsDAyQCL.js +0 -1
  453. package/ui/dist/assets/UserManagement-BGFQyTSr.js +0 -2
  454. package/ui/dist/assets/ViewSwitcher-CnL0OqA8.js +0 -1
  455. package/ui/dist/assets/alert-dialog-SKM6Gjz4.js +0 -7
  456. package/ui/dist/assets/badge-CVHH1a-v.js +0 -1
  457. package/ui/dist/assets/brain-6o_RHVpe.js +0 -1
  458. package/ui/dist/assets/constants-Q5Zivl-a.js +0 -1
  459. package/ui/dist/assets/dialog-BUqN9Psj.js +0 -1
  460. package/ui/dist/assets/index-BUmnwPQr.js +0 -1
  461. package/ui/dist/assets/index-BfF5G4Cw.js +0 -1
  462. package/ui/dist/assets/index-C8N375c2.js +0 -1
  463. package/ui/dist/assets/index-CuxnqVVz.css +0 -1
  464. package/ui/dist/assets/index-CzMM3QOk.js +0 -1
  465. package/ui/dist/assets/index-lJlNPFVJ.js +0 -67
  466. package/ui/dist/assets/layers-jFqVrWMD.js +0 -1
  467. package/ui/dist/assets/markdown-renderer-n1ToC4XQ.js +0 -36
  468. package/ui/dist/assets/popover-CrmZgoWu.js +0 -1
  469. package/ui/dist/assets/progress-uv4SPkL5.js +0 -1
  470. package/ui/dist/assets/select-CeQ8AHGy.js +0 -1
  471. package/ui/dist/assets/server-CVHTZB72.js +0 -1
  472. package/ui/dist/assets/sheet-DuQExSho.js +0 -1
  473. package/ui/dist/assets/skeleton-TFiFJ3nB.js +0 -1
  474. package/ui/dist/assets/switch-CAePkd6k.js +0 -1
  475. package/ui/dist/assets/table-ZjAZ7hkt.js +0 -1
  476. package/ui/dist/assets/textarea-DsVPnSgR.js +0 -1
  477. package/ui/dist/assets/tooltip-BYmQ331W.js +0 -1
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Plan Mode CLI Commands
3
+ *
4
+ * View and manage agent plans created during plan-mode sessions.
5
+ *
6
+ * Usage:
7
+ * profclaw plan list
8
+ * profclaw plan show <id>
9
+ * profclaw plan approve <id>
10
+ */
11
+ import { Command } from 'commander';
12
+ export declare function planCommands(): Command;
13
+ //# sourceMappingURL=plan.d.ts.map
@@ -0,0 +1,184 @@
1
+ /**
2
+ * Plan Mode CLI Commands
3
+ *
4
+ * View and manage agent plans created during plan-mode sessions.
5
+ *
6
+ * Usage:
7
+ * profclaw plan list
8
+ * profclaw plan show <id>
9
+ * profclaw plan approve <id>
10
+ */
11
+ import { Command } from 'commander';
12
+ import chalk from 'chalk';
13
+ import { planManager } from '../../agents/plan-mode.js';
14
+ import { createTable, formatRelativeTime, success, error, warn, truncate, } from '../utils/output.js';
15
+ // ─── Status formatting ───────────────────────────────────────────────────────
16
+ const PLAN_STATUS_COLORS = {
17
+ draft: chalk.yellow,
18
+ approved: chalk.blue,
19
+ in_progress: chalk.cyan,
20
+ completed: chalk.green,
21
+ rejected: chalk.red,
22
+ };
23
+ const STEP_STATUS_SYMBOLS = {
24
+ pending: chalk.dim('○'),
25
+ in_progress: chalk.cyan('◑'),
26
+ completed: chalk.green('●'),
27
+ skipped: chalk.gray('–'),
28
+ };
29
+ function formatPlanStatus(status) {
30
+ const colorFn = PLAN_STATUS_COLORS[status] ?? chalk.white;
31
+ return colorFn(status.toUpperCase().replace('_', ' '));
32
+ }
33
+ // ─── Command builder ─────────────────────────────────────────────────────────
34
+ export function planCommands() {
35
+ const plan = new Command('plan').description('Manage agent implementation plans');
36
+ // ── list ──────────────────────────────────────────────────────────────────
37
+ plan
38
+ .command('list')
39
+ .alias('ls')
40
+ .description('List all plans')
41
+ .option('-s, --status <status>', 'Filter by status (draft|approved|in_progress|completed|rejected)')
42
+ .option('--json', 'Output as JSON')
43
+ .action((options) => {
44
+ let plans = planManager.list();
45
+ if (options.status) {
46
+ plans = plans.filter((p) => p.status === options.status);
47
+ }
48
+ if (options.json) {
49
+ console.log(JSON.stringify(plans, null, 2));
50
+ return;
51
+ }
52
+ if (plans.length === 0) {
53
+ console.log(chalk.dim('No plans found.'));
54
+ return;
55
+ }
56
+ const table = createTable(['ID', 'Title', 'Status', 'Steps', 'Created']);
57
+ for (const p of plans) {
58
+ const doneSteps = p.steps.filter((s) => s.status === 'completed' || s.status === 'skipped').length;
59
+ table.push([
60
+ p.id.slice(0, 8),
61
+ truncate(p.title, 40),
62
+ formatPlanStatus(p.status),
63
+ `${doneSteps}/${p.steps.length}`,
64
+ formatRelativeTime(new Date(p.createdAt)),
65
+ ]);
66
+ }
67
+ console.log(table.toString());
68
+ console.log(chalk.dim(`\n${plans.length} plan(s) total`));
69
+ });
70
+ // ── show ──────────────────────────────────────────────────────────────────
71
+ plan
72
+ .command('show <id>')
73
+ .alias('get')
74
+ .description('Show plan details and step list')
75
+ .option('--json', 'Output as JSON')
76
+ .action((id, options) => {
77
+ // Support partial ID prefix matching
78
+ const allPlans = planManager.list();
79
+ const found = allPlans.find((p) => p.id === id || p.id.startsWith(id));
80
+ if (!found) {
81
+ error(`Plan not found: ${id}`);
82
+ process.exit(1);
83
+ }
84
+ if (options.json) {
85
+ console.log(JSON.stringify(found, null, 2));
86
+ return;
87
+ }
88
+ console.log('');
89
+ console.log(chalk.bold(`Plan: ${found.id}`));
90
+ console.log(`Title: ${found.title}`);
91
+ console.log(`Status: ${formatPlanStatus(found.status)}`);
92
+ console.log(`Created: ${formatRelativeTime(new Date(found.createdAt))}`);
93
+ if (found.approvedAt) {
94
+ console.log(`Approved: ${formatRelativeTime(new Date(found.approvedAt))}`);
95
+ }
96
+ if (found.completedAt) {
97
+ console.log(`Completed: ${formatRelativeTime(new Date(found.completedAt))}`);
98
+ }
99
+ if (found.rejectionReason) {
100
+ console.log(`Rejection reason: ${chalk.red(found.rejectionReason)}`);
101
+ }
102
+ if (found.taskId) {
103
+ console.log(`Task ID: ${found.taskId}`);
104
+ }
105
+ console.log('');
106
+ console.log(chalk.bold('Steps:'));
107
+ for (const step of found.steps) {
108
+ const symbol = STEP_STATUS_SYMBOLS[step.status];
109
+ const effort = step.estimatedEffort ? chalk.dim(` [${step.estimatedEffort}]`) : '';
110
+ console.log(` ${symbol} ${step.index}. ${step.description}${effort}`);
111
+ if (step.files && step.files.length > 0) {
112
+ for (const f of step.files) {
113
+ console.log(` ${chalk.dim(f)}`);
114
+ }
115
+ }
116
+ }
117
+ console.log('');
118
+ });
119
+ // ── approve ───────────────────────────────────────────────────────────────
120
+ plan
121
+ .command('approve <id>')
122
+ .description('Approve a pending plan so the agent can begin implementation')
123
+ .option('--json', 'Output as JSON')
124
+ .action((id, options) => {
125
+ const allPlans = planManager.list();
126
+ const found = allPlans.find((p) => p.id === id || p.id.startsWith(id));
127
+ if (!found) {
128
+ error(`Plan not found: ${id}`);
129
+ process.exit(1);
130
+ }
131
+ if (found.status !== 'draft') {
132
+ warn(`Plan ${found.id.slice(0, 8)} is already ${found.status}, cannot approve.`);
133
+ process.exit(1);
134
+ }
135
+ try {
136
+ const approved = planManager.approve(found.id);
137
+ if (options.json) {
138
+ console.log(JSON.stringify(approved, null, 2));
139
+ return;
140
+ }
141
+ success(`Plan approved: ${approved.id.slice(0, 8)} — "${approved.title}"`);
142
+ console.log(chalk.dim('The agent will now begin implementation.'));
143
+ }
144
+ catch (err) {
145
+ error(err instanceof Error ? err.message : 'Failed to approve plan');
146
+ process.exit(1);
147
+ }
148
+ });
149
+ // ── reject ────────────────────────────────────────────────────────────────
150
+ plan
151
+ .command('reject <id>')
152
+ .description('Reject a pending plan')
153
+ .option('-r, --reason <reason>', 'Reason for rejection')
154
+ .option('--json', 'Output as JSON')
155
+ .action((id, options) => {
156
+ const allPlans = planManager.list();
157
+ const found = allPlans.find((p) => p.id === id || p.id.startsWith(id));
158
+ if (!found) {
159
+ error(`Plan not found: ${id}`);
160
+ process.exit(1);
161
+ }
162
+ if (found.status !== 'draft') {
163
+ warn(`Plan ${found.id.slice(0, 8)} is already ${found.status}, cannot reject.`);
164
+ process.exit(1);
165
+ }
166
+ try {
167
+ const rejected = planManager.reject(found.id, options.reason);
168
+ if (options.json) {
169
+ console.log(JSON.stringify(rejected, null, 2));
170
+ return;
171
+ }
172
+ console.log(chalk.red('✗') + ` Plan rejected: ${rejected.id.slice(0, 8)}`);
173
+ if (options.reason) {
174
+ console.log(chalk.dim(`Reason: ${options.reason}`));
175
+ }
176
+ }
177
+ catch (err) {
178
+ error(err instanceof Error ? err.message : 'Failed to reject plan');
179
+ process.exit(1);
180
+ }
181
+ });
182
+ return plan;
183
+ }
184
+ //# sourceMappingURL=plan.js.map
@@ -1,3 +1,10 @@
1
1
  import { Command } from 'commander';
2
+ export declare function checkPortAvailable(port: number): Promise<boolean>;
3
+ /**
4
+ * Try to find an available port starting at `startPort`.
5
+ * Attempts up to MAX_PORT_ATTEMPTS consecutive ports.
6
+ * Returns the available port, or null if all attempts fail.
7
+ */
8
+ export declare function resolvePort(startPort: number): Promise<number | null>;
2
9
  export declare function serveCommand(): Command;
3
10
  //# sourceMappingURL=serve.d.ts.map
@@ -5,23 +5,21 @@ import { spawn } from 'child_process';
5
5
  import { resolve } from 'path';
6
6
  import { existsSync } from 'fs';
7
7
  import { createServer } from 'net';
8
+ import * as readline from 'readline';
8
9
  import { success, error, info, warn } from '../utils/output.js';
10
+ import { isServerRunning, killExistingServer } from '../../utils/pid-file.js';
9
11
  const MAX_RESTART_ATTEMPTS = 5;
12
+ const MAX_PORT_ATTEMPTS = 3;
10
13
  const BASE_BACKOFF_MS = 1000;
11
14
  const MAX_BACKOFF_MS = 30000;
12
15
  const CRASH_WINDOW_MS = 10000;
13
16
  const HEALTH_CHECK_DELAY_MS = 3000;
14
17
  const HEALTH_CHECK_TIMEOUT_MS = 5000;
15
- function checkPortAvailable(port) {
18
+ export function checkPortAvailable(port) {
16
19
  return new Promise((resolve) => {
17
20
  const server = createServer();
18
21
  server.once('error', (err) => {
19
- if (err.code === 'EADDRINUSE') {
20
- resolve(false);
21
- }
22
- else {
23
- resolve(true);
24
- }
22
+ resolve(err.code !== 'EADDRINUSE');
25
23
  });
26
24
  server.once('listening', () => {
27
25
  server.close();
@@ -30,6 +28,21 @@ function checkPortAvailable(port) {
30
28
  server.listen(port, '127.0.0.1');
31
29
  });
32
30
  }
31
+ /**
32
+ * Try to find an available port starting at `startPort`.
33
+ * Attempts up to MAX_PORT_ATTEMPTS consecutive ports.
34
+ * Returns the available port, or null if all attempts fail.
35
+ */
36
+ export async function resolvePort(startPort) {
37
+ for (let offset = 0; offset < MAX_PORT_ATTEMPTS; offset++) {
38
+ const candidate = startPort + offset;
39
+ const available = await checkPortAvailable(candidate);
40
+ if (available) {
41
+ return candidate;
42
+ }
43
+ }
44
+ return null;
45
+ }
33
46
  async function healthCheck(port) {
34
47
  try {
35
48
  const res = await fetch(`http://localhost:${port}/health`, {
@@ -58,19 +71,46 @@ export function serveCommand() {
58
71
  console.log(chalk.cyan(banner));
59
72
  console.log(chalk.dim(' AI Agent Task Orchestrator\n'));
60
73
  const port = parseInt(options.port, 10);
61
- // Pre-flight: check port availability
62
- const portAvailable = await checkPortAvailable(port);
63
- if (!portAvailable) {
64
- error(`Port ${port} is already in use.`);
65
- info('Options:');
66
- console.log(` 1. Stop the existing process: ${chalk.cyan(`lsof -ti:${port} | xargs kill`)}`);
67
- console.log(` 2. Use a different port: ${chalk.cyan(`profclaw serve -p ${port + 1}`)}`);
74
+ // Pre-flight: check for an existing server instance via PID file
75
+ const running = isServerRunning();
76
+ if (running.running && running.pid !== undefined) {
77
+ warn(`A profClaw server is already running (PID ${running.pid}, port ${running.port}).`);
78
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
79
+ const answer = await new Promise((resolve) => {
80
+ rl.question(' Kill the existing server and start a new one? [y/N] ', (ans) => {
81
+ rl.close();
82
+ resolve(ans.trim().toLowerCase());
83
+ });
84
+ });
85
+ if (answer === 'y' || answer === 'yes') {
86
+ const killed = killExistingServer();
87
+ if (killed) {
88
+ success('Existing server stopped.');
89
+ }
90
+ else {
91
+ error('Could not stop the existing server within 5 seconds. Aborting.');
92
+ process.exit(1);
93
+ }
94
+ }
95
+ else {
96
+ info('Aborted. The existing server is still running.');
97
+ process.exit(0);
98
+ }
99
+ }
100
+ // Pre-flight: find an available port (retry up to MAX_PORT_ATTEMPTS)
101
+ const actualPort = await resolvePort(port);
102
+ if (actualPort === null) {
103
+ error(`Ports ${port}–${port + MAX_PORT_ATTEMPTS - 1} are all in use.`);
104
+ info(`Free a port or specify a different one: ${chalk.cyan(`profclaw serve -p <port>`)}`);
68
105
  process.exit(1);
69
106
  }
107
+ if (actualPort !== port) {
108
+ warn(`Port ${port} in use, started on port ${actualPort}`);
109
+ }
70
110
  // Set environment variables
71
111
  const env = {
72
112
  ...process.env,
73
- PORT: options.port,
113
+ PORT: String(actualPort),
74
114
  ENABLE_CRON: options.cron === false ? 'false' : 'true',
75
115
  };
76
116
  // Determine the project root
@@ -92,7 +132,7 @@ export function serveCommand() {
92
132
  command = 'npx';
93
133
  args = ['tsx', 'src/server.ts'];
94
134
  }
95
- console.log(chalk.blue(`Starting server on port ${options.port}...\n`));
135
+ console.log(chalk.blue(`Starting server on port ${actualPort}...\n`));
96
136
  }
97
137
  const autoRestart = options.restart !== false && !options.dev;
98
138
  const state = {
@@ -154,9 +194,28 @@ export function serveCommand() {
154
194
  setTimeout(async () => {
155
195
  if (state.shuttingDown)
156
196
  return;
157
- const healthy = await healthCheck(port);
197
+ const healthy = await healthCheck(actualPort);
158
198
  if (healthy) {
159
- success(`Server healthy on port ${port}`);
199
+ success(`Server healthy on port ${actualPort}`);
200
+ // WS-1.3: detect first-run (no admin users) and print setup prompt
201
+ try {
202
+ const res = await fetch(`http://localhost:${actualPort}/`, {
203
+ redirect: 'manual',
204
+ signal: AbortSignal.timeout(HEALTH_CHECK_TIMEOUT_MS),
205
+ });
206
+ if (res.status === 302) {
207
+ const location = res.headers.get('location') || '';
208
+ if (location.includes('/setup')) {
209
+ console.log('');
210
+ console.log(chalk.yellow(' First run detected.'));
211
+ console.log(chalk.yellow(` Visit ${chalk.cyan(`http://localhost:${port}/setup`)} to configure profClaw`));
212
+ console.log('');
213
+ }
214
+ }
215
+ }
216
+ catch {
217
+ // Non-critical — ignore
218
+ }
160
219
  }
161
220
  else {
162
221
  warn('Server may not be fully ready yet. Check logs above.');
@@ -14,11 +14,13 @@ import figlet from 'figlet';
14
14
  import { select, search, input, password as passwordPrompt, confirm, Separator } from '@inquirer/prompts';
15
15
  import { randomUUID } from 'crypto';
16
16
  import { eq } from 'drizzle-orm';
17
- import { spawn } from 'child_process';
17
+ import { spawn, execFile } from 'child_process';
18
18
  import { existsSync, mkdirSync, openSync } from 'node:fs';
19
19
  import { join } from 'node:path';
20
+ import { promisify } from 'node:util';
21
+ import * as os from 'os';
20
22
  import { createServer } from 'net';
21
- import { initStorage, getDb, saveProviderConfig, loadAllProviderConfigs } from '../../storage/index.js';
23
+ import { initStorage, getDb, closeStorage, saveProviderConfig, loadAllProviderConfigs } from '../../storage/index.js';
22
24
  import { users, inviteCodes } from '../../storage/schema.js';
23
25
  import { PROVIDER_CATALOG } from '../providers.js';
24
26
  import { hashPassword, validatePasswordStrength, generateRecoveryCodes, hashRecoveryCodes, generateInviteCode, hashInviteCode, } from '../../auth/password.js';
@@ -586,6 +588,80 @@ async function stepGitHubOAuth() {
586
588
  return true;
587
589
  }
588
590
  // Step 6: Summary
591
+ const execFileAsync = promisify(execFile);
592
+ async function runQuickHealthCheck() {
593
+ const results = [];
594
+ // 1. Node.js version
595
+ const nodeVersion = process.version;
596
+ const nodeMajor = parseInt(nodeVersion.slice(1).split('.')[0], 10);
597
+ results.push({
598
+ label: 'Node.js',
599
+ status: nodeMajor >= 20 ? 'pass' : 'warn',
600
+ detail: nodeMajor >= 20 ? nodeVersion : `${nodeVersion} (v20+ recommended)`,
601
+ });
602
+ // 2. Config files
603
+ const cwd = process.cwd();
604
+ const settingsExists = existsSync(join(cwd, 'config', 'settings.yml'));
605
+ const envExists = existsSync(join(cwd, '.env'));
606
+ const configStatus = settingsExists && envExists ? 'pass' : settingsExists || envExists ? 'warn' : 'fail';
607
+ const configDetail = settingsExists && envExists
608
+ ? 'settings.yml + .env found'
609
+ : settingsExists
610
+ ? 'settings.yml found, .env missing'
611
+ : envExists
612
+ ? '.env found, settings.yml missing'
613
+ : 'settings.yml and .env not found';
614
+ results.push({ label: 'Config', status: configStatus, detail: configDetail });
615
+ // 3. Database — initStorage() already ran, so if we get here the DB is initialized
616
+ results.push({ label: 'Database', status: 'pass', detail: 'Initialized' });
617
+ // 4. Memory
618
+ const freeBytes = os.freemem();
619
+ const freeMb = freeBytes / 1024 / 1024;
620
+ const freeGb = freeBytes / 1024 / 1024 / 1024;
621
+ const memDetail = freeGb >= 1 ? `${freeGb.toFixed(1)} GB free` : `${Math.round(freeMb)} MB free`;
622
+ results.push({
623
+ label: 'Memory',
624
+ status: freeMb >= 256 ? 'pass' : 'warn',
625
+ detail: freeMb >= 256 ? memDetail : `${memDetail} (low)`,
626
+ });
627
+ // 5. Disk — df on cwd
628
+ let diskDetail = 'unavailable';
629
+ let diskStatus = 'warn';
630
+ try {
631
+ const { stdout } = await execFileAsync('df', ['-k', cwd]);
632
+ const lines = stdout.trim().split('\n');
633
+ if (lines.length >= 2) {
634
+ const parts = lines[1].trim().split(/\s+/);
635
+ // df -k columns: Filesystem 1K-blocks Used Available Use% Mounted (macOS/Linux may vary)
636
+ const availIdx = parts.length >= 4 ? (parts.length === 6 ? 3 : parts.length - 3) : -1;
637
+ const useIdx = parts.length >= 5 ? parts.length - 2 : -1;
638
+ if (availIdx !== -1 && useIdx !== -1) {
639
+ const availKb = parseInt(parts[availIdx], 10);
640
+ const usePercent = parts[useIdx];
641
+ const availGb = availKb / 1024 / 1024;
642
+ diskDetail = `${availGb.toFixed(0)} GB free (${usePercent} used)`;
643
+ diskStatus = availGb >= 1 ? 'pass' : 'warn';
644
+ }
645
+ }
646
+ }
647
+ catch { /* df not available */ }
648
+ results.push({ label: 'Disk', status: diskStatus, detail: diskDetail });
649
+ // Render
650
+ const icon = (s) => s === 'pass' ? chalk.green('\u2713') : s === 'warn' ? chalk.yellow('\u26a0') : chalk.red('\u2717');
651
+ const labelWidth = 12;
652
+ console.log('');
653
+ console.log(chalk.bold.white(' Quick Health Check'));
654
+ console.log(' ' + '\u2500'.repeat(44));
655
+ for (const r of results) {
656
+ const label = r.label.padEnd(labelWidth);
657
+ console.log(` ${icon(r.status)} ${chalk.dim(label)} ${r.detail}`);
658
+ }
659
+ console.log(' ' + '\u2500'.repeat(44));
660
+ const passed = results.filter(r => r.status === 'pass').length;
661
+ const total = results.length;
662
+ const summary = passed === total ? chalk.green(`${passed}/${total} checks passed`) : chalk.yellow(`${passed}/${total} checks passed`);
663
+ console.log(` ${summary}`);
664
+ }
589
665
  function checkPortAvailable(port) {
590
666
  return new Promise((resolve) => {
591
667
  const server = createServer();
@@ -605,6 +681,7 @@ async function showSummaryAndOffer(results) {
605
681
  console.log(` ${mark(true)} Registration: ${results.registrationMode}${results.inviteCodes.length ? ` (${results.inviteCodes.length} codes)` : ''}`);
606
682
  console.log(` ${mark(results.githubOAuth)} GitHub OAuth: ${results.githubOAuth ? 'configured' : 'skipped'}`);
607
683
  console.log(' ' + '\u2500'.repeat(44));
684
+ await runQuickHealthCheck();
608
685
  // Check if server is already running
609
686
  const portFree = await checkPortAvailable(port);
610
687
  const serverRunning = !portFree;
@@ -828,7 +905,8 @@ export function setupCommand() {
828
905
  aiProvider: options.aiProvider,
829
906
  registrationMode: options.registrationMode,
830
907
  });
831
- return;
908
+ await closeStorage();
909
+ process.exit(0);
832
910
  }
833
911
  const fromOnboard = !!options.fromOnboard;
834
912
  // Interactive mode
@@ -904,9 +982,12 @@ export function setupCommand() {
904
982
  githubOAuth,
905
983
  fromOnboard,
906
984
  });
985
+ await closeStorage();
986
+ process.exit(0);
907
987
  }
908
988
  catch (err) {
909
989
  error(err instanceof Error ? err.message : 'Setup failed');
990
+ await closeStorage();
910
991
  process.exit(1);
911
992
  }
912
993
  });
@@ -2,6 +2,25 @@ import { Command } from 'commander';
2
2
  import chalk from 'chalk';
3
3
  import { api } from '../utils/api.js';
4
4
  import { spinner } from '../utils/output.js';
5
+ import { isServerRunning } from '../../utils/pid-file.js';
6
+ function formatUptime(seconds) {
7
+ if (seconds < 60) {
8
+ return `${seconds}s`;
9
+ }
10
+ if (seconds < 3600) {
11
+ const m = Math.floor(seconds / 60);
12
+ const s = seconds % 60;
13
+ return `${m}m ${s}s`;
14
+ }
15
+ if (seconds < 86400) {
16
+ const h = Math.floor(seconds / 3600);
17
+ const m = Math.floor((seconds % 3600) / 60);
18
+ return `${h}h ${m}m`;
19
+ }
20
+ const d = Math.floor(seconds / 86400);
21
+ const h = Math.floor((seconds % 86400) / 3600);
22
+ return `${d}d ${h}h`;
23
+ }
5
24
  export function statusCommand() {
6
25
  const cmd = new Command('status')
7
26
  .description('System status overview')
@@ -35,6 +54,41 @@ export function statusCommand() {
35
54
  ? chalk.green('healthy')
36
55
  : chalk.red('unhealthy');
37
56
  console.log(`\nprofClaw v${version} | Mode: ${mode} | Status: ${statusText}\n`);
57
+ // PID / port from PID file (fast local read) or health endpoint
58
+ const pidInfo = isServerRunning();
59
+ const pid = health.data?.process?.pid ?? pidInfo.pid;
60
+ const port = health.data?.process?.port ?? pidInfo.port;
61
+ if (pid !== undefined) {
62
+ console.log(`${chalk.bold('Process')} PID ${pid}${port ? `, port ${port}` : ''}`);
63
+ }
64
+ // Uptime
65
+ if (health.data?.uptime !== undefined) {
66
+ console.log(`${chalk.bold('Uptime')} ${formatUptime(health.data.uptime)}`);
67
+ }
68
+ // SSE clients
69
+ if (health.data?.sseClients !== undefined) {
70
+ console.log(`${chalk.bold('SSE Clients')} ${health.data.sseClients}`);
71
+ }
72
+ // Active agent sessions
73
+ if (health.data?.activeSessions !== undefined) {
74
+ console.log(`${chalk.bold('Sessions')} ${health.data.activeSessions} active`);
75
+ }
76
+ // Queue depth
77
+ if (health.data?.queueDepth !== undefined) {
78
+ const q = health.data.queueDepth;
79
+ console.log(`${chalk.bold('Queue')} ${q.pending} pending, ${q.running} running`);
80
+ }
81
+ // Memory and CPU
82
+ if (health.data?.process !== undefined) {
83
+ const p = health.data.process;
84
+ const load = p.cpuLoadAvg.length > 0 ? p.cpuLoadAvg[0].toFixed(2) : '?';
85
+ console.log(`${chalk.bold('Resources')} ${p.memoryMb} MB RSS | CPU load ${load}`);
86
+ }
87
+ // Last error
88
+ if (health.data?.lastError) {
89
+ console.log(`${chalk.bold('Last error')} ${chalk.red(health.data.lastError)}`);
90
+ }
91
+ console.log('');
38
92
  if (providers.ok && providers.data) {
39
93
  const active = providers.data.providers.filter((p) => p.enabled || p.configured);
40
94
  const healthySummary = active
@@ -11,9 +11,9 @@ import { registerBuiltinTools } from '../../chat/execution/tools/index.js';
11
11
  import { getToolRegistry } from '../../chat/execution/registry.js';
12
12
  // Lazy initialization - only register tools when a tools command actually runs
13
13
  let toolsInitialized = false;
14
- function getRegistry() {
14
+ async function getRegistry() {
15
15
  if (!toolsInitialized) {
16
- registerBuiltinTools();
16
+ await registerBuiltinTools();
17
17
  toolsInitialized = true;
18
18
  }
19
19
  return getToolRegistry();
@@ -93,7 +93,7 @@ export function toolsCommands() {
93
93
  .option('--json', 'Output as JSON')
94
94
  .option('-c, --category <cat>', 'Filter by category')
95
95
  .action(async (options) => {
96
- const registry = getRegistry();
96
+ const registry = await getRegistry();
97
97
  let toolList = registry.list();
98
98
  if (options.category) {
99
99
  toolList = toolList.filter((t) => t.category === options.category);
@@ -145,7 +145,7 @@ export function toolsCommands() {
145
145
  .description('Show detailed information about a tool')
146
146
  .option('--json', 'Output as JSON')
147
147
  .action(async (name, options) => {
148
- const registry = getRegistry();
148
+ const registry = await getRegistry();
149
149
  const tool = registry.get(name);
150
150
  if (!tool) {
151
151
  error(`Tool '${name}' not found`);
@@ -192,7 +192,7 @@ export function toolsCommands() {
192
192
  .option('--json', 'Output result as JSON')
193
193
  .option('-y, --yes', 'Skip approval for moderate tools')
194
194
  .action(async (name, options) => {
195
- const registry = getRegistry();
195
+ const registry = await getRegistry();
196
196
  const tool = registry.get(name);
197
197
  if (!tool) {
198
198
  error(`Tool '${name}' not found`);
@@ -270,7 +270,7 @@ export function toolsCommands() {
270
270
  .option('--json', 'Output as JSON')
271
271
  .action(async (commandParts, options) => {
272
272
  const command = commandParts.join(' ');
273
- const registry = getRegistry();
273
+ const registry = await getRegistry();
274
274
  const tool = registry.get('exec');
275
275
  if (!tool) {
276
276
  error('exec tool not found');
@@ -308,7 +308,7 @@ export function toolsCommands() {
308
308
  .option('-s, --short', 'Short format')
309
309
  .option('-w, --workdir <path>', 'Repository path')
310
310
  .action(async (options) => {
311
- const registry = getRegistry();
311
+ const registry = await getRegistry();
312
312
  const tool = registry.get('git_status');
313
313
  if (!tool) {
314
314
  error('git_status tool not found');
@@ -332,7 +332,7 @@ export function toolsCommands() {
332
332
  .option('-t, --type <type>', 'Info type: all, cpu, memory, os, network', 'all')
333
333
  .option('--json', 'Output as JSON')
334
334
  .action(async (options) => {
335
- const registry = getRegistry();
335
+ const registry = await getRegistry();
336
336
  const tool = registry.get('system_info');
337
337
  if (!tool) {
338
338
  error('system_info tool not found');
@@ -359,7 +359,7 @@ export function toolsCommands() {
359
359
  .description('Shortcut: Show environment variables')
360
360
  .option('-f, --filter <pattern>', 'Filter by pattern')
361
361
  .action(async (name, options) => {
362
- const registry = getRegistry();
362
+ const registry = await getRegistry();
363
363
  const tool = registry.get('env');
364
364
  if (!tool) {
365
365
  error('env tool not found');
@@ -381,7 +381,7 @@ export function toolsCommands() {
381
381
  .command('which <command>')
382
382
  .description('Shortcut: Find command location')
383
383
  .action(async (command) => {
384
- const registry = getRegistry();
384
+ const registry = await getRegistry();
385
385
  const tool = registry.get('which');
386
386
  if (!tool) {
387
387
  error('which tool not found');
@@ -403,7 +403,7 @@ export function toolsCommands() {
403
403
  .description('Shortcut: Read a file')
404
404
  .option('-l, --lines <n>', 'Max lines to read', '100')
405
405
  .action(async (filePath, options) => {
406
- const registry = getRegistry();
406
+ const registry = await getRegistry();
407
407
  const tool = registry.get('read_file');
408
408
  if (!tool) {
409
409
  error('read_file tool not found');
@@ -431,7 +431,7 @@ export function toolsCommands() {
431
431
  .option('-p, --path <dir>', 'Search directory', '.')
432
432
  .option('-t, --type <type>', 'File type: file, directory, both', 'file')
433
433
  .action(async (pattern, options) => {
434
- const registry = getRegistry();
434
+ const registry = await getRegistry();
435
435
  const tool = registry.get('search_files');
436
436
  if (!tool) {
437
437
  error('search_files tool not found');
@@ -469,7 +469,7 @@ export function toolsCommands() {
469
469
  .option('-i, --ignore-case', 'Case insensitive')
470
470
  .option('-c, --context <n>', 'Context lines', '0')
471
471
  .action(async (pattern, searchPath, options) => {
472
- const registry = getRegistry();
472
+ const registry = await getRegistry();
473
473
  const tool = registry.get('grep');
474
474
  if (!tool) {
475
475
  error('grep tool not found');