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,381 @@
1
+ /**
2
+ * CLI Init Command
3
+ *
4
+ * Scans the current project directory and generates a `.profclaw/context.md`
5
+ * file describing the tech stack, structure, build/test commands, and conventions.
6
+ *
7
+ * Usage:
8
+ * profclaw init # interactive (asks before overwriting)
9
+ * profclaw init --force # overwrite without prompting
10
+ */
11
+ import { Command } from 'commander';
12
+ import { existsSync, readFileSync } from 'node:fs';
13
+ import fs from 'node:fs/promises';
14
+ import path from 'node:path';
15
+ import { execSync } from 'node:child_process';
16
+ import { confirm } from '@inquirer/prompts';
17
+ import { success, error, info, spinner } from '../utils/output.js';
18
+ // ── Manifest readers ──────────────────────────────────────────────────────────
19
+ function readJson(filePath) {
20
+ try {
21
+ return JSON.parse(readFileSync(filePath, 'utf-8'));
22
+ }
23
+ catch {
24
+ return null;
25
+ }
26
+ }
27
+ function readText(filePath) {
28
+ try {
29
+ return readFileSync(filePath, 'utf-8');
30
+ }
31
+ catch {
32
+ return null;
33
+ }
34
+ }
35
+ function fileExists(filePath) {
36
+ return existsSync(filePath);
37
+ }
38
+ // ── Detectors ─────────────────────────────────────────────────────────────────
39
+ function detectLanguage(cwd) {
40
+ if (fileExists(path.join(cwd, 'Cargo.toml')))
41
+ return 'Rust';
42
+ if (fileExists(path.join(cwd, 'go.mod')))
43
+ return 'Go';
44
+ if (fileExists(path.join(cwd, 'pyproject.toml')) || fileExists(path.join(cwd, 'setup.py')))
45
+ return 'Python';
46
+ if (fileExists(path.join(cwd, 'tsconfig.json')))
47
+ return 'TypeScript';
48
+ if (fileExists(path.join(cwd, 'package.json')))
49
+ return 'JavaScript';
50
+ if (fileExists(path.join(cwd, 'pom.xml')) || fileExists(path.join(cwd, 'build.gradle')))
51
+ return 'Java';
52
+ if (fileExists(path.join(cwd, 'mix.exs')))
53
+ return 'Elixir';
54
+ if (fileExists(path.join(cwd, 'Gemfile')))
55
+ return 'Ruby';
56
+ return 'Unknown';
57
+ }
58
+ function detectPackageManager(cwd) {
59
+ if (fileExists(path.join(cwd, 'pnpm-lock.yaml')))
60
+ return 'pnpm';
61
+ if (fileExists(path.join(cwd, 'yarn.lock')))
62
+ return 'yarn';
63
+ if (fileExists(path.join(cwd, 'bun.lockb')))
64
+ return 'bun';
65
+ if (fileExists(path.join(cwd, 'package-lock.json')))
66
+ return 'npm';
67
+ return 'npm';
68
+ }
69
+ function detectFramework(cwd, pkg) {
70
+ const deps = {
71
+ ...(pkg?.dependencies ?? {}),
72
+ ...(pkg?.devDependencies ?? {}),
73
+ };
74
+ const hasDep = (name) => name in deps;
75
+ if (hasDep('next'))
76
+ return 'Next.js';
77
+ if (hasDep('nuxt'))
78
+ return 'Nuxt';
79
+ if (hasDep('astro'))
80
+ return 'Astro';
81
+ if (hasDep('remix'))
82
+ return 'Remix';
83
+ if (hasDep('@sveltejs/kit'))
84
+ return 'SvelteKit';
85
+ if (hasDep('svelte'))
86
+ return 'Svelte';
87
+ if (hasDep('react'))
88
+ return 'React';
89
+ if (hasDep('vue'))
90
+ return 'Vue';
91
+ if (hasDep('express'))
92
+ return 'Express';
93
+ if (hasDep('fastify'))
94
+ return 'Fastify';
95
+ if (hasDep('hono'))
96
+ return 'Hono';
97
+ if (hasDep('@nestjs/core'))
98
+ return 'NestJS';
99
+ if (hasDep('commander'))
100
+ return 'CLI (commander)';
101
+ if (hasDep('ink'))
102
+ return 'CLI (ink/TUI)';
103
+ if (fileExists(path.join(cwd, 'pyproject.toml'))) {
104
+ const content = readText(path.join(cwd, 'pyproject.toml')) ?? '';
105
+ if (content.includes('fastapi'))
106
+ return 'FastAPI';
107
+ if (content.includes('flask'))
108
+ return 'Flask';
109
+ if (content.includes('django'))
110
+ return 'Django';
111
+ }
112
+ if (fileExists(path.join(cwd, 'Cargo.toml'))) {
113
+ const content = readText(path.join(cwd, 'Cargo.toml')) ?? '';
114
+ if (content.includes('axum'))
115
+ return 'Axum';
116
+ if (content.includes('actix-web'))
117
+ return 'Actix-web';
118
+ if (content.includes('rocket'))
119
+ return 'Rocket';
120
+ }
121
+ if (fileExists(path.join(cwd, 'go.mod'))) {
122
+ const content = readText(path.join(cwd, 'go.mod')) ?? '';
123
+ if (content.includes('gin-gonic'))
124
+ return 'Gin';
125
+ if (content.includes('echo'))
126
+ return 'Echo';
127
+ if (content.includes('fiber'))
128
+ return 'Fiber';
129
+ }
130
+ return 'None detected';
131
+ }
132
+ function detectBuildAndTestCommands(cwd, pkg, pm, language) {
133
+ const scripts = pkg?.scripts ?? {};
134
+ const run = (script) => `${pm} run ${script}`;
135
+ const build = scripts['build'] ? run('build') :
136
+ language === 'Rust' ? 'cargo build --release' :
137
+ language === 'Go' ? 'go build ./...' :
138
+ language === 'Python' ? (fileExists(path.join(cwd, 'pyproject.toml')) ? 'python -m build' : 'python setup.py build') :
139
+ scripts['compile'] ? run('compile') :
140
+ 'N/A';
141
+ const test = scripts['test'] ? run('test') :
142
+ language === 'Rust' ? 'cargo test' :
143
+ language === 'Go' ? 'go test ./...' :
144
+ language === 'Python' ? 'pytest' :
145
+ scripts['check'] ? run('check') :
146
+ 'N/A';
147
+ const dev = scripts['dev'] ? run('dev') :
148
+ scripts['start'] ? run('start') :
149
+ scripts['serve'] ? run('serve') :
150
+ 'N/A';
151
+ return { build, test, dev };
152
+ }
153
+ function detectKeyDirs(cwd) {
154
+ const candidates = [
155
+ { name: 'src', purpose: 'Source code' },
156
+ { name: 'app', purpose: 'Application code' },
157
+ { name: 'lib', purpose: 'Library / shared utilities' },
158
+ { name: 'packages', purpose: 'Monorepo packages' },
159
+ { name: 'apps', purpose: 'Monorepo applications' },
160
+ { name: 'tests', purpose: 'Test files' },
161
+ { name: 'test', purpose: 'Test files' },
162
+ { name: '__tests__', purpose: 'Jest test files' },
163
+ { name: 'docs', purpose: 'Documentation' },
164
+ { name: 'scripts', purpose: 'Build / utility scripts' },
165
+ { name: 'public', purpose: 'Static assets' },
166
+ { name: 'assets', purpose: 'Static assets' },
167
+ { name: 'api', purpose: 'API layer' },
168
+ { name: 'components', purpose: 'UI components' },
169
+ { name: 'pages', purpose: 'Page components / routes' },
170
+ { name: 'hooks', purpose: 'React hooks' },
171
+ { name: 'services', purpose: 'Service / business logic layer' },
172
+ { name: 'utils', purpose: 'Utility functions' },
173
+ { name: 'config', purpose: 'Configuration files' },
174
+ { name: 'migrations', purpose: 'Database migrations' },
175
+ { name: 'prisma', purpose: 'Prisma schema and migrations' },
176
+ { name: 'drizzle', purpose: 'Drizzle ORM schema' },
177
+ { name: '.github', purpose: 'GitHub Actions / workflows' },
178
+ { name: 'docker', purpose: 'Docker configuration' },
179
+ { name: 'infra', purpose: 'Infrastructure / IaC' },
180
+ { name: 'k8s', purpose: 'Kubernetes manifests' },
181
+ ];
182
+ return candidates
183
+ .filter(c => fileExists(path.join(cwd, c.name)))
184
+ .map(c => ({ path: c.name, purpose: c.purpose }));
185
+ }
186
+ function detectConventions(cwd, pkg) {
187
+ const conventions = [];
188
+ // Linting
189
+ if (fileExists(path.join(cwd, '.eslintrc.js')) ||
190
+ fileExists(path.join(cwd, '.eslintrc.json')) ||
191
+ fileExists(path.join(cwd, 'eslint.config.js')) ||
192
+ fileExists(path.join(cwd, 'eslint.config.ts'))) {
193
+ conventions.push('ESLint for linting');
194
+ }
195
+ if (fileExists(path.join(cwd, '.prettierrc')) ||
196
+ fileExists(path.join(cwd, '.prettierrc.json')) ||
197
+ fileExists(path.join(cwd, 'prettier.config.js')) ||
198
+ fileExists(path.join(cwd, 'prettier.config.ts'))) {
199
+ conventions.push('Prettier for formatting');
200
+ }
201
+ if (fileExists(path.join(cwd, 'biome.json')) || fileExists(path.join(cwd, 'biome.jsonc'))) {
202
+ conventions.push('Biome for linting and formatting');
203
+ }
204
+ // Editor config
205
+ if (fileExists(path.join(cwd, '.editorconfig'))) {
206
+ const content = readText(path.join(cwd, '.editorconfig')) ?? '';
207
+ const indentMatch = content.match(/indent_style\s*=\s*(\w+)/);
208
+ const sizeMatch = content.match(/indent_size\s*=\s*(\d+)/);
209
+ if (indentMatch && sizeMatch) {
210
+ conventions.push(`${indentMatch[1] === 'tab' ? 'Tabs' : `${sizeMatch[1]}-space`} indentation (from .editorconfig)`);
211
+ }
212
+ }
213
+ // TypeScript strictness
214
+ if (fileExists(path.join(cwd, 'tsconfig.json'))) {
215
+ const tsconfig = readJson(path.join(cwd, 'tsconfig.json'));
216
+ const co = tsconfig?.compilerOptions;
217
+ if (co?.strict === true)
218
+ conventions.push('TypeScript strict mode enabled');
219
+ if (co?.noUncheckedIndexedAccess === true)
220
+ conventions.push('noUncheckedIndexedAccess enforced');
221
+ }
222
+ // Git hooks
223
+ if (fileExists(path.join(cwd, '.husky')))
224
+ conventions.push('Husky git hooks');
225
+ // Commit conventions
226
+ if (fileExists(path.join(cwd, 'commitlint.config.js')) ||
227
+ fileExists(path.join(cwd, 'commitlint.config.ts'))) {
228
+ conventions.push('commitlint for conventional commits');
229
+ }
230
+ const scripts = pkg?.scripts ?? {};
231
+ if (scripts['lint'])
232
+ conventions.push(`Lint command: \`${scripts['lint']}\``);
233
+ if (scripts['format'])
234
+ conventions.push(`Format command: \`${scripts['format']}\``);
235
+ if (scripts['typecheck'] || scripts['type-check']) {
236
+ conventions.push(`Type-check command: \`${scripts['typecheck'] ?? scripts['type-check']}\``);
237
+ }
238
+ return conventions;
239
+ }
240
+ function detectRecentActivity(cwd) {
241
+ try {
242
+ const log = execSync('git log --oneline --no-merges -10', { cwd, encoding: 'utf-8', timeout: 5000, stdio: ['pipe', 'pipe', 'pipe'] }).trim();
243
+ if (!log)
244
+ return 'No git history found.';
245
+ return log;
246
+ }
247
+ catch {
248
+ return 'No git repository or git unavailable.';
249
+ }
250
+ }
251
+ function extractDescription(cwd, pkg) {
252
+ if (pkg?.description && typeof pkg.description === 'string' && pkg.description.trim()) {
253
+ return pkg.description.trim();
254
+ }
255
+ const readme = readText(path.join(cwd, 'README.md')) ?? readText(path.join(cwd, 'readme.md'));
256
+ if (readme) {
257
+ // Take the first non-heading paragraph (strip markdown headings)
258
+ const lines = readme.split('\n');
259
+ for (const line of lines) {
260
+ const trimmed = line.trim();
261
+ if (trimmed && !trimmed.startsWith('#') && !trimmed.startsWith('!') && trimmed.length > 20) {
262
+ return trimmed.replace(/[*_`]/g, '').slice(0, 200);
263
+ }
264
+ }
265
+ }
266
+ return 'No description found. Add one in README.md or package.json.';
267
+ }
268
+ // ── Main scan function ────────────────────────────────────────────────────────
269
+ async function scanProject(cwd) {
270
+ const pkg = readJson(path.join(cwd, 'package.json'));
271
+ const language = detectLanguage(cwd);
272
+ const pm = detectPackageManager(cwd);
273
+ const framework = detectFramework(cwd, pkg);
274
+ const { build, test, dev } = detectBuildAndTestCommands(cwd, pkg, pm, language);
275
+ const keyDirs = detectKeyDirs(cwd);
276
+ const conventions = detectConventions(cwd, pkg);
277
+ const recentActivity = detectRecentActivity(cwd);
278
+ const description = extractDescription(cwd, pkg);
279
+ const name = pkg?.name ?? path.basename(cwd);
280
+ return {
281
+ name,
282
+ description,
283
+ language,
284
+ framework,
285
+ buildCommand: build,
286
+ testCommand: test,
287
+ devCommand: dev,
288
+ keyDirs,
289
+ conventions,
290
+ recentActivity,
291
+ packageManager: pm,
292
+ };
293
+ }
294
+ // ── Context file generator ────────────────────────────────────────────────────
295
+ function generateContextMarkdown(info) {
296
+ const now = new Date().toISOString().slice(0, 10);
297
+ const structureLines = info.keyDirs.length > 0
298
+ ? info.keyDirs.map(d => `- \`${d.path}/\` — ${d.purpose}`).join('\n')
299
+ : '- No key directories detected automatically.';
300
+ const conventionLines = info.conventions.length > 0
301
+ ? info.conventions.map(c => `- ${c}`).join('\n')
302
+ : '- No convention files detected.';
303
+ return `# Project Context
304
+ > Auto-generated by \`profclaw init\` on ${now}. Edit freely — this file is yours.
305
+
306
+ ## Overview
307
+
308
+ ${info.description}
309
+
310
+ **Project name:** \`${info.name}\`
311
+
312
+ ## Tech Stack
313
+
314
+ - **Language:** ${info.language}
315
+ - **Framework:** ${info.framework}
316
+ - **Package manager:** ${info.packageManager}
317
+ - **Build:** \`${info.buildCommand}\`
318
+ - **Test:** \`${info.testCommand}\`
319
+ - **Dev server:** \`${info.devCommand}\`
320
+
321
+ ## Structure
322
+
323
+ ${structureLines}
324
+
325
+ ## Conventions
326
+
327
+ ${conventionLines}
328
+
329
+ ## Recent Activity
330
+
331
+ \`\`\`
332
+ ${info.recentActivity}
333
+ \`\`\`
334
+ `;
335
+ }
336
+ // ── Command ───────────────────────────────────────────────────────────────────
337
+ export function initCommand() {
338
+ const cmd = new Command('init')
339
+ .description('Scan the project and generate .profclaw/context.md')
340
+ .option('-f, --force', 'Overwrite existing context.md without prompting')
341
+ .option('--dir <path>', 'Project directory to scan (default: cwd)')
342
+ .action(async (options) => {
343
+ const cwd = options.dir ? path.resolve(options.dir) : process.cwd();
344
+ const outputDir = path.join(cwd, '.profclaw');
345
+ const outputPath = path.join(outputDir, 'context.md');
346
+ // Check for existing file
347
+ if (fileExists(outputPath) && !options.force) {
348
+ const overwrite = await confirm({
349
+ message: '.profclaw/context.md already exists. Overwrite?',
350
+ default: false,
351
+ });
352
+ if (!overwrite) {
353
+ info('Aborted. Use --force to overwrite without prompting.');
354
+ return;
355
+ }
356
+ }
357
+ const spin = spinner('Scanning project...').start();
358
+ try {
359
+ const projectInfo = await scanProject(cwd);
360
+ spin.stop();
361
+ const markdown = generateContextMarkdown(projectInfo);
362
+ await fs.mkdir(outputDir, { recursive: true });
363
+ await fs.writeFile(outputPath, markdown, 'utf-8');
364
+ success(`Context written to .profclaw/context.md`);
365
+ console.log('');
366
+ console.log(` Project : ${projectInfo.name}`);
367
+ console.log(` Language: ${projectInfo.language}`);
368
+ console.log(` Framework: ${projectInfo.framework}`);
369
+ console.log(` Dirs scanned: ${projectInfo.keyDirs.length}`);
370
+ console.log('');
371
+ info('Edit .profclaw/context.md to add your own notes and conventions.');
372
+ }
373
+ catch (err) {
374
+ spin.stop();
375
+ error(err instanceof Error ? err.message : 'Init failed');
376
+ process.exit(1);
377
+ }
378
+ });
379
+ return cmd;
380
+ }
381
+ //# sourceMappingURL=init.js.map
@@ -11,12 +11,40 @@
11
11
  import { Command } from 'commander';
12
12
  import chalk from 'chalk';
13
13
  import figlet from 'figlet';
14
- import { select, search, input, Separator } from '@inquirer/prompts';
14
+ import { select, search, input, confirm, Separator } from '@inquirer/prompts';
15
15
  import { existsSync, writeFileSync, readFileSync } from 'node:fs';
16
16
  import { join } from 'node:path';
17
17
  import { execSync } from 'node:child_process';
18
18
  import { success, error, info, warn, spinner } from '../utils/output.js';
19
19
  import { PROVIDER_CATALOG, PROVIDER_ENV_KEYS } from '../providers.js';
20
+ /** Returns true if an env var name should have its value masked. */
21
+ function isSensitiveKey(key) {
22
+ return key.includes('KEY') || key.includes('TOKEN') || key.includes('SECRET');
23
+ }
24
+ /** Mask an API key for display — shows first 8 chars and last 4, dots in between. */
25
+ function maskApiKey(key) {
26
+ if (key.length <= 12)
27
+ return key.slice(0, 4) + '•'.repeat(key.length - 4);
28
+ return key.slice(0, 8) + '•'.repeat(8) + key.slice(-4);
29
+ }
30
+ /** Format a generated env file for display with sensitive values masked. */
31
+ function formatEnvPreview(content) {
32
+ return content.split('\n')
33
+ .map(line => {
34
+ if (line.startsWith('#') || line.trim() === '')
35
+ return chalk.dim(` ${line}`);
36
+ const eqIndex = line.indexOf('=');
37
+ if (eqIndex === -1)
38
+ return chalk.dim(` ${line}`);
39
+ const key = line.slice(0, eqIndex);
40
+ const value = line.slice(eqIndex + 1);
41
+ if (isSensitiveKey(key)) {
42
+ return ` ${chalk.cyan(key)}=${chalk.yellow(maskApiKey(value))}`;
43
+ }
44
+ return ` ${chalk.cyan(key)}=${chalk.white(value)}`;
45
+ })
46
+ .join('\n');
47
+ }
20
48
  /** Render a step header with progress bar. */
21
49
  function stepHeader(step, total, title) {
22
50
  const barLen = 20;
@@ -148,6 +176,89 @@ function generateEnvFile(opts) {
148
176
  }
149
177
  return lines.join('\n');
150
178
  }
179
+ const KEY_FORMAT_PREFIXES = {
180
+ anthropic: 'sk-ant-',
181
+ openai: 'sk-',
182
+ groq: 'gsk_',
183
+ };
184
+ async function validateProviderKey(providerKey, apiKey) {
185
+ // Fast-fail: format check for known prefix patterns
186
+ const expectedPrefix = KEY_FORMAT_PREFIXES[providerKey];
187
+ if (expectedPrefix && !apiKey.startsWith(expectedPrefix)) {
188
+ return {
189
+ valid: false,
190
+ error: `Key should start with "${expectedPrefix}"`,
191
+ };
192
+ }
193
+ // Ollama uses a local URL, no key validation needed
194
+ if (providerKey === 'ollama') {
195
+ return { valid: true };
196
+ }
197
+ // Lightweight API call to verify the key works
198
+ try {
199
+ let response;
200
+ if (providerKey === 'anthropic') {
201
+ response = await fetch('https://api.anthropic.com/v1/messages', {
202
+ method: 'POST',
203
+ signal: AbortSignal.timeout(5000),
204
+ headers: {
205
+ 'x-api-key': apiKey,
206
+ 'anthropic-version': '2023-06-01',
207
+ 'content-type': 'application/json',
208
+ },
209
+ body: JSON.stringify({
210
+ model: 'claude-3-haiku-20240307',
211
+ max_tokens: 1,
212
+ messages: [{ role: 'user', content: 'hi' }],
213
+ }),
214
+ });
215
+ }
216
+ else if (providerKey === 'openai') {
217
+ response = await fetch('https://api.openai.com/v1/models', {
218
+ signal: AbortSignal.timeout(5000),
219
+ headers: { Authorization: `Bearer ${apiKey}` },
220
+ });
221
+ }
222
+ else if (providerKey === 'google') {
223
+ response = await fetch(`https://generativelanguage.googleapis.com/v1beta/models?key=${encodeURIComponent(apiKey)}`, { signal: AbortSignal.timeout(5000) });
224
+ }
225
+ else if (providerKey === 'groq') {
226
+ response = await fetch('https://api.groq.com/openai/v1/models', {
227
+ signal: AbortSignal.timeout(5000),
228
+ headers: { Authorization: `Bearer ${apiKey}` },
229
+ });
230
+ }
231
+ else {
232
+ // Provider not supported for live validation — skip
233
+ return { valid: true };
234
+ }
235
+ if (response.ok) {
236
+ return { valid: true };
237
+ }
238
+ // Parse error message from response body when possible
239
+ let detail;
240
+ try {
241
+ const body = (await response.json());
242
+ detail = body?.error?.message ?? (typeof body?.message === 'string' ? body.message : undefined);
243
+ }
244
+ catch {
245
+ // ignore parse failure
246
+ }
247
+ return {
248
+ valid: false,
249
+ error: detail ?? `HTTP ${response.status}`,
250
+ };
251
+ }
252
+ catch (err) {
253
+ if (err instanceof Error && err.name === 'TimeoutError') {
254
+ return { valid: false, error: 'Request timed out (5s)' };
255
+ }
256
+ return {
257
+ valid: false,
258
+ error: err instanceof Error ? err.message : 'Network error',
259
+ };
260
+ }
261
+ }
151
262
  // Interactive Onboarding
152
263
  async function runInteractive() {
153
264
  const banner = figlet.textSync('profClaw', { font: 'Standard' });
@@ -364,28 +475,56 @@ async function runInteractive() {
364
475
  success(`${chosen.name} already configured from ${chosen.envVar}`);
365
476
  }
366
477
  else {
367
- try {
368
- const keyInput = await input({
369
- message: chosen.envVar,
370
- theme: { prefix: ' ' },
371
- });
372
- if (keyInput) {
478
+ let configured = false;
479
+ while (!configured) {
480
+ let keyInput;
481
+ try {
482
+ keyInput = await input({
483
+ message: chosen.envVar,
484
+ theme: { prefix: ' ' },
485
+ });
486
+ }
487
+ catch {
488
+ warn('Input cancelled, skipping provider.');
489
+ break;
490
+ }
491
+ if (!keyInput) {
492
+ warn('No key provided, skipping.');
493
+ break;
494
+ }
495
+ const verifySpin = spinner('Verifying API key...');
496
+ verifySpin.start();
497
+ const validation = await validateProviderKey(chosen.key, keyInput);
498
+ verifySpin.stop();
499
+ if (validation.valid) {
373
500
  if (chosen.key === 'anthropic')
374
501
  anthropicKey = keyInput;
375
502
  else if (chosen.key === 'openai')
376
503
  openaiKey = keyInput;
377
- else {
504
+ else
378
505
  process.env[chosen.envVar] = keyInput;
379
- }
380
506
  success(`${chosen.name} configured.`);
507
+ configured = true;
381
508
  }
382
509
  else {
383
- warn('No key provided, skipping.');
510
+ error(`Invalid key: ${validation.error ?? 'verification failed'}`);
511
+ let retry = false;
512
+ try {
513
+ retry = await confirm({
514
+ message: 'Re-enter the key?',
515
+ default: true,
516
+ theme: { prefix: ' ' },
517
+ });
518
+ }
519
+ catch {
520
+ // cancelled
521
+ }
522
+ if (!retry) {
523
+ warn(`Skipping ${chosen.name}.`);
524
+ break;
525
+ }
384
526
  }
385
527
  }
386
- catch {
387
- warn('Input cancelled, skipping provider.');
388
- }
389
528
  }
390
529
  }
391
530
  else {
@@ -411,13 +550,30 @@ async function runInteractive() {
411
550
  ollamaUrl,
412
551
  extraEnvVars,
413
552
  });
553
+ console.log(chalk.bold.white('\n Configuration Preview:\n'));
554
+ console.log(formatEnvPreview(envContent));
555
+ console.log('');
556
+ let writeConfirmed = true;
414
557
  try {
415
- writeFileSync(envPath, envContent, { mode: 0o600 });
416
- success('.env file created.');
558
+ writeConfirmed = await confirm({
559
+ message: 'Write this configuration to .env?',
560
+ default: true,
561
+ theme: { prefix: ' ' },
562
+ });
417
563
  }
418
- catch (err) {
419
- error(`Failed to write .env: ${err instanceof Error ? err.message : 'unknown'}`);
420
- info('Create .env manually with the values above.');
564
+ catch { /* Ctrl+C — keep default true */ }
565
+ if (!writeConfirmed) {
566
+ warn('Skipped .env write. You can create it manually.');
567
+ }
568
+ else {
569
+ try {
570
+ writeFileSync(envPath, envContent, { mode: 0o600 });
571
+ success('.env file created.');
572
+ }
573
+ catch (err) {
574
+ error(`Failed to write .env: ${err instanceof Error ? err.message : 'unknown'}`);
575
+ info('Create .env manually with the values above.');
576
+ }
421
577
  }
422
578
  }
423
579
  else {
@@ -437,21 +593,44 @@ async function runInteractive() {
437
593
  keysToWrite['OPENAI_API_KEY'] = openaiKey;
438
594
  if (ollamaUrl)
439
595
  keysToWrite['OLLAMA_BASE_URL'] = ollamaUrl;
440
- for (const [key, value] of Object.entries(keysToWrite)) {
441
- if (content.includes(`${key}=`)) {
442
- content = content.replace(new RegExp(`${key}=.*`), `${key}=${value}`);
443
- }
444
- else {
445
- content += `${key}=${value}\n`;
446
- }
596
+ // Show preview of what will change
597
+ const allUpdates = { PROFCLAW_MODE: mode, ...keysToWrite };
598
+ console.log(chalk.bold.white('\n Changes to existing .env:\n'));
599
+ for (const [key, value] of Object.entries(allUpdates)) {
600
+ const masked = isSensitiveKey(key) ? maskApiKey(value) : value;
601
+ const action = content.includes(`${key}=`) ? chalk.yellow('update') : chalk.green('add');
602
+ console.log(` [${action}] ${chalk.cyan(key)}=${chalk.white(masked)}`);
603
+ }
604
+ console.log('');
605
+ let writeConfirmed = true;
606
+ try {
607
+ writeConfirmed = await confirm({
608
+ message: 'Apply these changes to .env?',
609
+ default: true,
610
+ theme: { prefix: ' ' },
611
+ });
447
612
  }
448
- writeFileSync(envPath, content);
449
- const keyCount = Object.keys(keysToWrite).length;
450
- if (keyCount > 0) {
451
- success(`PROFCLAW_MODE=${mode} + ${keyCount} provider key(s) saved to .env`);
613
+ catch { /* Ctrl+C — keep default true */ }
614
+ if (!writeConfirmed) {
615
+ warn('Skipped .env update. You can edit it manually.');
452
616
  }
453
617
  else {
454
- success(`PROFCLAW_MODE=${mode} set in .env`);
618
+ for (const [key, value] of Object.entries(keysToWrite)) {
619
+ if (content.includes(`${key}=`)) {
620
+ content = content.replace(new RegExp(`${key}=.*`), `${key}=${value}`);
621
+ }
622
+ else {
623
+ content += `${key}=${value}\n`;
624
+ }
625
+ }
626
+ writeFileSync(envPath, content);
627
+ const keyCount = Object.keys(keysToWrite).length;
628
+ if (keyCount > 0) {
629
+ success(`PROFCLAW_MODE=${mode} + ${keyCount} provider key(s) saved to .env`);
630
+ }
631
+ else {
632
+ success(`PROFCLAW_MODE=${mode} set in .env`);
633
+ }
455
634
  }
456
635
  }
457
636
  // Steps 5-6: Delegate to setup wizard for admin account + registration
@@ -523,6 +702,7 @@ export function onboardCommand() {
523
702
  else {
524
703
  await runInteractive();
525
704
  }
705
+ process.exit(0);
526
706
  }
527
707
  catch (err) {
528
708
  error(err instanceof Error ? err.message : 'Onboarding failed');