claude-code-workflow 6.1.4 → 6.2.2

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 (437) hide show
  1. package/.claude/CLAUDE.md +10 -0
  2. package/.claude/agents/action-planning-agent.md +857 -778
  3. package/.claude/agents/cli-execution-agent.md +266 -269
  4. package/.claude/agents/cli-explore-agent.md +2 -2
  5. package/.claude/agents/cli-lite-planning-agent.md +142 -92
  6. package/.claude/agents/cli-planning-agent.md +4 -4
  7. package/.claude/agents/code-developer.md +7 -6
  8. package/.claude/agents/conceptual-planning-agent.md +2 -2
  9. package/.claude/agents/context-search-agent.md +31 -32
  10. package/.claude/agents/doc-generator.md +4 -4
  11. package/.claude/agents/memory-bridge.md +93 -93
  12. package/.claude/agents/test-context-search-agent.md +8 -7
  13. package/.claude/agents/test-fix-agent.md +7 -6
  14. package/.claude/commands/clean.md +516 -0
  15. package/.claude/commands/memory/compact.md +383 -0
  16. package/.claude/commands/memory/docs-full-cli.md +471 -471
  17. package/.claude/commands/memory/docs-related-cli.md +386 -386
  18. package/.claude/commands/memory/docs.md +615 -615
  19. package/.claude/commands/memory/load.md +5 -5
  20. package/.claude/commands/memory/tech-research-rules.md +310 -0
  21. package/.claude/commands/memory/update-full.md +332 -332
  22. package/.claude/commands/memory/workflow-skill-memory.md +4 -4
  23. package/.claude/commands/task/create.md +151 -151
  24. package/.claude/commands/version.md +254 -254
  25. package/.claude/commands/workflow/brainstorm/api-designer.md +587 -585
  26. package/.claude/commands/workflow/brainstorm/artifacts.md +1 -0
  27. package/.claude/commands/workflow/brainstorm/auto-parallel.md +443 -443
  28. package/.claude/commands/workflow/brainstorm/data-architect.md +220 -220
  29. package/.claude/commands/workflow/brainstorm/product-manager.md +200 -200
  30. package/.claude/commands/workflow/brainstorm/product-owner.md +200 -200
  31. package/.claude/commands/workflow/brainstorm/scrum-master.md +200 -200
  32. package/.claude/commands/workflow/brainstorm/subject-matter-expert.md +200 -200
  33. package/.claude/commands/workflow/brainstorm/system-architect.md +389 -387
  34. package/.claude/commands/workflow/brainstorm/ui-designer.md +221 -221
  35. package/.claude/commands/workflow/brainstorm/ux-expert.md +221 -221
  36. package/.claude/commands/workflow/debug.md +321 -0
  37. package/.claude/commands/workflow/execute.md +13 -0
  38. package/.claude/commands/workflow/init.md +165 -164
  39. package/.claude/commands/workflow/lite-execute.md +119 -13
  40. package/.claude/commands/workflow/lite-fix.md +623 -621
  41. package/.claude/commands/workflow/lite-plan.md +610 -592
  42. package/.claude/commands/workflow/plan.md +5 -5
  43. package/.claude/commands/workflow/review-module-cycle.md +2 -0
  44. package/.claude/commands/workflow/review-session-cycle.md +2 -0
  45. package/.claude/commands/workflow/review.md +297 -291
  46. package/.claude/commands/workflow/session/complete.md +153 -500
  47. package/.claude/commands/workflow/session/list.md +95 -95
  48. package/.claude/commands/workflow/session/resume.md +60 -60
  49. package/.claude/commands/workflow/session/start.md +199 -199
  50. package/.claude/commands/workflow/tdd-plan.md +3 -3
  51. package/.claude/commands/workflow/tdd-verify.md +23 -9
  52. package/.claude/commands/workflow/test-cycle-execute.md +2 -0
  53. package/.claude/commands/workflow/test-fix-gen.md +699 -699
  54. package/.claude/commands/workflow/tools/conflict-resolution.md +104 -18
  55. package/.claude/commands/workflow/tools/context-gather.md +436 -434
  56. package/.claude/commands/workflow/tools/task-generate-agent.md +490 -291
  57. package/.claude/commands/workflow/tools/task-generate-tdd.md +18 -10
  58. package/.claude/commands/workflow/tools/test-concept-enhanced.md +2 -1
  59. package/.claude/commands/workflow/tools/test-context-gather.md +1 -0
  60. package/.claude/commands/workflow/tools/test-task-generate.md +1 -0
  61. package/.claude/commands/workflow/ui-design/import-from-code.md +9 -6
  62. package/.claude/skills/command-guide/SKILL.md +5 -5
  63. package/.claude/skills/command-guide/index/all-commands.json +1 -1
  64. package/.claude/skills/command-guide/index/by-category.json +1 -1
  65. package/.claude/skills/command-guide/index/by-use-case.json +1 -1
  66. package/.claude/skills/command-guide/reference/agents/action-planning-agent.md +857 -778
  67. package/.claude/skills/command-guide/reference/agents/cli-execution-agent.md +266 -269
  68. package/.claude/skills/command-guide/reference/agents/cli-explore-agent.md +2 -2
  69. package/.claude/skills/command-guide/reference/agents/cli-lite-planning-agent.md +142 -92
  70. package/.claude/skills/command-guide/reference/agents/cli-planning-agent.md +4 -4
  71. package/.claude/skills/command-guide/reference/agents/code-developer.md +7 -6
  72. package/.claude/skills/command-guide/reference/agents/conceptual-planning-agent.md +2 -2
  73. package/.claude/skills/command-guide/reference/agents/context-search-agent.md +31 -32
  74. package/.claude/skills/command-guide/reference/agents/doc-generator.md +4 -4
  75. package/.claude/skills/command-guide/reference/agents/memory-bridge.md +93 -93
  76. package/.claude/skills/command-guide/reference/agents/test-context-search-agent.md +8 -7
  77. package/.claude/skills/command-guide/reference/agents/test-fix-agent.md +7 -6
  78. package/.claude/skills/command-guide/reference/commands/memory/docs-full-cli.md +471 -471
  79. package/.claude/skills/command-guide/reference/commands/memory/docs-related-cli.md +386 -386
  80. package/.claude/skills/command-guide/reference/commands/memory/docs.md +17 -16
  81. package/.claude/skills/command-guide/reference/commands/memory/load.md +5 -5
  82. package/.claude/skills/command-guide/reference/commands/memory/tech-research.md +194 -357
  83. package/.claude/skills/command-guide/reference/commands/memory/update-full.md +332 -332
  84. package/.claude/skills/command-guide/reference/commands/memory/workflow-skill-memory.md +4 -4
  85. package/.claude/skills/command-guide/reference/commands/task/create.md +151 -151
  86. package/.claude/skills/command-guide/reference/commands/version.md +254 -254
  87. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/api-designer.md +585 -585
  88. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/auto-parallel.md +443 -443
  89. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/data-architect.md +220 -220
  90. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/product-manager.md +200 -200
  91. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/product-owner.md +200 -200
  92. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/scrum-master.md +200 -200
  93. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/subject-matter-expert.md +200 -200
  94. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/system-architect.md +387 -387
  95. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/ui-designer.md +221 -221
  96. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/ux-expert.md +221 -221
  97. package/.claude/skills/command-guide/reference/commands/workflow/execute.md +25 -20
  98. package/.claude/skills/command-guide/reference/commands/workflow/init.md +164 -164
  99. package/.claude/skills/command-guide/reference/commands/workflow/lite-execute.md +748 -686
  100. package/.claude/skills/command-guide/reference/commands/workflow/lite-fix.md +664 -621
  101. package/.claude/skills/command-guide/reference/commands/workflow/lite-plan.md +645 -592
  102. package/.claude/skills/command-guide/reference/commands/workflow/plan.md +5 -5
  103. package/.claude/skills/command-guide/reference/commands/workflow/review.md +25 -18
  104. package/.claude/skills/command-guide/reference/commands/workflow/session/complete.md +547 -500
  105. package/.claude/skills/command-guide/reference/commands/workflow/session/list.md +45 -27
  106. package/.claude/skills/command-guide/reference/commands/workflow/session/resume.md +35 -19
  107. package/.claude/skills/command-guide/reference/commands/workflow/session/start.md +90 -33
  108. package/.claude/skills/command-guide/reference/commands/workflow/tdd-plan.md +3 -3
  109. package/.claude/skills/command-guide/reference/commands/workflow/tdd-verify.md +23 -9
  110. package/.claude/skills/command-guide/reference/commands/workflow/test-fix-gen.md +699 -699
  111. package/.claude/skills/command-guide/reference/commands/workflow/tools/conflict-resolution.md +103 -17
  112. package/.claude/skills/command-guide/reference/commands/workflow/tools/context-gather.md +434 -434
  113. package/.claude/skills/command-guide/reference/commands/workflow/tools/task-generate-agent.md +487 -291
  114. package/.claude/skills/command-guide/reference/commands/workflow/tools/task-generate-tdd.md +17 -10
  115. package/.claude/skills/command-guide/reference/commands/workflow/tools/test-concept-enhanced.md +1 -1
  116. package/.claude/skills/command-guide/reference/commands/workflow/ui-design/import-from-code.md +6 -6
  117. package/.claude/workflows/chinese-response.md +38 -0
  118. package/.claude/workflows/cli-templates/prompts/rules/rule-api.txt +122 -0
  119. package/.claude/workflows/cli-templates/prompts/rules/rule-components.txt +122 -0
  120. package/.claude/workflows/cli-templates/prompts/rules/rule-config.txt +89 -0
  121. package/.claude/workflows/cli-templates/prompts/rules/rule-core.txt +60 -0
  122. package/.claude/workflows/cli-templates/prompts/rules/rule-patterns.txt +70 -0
  123. package/.claude/workflows/cli-templates/prompts/rules/rule-testing.txt +81 -0
  124. package/.claude/workflows/cli-templates/prompts/rules/tech-rules-agent-prompt.txt +89 -0
  125. package/.claude/workflows/cli-templates/prompts/workflow/gemini-solution-design.txt +131 -131
  126. package/.claude/workflows/cli-templates/prompts/workflow/skill-conflict-patterns.txt +5 -9
  127. package/.claude/workflows/cli-templates/prompts/workflow/skill-lessons-learned.txt +5 -9
  128. package/.claude/workflows/cli-templates/protocols/analysis-protocol.md +112 -0
  129. package/.claude/workflows/cli-templates/protocols/write-protocol.md +201 -0
  130. package/.claude/workflows/cli-templates/schemas/conflict-resolution-schema.json +137 -0
  131. package/.claude/workflows/cli-templates/schemas/debug-log-json-schema.json +127 -0
  132. package/.claude/workflows/cli-templates/schemas/fix-plan-json-schema.json +25 -0
  133. package/.claude/workflows/cli-templates/schemas/plan-json-schema.json +25 -0
  134. package/.claude/workflows/cli-tools-usage.md +526 -0
  135. package/{CLAUDE.md → .claude/workflows/coding-philosophy.md} +24 -45
  136. package/.claude/workflows/context-tools.md +84 -0
  137. package/.claude/workflows/file-modification.md +64 -0
  138. package/.claude/workflows/tool-strategy.md +216 -79
  139. package/.claude/workflows/windows-platform.md +16 -0
  140. package/.claude/workflows/workflow-architecture.md +942 -942
  141. package/.codex/AGENTS.md +63 -330
  142. package/.codex/prompts/debug.md +318 -0
  143. package/.codex/prompts/execute.md +273 -0
  144. package/.codex/prompts/lite-execute.md +164 -0
  145. package/.codex/prompts/lite-plan.md +469 -0
  146. package/.codex/prompts.zip +0 -0
  147. package/.gemini/GEMINI.md +25 -164
  148. package/.qwen/QWEN.md +0 -139
  149. package/README.md +29 -9
  150. package/ccw/README.md +30 -6
  151. package/ccw/bin/ccw-mcp.js +7 -0
  152. package/ccw/bin/ccw.js +9 -9
  153. package/ccw/package.json +65 -47
  154. package/ccw/src/.workflow/.cli-history/history.db +0 -0
  155. package/ccw/src/.workflow/.cli-history/history.db-shm +0 -0
  156. package/ccw/src/.workflow/.cli-history/history.db-wal +0 -0
  157. package/ccw/src/cli.ts +244 -0
  158. package/ccw/src/commands/cli.ts +740 -0
  159. package/ccw/src/commands/core-memory.ts +770 -0
  160. package/ccw/src/commands/hook.ts +315 -0
  161. package/ccw/src/commands/install.ts +519 -0
  162. package/ccw/src/commands/{list.js → list.ts} +1 -1
  163. package/ccw/src/commands/memory.ts +1090 -0
  164. package/ccw/src/commands/{serve.js → serve.ts} +14 -5
  165. package/ccw/src/commands/session-path-resolver.ts +372 -0
  166. package/ccw/src/commands/session.ts +1141 -0
  167. package/ccw/src/commands/{stop.js → stop.ts} +16 -6
  168. package/ccw/src/commands/tool.ts +201 -0
  169. package/ccw/src/commands/{uninstall.js → uninstall.ts} +89 -40
  170. package/ccw/src/commands/{upgrade.js → upgrade.ts} +68 -23
  171. package/ccw/src/commands/{view.js → view.ts} +22 -8
  172. package/ccw/src/config/storage-paths.ts +670 -0
  173. package/ccw/src/core/cache-manager.ts +294 -0
  174. package/ccw/src/core/claude-freshness.ts +319 -0
  175. package/ccw/src/core/core-memory-store.ts +1528 -0
  176. package/ccw/src/core/{dashboard-generator-patch.js → dashboard-generator-patch.ts} +18 -0
  177. package/ccw/src/core/{dashboard-generator.js → dashboard-generator.ts} +69 -12
  178. package/ccw/src/core/data-aggregator.ts +584 -0
  179. package/ccw/src/core/history-importer.ts +625 -0
  180. package/ccw/src/core/{lite-scanner.js → lite-scanner-complete.ts} +162 -66
  181. package/ccw/src/core/lite-scanner.ts +469 -0
  182. package/ccw/src/core/{manifest.js → manifest.ts} +104 -34
  183. package/ccw/src/core/memory-embedder-bridge.ts +262 -0
  184. package/ccw/src/core/memory-store.ts +978 -0
  185. package/ccw/src/core/routes/ccw-routes.ts +96 -0
  186. package/ccw/src/core/routes/claude-routes.ts +1183 -0
  187. package/ccw/src/core/routes/cli-routes.ts +561 -0
  188. package/ccw/src/core/routes/codexlens-routes.ts +806 -0
  189. package/ccw/src/core/routes/core-memory-routes.ts +605 -0
  190. package/ccw/src/core/routes/files-routes.ts +428 -0
  191. package/ccw/src/core/routes/graph-routes.md +164 -0
  192. package/ccw/src/core/routes/graph-routes.ts +626 -0
  193. package/ccw/src/core/routes/help-routes.ts +308 -0
  194. package/ccw/src/core/routes/hooks-routes.ts +405 -0
  195. package/ccw/src/core/routes/mcp-routes.ts +1271 -0
  196. package/ccw/src/core/routes/mcp-routes.ts.backup +550 -0
  197. package/ccw/src/core/routes/mcp-templates-db.ts +268 -0
  198. package/ccw/src/core/routes/memory-routes.ts +1206 -0
  199. package/ccw/src/core/routes/rules-routes.ts +526 -0
  200. package/ccw/src/core/routes/session-routes.ts +467 -0
  201. package/ccw/src/core/routes/skills-routes.ts +599 -0
  202. package/ccw/src/core/routes/status-routes.ts +57 -0
  203. package/ccw/src/core/routes/system-routes.ts +427 -0
  204. package/ccw/src/core/server.ts +431 -0
  205. package/ccw/src/core/session-clustering-service.ts +1258 -0
  206. package/ccw/src/core/session-scanner.ts +283 -0
  207. package/ccw/src/core/websocket.ts +190 -0
  208. package/ccw/src/{index.js → index.ts} +1 -0
  209. package/ccw/src/mcp-server/index.ts +186 -0
  210. package/ccw/src/templates/assets/css/github-dark.min.css +10 -0
  211. package/ccw/src/templates/assets/css/github.min.css +10 -0
  212. package/ccw/src/templates/assets/js/cytoscape.min.js +32 -0
  213. package/ccw/src/templates/assets/js/d3.min.js +2 -0
  214. package/ccw/src/templates/assets/js/highlight.min.js +1244 -0
  215. package/ccw/src/templates/assets/js/lucide.min.js +12 -0
  216. package/ccw/src/templates/assets/js/marked.min.js +69 -0
  217. package/ccw/src/templates/assets/js/tailwind.js +83 -0
  218. package/ccw/src/templates/dashboard-css/01-base.css +11 -0
  219. package/ccw/src/templates/dashboard-css/02-session.css +22 -0
  220. package/ccw/src/templates/dashboard-css/04-lite-tasks.css +10 -0
  221. package/ccw/src/templates/dashboard-css/06-cards.css +10 -4
  222. package/ccw/src/templates/dashboard-css/07-managers.css +1178 -7
  223. package/ccw/src/templates/dashboard-css/09-explorer.css +23 -12
  224. package/ccw/src/templates/dashboard-css/10-cli-status.css +337 -0
  225. package/ccw/src/templates/dashboard-css/11-cli-history.css +271 -0
  226. package/ccw/src/templates/dashboard-css/12-cli-legacy.css +796 -0
  227. package/ccw/src/templates/dashboard-css/13-cli-ccw.css +199 -0
  228. package/ccw/src/templates/dashboard-css/14-cli-modals.css +258 -0
  229. package/ccw/src/templates/dashboard-css/15-cli-endpoints.css +305 -0
  230. package/ccw/src/templates/dashboard-css/16-cli-session.css +241 -0
  231. package/ccw/src/templates/dashboard-css/17-cli-conversation.css +283 -0
  232. package/ccw/src/templates/dashboard-css/18-cli-settings.css +160 -0
  233. package/ccw/src/templates/dashboard-css/19-cli-native-session.css +496 -0
  234. package/ccw/src/templates/dashboard-css/20-cli-taskqueue.css +188 -0
  235. package/ccw/src/templates/dashboard-css/21-cli-toolmgmt.css +310 -0
  236. package/ccw/src/templates/dashboard-css/22-cli-semantic.css +240 -0
  237. package/ccw/src/templates/dashboard-css/23-memory.css +2390 -0
  238. package/ccw/src/templates/dashboard-css/24-prompt-history.css +1089 -0
  239. package/ccw/src/templates/dashboard-css/25-skills-rules.css +326 -0
  240. package/ccw/src/templates/dashboard-css/26-claude-manager.css +908 -0
  241. package/ccw/src/templates/dashboard-css/27-graph-explorer.css +1678 -0
  242. package/ccw/src/templates/dashboard-css/28-mcp-manager.css +748 -0
  243. package/ccw/src/templates/dashboard-css/29-help.css +264 -0
  244. package/ccw/src/templates/dashboard-css/30-core-memory.css +1700 -0
  245. package/ccw/src/templates/dashboard-js/api.js +162 -142
  246. package/ccw/src/templates/dashboard-js/components/carousel.js +4 -4
  247. package/ccw/src/templates/dashboard-js/components/cli-history.js +876 -0
  248. package/ccw/src/templates/dashboard-js/components/cli-status.js +978 -0
  249. package/ccw/src/templates/dashboard-js/components/global-notifications.js +508 -219
  250. package/ccw/src/templates/dashboard-js/components/hook-manager.js +1277 -282
  251. package/ccw/src/templates/dashboard-js/components/index-manager.js +302 -0
  252. package/ccw/src/templates/dashboard-js/components/mcp-manager.js +718 -27
  253. package/ccw/src/templates/dashboard-js/components/modals.js +66 -0
  254. package/ccw/src/templates/dashboard-js/components/navigation.js +80 -12
  255. package/ccw/src/templates/dashboard-js/components/notifications.js +758 -194
  256. package/ccw/src/templates/dashboard-js/components/storage-manager.js +478 -0
  257. package/ccw/src/templates/dashboard-js/components/tabs-other.js +157 -6
  258. package/ccw/src/templates/dashboard-js/components/task-queue-sidebar.js +716 -0
  259. package/ccw/src/templates/dashboard-js/help-i18n.js +272 -0
  260. package/ccw/src/templates/dashboard-js/i18n.js +2807 -0
  261. package/ccw/src/templates/dashboard-js/main.js +15 -0
  262. package/ccw/src/templates/dashboard-js/state.js +243 -42
  263. package/ccw/src/templates/dashboard-js/utils.js +47 -1
  264. package/ccw/src/templates/dashboard-js/views/claude-manager.js +912 -0
  265. package/ccw/src/templates/dashboard-js/views/cli-manager.js +2272 -0
  266. package/ccw/src/templates/dashboard-js/views/codexlens-manager.js +964 -0
  267. package/ccw/src/templates/dashboard-js/views/core-memory-clusters.js +503 -0
  268. package/ccw/src/templates/dashboard-js/views/core-memory.js +782 -0
  269. package/ccw/src/templates/dashboard-js/views/explorer.js +888 -852
  270. package/ccw/src/templates/dashboard-js/views/graph-explorer.js +1157 -0
  271. package/ccw/src/templates/dashboard-js/views/help.js +856 -0
  272. package/ccw/src/templates/dashboard-js/views/history.js +337 -0
  273. package/ccw/src/templates/dashboard-js/views/home.js +61 -15
  274. package/ccw/src/templates/dashboard-js/views/hook-manager.js +311 -43
  275. package/ccw/src/templates/dashboard-js/views/lite-tasks.js +204 -28
  276. package/ccw/src/templates/dashboard-js/views/mcp-manager.js +2187 -411
  277. package/ccw/src/templates/dashboard-js/views/mcp-manager.js.backup +1729 -0
  278. package/ccw/src/templates/dashboard-js/views/mcp-manager.js.new +928 -0
  279. package/ccw/src/templates/dashboard-js/views/memory.js +1221 -0
  280. package/ccw/src/templates/dashboard-js/views/prompt-history.js +713 -0
  281. package/ccw/src/templates/dashboard-js/views/rules-manager.js +828 -0
  282. package/ccw/src/templates/dashboard-js/views/session-detail.js +54 -53
  283. package/ccw/src/templates/dashboard-js/views/skills-manager.js +819 -0
  284. package/ccw/src/templates/dashboard.html +185 -85
  285. package/ccw/src/templates/hooks-config-example.json +60 -0
  286. package/ccw/src/tools/classify-folders.ts +245 -0
  287. package/ccw/src/tools/cli-config-manager.ts +268 -0
  288. package/ccw/src/tools/cli-executor.ts +2014 -0
  289. package/ccw/src/tools/cli-history-store.ts +1195 -0
  290. package/ccw/src/tools/codex-lens.ts +1141 -0
  291. package/ccw/src/tools/{convert-tokens-to-css.js → convert-tokens-to-css.ts} +73 -23
  292. package/ccw/src/tools/core-memory.ts +444 -0
  293. package/ccw/src/tools/detect-changed-modules.ts +325 -0
  294. package/ccw/src/tools/{discover-design-files.js → discover-design-files.ts} +74 -24
  295. package/ccw/src/tools/edit-file.ts +568 -0
  296. package/ccw/src/tools/{generate-module-docs.js → generate-module-docs.ts} +207 -185
  297. package/ccw/src/tools/{get-modules-by-depth.js → get-modules-by-depth.ts} +120 -79
  298. package/ccw/src/tools/index.ts +370 -0
  299. package/ccw/src/tools/native-session-discovery.ts +795 -0
  300. package/ccw/src/tools/notifier.ts +129 -0
  301. package/ccw/src/tools/read-file.ts +410 -0
  302. package/ccw/src/tools/resume-strategy.ts +345 -0
  303. package/ccw/src/tools/session-content-parser.ts +619 -0
  304. package/ccw/src/tools/session-manager.ts +1026 -0
  305. package/ccw/src/tools/smart-context.ts +228 -0
  306. package/ccw/src/tools/smart-search.ts +2065 -0
  307. package/ccw/src/tools/smart-search.ts.backup +1233 -0
  308. package/ccw/src/tools/storage-manager.ts +455 -0
  309. package/ccw/src/tools/write-file.ts +222 -0
  310. package/ccw/src/types/config.ts +11 -0
  311. package/ccw/src/types/index.ts +3 -0
  312. package/ccw/src/types/session.ts +25 -0
  313. package/ccw/src/types/tool.ts +41 -0
  314. package/ccw/src/utils/{browser-launcher.js → browser-launcher.ts} +10 -8
  315. package/ccw/src/utils/file-utils.ts +48 -0
  316. package/ccw/src/utils/{path-resolver.js → path-resolver.ts} +114 -78
  317. package/ccw/src/utils/path-validator.ts +153 -0
  318. package/ccw/src/utils/{ui.js → ui.ts} +32 -25
  319. package/codex-lens/pyproject.toml +48 -0
  320. package/codex-lens/src/codexlens/.workflow/.cli-history/history.db +0 -0
  321. package/codex-lens/src/codexlens/__init__.py +28 -0
  322. package/codex-lens/src/codexlens/__main__.py +14 -0
  323. package/codex-lens/src/codexlens/__pycache__/__init__.cpython-313.pyc +0 -0
  324. package/codex-lens/src/codexlens/__pycache__/__main__.cpython-313.pyc +0 -0
  325. package/codex-lens/src/codexlens/__pycache__/config.cpython-313.pyc +0 -0
  326. package/codex-lens/src/codexlens/__pycache__/entities.cpython-313.pyc +0 -0
  327. package/codex-lens/src/codexlens/__pycache__/errors.cpython-313.pyc +0 -0
  328. package/codex-lens/src/codexlens/cli/__init__.py +27 -0
  329. package/codex-lens/src/codexlens/cli/__pycache__/__init__.cpython-313.pyc +0 -0
  330. package/codex-lens/src/codexlens/cli/__pycache__/commands.cpython-313.pyc +0 -0
  331. package/codex-lens/src/codexlens/cli/__pycache__/embedding_manager.cpython-313.pyc +0 -0
  332. package/codex-lens/src/codexlens/cli/__pycache__/model_manager.cpython-313.pyc +0 -0
  333. package/codex-lens/src/codexlens/cli/__pycache__/output.cpython-313.pyc +0 -0
  334. package/codex-lens/src/codexlens/cli/commands.py +1931 -0
  335. package/codex-lens/src/codexlens/cli/embedding_manager.py +620 -0
  336. package/codex-lens/src/codexlens/cli/model_manager.py +289 -0
  337. package/codex-lens/src/codexlens/cli/output.py +124 -0
  338. package/codex-lens/src/codexlens/config.py +201 -0
  339. package/codex-lens/src/codexlens/entities.py +121 -0
  340. package/codex-lens/src/codexlens/errors.py +55 -0
  341. package/codex-lens/src/codexlens/indexing/README.md +77 -0
  342. package/codex-lens/src/codexlens/indexing/__init__.py +4 -0
  343. package/codex-lens/src/codexlens/indexing/__pycache__/__init__.cpython-313.pyc +0 -0
  344. package/codex-lens/src/codexlens/indexing/__pycache__/symbol_extractor.cpython-313.pyc +0 -0
  345. package/codex-lens/src/codexlens/indexing/symbol_extractor.py +243 -0
  346. package/codex-lens/src/codexlens/parsers/__init__.py +8 -0
  347. package/codex-lens/src/codexlens/parsers/__pycache__/__init__.cpython-313.pyc +0 -0
  348. package/codex-lens/src/codexlens/parsers/__pycache__/encoding.cpython-313.pyc +0 -0
  349. package/codex-lens/src/codexlens/parsers/__pycache__/factory.cpython-313.pyc +0 -0
  350. package/codex-lens/src/codexlens/parsers/__pycache__/tokenizer.cpython-313.pyc +0 -0
  351. package/codex-lens/src/codexlens/parsers/__pycache__/treesitter_parser.cpython-313.pyc +0 -0
  352. package/codex-lens/src/codexlens/parsers/encoding.py +202 -0
  353. package/codex-lens/src/codexlens/parsers/factory.py +256 -0
  354. package/codex-lens/src/codexlens/parsers/tokenizer.py +98 -0
  355. package/codex-lens/src/codexlens/parsers/treesitter_parser.py +335 -0
  356. package/codex-lens/src/codexlens/search/__init__.py +15 -0
  357. package/codex-lens/src/codexlens/search/__pycache__/__init__.cpython-313.pyc +0 -0
  358. package/codex-lens/src/codexlens/search/__pycache__/chain_search.cpython-313.pyc +0 -0
  359. package/codex-lens/src/codexlens/search/__pycache__/enrichment.cpython-313.pyc +0 -0
  360. package/codex-lens/src/codexlens/search/__pycache__/hybrid_search.cpython-313.pyc +0 -0
  361. package/codex-lens/src/codexlens/search/__pycache__/query_parser.cpython-313.pyc +0 -0
  362. package/codex-lens/src/codexlens/search/__pycache__/ranking.cpython-313.pyc +0 -0
  363. package/codex-lens/src/codexlens/search/chain_search.py +647 -0
  364. package/codex-lens/src/codexlens/search/enrichment.py +150 -0
  365. package/codex-lens/src/codexlens/search/hybrid_search.py +313 -0
  366. package/codex-lens/src/codexlens/search/query_parser.py +242 -0
  367. package/codex-lens/src/codexlens/search/ranking.py +274 -0
  368. package/codex-lens/src/codexlens/semantic/__init__.py +39 -0
  369. package/codex-lens/src/codexlens/semantic/__pycache__/__init__.cpython-313.pyc +0 -0
  370. package/codex-lens/src/codexlens/semantic/__pycache__/ann_index.cpython-313.pyc +0 -0
  371. package/codex-lens/src/codexlens/semantic/__pycache__/chunker.cpython-313.pyc +0 -0
  372. package/codex-lens/src/codexlens/semantic/__pycache__/code_extractor.cpython-313.pyc +0 -0
  373. package/codex-lens/src/codexlens/semantic/__pycache__/embedder.cpython-313.pyc +0 -0
  374. package/codex-lens/src/codexlens/semantic/__pycache__/graph_analyzer.cpython-313.pyc +0 -0
  375. package/codex-lens/src/codexlens/semantic/__pycache__/llm_enhancer.cpython-313.pyc +0 -0
  376. package/codex-lens/src/codexlens/semantic/__pycache__/vector_store.cpython-313.pyc +0 -0
  377. package/codex-lens/src/codexlens/semantic/ann_index.py +414 -0
  378. package/codex-lens/src/codexlens/semantic/chunker.py +448 -0
  379. package/codex-lens/src/codexlens/semantic/code_extractor.py +274 -0
  380. package/codex-lens/src/codexlens/semantic/embedder.py +185 -0
  381. package/codex-lens/src/codexlens/semantic/vector_store.py +955 -0
  382. package/codex-lens/src/codexlens/storage/__init__.py +29 -0
  383. package/codex-lens/src/codexlens/storage/__pycache__/__init__.cpython-313.pyc +0 -0
  384. package/codex-lens/src/codexlens/storage/__pycache__/dir_index.cpython-313.pyc +0 -0
  385. package/codex-lens/src/codexlens/storage/__pycache__/file_cache.cpython-313.pyc +0 -0
  386. package/codex-lens/src/codexlens/storage/__pycache__/index_tree.cpython-313.pyc +0 -0
  387. package/codex-lens/src/codexlens/storage/__pycache__/migration_manager.cpython-313.pyc +0 -0
  388. package/codex-lens/src/codexlens/storage/__pycache__/path_mapper.cpython-313.pyc +0 -0
  389. package/codex-lens/src/codexlens/storage/__pycache__/registry.cpython-313.pyc +0 -0
  390. package/codex-lens/src/codexlens/storage/__pycache__/sqlite_store.cpython-313.pyc +0 -0
  391. package/codex-lens/src/codexlens/storage/__pycache__/sqlite_utils.cpython-313.pyc +0 -0
  392. package/codex-lens/src/codexlens/storage/dir_index.py +1850 -0
  393. package/codex-lens/src/codexlens/storage/file_cache.py +32 -0
  394. package/codex-lens/src/codexlens/storage/index_tree.py +776 -0
  395. package/codex-lens/src/codexlens/storage/migration_manager.py +154 -0
  396. package/codex-lens/src/codexlens/storage/migrations/__init__.py +1 -0
  397. package/codex-lens/src/codexlens/storage/migrations/__pycache__/__init__.cpython-313.pyc +0 -0
  398. package/codex-lens/src/codexlens/storage/migrations/__pycache__/migration_001_normalize_keywords.cpython-313.pyc +0 -0
  399. package/codex-lens/src/codexlens/storage/migrations/__pycache__/migration_002_add_token_metadata.cpython-313.pyc +0 -0
  400. package/codex-lens/src/codexlens/storage/migrations/__pycache__/migration_003_code_relationships.cpython-313.pyc +0 -0
  401. package/codex-lens/src/codexlens/storage/migrations/__pycache__/migration_004_dual_fts.cpython-313.pyc +0 -0
  402. package/codex-lens/src/codexlens/storage/migrations/__pycache__/migration_005_cleanup_unused_fields.cpython-313.pyc +0 -0
  403. package/codex-lens/src/codexlens/storage/migrations/migration_001_normalize_keywords.py +123 -0
  404. package/codex-lens/src/codexlens/storage/migrations/migration_002_add_token_metadata.py +48 -0
  405. package/codex-lens/src/codexlens/storage/migrations/migration_004_dual_fts.py +232 -0
  406. package/codex-lens/src/codexlens/storage/migrations/migration_005_cleanup_unused_fields.py +196 -0
  407. package/codex-lens/src/codexlens/storage/path_mapper.py +274 -0
  408. package/codex-lens/src/codexlens/storage/registry.py +670 -0
  409. package/codex-lens/src/codexlens/storage/sqlite_store.py +576 -0
  410. package/codex-lens/src/codexlens/storage/sqlite_utils.py +64 -0
  411. package/package.json +4 -1
  412. package/.claude/commands/memory/tech-research.md +0 -477
  413. package/.claude/scripts/classify-folders.sh +0 -39
  414. package/.claude/scripts/convert_tokens_to_css.sh +0 -229
  415. package/.claude/scripts/detect_changed_modules.sh +0 -161
  416. package/.claude/scripts/discover-design-files.sh +0 -87
  417. package/.claude/scripts/extract-animations.js +0 -243
  418. package/.claude/scripts/extract-computed-styles.js +0 -118
  419. package/.claude/scripts/extract-layout-structure.js +0 -411
  420. package/.claude/scripts/generate_module_docs.sh +0 -717
  421. package/.claude/scripts/get_modules_by_depth.sh +0 -170
  422. package/.claude/scripts/ui-generate-preview.sh +0 -395
  423. package/.claude/scripts/ui-instantiate-prototypes.sh +0 -815
  424. package/.claude/scripts/update_module_claude.sh +0 -337
  425. package/.claude/workflows/context-search-strategy.md +0 -77
  426. package/.claude/workflows/intelligent-tools-strategy.md +0 -662
  427. package/ccw/src/cli.js +0 -119
  428. package/ccw/src/commands/install.js +0 -324
  429. package/ccw/src/commands/tool.js +0 -138
  430. package/ccw/src/core/data-aggregator.js +0 -409
  431. package/ccw/src/core/server.js +0 -2063
  432. package/ccw/src/core/session-scanner.js +0 -235
  433. package/ccw/src/tools/classify-folders.js +0 -204
  434. package/ccw/src/tools/detect-changed-modules.js +0 -288
  435. package/ccw/src/tools/edit-file.js +0 -266
  436. package/ccw/src/tools/index.js +0 -176
  437. package/ccw/src/utils/file-utils.js +0 -48
