compact-agent 1.1.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 (324) hide show
  1. package/README.md +394 -0
  2. package/bin/anycode.js +2 -0
  3. package/bin/crowcoder.js +19 -0
  4. package/bin/ecc-hooks.cjs +138 -0
  5. package/dist/agents.d.ts +17 -0
  6. package/dist/agents.js +1603 -0
  7. package/dist/agents.js.map +1 -0
  8. package/dist/api.d.ts +16 -0
  9. package/dist/api.js +115 -0
  10. package/dist/api.js.map +1 -0
  11. package/dist/autonomous-loops.d.ts +108 -0
  12. package/dist/autonomous-loops.js +526 -0
  13. package/dist/autonomous-loops.js.map +1 -0
  14. package/dist/codemaps.d.ts +53 -0
  15. package/dist/codemaps.js +325 -0
  16. package/dist/codemaps.js.map +1 -0
  17. package/dist/compaction.d.ts +30 -0
  18. package/dist/compaction.js +125 -0
  19. package/dist/compaction.js.map +1 -0
  20. package/dist/config.d.ts +5 -0
  21. package/dist/config.js +79 -0
  22. package/dist/config.js.map +1 -0
  23. package/dist/content-engine.d.ts +97 -0
  24. package/dist/content-engine.js +721 -0
  25. package/dist/content-engine.js.map +1 -0
  26. package/dist/cost-tracker.d.ts +49 -0
  27. package/dist/cost-tracker.js +150 -0
  28. package/dist/cost-tracker.js.map +1 -0
  29. package/dist/counter-button.d.ts +35 -0
  30. package/dist/counter-button.js +48 -0
  31. package/dist/counter-button.js.map +1 -0
  32. package/dist/counter.d.ts +21 -0
  33. package/dist/counter.js +31 -0
  34. package/dist/counter.js.map +1 -0
  35. package/dist/coverage.d.ts +23 -0
  36. package/dist/coverage.js +215 -0
  37. package/dist/coverage.js.map +1 -0
  38. package/dist/docs-sync.d.ts +23 -0
  39. package/dist/docs-sync.js +266 -0
  40. package/dist/docs-sync.js.map +1 -0
  41. package/dist/ecc.d.ts +41 -0
  42. package/dist/ecc.js +644 -0
  43. package/dist/ecc.js.map +1 -0
  44. package/dist/evaluation.d.ts +24 -0
  45. package/dist/evaluation.js +412 -0
  46. package/dist/evaluation.js.map +1 -0
  47. package/dist/export.d.ts +22 -0
  48. package/dist/export.js +109 -0
  49. package/dist/export.js.map +1 -0
  50. package/dist/git-workflow.d.ts +22 -0
  51. package/dist/git-workflow.js +197 -0
  52. package/dist/git-workflow.js.map +1 -0
  53. package/dist/hook-controls.d.ts +34 -0
  54. package/dist/hook-controls.js +90 -0
  55. package/dist/hook-controls.js.map +1 -0
  56. package/dist/hooks.d.ts +30 -0
  57. package/dist/hooks.js +130 -0
  58. package/dist/hooks.js.map +1 -0
  59. package/dist/html-parser.d.ts +18 -0
  60. package/dist/html-parser.js +101 -0
  61. package/dist/html-parser.js.map +1 -0
  62. package/dist/index.d.ts +12 -0
  63. package/dist/index.js +1230 -0
  64. package/dist/index.js.map +1 -0
  65. package/dist/learning.d.ts +35 -0
  66. package/dist/learning.js +238 -0
  67. package/dist/learning.js.map +1 -0
  68. package/dist/login.d.ts +37 -0
  69. package/dist/login.js +191 -0
  70. package/dist/login.js.map +1 -0
  71. package/dist/memory.d.ts +39 -0
  72. package/dist/memory.js +183 -0
  73. package/dist/memory.js.map +1 -0
  74. package/dist/model-router.d.ts +23 -0
  75. package/dist/model-router.js +145 -0
  76. package/dist/model-router.js.map +1 -0
  77. package/dist/modes.d.ts +17 -0
  78. package/dist/modes.js +217 -0
  79. package/dist/modes.js.map +1 -0
  80. package/dist/orchestration.d.ts +37 -0
  81. package/dist/orchestration.js +139 -0
  82. package/dist/orchestration.js.map +1 -0
  83. package/dist/package-detect.d.ts +36 -0
  84. package/dist/package-detect.js +529 -0
  85. package/dist/package-detect.js.map +1 -0
  86. package/dist/permissions.d.ts +25 -0
  87. package/dist/permissions.js +50 -0
  88. package/dist/permissions.js.map +1 -0
  89. package/dist/pm2-manager.d.ts +40 -0
  90. package/dist/pm2-manager.js +127 -0
  91. package/dist/pm2-manager.js.map +1 -0
  92. package/dist/query.d.ts +15 -0
  93. package/dist/query.js +278 -0
  94. package/dist/query.js.map +1 -0
  95. package/dist/refactor.d.ts +22 -0
  96. package/dist/refactor.js +226 -0
  97. package/dist/refactor.js.map +1 -0
  98. package/dist/retry.d.ts +20 -0
  99. package/dist/retry.js +88 -0
  100. package/dist/retry.js.map +1 -0
  101. package/dist/rules.d.ts +34 -0
  102. package/dist/rules.js +942 -0
  103. package/dist/rules.js.map +1 -0
  104. package/dist/schema.d.ts +23 -0
  105. package/dist/schema.js +12 -0
  106. package/dist/schema.js.map +1 -0
  107. package/dist/search-first.d.ts +17 -0
  108. package/dist/search-first.js +301 -0
  109. package/dist/search-first.js.map +1 -0
  110. package/dist/security.d.ts +10 -0
  111. package/dist/security.js +145 -0
  112. package/dist/security.js.map +1 -0
  113. package/dist/sessions.d.ts +21 -0
  114. package/dist/sessions.js +112 -0
  115. package/dist/sessions.js.map +1 -0
  116. package/dist/skill-create.d.ts +38 -0
  117. package/dist/skill-create.js +389 -0
  118. package/dist/skill-create.js.map +1 -0
  119. package/dist/skills.d.ts +34 -0
  120. package/dist/skills.js +161 -0
  121. package/dist/skills.js.map +1 -0
  122. package/dist/strategic-compaction.d.ts +24 -0
  123. package/dist/strategic-compaction.js +144 -0
  124. package/dist/strategic-compaction.js.map +1 -0
  125. package/dist/system-prompt.d.ts +3 -0
  126. package/dist/system-prompt.js +101 -0
  127. package/dist/system-prompt.js.map +1 -0
  128. package/dist/theme.d.ts +60 -0
  129. package/dist/theme.js +220 -0
  130. package/dist/theme.js.map +1 -0
  131. package/dist/tools/bash.d.ts +2 -0
  132. package/dist/tools/bash.js +49 -0
  133. package/dist/tools/bash.js.map +1 -0
  134. package/dist/tools/edit.d.ts +2 -0
  135. package/dist/tools/edit.js +76 -0
  136. package/dist/tools/edit.js.map +1 -0
  137. package/dist/tools/glob.d.ts +2 -0
  138. package/dist/tools/glob.js +54 -0
  139. package/dist/tools/glob.js.map +1 -0
  140. package/dist/tools/grep.d.ts +2 -0
  141. package/dist/tools/grep.js +64 -0
  142. package/dist/tools/grep.js.map +1 -0
  143. package/dist/tools/index.d.ts +5 -0
  144. package/dist/tools/index.js +27 -0
  145. package/dist/tools/index.js.map +1 -0
  146. package/dist/tools/list-dir.d.ts +2 -0
  147. package/dist/tools/list-dir.js +51 -0
  148. package/dist/tools/list-dir.js.map +1 -0
  149. package/dist/tools/read.d.ts +2 -0
  150. package/dist/tools/read.js +56 -0
  151. package/dist/tools/read.js.map +1 -0
  152. package/dist/tools/types.d.ts +45 -0
  153. package/dist/tools/types.js +2 -0
  154. package/dist/tools/types.js.map +1 -0
  155. package/dist/tools/web-fetch.d.ts +2 -0
  156. package/dist/tools/web-fetch.js +41 -0
  157. package/dist/tools/web-fetch.js.map +1 -0
  158. package/dist/tools/web-search.d.ts +27 -0
  159. package/dist/tools/web-search.js +139 -0
  160. package/dist/tools/web-search.js.map +1 -0
  161. package/dist/tools/write.d.ts +2 -0
  162. package/dist/tools/write.js +36 -0
  163. package/dist/tools/write.js.map +1 -0
  164. package/dist/types.d.ts +28 -0
  165. package/dist/types.js +57 -0
  166. package/dist/types.js.map +1 -0
  167. package/dist/users.d.ts +51 -0
  168. package/dist/users.js +193 -0
  169. package/dist/users.js.map +1 -0
  170. package/dist/verification.d.ts +73 -0
  171. package/dist/verification.js +269 -0
  172. package/dist/verification.js.map +1 -0
  173. package/dist/walkthrough.d.ts +10 -0
  174. package/dist/walkthrough.js +121 -0
  175. package/dist/walkthrough.js.map +1 -0
  176. package/package.json +58 -0
  177. package/resources/ecc/agents/architect.json +16 -0
  178. package/resources/ecc/agents/architect.md +212 -0
  179. package/resources/ecc/agents/build-error-resolver.json +17 -0
  180. package/resources/ecc/agents/build-error-resolver.md +116 -0
  181. package/resources/ecc/agents/chief-of-staff.json +17 -0
  182. package/resources/ecc/agents/chief-of-staff.md +153 -0
  183. package/resources/ecc/agents/code-reviewer.json +16 -0
  184. package/resources/ecc/agents/code-reviewer.md +238 -0
  185. package/resources/ecc/agents/database-reviewer.json +16 -0
  186. package/resources/ecc/agents/database-reviewer.md +92 -0
  187. package/resources/ecc/agents/doc-updater.json +16 -0
  188. package/resources/ecc/agents/doc-updater.md +108 -0
  189. package/resources/ecc/agents/e2e-runner.json +17 -0
  190. package/resources/ecc/agents/e2e-runner.md +109 -0
  191. package/resources/ecc/agents/go-build-resolver.json +17 -0
  192. package/resources/ecc/agents/go-build-resolver.md +96 -0
  193. package/resources/ecc/agents/go-reviewer.json +16 -0
  194. package/resources/ecc/agents/go-reviewer.md +77 -0
  195. package/resources/ecc/agents/harness-optimizer.json +15 -0
  196. package/resources/ecc/agents/harness-optimizer.md +34 -0
  197. package/resources/ecc/agents/loop-operator.json +16 -0
  198. package/resources/ecc/agents/loop-operator.md +36 -0
  199. package/resources/ecc/agents/planner.json +15 -0
  200. package/resources/ecc/agents/planner.md +212 -0
  201. package/resources/ecc/agents/python-reviewer.json +16 -0
  202. package/resources/ecc/agents/python-reviewer.md +99 -0
  203. package/resources/ecc/agents/refactor-cleaner.json +17 -0
  204. package/resources/ecc/agents/refactor-cleaner.md +87 -0
  205. package/resources/ecc/agents/security-reviewer.json +16 -0
  206. package/resources/ecc/agents/security-reviewer.md +109 -0
  207. package/resources/ecc/agents/tdd-guide.json +17 -0
  208. package/resources/ecc/agents/tdd-guide.md +93 -0
  209. package/resources/ecc/commands/add-language-rules.md +39 -0
  210. package/resources/ecc/commands/database-migration.md +36 -0
  211. package/resources/ecc/commands/feature-development.md +38 -0
  212. package/resources/ecc/prompts/build-fix.prompt.md +47 -0
  213. package/resources/ecc/prompts/code-review.prompt.md +56 -0
  214. package/resources/ecc/prompts/plan.prompt.md +52 -0
  215. package/resources/ecc/prompts/refactor.prompt.md +50 -0
  216. package/resources/ecc/prompts/security-review.prompt.md +70 -0
  217. package/resources/ecc/prompts/tdd.prompt.md +47 -0
  218. package/resources/ecc/rules/common-agents.md +53 -0
  219. package/resources/ecc/rules/common-coding-style.md +52 -0
  220. package/resources/ecc/rules/common-development-workflow.md +33 -0
  221. package/resources/ecc/rules/common-git-workflow.md +28 -0
  222. package/resources/ecc/rules/common-hooks.md +34 -0
  223. package/resources/ecc/rules/common-patterns.md +35 -0
  224. package/resources/ecc/rules/common-performance.md +59 -0
  225. package/resources/ecc/rules/common-security.md +33 -0
  226. package/resources/ecc/rules/common-testing.md +33 -0
  227. package/resources/ecc/rules/golang-coding-style.md +31 -0
  228. package/resources/ecc/rules/golang-hooks.md +16 -0
  229. package/resources/ecc/rules/golang-patterns.md +44 -0
  230. package/resources/ecc/rules/golang-security.md +33 -0
  231. package/resources/ecc/rules/golang-testing.md +30 -0
  232. package/resources/ecc/rules/kotlin-coding-style.md +39 -0
  233. package/resources/ecc/rules/kotlin-hooks.md +16 -0
  234. package/resources/ecc/rules/kotlin-patterns.md +50 -0
  235. package/resources/ecc/rules/kotlin-security.md +58 -0
  236. package/resources/ecc/rules/kotlin-testing.md +38 -0
  237. package/resources/ecc/rules/php-coding-style.md +25 -0
  238. package/resources/ecc/rules/php-hooks.md +21 -0
  239. package/resources/ecc/rules/php-patterns.md +23 -0
  240. package/resources/ecc/rules/php-security.md +24 -0
  241. package/resources/ecc/rules/php-testing.md +26 -0
  242. package/resources/ecc/rules/python-coding-style.md +42 -0
  243. package/resources/ecc/rules/python-hooks.md +19 -0
  244. package/resources/ecc/rules/python-patterns.md +39 -0
  245. package/resources/ecc/rules/python-security.md +30 -0
  246. package/resources/ecc/rules/python-testing.md +38 -0
  247. package/resources/ecc/rules/swift-coding-style.md +47 -0
  248. package/resources/ecc/rules/swift-hooks.md +20 -0
  249. package/resources/ecc/rules/swift-patterns.md +66 -0
  250. package/resources/ecc/rules/swift-security.md +33 -0
  251. package/resources/ecc/rules/swift-testing.md +45 -0
  252. package/resources/ecc/rules/typescript-coding-style.md +63 -0
  253. package/resources/ecc/rules/typescript-hooks.md +20 -0
  254. package/resources/ecc/rules/typescript-patterns.md +50 -0
  255. package/resources/ecc/rules/typescript-security.md +26 -0
  256. package/resources/ecc/rules/typescript-testing.md +16 -0
  257. package/resources/ecc/skills/agent-introspection-debugging/SKILL.md +152 -0
  258. package/resources/ecc/skills/agent-introspection-debugging/agents/openai.yaml +7 -0
  259. package/resources/ecc/skills/agent-sort/SKILL.md +214 -0
  260. package/resources/ecc/skills/agent-sort/agents/openai.yaml +7 -0
  261. package/resources/ecc/skills/api-design/SKILL.md +522 -0
  262. package/resources/ecc/skills/api-design/agents/openai.yaml +7 -0
  263. package/resources/ecc/skills/article-writing/SKILL.md +78 -0
  264. package/resources/ecc/skills/article-writing/agents/openai.yaml +7 -0
  265. package/resources/ecc/skills/backend-patterns/SKILL.md +597 -0
  266. package/resources/ecc/skills/backend-patterns/agents/openai.yaml +7 -0
  267. package/resources/ecc/skills/brand-voice/SKILL.md +96 -0
  268. package/resources/ecc/skills/brand-voice/agents/openai.yaml +7 -0
  269. package/resources/ecc/skills/brand-voice/references/voice-profile-schema.md +55 -0
  270. package/resources/ecc/skills/bun-runtime/SKILL.md +83 -0
  271. package/resources/ecc/skills/bun-runtime/agents/openai.yaml +7 -0
  272. package/resources/ecc/skills/coding-standards/SKILL.md +548 -0
  273. package/resources/ecc/skills/coding-standards/agents/openai.yaml +7 -0
  274. package/resources/ecc/skills/content-engine/SKILL.md +130 -0
  275. package/resources/ecc/skills/content-engine/agents/openai.yaml +7 -0
  276. package/resources/ecc/skills/crosspost/SKILL.md +110 -0
  277. package/resources/ecc/skills/crosspost/agents/openai.yaml +7 -0
  278. package/resources/ecc/skills/deep-research/SKILL.md +154 -0
  279. package/resources/ecc/skills/deep-research/agents/openai.yaml +7 -0
  280. package/resources/ecc/skills/dmux-workflows/SKILL.md +143 -0
  281. package/resources/ecc/skills/dmux-workflows/agents/openai.yaml +7 -0
  282. package/resources/ecc/skills/documentation-lookup/SKILL.md +89 -0
  283. package/resources/ecc/skills/documentation-lookup/agents/openai.yaml +7 -0
  284. package/resources/ecc/skills/e2e-testing/SKILL.md +325 -0
  285. package/resources/ecc/skills/e2e-testing/agents/openai.yaml +7 -0
  286. package/resources/ecc/skills/eval-harness/SKILL.md +235 -0
  287. package/resources/ecc/skills/eval-harness/agents/openai.yaml +7 -0
  288. package/resources/ecc/skills/everything-claude-code/SKILL.md +442 -0
  289. package/resources/ecc/skills/everything-claude-code/agents/openai.yaml +7 -0
  290. package/resources/ecc/skills/exa-search/SKILL.md +169 -0
  291. package/resources/ecc/skills/exa-search/agents/openai.yaml +7 -0
  292. package/resources/ecc/skills/fal-ai-media/SKILL.md +276 -0
  293. package/resources/ecc/skills/fal-ai-media/agents/openai.yaml +7 -0
  294. package/resources/ecc/skills/frontend-patterns/SKILL.md +647 -0
  295. package/resources/ecc/skills/frontend-patterns/agents/openai.yaml +7 -0
  296. package/resources/ecc/skills/frontend-slides/SKILL.md +183 -0
  297. package/resources/ecc/skills/frontend-slides/STYLE_PRESETS.md +330 -0
  298. package/resources/ecc/skills/frontend-slides/agents/openai.yaml +7 -0
  299. package/resources/ecc/skills/investor-materials/SKILL.md +95 -0
  300. package/resources/ecc/skills/investor-materials/agents/openai.yaml +7 -0
  301. package/resources/ecc/skills/investor-outreach/SKILL.md +90 -0
  302. package/resources/ecc/skills/investor-outreach/agents/openai.yaml +7 -0
  303. package/resources/ecc/skills/market-research/SKILL.md +74 -0
  304. package/resources/ecc/skills/market-research/agents/openai.yaml +7 -0
  305. package/resources/ecc/skills/mcp-server-patterns/SKILL.md +66 -0
  306. package/resources/ecc/skills/mcp-server-patterns/agents/openai.yaml +7 -0
  307. package/resources/ecc/skills/mle-workflow/SKILL.md +346 -0
  308. package/resources/ecc/skills/mle-workflow/agents/openai.yaml +7 -0
  309. package/resources/ecc/skills/nextjs-turbopack/SKILL.md +43 -0
  310. package/resources/ecc/skills/nextjs-turbopack/agents/openai.yaml +7 -0
  311. package/resources/ecc/skills/product-capability/SKILL.md +140 -0
  312. package/resources/ecc/skills/product-capability/agents/openai.yaml +7 -0
  313. package/resources/ecc/skills/security-review/SKILL.md +494 -0
  314. package/resources/ecc/skills/security-review/agents/openai.yaml +7 -0
  315. package/resources/ecc/skills/strategic-compact/SKILL.md +102 -0
  316. package/resources/ecc/skills/strategic-compact/agents/openai.yaml +7 -0
  317. package/resources/ecc/skills/tdd-workflow/SKILL.md +409 -0
  318. package/resources/ecc/skills/tdd-workflow/agents/openai.yaml +7 -0
  319. package/resources/ecc/skills/verification-loop/SKILL.md +125 -0
  320. package/resources/ecc/skills/verification-loop/agents/openai.yaml +7 -0
  321. package/resources/ecc/skills/video-editing/SKILL.md +307 -0
  322. package/resources/ecc/skills/video-editing/agents/openai.yaml +7 -0
  323. package/resources/ecc/skills/x-api/SKILL.md +229 -0
  324. package/resources/ecc/skills/x-api/agents/openai.yaml +7 -0