@@ -0,0 +1,568 @@
1
+ /**
2
+ * Edit File Tool - AI-focused file editing
3
+ * Two complementary modes:
4
+ * - update: Content-driven text replacement (AI primary use)
5
+ * - line: Position-driven line operations (precise control)
6
+ *
7
+ * Features:
8
+ * - dryRun mode for previewing changes
9
+ * - Git-style diff output
10
+ * - Multi-edit support in update mode
11
+ * - Auto line-ending adaptation (CRLF/LF)
12
+ */
13
+
14
+ import { z } from 'zod';
15
+ import type { ToolSchema, ToolResult } from '../types/tool.js';
16
+ import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs';
17
+ import { resolve, isAbsolute, dirname } from 'path';
18
+ import { validatePath } from '../utils/path-validator.js';
19
+
20
+ // Define Zod schemas for validation
21
+ const EditItemSchema = z.object({
22
+ oldText: z.string(),
23
+ newText: z.string(),
24
+ });
25
+
26
+ const ParamsSchema = z.object({
27
+ path: z.string().min(1, 'Path is required'),
28
+ mode: z.enum(['update', 'line']).default('update'),
29
+ dryRun: z.boolean().default(false),
30
+ // Update mode params
31
+ oldText: z.string().optional(),
32
+ newText: z.string().optional(),
33
+ edits: z.array(EditItemSchema).optional(),
34
+ replaceAll: z.boolean().optional(),
35
+ // Line mode params
36
+ operation: z.enum(['insert_before', 'insert_after', 'replace', 'delete']).optional(),
37
+ line: z.number().optional(),
38
+ end_line: z.number().optional(),
39
+ text: z.string().optional(),
40
+ });
41
+
42
+ type Params = z.infer<typeof ParamsSchema>;
43
+ type EditItem = z.infer<typeof EditItemSchema>;
44
+
45
+ interface UpdateModeResult {
46
+ content: string;
47
+ modified: boolean;
48
+ status: string;
49
+ replacements: number;
50
+ editResults: Array<Record<string, unknown>>;
51
+ diff: string;
52
+ dryRun: boolean;
53
+ message: string;
54
+ }
55
+
56
+ // Max lines to show in diff preview
57
+ const MAX_DIFF_LINES = 15;
58
+
59
+ interface LineModeResult {
60
+ content: string;
61
+ modified: boolean;
62
+ operation: string;
63
+ line: number;
64
+ end_line?: number;
65
+ message: string;
66
+ }
67
+
68
+ // Internal type for mode results (content excluded in final output)
69
+
70
+ /**
71
+ * Resolve file path and read content
72
+ * @param filePath - Path to file
73
+ * @returns Resolved path and content
74
+ */
75
+ async function readFile(filePath: string): Promise<{ resolvedPath: string; content: string }> {
76
+ const resolvedPath = await validatePath(filePath, { mustExist: true });
77
+
78
+ if (!existsSync(resolvedPath)) {
79
+ throw new Error(`File not found: ${resolvedPath}`);
80
+ }
81
+
82
+ try {
83
+ const content = readFileSync(resolvedPath, 'utf8');
84
+ return { resolvedPath, content };
85
+ } catch (error) {
86
+ throw new Error(`Failed to read file: ${(error as Error).message}`);
87
+ }
88
+ }
89
+
90
+ /**
91
+ * Write content to file with optional parent directory creation
92
+ * @param filePath - Path to file
93
+ * @param content - Content to write
94
+ * @param createDirs - Create parent directories if needed
95
+ */
96
+ function writeFile(filePath: string, content: string, createDirs = false): void {
97
+ try {
98
+ if (createDirs) {
99
+ const dir = dirname(filePath);
100
+ if (!existsSync(dir)) {
101
+ mkdirSync(dir, { recursive: true });
102
+ }
103
+ }
104
+ writeFileSync(filePath, content, 'utf8');
105
+ } catch (error) {
106
+ throw new Error(`Failed to write file: ${(error as Error).message}`);
107
+ }
108
+ }
109
+
110
+ /**
111
+ * Normalize line endings to LF
112
+ * @param text - Input text
113
+ * @returns Text with LF line endings
114
+ */
115
+ function normalizeLineEndings(text: string): string {
116
+ return text.replace(/\r\n/g, '\n');
117
+ }
118
+
119
+ /**
120
+ * Create unified diff between two strings
121
+ * @param original - Original content
122
+ * @param modified - Modified content
123
+ * @param filePath - File path for diff header
124
+ * @returns Unified diff string
125
+ */
126
+ function createUnifiedDiff(original: string, modified: string, filePath: string): string {
127
+ const origLines = normalizeLineEndings(original).split('\n');
128
+ const modLines = normalizeLineEndings(modified).split('\n');
129
+
130
+ const diffLines = [`--- a/${filePath}`, `+++ b/${filePath}`];
131
+
132
+ // Simple diff algorithm - find changes
133
+ let i = 0,
134
+ j = 0;
135
+ let hunk: string[] = [];
136
+ let origStart = 0;
137
+ let modStart = 0;
138
+
139
+ while (i < origLines.length || j < modLines.length) {
140
+ if (i < origLines.length && j < modLines.length && origLines[i] === modLines[j]) {
141
+ // Context line
142
+ if (hunk.length > 0) {
143
+ hunk.push(` ${origLines[i]}`);
144
+ }
145
+ i++;
146
+ j++;
147
+ } else {
148
+ // Start or continue hunk
149
+ if (hunk.length === 0) {
150
+ origStart = i + 1;
151
+ modStart = j + 1;
152
+ // Add context before
153
+ const contextStart = Math.max(0, i - 3);
154
+ for (let c = contextStart; c < i; c++) {
155
+ hunk.push(` ${origLines[c]}`);
156
+ }
157
+ origStart = contextStart + 1;
158
+ modStart = contextStart + 1;
159
+ }
160
+
161
+ // Find where lines match again
162
+ let foundMatch = false;
163
+ for (let lookAhead = 1; lookAhead <= 10; lookAhead++) {
164
+ if (
165
+ i + lookAhead < origLines.length &&
166
+ j < modLines.length &&
167
+ origLines[i + lookAhead] === modLines[j]
168
+ ) {
169
+ // Remove lines from original
170
+ for (let r = 0; r < lookAhead; r++) {
171
+ hunk.push(`-${origLines[i + r]}`);
172
+ }
173
+ i += lookAhead;
174
+ foundMatch = true;
175
+ break;
176
+ }
177
+ if (
178
+ j + lookAhead < modLines.length &&
179
+ i < origLines.length &&
180
+ modLines[j + lookAhead] === origLines[i]
181
+ ) {
182
+ // Add lines to modified
183
+ for (let a = 0; a < lookAhead; a++) {
184
+ hunk.push(`+${modLines[j + a]}`);
185
+ }
186
+ j += lookAhead;
187
+ foundMatch = true;
188
+ break;
189
+ }
190
+ }
191
+
192
+ if (!foundMatch) {
193
+ // Replace line
194
+ if (i < origLines.length) {
195
+ hunk.push(`-${origLines[i]}`);
196
+ i++;
197
+ }
198
+ if (j < modLines.length) {
199
+ hunk.push(`+${modLines[j]}`);
200
+ j++;
201
+ }
202
+ }
203
+ }
204
+
205
+ // Flush hunk if we've had 3 context lines after changes
206
+ const lastChangeIdx = hunk.findLastIndex((l) => l.startsWith('+') || l.startsWith('-'));
207
+ if (lastChangeIdx >= 0 && hunk.length - lastChangeIdx > 3) {
208
+ const origCount = hunk.filter((l) => !l.startsWith('+')).length;
209
+ const modCount = hunk.filter((l) => !l.startsWith('-')).length;
210
+ diffLines.push(`@@ -${origStart},${origCount} +${modStart},${modCount} @@`);
211
+ diffLines.push(...hunk);
212
+ hunk = [];
213
+ }
214
+ }
215
+
216
+ // Flush remaining hunk
217
+ if (hunk.length > 0) {
218
+ const origCount = hunk.filter((l) => !l.startsWith('+')).length;
219
+ const modCount = hunk.filter((l) => !l.startsWith('-')).length;
220
+ diffLines.push(`@@ -${origStart},${origCount} +${modStart},${modCount} @@`);
221
+ diffLines.push(...hunk);
222
+ }
223
+
224
+ return diffLines.length > 2 ? diffLines.join('\n') : '';
225
+ }
226
+
227
+ /**
228
+ * Mode: update - Simple text replacement
229
+ * Auto-adapts line endings (CRLF/LF)
230
+ * Supports multiple edits via 'edits' array
231
+ */
232
+ function executeUpdateMode(content: string, params: Params, filePath: string): UpdateModeResult {
233
+ const { oldText, newText, replaceAll, edits, dryRun = false } = params;
234
+
235
+ // Detect original line ending
236
+ const hasCRLF = content.includes('\r\n');
237
+ const normalizedContent = normalizeLineEndings(content);
238
+ const originalContent = normalizedContent;
239
+
240
+ let newContent = normalizedContent;
241
+ let replacements = 0;
242
+ const editResults: Array<Record<string, unknown>> = [];
243
+
244
+ // Support multiple edits via 'edits' array
245
+ const editOperations: EditItem[] =
246
+ edits || (oldText !== undefined ? [{ oldText, newText: newText || '' }] : []);
247
+
248
+ if (editOperations.length === 0) {
249
+ throw new Error('Either "oldText/newText" or "edits" array is required for update mode');
250
+ }
251
+
252
+ for (const edit of editOperations) {
253
+ const normalizedOld = normalizeLineEndings(edit.oldText || '');
254
+ const normalizedNew = normalizeLineEndings(edit.newText || '');
255
+
256
+ if (!normalizedOld) {
257
+ editResults.push({ status: 'error', message: 'Empty oldText' });
258
+ continue;
259
+ }
260
+
261
+ if (newContent.includes(normalizedOld)) {
262
+ if (replaceAll) {
263
+ const parts = newContent.split(normalizedOld);
264
+ const count = parts.length - 1;
265
+ newContent = parts.join(normalizedNew);
266
+ replacements += count;
267
+ editResults.push({ status: 'replaced_all', count });
268
+ } else {
269
+ newContent = newContent.replace(normalizedOld, normalizedNew);
270
+ replacements += 1;
271
+ editResults.push({ status: 'replaced', count: 1 });
272
+ }
273
+ } else {
274
+ // Try fuzzy match (trimmed whitespace)
275
+ const lines = newContent.split('\n');
276
+ const oldLines = normalizedOld.split('\n');
277
+ let matchFound = false;
278
+
279
+ for (let i = 0; i <= lines.length - oldLines.length; i++) {
280
+ const potentialMatch = lines.slice(i, i + oldLines.length);
281
+ const isMatch = oldLines.every(
282
+ (oldLine, j) => oldLine.trim() === potentialMatch[j].trim()
283
+ );
284
+
285
+ if (isMatch) {
286
+ // Preserve indentation of first line
287
+ const indent = lines[i].match(/^\s*/)?.[0] || '';
288
+ const newLines = normalizedNew.split('\n').map((line, j) => {
289
+ if (j === 0) return indent + line.trimStart();
290
+ return line;
291
+ });
292
+ lines.splice(i, oldLines.length, ...newLines);
293
+ newContent = lines.join('\n');
294
+ replacements += 1;
295
+ editResults.push({ status: 'replaced_fuzzy', count: 1 });
296
+ matchFound = true;
297
+ break;
298
+ }
299
+ }
300
+
301
+ if (!matchFound) {
302
+ editResults.push({ status: 'not_found', oldText: normalizedOld.substring(0, 50) });
303
+ }
304
+ }
305
+ }
306
+
307
+ // Restore original line ending
308
+ if (hasCRLF) {
309
+ newContent = newContent.replace(/\n/g, '\r\n');
310
+ }
311
+
312
+ // Generate diff if content changed
313
+ let diff = '';
314
+ if (originalContent !== normalizeLineEndings(newContent)) {
315
+ diff = createUnifiedDiff(originalContent, normalizeLineEndings(newContent), filePath);
316
+ }
317
+
318
+ return {
319
+ content: newContent,
320
+ modified: content !== newContent,
321
+ status: replacements > 0 ? 'replaced' : 'not found',
322
+ replacements,
323
+ editResults,
324
+ diff,
325
+ dryRun,
326
+ message:
327
+ replacements > 0
328
+ ? `${replacements} replacement(s) made${dryRun ? ' (dry run)' : ''}`
329
+ : 'No matches found',
330
+ };
331
+ }
332
+
333
+ /**
334
+ * Mode: line - Line-based operations
335
+ * Operations: insert_before, insert_after, replace, delete
336
+ */
337
+ function executeLineMode(content: string, params: Params): LineModeResult {
338
+ const { operation, line, text, end_line } = params;
339
+
340
+ if (!operation) throw new Error('Parameter "operation" is required for line mode');
341
+ if (line === undefined) throw new Error('Parameter "line" is required for line mode');
342
+
343
+ // Detect original line ending and normalize for processing
344
+ const hasCRLF = content.includes('\r\n');
345
+ const normalizedContent = hasCRLF ? content.replace(/\r\n/g, '\n') : content;
346
+
347
+ const lines = normalizedContent.split('\n');
348
+ const lineIndex = line - 1; // Convert to 0-based
349
+
350
+ if (lineIndex < 0 || lineIndex >= lines.length) {
351
+ throw new Error(`Line ${line} out of range (1-${lines.length})`);
352
+ }
353
+
354
+ const newLines = [...lines];
355
+ let message = '';
356
+
357
+ switch (operation) {
358
+ case 'insert_before':
359
+ if (text === undefined) throw new Error('Parameter "text" is required for insert_before');
360
+ newLines.splice(lineIndex, 0, text);
361
+ message = `Inserted before line ${line}`;
362
+ break;
363
+
364
+ case 'insert_after':
365
+ if (text === undefined) throw new Error('Parameter "text" is required for insert_after');
366
+ newLines.splice(lineIndex + 1, 0, text);
367
+ message = `Inserted after line ${line}`;
368
+ break;
369
+
370
+ case 'replace': {
371
+ if (text === undefined) throw new Error('Parameter "text" is required for replace');
372
+ const endIdx = end_line ? end_line - 1 : lineIndex;
373
+ if (endIdx < lineIndex || endIdx >= lines.length) {
374
+ throw new Error(`end_line ${end_line} is invalid`);
375
+ }
376
+ const deleteCount = endIdx - lineIndex + 1;
377
+ newLines.splice(lineIndex, deleteCount, text);
378
+ message = end_line ? `Replaced lines ${line}-${end_line}` : `Replaced line ${line}`;
379
+ break;
380
+ }
381
+
382
+ case 'delete': {
383
+ const endDelete = end_line ? end_line - 1 : lineIndex;
384
+ if (endDelete < lineIndex || endDelete >= lines.length) {
385
+ throw new Error(`end_line ${end_line} is invalid`);
386
+ }
387
+ const count = endDelete - lineIndex + 1;
388
+ newLines.splice(lineIndex, count);
389
+ message = end_line ? `Deleted lines ${line}-${end_line}` : `Deleted line ${line}`;
390
+ break;
391
+ }
392
+
393
+ default:
394
+ throw new Error(
395
+ `Unknown operation: ${operation}. Valid: insert_before, insert_after, replace, delete`
396
+ );
397
+ }
398
+
399
+ let newContent = newLines.join('\n');
400
+
401
+ // Restore original line endings
402
+ if (hasCRLF) {
403
+ newContent = newContent.replace(/\n/g, '\r\n');
404
+ }
405
+
406
+ return {
407
+ content: newContent,
408
+ modified: content !== newContent,
409
+ operation,
410
+ line,
411
+ end_line,
412
+ message,
413
+ };
414
+ }
415
+
416
+ // Tool schema for MCP
417
+ export const schema: ToolSchema = {
418
+ name: 'edit_file',
419
+ description: `Edit file using two modes: "update" for text replacement (default) and "line" for line-based operations.
420
+
421
+ Usage (update mode):
422
+ edit_file(path="f.js", oldText="old", newText="new")
423
+ edit_file(path="f.js", edits=[{oldText:"a",newText:"b"},{oldText:"c",newText:"d"}])
424
+
425
+ Usage (line mode):
426
+ edit_file(path="f.js", mode="line", operation="insert_after", line=10, text="new line")
427
+ edit_file(path="f.js", mode="line", operation="delete", line=5, end_line=8)
428
+
429
+ Options: dryRun=true (preview diff), replaceAll=true (update mode only)`,
430
+ inputSchema: {
431
+ type: 'object',
432
+ properties: {
433
+ path: {
434
+ type: 'string',
435
+ description: 'Path to the file to modify',
436
+ },
437
+ mode: {
438
+ type: 'string',
439
+ enum: ['update', 'line'],
440
+ description: 'Edit mode (default: update)',
441
+ default: 'update',
442
+ },
443
+ dryRun: {
444
+ type: 'boolean',
445
+ description: 'Preview changes using git-style diff without modifying file (default: false)',
446
+ default: false,
447
+ },
448
+ // Update mode params
449
+ oldText: {
450
+ type: 'string',
451
+ description: '[update mode] Text to find and replace (use oldText/newText OR edits array)',
452
+ },
453
+ newText: {
454
+ type: 'string',
455
+ description: '[update mode] Replacement text',
456
+ },
457
+ edits: {
458
+ type: 'array',
459
+ description: '[update mode] Array of {oldText, newText} for multiple replacements',
460
+ items: {
461
+ type: 'object',
462
+ properties: {
463
+ oldText: { type: 'string', description: 'Text to search for - must match exactly' },
464
+ newText: { type: 'string', description: 'Text to replace with' },
465
+ },
466
+ required: ['oldText', 'newText'],
467
+ },
468
+ },
469
+ replaceAll: {
470
+ type: 'boolean',
471
+ description: '[update mode] Replace all occurrences of oldText (default: false)',
472
+ },
473
+ // Line mode params
474
+ operation: {
475
+ type: 'string',
476
+ enum: ['insert_before', 'insert_after', 'replace', 'delete'],
477
+ description: '[line mode] Line operation type',
478
+ },
479
+ line: {
480
+ type: 'number',
481
+ description: '[line mode] Line number (1-based)',
482
+ },
483
+ end_line: {
484
+ type: 'number',
485
+ description: '[line mode] End line for range operations',
486
+ },
487
+ text: {
488
+ type: 'string',
489
+ description: '[line mode] Text for insert/replace operations',
490
+ },
491
+ },
492
+ required: ['path'],
493
+ },
494
+ };
495
+
496
+ /**
497
+ * Truncate diff to max lines with indicator
498
+ */
499
+ function truncateDiff(diff: string, maxLines: number): string {
500
+ if (!diff) return '';
501
+ const lines = diff.split('\n');
502
+ if (lines.length <= maxLines) return diff;
503
+ return lines.slice(0, maxLines).join('\n') + `\n... (+${lines.length - maxLines} more lines)`;
504
+ }
505
+
506
+ /**
507
+ * Build compact result for output
508
+ */
509
+ interface CompactEditResult {
510
+ path: string;
511
+ modified: boolean;
512
+ message: string;
513
+ replacements?: number;
514
+ diff?: string;
515
+ dryRun?: boolean;
516
+ }
517
+
518
+ // Handler function
519
+ export async function handler(params: Record<string, unknown>): Promise<ToolResult<CompactEditResult>> {
520
+ const parsed = ParamsSchema.safeParse(params);
521
+ if (!parsed.success) {
522
+ return { success: false, error: `Invalid params: ${parsed.error.message}` };
523
+ }
524
+
525
+ const { path: filePath, mode = 'update', dryRun = false } = parsed.data;
526
+
527
+ try {
528
+ const { resolvedPath, content } = await readFile(filePath);
529
+
530
+ let result: UpdateModeResult | LineModeResult;
531
+ switch (mode) {
532
+ case 'update':
533
+ result = executeUpdateMode(content, parsed.data, filePath);
534
+ break;
535
+ case 'line':
536
+ result = executeLineMode(content, parsed.data);
537
+ break;
538
+ default:
539
+ throw new Error(`Unknown mode: ${mode}. Valid modes: update, line`);
540
+ }
541
+
542
+ // Write if modified and not dry run
543
+ if (result.modified && !dryRun) {
544
+ writeFile(resolvedPath, result.content);
545
+ }
546
+
547
+ // Build compact result
548
+ const compactResult: CompactEditResult = {
549
+ path: resolvedPath,
550
+ modified: result.modified,
551
+ message: result.message,
552
+ };
553
+
554
+ // Add mode-specific fields
555
+ if ('replacements' in result) {
556
+ compactResult.replacements = result.replacements;
557
+ compactResult.dryRun = result.dryRun;
558
+ // Truncate diff for compact output
559
+ if (result.diff) {
560
+ compactResult.diff = truncateDiff(result.diff, MAX_DIFF_LINES);
561
+ }
562
+ }
563
+
564
+ return { success: true, result: compactResult };
565
+ } catch (error) {
566
+ return { success: false, error: (error as Error).message };
567
+ }
568
+ }