package/dist/index.js ADDED
@@ -0,0 +1,1230 @@
1
+ #!/usr/bin/env node
2
+ import * as readline from 'node:readline/promises';
3
+ import { stdin, stdout } from 'node:process';
4
+ import { readFileSync as fsReadFileSync, writeFileSync as fsWriteFileSync } from 'node:fs';
5
+ import chalk from 'chalk';
6
+ import { loadConfig, saveConfig, configExists, getConfigDir } from './config.js';
7
+ import { resetClient } from './api.js';
8
+ import { runQuery } from './query.js';
9
+ import { ALL_TOOLS } from './tools/index.js';
10
+ import { PROVIDERS } from './types.js';
11
+ // New systems
12
+ import { createSession, autoSave, listSessions, loadSession, deleteSession } from './sessions.js';
13
+ import { initHooksDir, runHooks, listHooks } from './hooks.js';
14
+ import { printUsageSummary, setBudget } from './cost-tracker.js';
15
+ import { getCompactionStats } from './compaction.js';
16
+ import { extractPatterns, printInstinctStatus, pruneExpired, listInstincts, exportInstincts, importInstincts } from './learning.js';
17
+ import { MODES, listModes } from './modes.js';
18
+ import { printModelOptions, switchModel, classifyComplexity, routeModel } from './model-router.js';
19
+ import { buildCommitPrompt, buildPRPrompt, printDiff, printLog } from './git-workflow.js';
20
+ import { buildReviewPrompt, buildTDDPrompt, buildSecurityReviewPrompt, runAudit, printAuditReport, buildPlanPrompt, buildE2EPrompt, buildBuildFixPrompt, buildEvalPrompt } from './evaluation.js';
21
+ import { printRules } from './rules.js';
22
+ import { buildOrchestrationPrompt } from './orchestration.js';
23
+ import { printBanner as printThemedBanner, printSplash, theme, sym } from './theme.js';
24
+ import { saveExport } from './export.js';
25
+ // New feature modules
26
+ import { buildVerifyPrompt, saveCheckpoint, listCheckpoints } from './verification.js';
27
+ import { detectPackageManager, detectTestRunner, detectBuildTool } from './package-detect.js';
28
+ import { buildCoveragePrompt } from './coverage.js';
29
+ import { buildRefactorPrompt, buildCleanupPrompt } from './refactor.js';
30
+ import { buildDocsUpdatePrompt } from './docs-sync.js';
31
+ import { printSkillList, evolveInstinctsToSkills } from './skills.js';
32
+ import { onSessionStart, onSessionEnd, printMemoryStatus } from './memory.js';
33
+ import { incrementCounter, decrementCounter, resetCounter, getCounter } from './counter.js';
34
+ import { createUser, setActiveUser, deleteUser, setUserMetadata, getUserMetadata, printUserList, } from './users.js';
35
+ import { shouldSuggestCompaction } from './strategic-compaction.js';
36
+ // Language-specific agents & review
37
+ import { buildTSReviewPrompt, buildPyReviewPrompt, buildGoReviewPrompt, buildRustReviewPrompt, buildJavaReviewPrompt, buildCppReviewPrompt, buildKotlinReviewPrompt, buildPhpReviewPrompt, buildDbReviewPrompt, buildAutoReviewPrompt, buildTSBuildFixPrompt, buildGoBuildFixPrompt, buildRustBuildFixPrompt, buildJavaBuildFixPrompt, buildCppBuildFixPrompt, buildPyTorchBuildFixPrompt, } from './agents.js';
38
+ // Autonomous loops & DAG orchestration
39
+ import { buildPRLoopPrompt, buildMultiPlanPrompt, buildMultiExecutePrompt, buildMultiBackendPrompt, buildMultiFrontendPrompt, } from './autonomous-loops.js';
40
+ // Search-first research workflow
41
+ import { buildSearchFirstPrompt, buildDocsLookupPrompt } from './search-first.js';
42
+ // Codemaps
43
+ import { generateCodeMap, saveCodeMap, printCodeMap, printCodemapStatus } from './codemaps.js';
44
+ // Skill creation from git patterns
45
+ import { buildSkillCreatePrompt, analyzeGitPatterns, printGitPatterns, printGitWorkflowSummary } from './skill-create.js';
46
+ // Content engine
47
+ import { buildArticlePrompt, buildSlidePrompt, buildContentRepurposePrompt, buildMarketResearchPrompt, buildInvestorDeckPrompt, buildInvestorOutreachPrompt, buildCodeQualityPrompt, buildSkillStocktakePrompt, buildChiefOfStaffPrompt, } from './content-engine.js';
48
+ // Hook controls
49
+ import { printHookControlStatus } from './hook-controls.js';
50
+ // PM2 manager
51
+ import { buildPM2Prompt, isPM2Available, listPM2Services } from './pm2-manager.js';
52
+ // ECC (everything-claude-code) integration
53
+ import { installEcc, printEccStatus, printEccSkills, printEccAgents, printEccCommandList, getEccCommandPrompt, listEccCommands, loadEccState, eccResourcesAvailable, } from './ecc.js';
54
+ // Walkthrough — agent-led tour of Crowcoder (/walkthrough, /tour, /guide)
55
+ import { buildWalkthroughPrompt } from './walkthrough.js';
56
+ /**
57
+ * Unified prompt resolver — prefers the bundled ECC prompt for a given
58
+ * intent and falls back to the built-in builder when ECC isn't installed.
59
+ * Keeps the user-facing surface to ONE command per intent (e.g. /tdd, not
60
+ * /tdd vs /ecc-tdd). When ECC supplies the prompt, the user's args are
61
+ * appended under a "## User Input" section so the model still sees them.
62
+ */
63
+ function buildUnifiedPrompt(eccName, args, builtin) {
64
+ const ecc = getEccCommandPrompt(eccName);
65
+ if (!ecc)
66
+ return builtin();
67
+ return args.trim() ? `${ecc}\n\n## User Input\n\n${args}` : ecc;
68
+ }
69
+ // ── Setup Wizard ──────────────────────────────────────────
70
+ async function setupWizard(rl) {
71
+ console.log(chalk.bold.cyan('\n Compact Agent — First-time Setup\n'));
72
+ console.log(chalk.white(' Choose a provider:\n'));
73
+ const providerKeys = Object.keys(PROVIDERS);
74
+ providerKeys.forEach((key, i) => {
75
+ const p = PROVIDERS[key];
76
+ console.log(chalk.white(` ${i + 1}. ${p.name}`) + chalk.dim(` (${p.baseURL || 'you provide'})`));
77
+ });
78
+ const choice = await rl.question(chalk.yellow('\n Provider [1]: '));
79
+ const idx = parseInt(choice || '1', 10) - 1;
80
+ const providerKey = providerKeys[Math.max(0, Math.min(idx, providerKeys.length - 1))];
81
+ const provider = PROVIDERS[providerKey];
82
+ let baseURL = provider.baseURL;
83
+ if (providerKey === 'custom') {
84
+ baseURL = await rl.question(chalk.yellow(' Base URL: '));
85
+ }
86
+ let apiKey = '';
87
+ if (provider.requiresKey) {
88
+ apiKey = await rl.question(chalk.yellow(` API Key for ${provider.name}: `));
89
+ }
90
+ let model = provider.defaultModel;
91
+ const modelInput = await rl.question(chalk.yellow(` Model [${provider.defaultModel}]: `));
92
+ if (modelInput.trim())
93
+ model = modelInput.trim();
94
+ console.log(chalk.white('\n Permission modes:'));
95
+ console.log(chalk.dim(' 1. ask — prompt before writes/commands (safest)'));
96
+ console.log(chalk.dim(' 2. auto — auto-approve reads, ask for destructive'));
97
+ console.log(chalk.dim(' 3. yolo — approve everything (fastest)\n'));
98
+ const permChoice = await rl.question(chalk.yellow(' Permission mode [1]: '));
99
+ const permMode = ['ask', 'auto', 'yolo'][parseInt(permChoice || '1', 10) - 1] || 'ask';
100
+ const config = {
101
+ apiKey,
102
+ baseURL,
103
+ model,
104
+ provider: provider.name,
105
+ maxTokens: 8192,
106
+ temperature: 0.3,
107
+ permissionMode: permMode,
108
+ };
109
+ saveConfig(config);
110
+ console.log(chalk.green(`\n Config saved to ${getConfigDir()}/config.json\n`));
111
+ return config;
112
+ }
113
+ /**
114
+ * Parse slash command respecting quoted strings
115
+ */
116
+ function parseSlashCommand(input) {
117
+ const trimmed = input.trim();
118
+ const spaceIdx = trimmed.indexOf(' ');
119
+ if (spaceIdx === -1) {
120
+ return { cmd: trimmed.toLowerCase(), args: '' };
121
+ }
122
+ const cmd = trimmed.slice(0, spaceIdx).toLowerCase();
123
+ const argsRaw = trimmed.slice(spaceIdx + 1);
124
+ // Keep quoted strings intact
125
+ return { cmd, args: argsRaw };
126
+ }
127
+ // ── Slash Commands ────────────────────────────────────────
128
+ // Exported so smoke tests can dispatch commands directly without spawning a
129
+ // readline REPL or burning LLM tokens. Returns shape is stable contract:
130
+ // { handled: true } — local command, output printed to stdout
131
+ // { handled: false, injectPrompt } — LLM-driven, prompt ready to send
132
+ export function handleSlashCommand(input, config, messages, session, mode) {
133
+ const { cmd, args } = parseSlashCommand(input);
134
+ switch (cmd) {
135
+ // ── Help ──────────────────────────────────────────
136
+ case '/help': {
137
+ const h = theme.header;
138
+ const d = theme.dim;
139
+ const c = theme.command;
140
+ console.log(h('\n ── General ──'));
141
+ console.log(d(' ') + c('/help') + d(' — this help'));
142
+ console.log(d(' ') + c('/config') + d(' — reconfigure provider/model/key'));
143
+ console.log(d(' ') + c('/theme [mode]') + d(' — toggle display mode (full/compact/minimal)'));
144
+ console.log(d(' ') + c('/clear') + d(' — clear conversation'));
145
+ console.log(d(' ') + c('/history') + d(' — message count & token estimate'));
146
+ console.log(d(' ') + c('/export [fmt]') + d(' — export conversation (md/json/txt)'));
147
+ console.log(d(' ') + c('/exit') + d(' — quit (alias: /quit)'));
148
+ console.log(d(' ') + c('/walkthrough') + d(' — agent-led tour of Crowcoder (aliases: /tour, /guide)'));
149
+ console.log(d(' ') + c('!<cmd>') + d(' — run shell command directly'));
150
+ console.log(h('\n ── Model & Provider ──'));
151
+ console.log(d(' ') + c('/model [name]') + d(' — switch or show model'));
152
+ console.log(d(' ') + c('/models') + d(' — list available models for provider'));
153
+ console.log(d(' ') + c('/provider') + d(' — show provider info'));
154
+ console.log(d(' ') + c('/route') + d(' — auto-route model based on next message'));
155
+ console.log(h('\n ── Modes ──'));
156
+ console.log(d(' ') + c('/mode [name]') + d(' — switch mode (dev/review/tdd/research/plan/debug/architect/hermes)'));
157
+ console.log(d(' ') + c('/modes') + d(' — list all modes (read-only; use /mode <name> to switch)'));
158
+ console.log(d(' ') + c('/hermes') + d(' — alias for /mode hermes (self-improving learning loop)'));
159
+ console.log(h('\n ── Session ──'));
160
+ console.log(d(' ') + c('/sessions') + d(' — list saved sessions'));
161
+ console.log(d(' ') + c('/save [name]') + d(' — save current session'));
162
+ console.log(d(' ') + c('/resume <id>') + d(' — resume a saved session'));
163
+ console.log(d(' ') + c('/delete <id>') + d(' — delete a session'));
164
+ console.log(h('\n ── Git ──'));
165
+ console.log(d(' ') + c('/commit') + d(' — AI-generated commit'));
166
+ console.log(d(' ') + c('/pr') + d(' — AI-generated pull request'));
167
+ console.log(d(' ') + c('/diff') + d(' — show git diff'));
168
+ console.log(d(' ') + c('/log') + d(' — show git log'));
169
+ console.log(h('\n ── Code Quality ──'));
170
+ console.log(d(' ') + c('/review [target]') + d(' — AI code review'));
171
+ console.log(d(' ') + c('/tdd <desc>') + d(' — test-driven development'));
172
+ console.log(d(' ') + c('/security-review') + d(' — security audit'));
173
+ console.log(d(' ') + c('/audit') + d(' — harness audit (score project health)'));
174
+ console.log(d(' ') + c('/verify [cmd]') + d(' — run tests, fix failures, repeat until green'));
175
+ console.log(d(' ') + c('/build-fix') + d(' — auto-detect and fix build errors'));
176
+ console.log(d(' ') + c('/test-coverage') + d(' — analyze test coverage, suggest tests'));
177
+ console.log(d(' ') + c('/refactor [target]') + d(' — dead code detection & cleanup'));
178
+ console.log(d(' ') + c('/e2e <feature>') + d(' — generate E2E tests'));
179
+ console.log(d(' ') + c('/eval <criteria>') + d(' — evaluate project against criteria'));
180
+ console.log(h('\n ── Tools & Config ──'));
181
+ console.log(d(' ') + c('/tools') + d(' — list tools'));
182
+ console.log(d(' ') + c('/rules') + d(' — show coding rules'));
183
+ console.log(d(' ') + c('/perm <mode>') + d(' — set permission mode'));
184
+ console.log(d(' ') + c('/dry-run') + d(' — toggle dry-run mode'));
185
+ console.log(d(' ') + c('/thinking') + d(' — toggle thinking/reasoning display'));
186
+ console.log(d(' ') + c('/cd <path>') + d(' — change directory'));
187
+ console.log(d(' ') + c('/hooks') + d(' — list configured hooks'));
188
+ console.log(h('\n ── Planning & Docs ──'));
189
+ console.log(d(' ') + c('/plan <task>') + d(' — structured implementation planning'));
190
+ console.log(d(' ') + c('/update-docs') + d(' — sync documentation with code'));
191
+ console.log(d(' ') + c('/checkpoint [label]') + d(' — save git state checkpoint'));
192
+ console.log(d(' ') + c('/checkpoints') + d(' — list saved checkpoints'));
193
+ console.log(d(' ') + c('/search-first <task>') + d(' — research before coding'));
194
+ console.log(d(' ') + c('/docs-lookup <query>') + d(' — search docs for answers'));
195
+ console.log(h('\n ── Language Reviews ──'));
196
+ console.log(d(' ') + c('/auto-review') + d(' — auto-detect language & review'));
197
+ console.log(d(' ') + c('/ts-review') + d(' — TypeScript-specific review'));
198
+ console.log(d(' ') + c('/py-review') + d(' — Python-specific review'));
199
+ console.log(d(' ') + c('/go-review') + d(' — Go-specific review'));
200
+ console.log(d(' ') + c('/rust-review') + d(' — Rust-specific review'));
201
+ console.log(d(' ') + c('/java-review') + d(' — Java-specific review'));
202
+ console.log(d(' ') + c('/cpp-review') + d(' — C++ review'));
203
+ console.log(d(' ') + c('/kotlin-review') + d(' — Kotlin review'));
204
+ console.log(d(' ') + c('/php-review') + d(' — PHP review'));
205
+ console.log(d(' ') + c('/db-review') + d(' — Database/SQL review'));
206
+ console.log(h('\n ── Language Build Fixes ──'));
207
+ console.log(d(' ') + c('/ts-build-fix') + d(' — fix TypeScript build errors'));
208
+ console.log(d(' ') + c('/go-build-fix') + d(' — fix Go build errors'));
209
+ console.log(d(' ') + c('/rust-build-fix') + d(' — fix Rust build errors'));
210
+ console.log(d(' ') + c('/java-build-fix') + d(' — fix Java build errors'));
211
+ console.log(d(' ') + c('/cpp-build-fix') + d(' — fix C++ build errors'));
212
+ console.log(d(' ') + c('/pytorch-fix') + d(' — fix PyTorch/CUDA errors'));
213
+ console.log(h('\n ── Orchestration ──'));
214
+ console.log(d(' ') + c('/orchestrate <task>') + d(' — decompose into parallel sub-agents'));
215
+ console.log(d(' ') + c('/pr-loop') + d(' — autonomous PR review loop'));
216
+ console.log(d(' ') + c('/multi-plan <task>') + d(' — multi-agent planning'));
217
+ console.log(d(' ') + c('/multi-execute') + d(' — multi-agent execution'));
218
+ console.log(d(' ') + c('/multi-backend') + d(' — multi-service backend generation'));
219
+ console.log(d(' ') + c('/multi-frontend') + d(' — multi-component frontend generation'));
220
+ console.log(h('\n ── Codemaps ──'));
221
+ console.log(d(' ') + c('/codemap') + d(' — show project structure map'));
222
+ console.log(d(' ') + c('/update-codemaps') + d(' — regenerate and save codemap'));
223
+ console.log(h('\n ── Content Engine ──'));
224
+ console.log(d(' ') + c('/article <topic>') + d(' — generate article/blog post'));
225
+ console.log(d(' ') + c('/slides <topic>') + d(' — generate slide outline'));
226
+ console.log(d(' ') + c('/repurpose <text>') + d(' — repurpose content for channels'));
227
+ console.log(d(' ') + c('/market-research') + d(' — market research report'));
228
+ console.log(d(' ') + c('/investor-deck') + d(' — investor pitch deck'));
229
+ console.log(d(' ') + c('/investor-outreach') + d(' — investor outreach emails'));
230
+ console.log(d(' ') + c('/code-quality') + d(' — comprehensive code quality audit'));
231
+ console.log(d(' ') + c('/skill-stocktake') + d(' — inventory skills & capabilities'));
232
+ console.log(d(' ') + c('/chief-of-staff') + d(' — executive briefing & priorities'));
233
+ console.log(h('\n ── Skills & Patterns ──'));
234
+ console.log(d(' ') + c('/skill-create') + d(' — create skill from git patterns'));
235
+ console.log(d(' ') + c('/git-patterns') + d(' — analyze git commit patterns'));
236
+ console.log(d(' ') + c('/git-workflow') + d(' — summarize git workflow'));
237
+ console.log(h('\n ── Learning & Cost ──'));
238
+ console.log(d(' ') + c('/usage') + d(' — token/cost summary'));
239
+ console.log(d(' ') + c('/budget <d> <m>') + d(' — set daily/monthly budget (USD)'));
240
+ console.log(d(' ') + c('/learn') + d(' — extract patterns from this session'));
241
+ console.log(d(' ') + c('/instincts') + d(' — show learned instincts'));
242
+ console.log(d(' ') + c('/instinct-export') + d(' — export instincts to JSON file'));
243
+ console.log(d(' ') + c('/instinct-import') + d(' — import instincts from JSON file'));
244
+ console.log(d(' ') + c('/evolve') + d(' — cluster instincts into reusable skills'));
245
+ console.log(d(' ') + c('/prune') + d(' — delete expired instincts'));
246
+ console.log(d(' ') + c('/skills') + d(' — list learned skills'));
247
+ console.log(d(' ') + c('/memory') + d(' — show memory status'));
248
+ console.log(d(' ') + c('/users') + d(' — manage users table'));
249
+ console.log(d(' ') + c('/count [inc|dec|reset]') + d(' — increment/decrement/reset counter'));
250
+ console.log(d(' ') + c('/detect') + d(' — detect package manager, test runner, build tool'));
251
+ console.log(d(' ') + c('/hook-profile') + d(' — show hook profile & controls'));
252
+ console.log(d(' ') + c('/pm2 [action]') + d(' — PM2 service management'));
253
+ console.log(h('\n ── ECC (everything-claude-code) ──'));
254
+ console.log(d(' ') + d(' Note: /tdd, /review, /security-review, /plan, /refactor, /build-fix'));
255
+ console.log(d(' automatically use ECC prompts when ECC is installed. No /ecc-tdd duplicates.'));
256
+ console.log(d(' ') + c('/ecc') + d(' — show ECC integration status'));
257
+ console.log(d(' ') + c('/ecc-install') + d(' — install/refresh bundled ECC skills, agents, commands, rules, hooks'));
258
+ console.log(d(' ') + c('/ecc-skills') + d(' — filtered view: /skills entries with category=ecc'));
259
+ console.log(d(' ') + c('/ecc-agents') + d(' — filtered view: /skills entries that are ECC agents'));
260
+ console.log(d(' ') + c('/ecc-commands') + d(' — list ECC-only commands (have no built-in equivalent)'));
261
+ console.log(d(' ') + c('/ecc-feature-development') + d(' — feature implementation workflow (ECC-only)'));
262
+ console.log(d(' ') + c('/ecc-add-language-rules') + d(' — add language-specific rule files (ECC-only)'));
263
+ console.log(d(' ') + c('/ecc-database-migration') + d(' — database migration workflow (ECC-only)'));
264
+ console.log();
265
+ return { handled: true };
266
+ }
267
+ // ── Theme ─────────────────────────────────────────
268
+ case '/theme':
269
+ if (args) {
270
+ const validThemes = ['full', 'compact', 'minimal'];
271
+ if (validThemes.includes(args)) {
272
+ config.theme = args;
273
+ saveConfig(config);
274
+ console.log(chalk.green(` Theme: ${config.theme}`));
275
+ }
276
+ else {
277
+ console.log(chalk.yellow(` Invalid theme: ${args}. Use: full, compact, or minimal`));
278
+ }
279
+ }
280
+ else {
281
+ const current = config.theme || 'full';
282
+ console.log(chalk.dim(` Current theme: ${current}`));
283
+ }
284
+ return { handled: true };
285
+ // ── Clear ─────────────────────────────────────────
286
+ case '/clear':
287
+ console.log(chalk.dim(' Conversation cleared.'));
288
+ return { handled: true, newMessages: [] };
289
+ // ── History ───────────────────────────────────────
290
+ case '/history': {
291
+ const stats = getCompactionStats(messages);
292
+ const userMsgs = messages.filter((m) => m.role === 'user').length;
293
+ const assistMsgs = messages.filter((m) => m.role === 'assistant').length;
294
+ const toolMsgs = messages.filter((m) => m.role === 'tool').length;
295
+ console.log(chalk.dim(` Messages: ${messages.length} (${userMsgs} user, ${assistMsgs} assistant, ${toolMsgs} tool)`));
296
+ console.log(chalk.dim(` Est. tokens: ~${stats.estimatedTokens.toLocaleString()}${stats.needsCompaction ? ' (compaction recommended)' : ''}`));
297
+ return { handled: true };
298
+ }
299
+ // ── Model ─────────────────────────────────────────
300
+ case '/model':
301
+ if (args) {
302
+ const newModel = switchModel(config, args);
303
+ if (newModel) {
304
+ config.model = newModel;
305
+ saveConfig(config);
306
+ resetClient();
307
+ console.log(chalk.green(` Model: ${config.model}`));
308
+ }
309
+ else {
310
+ config.model = args;
311
+ saveConfig(config);
312
+ resetClient();
313
+ console.log(chalk.green(` Model: ${config.model} (custom)`));
314
+ }
315
+ }
316
+ else {
317
+ console.log(chalk.dim(` Current: ${config.model}`));
318
+ }
319
+ return { handled: true };
320
+ case '/models':
321
+ printModelOptions(config);
322
+ return { handled: true };
323
+ case '/route': {
324
+ console.log(chalk.dim(' Auto-routing enabled for next message.'));
325
+ return { handled: true };
326
+ }
327
+ case '/provider':
328
+ console.log(chalk.dim(` Provider: ${config.provider}`));
329
+ console.log(chalk.dim(` Base URL: ${config.baseURL}`));
330
+ console.log(chalk.dim(` Model: ${config.model}`));
331
+ console.log(chalk.dim(` API Key: ${config.apiKey ? '***' + config.apiKey.slice(-4) : '(none)'}`));
332
+ return { handled: true };
333
+ // ── Mode ──────────────────────────────────────────
334
+ case '/mode':
335
+ if (args && MODES[args]) {
336
+ mode.current = args;
337
+ const m = MODES[mode.current];
338
+ console.log(chalk.green(` Mode: ${m.label} — ${m.description}`));
339
+ }
340
+ else if (args) {
341
+ console.log(chalk.yellow(` Unknown mode: ${args}`));
342
+ console.log(chalk.dim(` Available: ${Object.keys(MODES).join(', ')}`));
343
+ }
344
+ else {
345
+ console.log(chalk.dim(` Current: ${mode.current} (${MODES[mode.current].description})`));
346
+ }
347
+ return { handled: true };
348
+ // ── Hermes shorthand (inspired by nousresearch/hermes-agent) ──
349
+ case '/hermes': {
350
+ mode.current = 'hermes';
351
+ const m = MODES.hermes;
352
+ console.log(chalk.cyan(` Mode: ${m.label}`));
353
+ console.log(chalk.dim(` ${m.description}`));
354
+ console.log(chalk.dim(` Recall → user-model → parallelize → distill → persist → schedule.`));
355
+ return { handled: true };
356
+ }
357
+ case '/modes':
358
+ // List-only. Use `/mode <name>` to switch — single switcher, no duplicates.
359
+ if (args) {
360
+ console.log(chalk.dim(` /modes lists modes only. To switch: /mode ${args}`));
361
+ }
362
+ console.log(chalk.cyan('\n Modes:'));
363
+ for (const m of listModes()) {
364
+ const marker = m.name === mode.current ? chalk.green(' ◀') : '';
365
+ console.log(chalk.white(` ${m.name.padEnd(12)}`) + chalk.dim(m.description) + marker);
366
+ }
367
+ console.log(theme.dim('\n Switch with: /mode <name>'));
368
+ console.log();
369
+ return { handled: true };
370
+ // ── Session ───────────────────────────────────────
371
+ case '/sessions': {
372
+ const sessions = listSessions();
373
+ if (sessions.length === 0) {
374
+ console.log(chalk.dim(' No saved sessions.'));
375
+ }
376
+ else {
377
+ console.log(chalk.cyan(`\n Saved Sessions (${sessions.length}):`));
378
+ for (const s of sessions.slice(0, 20)) {
379
+ console.log(chalk.white(` ${s.id.slice(0, 12).padEnd(14)}`) +
380
+ chalk.dim(`${s.name.padEnd(30)} ${s.turnCount} turns ${s.model} ${s.updatedAt.slice(0, 10)}`));
381
+ }
382
+ console.log();
383
+ }
384
+ return { handled: true };
385
+ }
386
+ case '/save':
387
+ session.name = args || session.name;
388
+ autoSave(session, messages);
389
+ console.log(chalk.green(` Session saved: ${session.id} "${session.name}"`));
390
+ return { handled: true };
391
+ case '/resume': {
392
+ if (!args) {
393
+ console.log(chalk.yellow(' Usage: /resume <session-id>'));
394
+ return { handled: true };
395
+ }
396
+ const loaded = loadSession(args);
397
+ if (!loaded) {
398
+ console.log(chalk.red(` Session not found: ${args}`));
399
+ return { handled: true };
400
+ }
401
+ console.log(chalk.green(` Resumed: ${loaded.name} (${loaded.messages.length} messages)`));
402
+ return { handled: true, newMessages: loaded.messages };
403
+ }
404
+ case '/delete':
405
+ if (args && deleteSession(args)) {
406
+ console.log(chalk.green(` Deleted session: ${args}`));
407
+ }
408
+ else {
409
+ console.log(chalk.yellow(` Session not found: ${args}`));
410
+ }
411
+ return { handled: true };
412
+ // ── Git ───────────────────────────────────────────
413
+ case '/commit': {
414
+ const prompt = buildCommitPrompt(process.cwd());
415
+ if (!prompt) {
416
+ console.log(chalk.yellow(' No git changes to commit.'));
417
+ return { handled: true };
418
+ }
419
+ return { handled: false, injectPrompt: prompt };
420
+ }
421
+ case '/pr': {
422
+ const prompt = buildPRPrompt(process.cwd());
423
+ if (!prompt) {
424
+ console.log(chalk.yellow(' Not a git repo or no commits to PR.'));
425
+ return { handled: true };
426
+ }
427
+ return { handled: false, injectPrompt: prompt };
428
+ }
429
+ case '/diff':
430
+ printDiff(process.cwd());
431
+ return { handled: true };
432
+ case '/log':
433
+ printLog(process.cwd(), parseInt(args) || 15);
434
+ return { handled: true };
435
+ // ── Code Quality ──────────────────────────────────
436
+ case '/review': {
437
+ const builtin = buildReviewPrompt(process.cwd(), args || undefined);
438
+ const eccPrompt = getEccCommandPrompt('code-review');
439
+ if (!builtin && !eccPrompt) {
440
+ console.log(chalk.yellow(' No changes to review. Specify a target: /review HEAD~3'));
441
+ return { handled: true };
442
+ }
443
+ mode.current = 'review';
444
+ const prompt = eccPrompt
445
+ ? (args.trim() ? `${eccPrompt}\n\n## User Input\n\n${args}` : eccPrompt)
446
+ : builtin;
447
+ return { handled: false, injectPrompt: prompt };
448
+ }
449
+ case '/tdd':
450
+ if (!args) {
451
+ console.log(chalk.yellow(' Usage: /tdd <feature description>'));
452
+ return { handled: true };
453
+ }
454
+ mode.current = 'tdd';
455
+ return { handled: false, injectPrompt: buildUnifiedPrompt('tdd', args, () => buildTDDPrompt(args)) };
456
+ case '/security-review':
457
+ mode.current = 'review';
458
+ return {
459
+ handled: false,
460
+ injectPrompt: buildUnifiedPrompt('security-review', args, () => buildSecurityReviewPrompt(process.cwd())),
461
+ };
462
+ case '/audit': {
463
+ const report = runAudit(process.cwd());
464
+ printAuditReport(report);
465
+ return { handled: true };
466
+ }
467
+ // ── Tools & Config ────────────────────────────────
468
+ case '/tools':
469
+ console.log(chalk.cyan('\n Tools:'));
470
+ ALL_TOOLS.forEach((t) => {
471
+ const flags = [t.isReadOnly ? 'R' : 'RW', t.isDestructive ? '!' : ''].filter(Boolean).join('');
472
+ console.log(chalk.white(` ${t.name.padEnd(14)}`) + chalk.dim(`[${flags.padEnd(3)}] ${t.description.slice(0, 65)}`));
473
+ });
474
+ console.log();
475
+ return { handled: true };
476
+ case '/rules':
477
+ printRules();
478
+ return { handled: true };
479
+ case '/perm':
480
+ if (args && ['ask', 'auto', 'yolo'].includes(args)) {
481
+ config.permissionMode = args;
482
+ saveConfig(config);
483
+ console.log(chalk.green(` Permissions: ${config.permissionMode}`));
484
+ }
485
+ else {
486
+ console.log(chalk.dim(` Current: ${config.permissionMode} (options: ask, auto, yolo)`));
487
+ }
488
+ return { handled: true };
489
+ case '/dry-run':
490
+ config.dryRun = !config.dryRun;
491
+ saveConfig(config);
492
+ const dryRunStatus = config.dryRun ? chalk.yellow('ON') : chalk.green('OFF');
493
+ console.log(chalk.green(` Dry-run mode: ${dryRunStatus}`));
494
+ if (config.dryRun) {
495
+ console.log(chalk.dim(' Tools will show what they would execute without actually running.'));
496
+ }
497
+ return { handled: true };
498
+ case '/thinking': {
499
+ config.showThinking = !config.showThinking;
500
+ saveConfig(config);
501
+ const thinkingStatus = config.showThinking ? chalk.yellow('ON') : chalk.green('OFF');
502
+ console.log(chalk.green(` Show thinking: ${thinkingStatus}`));
503
+ if (config.showThinking) {
504
+ console.log(chalk.dim(' Model reasoning/chain-of-thought will be displayed when available.'));
505
+ console.log(chalk.dim(' Works with DeepSeek, OpenRouter reasoning models, and others.'));
506
+ }
507
+ return { handled: true };
508
+ }
509
+ case '/cd':
510
+ if (args) {
511
+ try {
512
+ process.chdir(args);
513
+ console.log(chalk.green(` cwd: ${process.cwd()}`));
514
+ }
515
+ catch (e) {
516
+ console.log(chalk.red(` ${e instanceof Error ? e.message : e}`));
517
+ }
518
+ }
519
+ else {
520
+ console.log(chalk.dim(` cwd: ${process.cwd()}`));
521
+ }
522
+ return { handled: true };
523
+ case '/hooks': {
524
+ const hooks = listHooks();
525
+ if (hooks.length === 0) {
526
+ console.log(chalk.dim(' No hooks configured. Edit ~/.crowcoder/hooks.json'));
527
+ }
528
+ else {
529
+ console.log(chalk.cyan(`\n Hooks (${hooks.length}):`));
530
+ hooks.forEach((h, i) => {
531
+ const status = h.enabled === false ? chalk.red('OFF') : chalk.green('ON');
532
+ console.log(chalk.dim(` ${i}. [${status}] ${h.event} → ${h.match} → ${h.command.slice(0, 50)}`));
533
+ });
534
+ }
535
+ console.log();
536
+ return { handled: true };
537
+ }
538
+ // ── Learning & Cost ───────────────────────────────
539
+ case '/usage':
540
+ printUsageSummary();
541
+ return { handled: true };
542
+ case '/budget': {
543
+ const [daily, monthly] = args.split(/\s+/).map(Number);
544
+ if (!daily || isNaN(daily)) {
545
+ console.log(chalk.yellow(' Usage: /budget <daily-usd> [monthly-usd]'));
546
+ return { handled: true };
547
+ }
548
+ setBudget(daily, monthly || daily * 30);
549
+ console.log(chalk.green(` Budget set: $${daily}/day, $${monthly || daily * 30}/month`));
550
+ return { handled: true };
551
+ }
552
+ case '/learn': {
553
+ const patterns = extractPatterns(messages, session.id);
554
+ if (patterns.length === 0) {
555
+ console.log(chalk.dim(' No patterns extracted from this session.'));
556
+ }
557
+ else {
558
+ console.log(chalk.green(` Extracted ${patterns.length} patterns:`));
559
+ for (const p of patterns) {
560
+ console.log(chalk.dim(` [${p.category}] ${p.pattern.slice(0, 80)}`));
561
+ }
562
+ }
563
+ return { handled: true };
564
+ }
565
+ case '/instincts':
566
+ printInstinctStatus();
567
+ return { handled: true };
568
+ case '/prune': {
569
+ const count = pruneExpired();
570
+ console.log(chalk.dim(` Pruned ${count} expired instincts.`));
571
+ return { handled: true };
572
+ }
573
+ // ── Orchestration ─────────────────────────────────
574
+ case '/orchestrate':
575
+ if (!args) {
576
+ console.log(chalk.yellow(' Usage: /orchestrate <task description>'));
577
+ return { handled: true };
578
+ }
579
+ mode.current = 'architect';
580
+ const orchPrompt = buildOrchestrationPrompt(args);
581
+ return { handled: false, injectPrompt: orchPrompt };
582
+ // ── Verification & Build ─────────────────────────
583
+ case '/verify': {
584
+ const prompt = buildVerifyPrompt(process.cwd(), args || undefined);
585
+ return { handled: false, injectPrompt: prompt };
586
+ }
587
+ case '/build-fix': {
588
+ return {
589
+ handled: false,
590
+ injectPrompt: buildUnifiedPrompt('build-fix', args, () => buildBuildFixPrompt(process.cwd(), args || undefined)),
591
+ };
592
+ }
593
+ case '/test-coverage': {
594
+ const prompt = buildCoveragePrompt(process.cwd());
595
+ return { handled: false, injectPrompt: prompt };
596
+ }
597
+ case '/refactor':
598
+ case '/refactor-clean': {
599
+ return {
600
+ handled: false,
601
+ injectPrompt: buildUnifiedPrompt('refactor', args, () => args ? buildRefactorPrompt(process.cwd(), args) : buildCleanupPrompt(process.cwd())),
602
+ };
603
+ }
604
+ case '/e2e': {
605
+ if (!args) {
606
+ console.log(chalk.yellow(' Usage: /e2e <feature description>'));
607
+ return { handled: true };
608
+ }
609
+ return { handled: false, injectPrompt: buildE2EPrompt(args, process.cwd()) };
610
+ }
611
+ case '/eval': {
612
+ if (!args) {
613
+ console.log(chalk.yellow(' Usage: /eval <criteria> [target]'));
614
+ return { handled: true };
615
+ }
616
+ return { handled: false, injectPrompt: buildEvalPrompt(args) };
617
+ }
618
+ case '/plan': {
619
+ if (!args) {
620
+ console.log(chalk.yellow(' Usage: /plan <task description>'));
621
+ return { handled: true };
622
+ }
623
+ mode.current = 'plan';
624
+ return {
625
+ handled: false,
626
+ injectPrompt: buildUnifiedPrompt('plan', args, () => buildPlanPrompt(args, process.cwd())),
627
+ };
628
+ }
629
+ case '/update-docs': {
630
+ return { handled: false, injectPrompt: buildDocsUpdatePrompt(process.cwd()) };
631
+ }
632
+ // ── Checkpoints ──────────────────────────────────
633
+ case '/checkpoint': {
634
+ const cp = saveCheckpoint(session.id, process.cwd(), args || undefined);
635
+ console.log(chalk.green(` Checkpoint saved: ${cp.id} ${cp.label ? `"${cp.label}"` : ''}`));
636
+ console.log(chalk.dim(` Git SHA: ${cp.headSha?.slice(0, 8) || 'N/A'}`));
637
+ return { handled: true };
638
+ }
639
+ case '/checkpoints': {
640
+ const cps = listCheckpoints(session.id);
641
+ if (cps.length === 0) {
642
+ console.log(chalk.dim(' No checkpoints for this session.'));
643
+ }
644
+ else {
645
+ console.log(chalk.cyan(`\n Checkpoints (${cps.length}):`));
646
+ for (const cp of cps) {
647
+ console.log(chalk.white(` ${cp.id.slice(0, 12).padEnd(14)}`) +
648
+ chalk.dim(`${(cp.label || 'unnamed').padEnd(20)} ${cp.headSha?.slice(0, 8) || 'N/A'} ${cp.timestamp.slice(0, 19)}`));
649
+ }
650
+ }
651
+ console.log();
652
+ return { handled: true };
653
+ }
654
+ // ── Instinct Management ──────────────────────────
655
+ case '/instinct-export': {
656
+ const json = exportInstincts();
657
+ const exportPath = `${process.cwd()}/instincts-export-${Date.now()}.json`;
658
+ fsWriteFileSync(exportPath, json, 'utf-8');
659
+ console.log(chalk.green(` Instincts exported to: ${exportPath}`));
660
+ return { handled: true };
661
+ }
662
+ case '/instinct-import': {
663
+ if (!args) {
664
+ console.log(chalk.yellow(' Usage: /instinct-import <path-to-json>'));
665
+ return { handled: true };
666
+ }
667
+ try {
668
+ const json = fsReadFileSync(args.trim(), 'utf-8');
669
+ const count = importInstincts(json);
670
+ console.log(chalk.green(` Imported ${count} instincts.`));
671
+ }
672
+ catch (e) {
673
+ console.log(chalk.red(` Error: ${e instanceof Error ? e.message : e}`));
674
+ }
675
+ return { handled: true };
676
+ }
677
+ case '/evolve': {
678
+ const instincts = listInstincts();
679
+ if (instincts.length < 3) {
680
+ console.log(chalk.yellow(' Need at least 3 instincts to evolve into skills.'));
681
+ return { handled: true };
682
+ }
683
+ const skills = evolveInstinctsToSkills(instincts);
684
+ if (skills.length === 0) {
685
+ console.log(chalk.dim(' No skill clusters found. Keep learning!'));
686
+ }
687
+ else {
688
+ console.log(chalk.green(` Evolved ${skills.length} skills from ${instincts.length} instincts:`));
689
+ for (const s of skills) {
690
+ console.log(chalk.dim(` [${s.category}] ${s.name}: ${s.description.slice(0, 60)}`));
691
+ }
692
+ }
693
+ return { handled: true };
694
+ }
695
+ case '/skills':
696
+ printSkillList();
697
+ return { handled: true };
698
+ case '/memory':
699
+ printMemoryStatus();
700
+ return { handled: true };
701
+ // ── Users Table ──────────────────────────────────────
702
+ case '/users': {
703
+ const sub = args.trim();
704
+ if (sub === 'ls' || sub === 'list' || !sub) {
705
+ printUserList();
706
+ return { handled: true };
707
+ }
708
+ const parts = sub.split(/\s+/);
709
+ const action = parts[0];
710
+ if (action === 'add') {
711
+ const name = parts[1] || '';
712
+ if (!name) {
713
+ console.log(chalk.yellow(' Usage: /users add <name> [email] [role]'));
714
+ return { handled: true };
715
+ }
716
+ const email = parts[2] || '';
717
+ const role = parts[3] || '';
718
+ const user = createUser(name, email || undefined, role || undefined);
719
+ console.log(chalk.green(` User created: ${user.id} — ${user.name}`));
720
+ return { handled: true };
721
+ }
722
+ if (action === 'rm' || action === 'del' || action === 'delete') {
723
+ const id = parts[1];
724
+ if (!id) {
725
+ console.log(chalk.yellow(' Usage: /users rm <id>'));
726
+ return { handled: true };
727
+ }
728
+ if (deleteUser(id)) {
729
+ console.log(chalk.green(` User deleted: ${id}`));
730
+ }
731
+ else {
732
+ console.log(chalk.yellow(` User not found: ${id}`));
733
+ }
734
+ return { handled: true };
735
+ }
736
+ if (action === 'set' || action === 'activate') {
737
+ const id = parts[1];
738
+ if (!id) {
739
+ console.log(chalk.yellow(' Usage: /users set <id>'));
740
+ return { handled: true };
741
+ }
742
+ const user = setActiveUser(id);
743
+ if (user) {
744
+ console.log(chalk.green(` Active user: ${user.name} (${user.id})`));
745
+ }
746
+ else {
747
+ console.log(chalk.yellow(` User not found: ${id}`));
748
+ }
749
+ return { handled: true };
750
+ }
751
+ if (action === 'meta' || action === 'metadata') {
752
+ const id = parts[1];
753
+ const key = parts[2];
754
+ const value = parts.slice(3).join(' ');
755
+ if (!id || !key) {
756
+ console.log(chalk.yellow(' Usage: /users meta <id> <key> [value]'));
757
+ return { handled: true };
758
+ }
759
+ if (value) {
760
+ setUserMetadata(id, key, value);
761
+ console.log(chalk.green(` Metadata set: ${key}=${value}`));
762
+ }
763
+ else {
764
+ const val = getUserMetadata(id, key);
765
+ console.log(chalk.dim(` ${key}: ${val || '(not set)'}`));
766
+ }
767
+ return { handled: true };
768
+ }
769
+ // Unknown subcommand
770
+ console.log(chalk.yellow(' Usage: /users [ls|add|rm|set|meta] ...'));
771
+ console.log(chalk.dim(' ls — list all users'));
772
+ console.log(chalk.dim(' add <name> [email] [role] — create user'));
773
+ console.log(chalk.dim(' rm <id> — delete user'));
774
+ console.log(chalk.dim(' set <id> — set active user'));
775
+ console.log(chalk.dim(' meta <id> <key> [value] — get/set metadata'));
776
+ return { handled: true };
777
+ }
778
+ // ── Counter ─────────────────────────────────────────
779
+ case '/count': {
780
+ const subCmd = args.trim();
781
+ if (subCmd === 'inc' || subCmd === '+') {
782
+ incrementCounter();
783
+ console.log(chalk.green(` Counter: ${getCounter()}`));
784
+ }
785
+ else if (subCmd === 'dec' || subCmd === '-') {
786
+ decrementCounter();
787
+ console.log(chalk.green(` Counter: ${getCounter()}`));
788
+ }
789
+ else if (subCmd === 'reset') {
790
+ resetCounter();
791
+ console.log(chalk.green(` Counter reset to 0`));
792
+ }
793
+ else if (subCmd === 'help') {
794
+ console.log(chalk.dim(' Usage: /count [inc|dec|reset|help]'));
795
+ console.log(chalk.dim(' inc (+) — increment counter'));
796
+ console.log(chalk.dim(' dec (-) — decrement counter'));
797
+ console.log(chalk.dim(' reset — reset counter to 0'));
798
+ console.log(chalk.dim(' help — show this help'));
799
+ }
800
+ else {
801
+ console.log(chalk.green(` Counter: ${getCounter()}`));
802
+ console.log(chalk.dim(' Use /count inc|dec|reset|help'));
803
+ }
804
+ return { handled: true };
805
+ }
806
+ // ── Language-Specific Reviews ───────────────────
807
+ case '/ts-review':
808
+ return { handled: false, injectPrompt: buildTSReviewPrompt(process.cwd(), args || undefined) };
809
+ case '/py-review':
810
+ return { handled: false, injectPrompt: buildPyReviewPrompt(process.cwd(), args || undefined) };
811
+ case '/go-review':
812
+ return { handled: false, injectPrompt: buildGoReviewPrompt(process.cwd(), args || undefined) };
813
+ case '/rust-review':
814
+ return { handled: false, injectPrompt: buildRustReviewPrompt(process.cwd(), args || undefined) };
815
+ case '/java-review':
816
+ return { handled: false, injectPrompt: buildJavaReviewPrompt(process.cwd(), args || undefined) };
817
+ case '/cpp-review':
818
+ return { handled: false, injectPrompt: buildCppReviewPrompt(process.cwd(), args || undefined) };
819
+ case '/kotlin-review':
820
+ return { handled: false, injectPrompt: buildKotlinReviewPrompt(process.cwd(), args || undefined) };
821
+ case '/php-review':
822
+ return { handled: false, injectPrompt: buildPhpReviewPrompt(process.cwd(), args || undefined) };
823
+ case '/db-review':
824
+ return { handled: false, injectPrompt: buildDbReviewPrompt(process.cwd(), args || undefined) };
825
+ case '/auto-review':
826
+ return { handled: false, injectPrompt: buildAutoReviewPrompt(process.cwd(), args || undefined) };
827
+ // ── Language-Specific Build Fixes ────────────────
828
+ case '/ts-build-fix':
829
+ return { handled: false, injectPrompt: buildTSBuildFixPrompt(process.cwd(), args || undefined) };
830
+ case '/go-build-fix':
831
+ return { handled: false, injectPrompt: buildGoBuildFixPrompt(process.cwd(), args || undefined) };
832
+ case '/rust-build-fix':
833
+ return { handled: false, injectPrompt: buildRustBuildFixPrompt(process.cwd(), args || undefined) };
834
+ case '/java-build-fix':
835
+ return { handled: false, injectPrompt: buildJavaBuildFixPrompt(process.cwd(), args || undefined) };
836
+ case '/cpp-build-fix':
837
+ return { handled: false, injectPrompt: buildCppBuildFixPrompt(process.cwd(), args || undefined) };
838
+ case '/pytorch-fix':
839
+ return { handled: false, injectPrompt: buildPyTorchBuildFixPrompt(process.cwd(), args || undefined) };
840
+ // ── Autonomous Loops & DAG ───────────────────────
841
+ case '/pr-loop':
842
+ return { handled: false, injectPrompt: buildPRLoopPrompt(process.cwd()) };
843
+ case '/multi-plan': {
844
+ if (!args) {
845
+ console.log(chalk.yellow(' Usage: /multi-plan <task description>'));
846
+ return { handled: true };
847
+ }
848
+ return { handled: false, injectPrompt: buildMultiPlanPrompt(args) };
849
+ }
850
+ case '/multi-execute': {
851
+ if (!args) {
852
+ console.log(chalk.yellow(' Usage: /multi-execute <plan>'));
853
+ return { handled: true };
854
+ }
855
+ return { handled: false, injectPrompt: buildMultiExecutePrompt(args) };
856
+ }
857
+ case '/multi-backend': {
858
+ if (!args) {
859
+ console.log(chalk.yellow(' Usage: /multi-backend <service1,service2,...>'));
860
+ return { handled: true };
861
+ }
862
+ return { handled: false, injectPrompt: buildMultiBackendPrompt(args.split(',').map(s => s.trim())) };
863
+ }
864
+ case '/multi-frontend': {
865
+ if (!args) {
866
+ console.log(chalk.yellow(' Usage: /multi-frontend <component1,component2,...>'));
867
+ return { handled: true };
868
+ }
869
+ return { handled: false, injectPrompt: buildMultiFrontendPrompt(args.split(',').map(s => s.trim())) };
870
+ }
871
+ // ── Search-First Research ────────────────────────
872
+ case '/search-first': {
873
+ if (!args) {
874
+ console.log(chalk.yellow(' Usage: /search-first <task description>'));
875
+ return { handled: true };
876
+ }
877
+ return { handled: false, injectPrompt: buildSearchFirstPrompt(args, process.cwd()) };
878
+ }
879
+ case '/docs-lookup': {
880
+ if (!args) {
881
+ console.log(chalk.yellow(' Usage: /docs-lookup <query>'));
882
+ return { handled: true };
883
+ }
884
+ return { handled: false, injectPrompt: buildDocsLookupPrompt(args, process.cwd()) };
885
+ }
886
+ // ── Codemaps ─────────────────────────────────────
887
+ case '/codemaps':
888
+ case '/codemap': {
889
+ printCodemapStatus(process.cwd());
890
+ return { handled: true };
891
+ }
892
+ case '/update-codemaps': {
893
+ const map = generateCodeMap(process.cwd());
894
+ saveCodeMap(process.cwd(), map);
895
+ printCodeMap(map);
896
+ console.log(chalk.green(' Codemap updated and saved.'));
897
+ return { handled: true };
898
+ }
899
+ // ── Skill Creation from Git ──────────────────────
900
+ case '/skill-create': {
901
+ return { handled: false, injectPrompt: buildSkillCreatePrompt(process.cwd(), args || undefined) };
902
+ }
903
+ case '/git-patterns': {
904
+ const patterns = analyzeGitPatterns(process.cwd());
905
+ if (patterns.length === 0) {
906
+ console.log(chalk.dim(' No git patterns found. Need a git repo with commit history.'));
907
+ }
908
+ else {
909
+ printGitPatterns(patterns);
910
+ }
911
+ return { handled: true };
912
+ }
913
+ case '/git-workflow': {
914
+ printGitWorkflowSummary(process.cwd());
915
+ return { handled: true };
916
+ }
917
+ // ── Content Engine ───────────────────────────────
918
+ case '/article': {
919
+ if (!args) {
920
+ console.log(chalk.yellow(' Usage: /article <topic> [--audience <who>] [--tone <tone>]'));
921
+ return { handled: true };
922
+ }
923
+ return { handled: false, injectPrompt: buildArticlePrompt(args) };
924
+ }
925
+ case '/slides': {
926
+ if (!args) {
927
+ console.log(chalk.yellow(' Usage: /slides <topic> [count]'));
928
+ return { handled: true };
929
+ }
930
+ const slideParts = args.match(/^(.+?)\s+(\d+)$/);
931
+ const slideTopic = slideParts ? slideParts[1] : args;
932
+ const slideCount = slideParts ? parseInt(slideParts[2], 10) : 10;
933
+ return { handled: false, injectPrompt: buildSlidePrompt(slideTopic, slideCount) };
934
+ }
935
+ case '/repurpose': {
936
+ if (!args) {
937
+ console.log(chalk.yellow(' Usage: /repurpose <content description>'));
938
+ return { handled: true };
939
+ }
940
+ return { handled: false, injectPrompt: buildContentRepurposePrompt(args, ['twitter', 'linkedin', 'blog']) };
941
+ }
942
+ case '/market-research': {
943
+ if (!args) {
944
+ console.log(chalk.yellow(' Usage: /market-research <market/topic>'));
945
+ return { handled: true };
946
+ }
947
+ return { handled: false, injectPrompt: buildMarketResearchPrompt(args) };
948
+ }
949
+ case '/investor-deck': {
950
+ if (!args) {
951
+ console.log(chalk.yellow(' Usage: /investor-deck <company description>'));
952
+ return { handled: true };
953
+ }
954
+ return { handled: false, injectPrompt: buildInvestorDeckPrompt(args) };
955
+ }
956
+ case '/investor-outreach': {
957
+ if (!args) {
958
+ console.log(chalk.yellow(' Usage: /investor-outreach <company description>'));
959
+ return { handled: true };
960
+ }
961
+ const outreachParts = args.split('--investor').map(s => s.trim());
962
+ const companyDesc = outreachParts[0] || args;
963
+ const investorName = outreachParts[1] || 'target investor';
964
+ return { handled: false, injectPrompt: buildInvestorOutreachPrompt(investorName, companyDesc) };
965
+ }
966
+ case '/code-quality':
967
+ return { handled: false, injectPrompt: buildCodeQualityPrompt(process.cwd()) };
968
+ case '/skill-stocktake':
969
+ return { handled: false, injectPrompt: buildSkillStocktakePrompt() };
970
+ case '/chief-of-staff': {
971
+ if (!args) {
972
+ console.log(chalk.yellow(' Usage: /chief-of-staff <context/priorities>'));
973
+ return { handled: true };
974
+ }
975
+ return { handled: false, injectPrompt: buildChiefOfStaffPrompt(args) };
976
+ }
977
+ // ── Hook Controls ────────────────────────────────
978
+ case '/hook-profile':
979
+ printHookControlStatus();
980
+ return { handled: true };
981
+ // ── PM2 Service Management ───────────────────────
982
+ case '/pm2': {
983
+ if (!isPM2Available()) {
984
+ console.log(chalk.yellow(' PM2 not installed. Run: npm install -g pm2'));
985
+ return { handled: true };
986
+ }
987
+ if (!args) {
988
+ console.log(listPM2Services(process.cwd()));
989
+ return { handled: true };
990
+ }
991
+ return { handled: false, injectPrompt: buildPM2Prompt(args) };
992
+ }
993
+ // ── Detection ────────────────────────────────────
994
+ case '/detect': {
995
+ const pm = detectPackageManager(process.cwd());
996
+ const tr = detectTestRunner(process.cwd());
997
+ const bt = detectBuildTool(process.cwd());
998
+ console.log(chalk.cyan('\n Project Detection:'));
999
+ console.log(chalk.dim(` Package Manager: ${pm.name} (${pm.command})`));
1000
+ console.log(chalk.dim(` Test Runner: ${tr.name} (${tr.command})`));
1001
+ console.log(chalk.dim(` Build Tool: ${bt.name} (${bt.command})`));
1002
+ console.log();
1003
+ return { handled: true };
1004
+ }
1005
+ // ── Export ────────────────────────────────────────
1006
+ case '/export': {
1007
+ if (!messages.length) {
1008
+ console.log(chalk.yellow(' No conversation to export.'));
1009
+ return { handled: true };
1010
+ }
1011
+ const format = args.trim() || 'md';
1012
+ if (!['md', 'json', 'txt'].includes(format)) {
1013
+ console.log(chalk.yellow(` Unknown format: ${format}. Use: md, json, or txt`));
1014
+ return { handled: true };
1015
+ }
1016
+ const filepath = saveExport(messages, format);
1017
+ console.log(chalk.green(` Exported to: ${filepath}`));
1018
+ return { handled: true };
1019
+ }
1020
+ // ── Walkthrough / guided tour ─────────────────────
1021
+ case '/walkthrough':
1022
+ case '/tour':
1023
+ case '/guide':
1024
+ return { handled: false, injectPrompt: buildWalkthroughPrompt() };
1025
+ // ── ECC (everything-claude-code) ──────────────────
1026
+ case '/ecc':
1027
+ printEccStatus();
1028
+ return { handled: true };
1029
+ case '/ecc-install': {
1030
+ if (!eccResourcesAvailable()) {
1031
+ console.log(chalk.yellow(' ECC resources not bundled with this Crowcoder install.'));
1032
+ return { handled: true };
1033
+ }
1034
+ const report = installEcc({ verbose: true });
1035
+ if (report.errors.length > 5) {
1036
+ console.log(chalk.dim(` +${report.errors.length - 5} more errors suppressed.`));
1037
+ }
1038
+ return { handled: true };
1039
+ }
1040
+ case '/ecc-skills':
1041
+ printEccSkills();
1042
+ return { handled: true };
1043
+ case '/ecc-agents':
1044
+ printEccAgents();
1045
+ return { handled: true };
1046
+ case '/ecc-commands':
1047
+ printEccCommandList();
1048
+ return { handled: true };
1049
+ // ── Config (trigger wizard) ───────────────────────
1050
+ case '/config':
1051
+ return { handled: true, shouldExit: false };
1052
+ case '/exit':
1053
+ case '/quit':
1054
+ return { handled: true, shouldExit: true };
1055
+ // ── Default: ECC dynamic dispatch + unknown command ──
1056
+ default: {
1057
+ if (cmd.startsWith('/ecc-')) {
1058
+ const eccName = cmd.slice('/ecc-'.length);
1059
+ const prompt = getEccCommandPrompt(eccName);
1060
+ if (prompt) {
1061
+ const merged = args.trim()
1062
+ ? `${prompt}\n\n## User Input\n\n${args}`
1063
+ : prompt;
1064
+ return { handled: false, injectPrompt: merged };
1065
+ }
1066
+ const available = listEccCommands();
1067
+ console.log(chalk.yellow(` Unknown ECC command: ${cmd}`));
1068
+ if (available.length) {
1069
+ console.log(chalk.dim(` Available: ${available.map(c => `/ecc-${c}`).join(', ')}`));
1070
+ }
1071
+ return { handled: true };
1072
+ }
1073
+ console.log(chalk.dim(` Unknown command: ${cmd}. Type /help`));
1074
+ return { handled: true };
1075
+ }
1076
+ }
1077
+ }
1078
+ // ── Main ──────────────────────────────────────────────────
1079
+ async function main() {
1080
+ const rl = readline.createInterface({ input: stdin, output: stdout });
1081
+ // Initialize subsystems
1082
+ initHooksDir();
1083
+ // First-run ECC install — silent if already installed, silent if resources missing
1084
+ if (eccResourcesAvailable() && !loadEccState()) {
1085
+ try {
1086
+ const report = installEcc({ verbose: false });
1087
+ console.log(chalk.dim(` ECC ready: ${report.skills} skills, ${report.agents} agents, ${report.commands + report.prompts} commands, ${report.rules} rule sets.`));
1088
+ }
1089
+ catch (err) {
1090
+ // Never block startup on ECC failures
1091
+ console.log(chalk.dim(` ECC install skipped: ${err instanceof Error ? err.message : err}`));
1092
+ }
1093
+ }
1094
+ // Load or create config
1095
+ let config;
1096
+ if (!configExists()) {
1097
+ config = await setupWizard(rl);
1098
+ }
1099
+ else {
1100
+ config = loadConfig();
1101
+ }
1102
+ // Create session
1103
+ const mode = { current: 'dev' };
1104
+ const session = createSession(process.cwd(), config.model, config.provider, mode.current);
1105
+ const messages = [];
1106
+ // Session start hook + memory persistence
1107
+ await runHooks({ event: 'SessionStart', sessionId: session.id, cwd: process.cwd() });
1108
+ const memoryContext = onSessionStart(session.id, process.cwd());
1109
+ if (memoryContext) {
1110
+ messages.push({ role: 'system', content: memoryContext });
1111
+ }
1112
+ // Show startup display based on theme setting
1113
+ const themeMode = config.theme || 'full';
1114
+ if (themeMode === 'full') {
1115
+ // Full mode: splash + banner
1116
+ printSplash();
1117
+ printThemedBanner(config.provider, config.model, mode.current, config.permissionMode, session.id, ALL_TOOLS.map((t) => t.name));
1118
+ }
1119
+ else if (themeMode === 'compact') {
1120
+ // Compact mode: just banner
1121
+ printThemedBanner(config.provider, config.model, mode.current, config.permissionMode, session.id, ALL_TOOLS.map((t) => t.name));
1122
+ }
1123
+ else {
1124
+ // Minimal mode: just a one-liner
1125
+ console.log(theme.brandBold('Compact Agent v1.1.0') + theme.dim(' — A dense, feature-rich AI coding agent'));
1126
+ console.log('');
1127
+ }
1128
+ let autoRoute = false;
1129
+ // Main REPL loop
1130
+ while (true) {
1131
+ let input;
1132
+ try {
1133
+ const modeTag = mode.current !== 'dev' ? theme.dim(`[${mode.current}] `) : '';
1134
+ input = await rl.question(modeTag + theme.prompt(`${sym.prompt} `));
1135
+ }
1136
+ catch {
1137
+ break;
1138
+ }
1139
+ const trimmed = input.trim();
1140
+ if (!trimmed)
1141
+ continue;
1142
+ // Shell escape
1143
+ if (trimmed.startsWith('!')) {
1144
+ const { exec } = await import('node:child_process');
1145
+ const cmd = trimmed.slice(1).trim();
1146
+ if (cmd) {
1147
+ exec(cmd, { cwd: process.cwd(), maxBuffer: 5 * 1024 * 1024 }, (_err, out, err) => {
1148
+ if (out)
1149
+ console.log(out);
1150
+ if (err)
1151
+ console.error(chalk.yellow(err));
1152
+ if (_err && !out && !err)
1153
+ console.error(chalk.red(_err.message));
1154
+ });
1155
+ }
1156
+ continue;
1157
+ }
1158
+ // Slash commands
1159
+ if (trimmed.startsWith('/')) {
1160
+ const result = handleSlashCommand(trimmed, config, messages, session, mode);
1161
+ if (result.shouldExit)
1162
+ break;
1163
+ if (result.newMessages !== undefined) {
1164
+ messages.length = 0;
1165
+ messages.push(...result.newMessages);
1166
+ }
1167
+ if (trimmed.startsWith('/config') && !result?.shouldExit) {
1168
+ config = await setupWizard(rl);
1169
+ resetClient();
1170
+ printThemedBanner(config.provider, config.model, mode.current, config.permissionMode, session.id, ALL_TOOLS.map((t) => t.name));
1171
+ continue;
1172
+ }
1173
+ if (trimmed === '/route') {
1174
+ autoRoute = true;
1175
+ continue;
1176
+ }
1177
+ // Some commands inject a prompt into the conversation (e.g. /commit, /review, /tdd)
1178
+ if (result.injectPrompt) {
1179
+ messages.push({ role: 'user', content: result.injectPrompt });
1180
+ await runQuery({ config, messages, cwd: process.cwd(), rl, sessionId: session.id, mode: mode.current });
1181
+ await autoSave(session, messages);
1182
+ continue;
1183
+ }
1184
+ if (result.handled)
1185
+ continue;
1186
+ }
1187
+ // Auto-route model if enabled
1188
+ if (autoRoute) {
1189
+ const complexity = classifyComplexity(trimmed);
1190
+ const route = routeModel(config, complexity);
1191
+ if (route.model !== config.model) {
1192
+ console.log(chalk.dim(` [routing: ${route.reason}]`));
1193
+ config.model = route.model;
1194
+ resetClient();
1195
+ }
1196
+ autoRoute = false;
1197
+ }
1198
+ // Add user message and run query
1199
+ messages.push({ role: 'user', content: trimmed });
1200
+ await runQuery({
1201
+ config,
1202
+ messages,
1203
+ cwd: process.cwd(),
1204
+ rl,
1205
+ sessionId: session.id,
1206
+ mode: mode.current,
1207
+ });
1208
+ // Auto-save session
1209
+ await autoSave(session, messages);
1210
+ // Strategic compaction check
1211
+ const compactionHint = shouldSuggestCompaction(messages, 0);
1212
+ if (compactionHint) {
1213
+ console.log(chalk.yellow(` ⚡ ${compactionHint.reason} (strategy: ${compactionHint.strategy}, ~${compactionHint.estimatedSavings.toLocaleString()} tokens saveable)`));
1214
+ }
1215
+ }
1216
+ // Session stop hook + memory persistence
1217
+ onSessionEnd(session.id, messages, process.cwd());
1218
+ await runHooks({ event: 'SessionStop', sessionId: session.id, cwd: process.cwd() });
1219
+ // Final save
1220
+ await autoSave(session, messages);
1221
+ console.log(chalk.dim(`\nSession saved: ${session.id}`));
1222
+ console.log(chalk.dim('Goodbye!\n'));
1223
+ rl.close();
1224
+ process.exit(0);
1225
+ }
1226
+ main().catch((err) => {
1227
+ console.error(chalk.red(`Fatal: ${err.message || err}`));
1228
+ process.exit(1);
1229
+ });
1230
+ //# sourceMappingURL=index.js.map