claude-code-workflow 6.3.18 → 6.3.20

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 (832) hide show
  1. package/.claude/CLAUDE.md +8 -5
  2. package/.claude/agents/action-planning-agent.md +26 -2
  3. package/.claude/agents/code-developer.md +132 -43
  4. package/.claude/agents/debug-explore-agent.md +434 -0
  5. package/.claude/agents/issue-plan-agent.md +31 -2
  6. package/.claude/agents/test-fix-agent.md +14 -0
  7. package/.claude/commands/issue/discover.md +41 -0
  8. package/.claude/commands/issue/execute.md +200 -19
  9. package/.claude/commands/issue/new.md +93 -3
  10. package/.claude/commands/issue/plan.md +9 -3
  11. package/.claude/commands/issue/queue.md +94 -39
  12. package/.claude/commands/memory/swagger-docs.md +773 -0
  13. package/.claude/commands/workflow/brainstorm/auto-parallel.md +21 -21
  14. package/.claude/commands/workflow/execute.md +54 -34
  15. package/.claude/commands/workflow/lite-execute.md +48 -164
  16. package/.claude/commands/workflow/lite-fix.md +4 -4
  17. package/.claude/commands/workflow/lite-plan.md +5 -5
  18. package/.claude/commands/workflow/plan.md +27 -27
  19. package/.claude/commands/workflow/review.md +42 -17
  20. package/.claude/commands/workflow/tdd-plan.md +25 -25
  21. package/.claude/commands/workflow/test-fix-gen.md +10 -10
  22. package/.claude/commands/workflow/test-gen.md +14 -14
  23. package/.claude/commands/workflow/ui-design/explore-auto.md +21 -21
  24. package/.claude/commands/workflow/ui-design/imitate-auto.md +24 -24
  25. package/.claude/skills/_shared/SKILL-DESIGN-SPEC.md +693 -0
  26. package/.claude/skills/ccw/SKILL.md +462 -0
  27. package/.claude/skills/ccw/index/command-capabilities.json +127 -0
  28. package/.claude/skills/ccw/index/intent-rules.json +136 -0
  29. package/.claude/skills/ccw/index/workflow-chains.json +451 -0
  30. package/.claude/skills/ccw/phases/actions/bugfix.md +218 -0
  31. package/.claude/skills/ccw/phases/actions/coupled.md +194 -0
  32. package/.claude/skills/ccw/phases/actions/docs.md +93 -0
  33. package/.claude/skills/ccw/phases/actions/full.md +154 -0
  34. package/.claude/skills/ccw/phases/actions/issue.md +201 -0
  35. package/.claude/skills/ccw/phases/actions/rapid.md +104 -0
  36. package/.claude/skills/ccw/phases/actions/review-fix.md +84 -0
  37. package/.claude/skills/ccw/phases/actions/tdd.md +66 -0
  38. package/.claude/skills/ccw/phases/actions/ui.md +79 -0
  39. package/.claude/skills/ccw/phases/orchestrator.md +435 -0
  40. package/.claude/skills/ccw/specs/intent-classification.md +336 -0
  41. package/.claude/skills/ccw-help/SKILL.md +177 -0
  42. package/.claude/skills/ccw-help/index/all-agents.json +82 -0
  43. package/.claude/skills/{command-guide → ccw-help}/index/all-commands.json +183 -73
  44. package/.claude/skills/{command-guide → ccw-help}/index/by-category.json +187 -73
  45. package/.claude/skills/{command-guide → ccw-help}/index/by-use-case.json +295 -185
  46. package/.claude/skills/{command-guide → ccw-help}/index/command-relationships.json +19 -166
  47. package/.claude/skills/{command-guide → ccw-help}/index/essential-commands.json +10 -10
  48. package/.claude/skills/ccw-help/scripts/analyze_commands.py +337 -0
  49. package/.claude/skills/code-reviewer/README.md +340 -0
  50. package/.claude/skills/code-reviewer/SKILL.md +308 -0
  51. package/.claude/skills/code-reviewer/phases/01-code-discovery.md +246 -0
  52. package/.claude/skills/code-reviewer/phases/02-security-analysis.md +442 -0
  53. package/.claude/skills/code-reviewer/phases/03-best-practices-review.md +36 -0
  54. package/.claude/skills/code-reviewer/phases/04-report-generation.md +278 -0
  55. package/.claude/skills/code-reviewer/specs/best-practices-requirements.md +346 -0
  56. package/.claude/skills/code-reviewer/specs/quality-standards.md +252 -0
  57. package/.claude/skills/code-reviewer/specs/security-requirements.md +243 -0
  58. package/.claude/skills/code-reviewer/templates/best-practice-finding.md +234 -0
  59. package/.claude/skills/code-reviewer/templates/report-template.md +316 -0
  60. package/.claude/skills/code-reviewer/templates/security-finding.md +161 -0
  61. package/.claude/skills/skill-generator/SKILL.md +187 -0
  62. package/.claude/skills/skill-generator/phases/01-requirements-discovery.md +239 -0
  63. package/.claude/skills/skill-generator/phases/02-structure-generation.md +207 -0
  64. package/.claude/skills/skill-generator/phases/03-phase-generation.md +802 -0
  65. package/.claude/skills/skill-generator/phases/04-specs-templates.md +328 -0
  66. package/.claude/skills/skill-generator/phases/05-validation.md +334 -0
  67. package/.claude/skills/skill-generator/specs/cli-integration.md +448 -0
  68. package/.claude/skills/skill-generator/specs/execution-modes.md +396 -0
  69. package/.claude/skills/skill-generator/specs/scripting-integration.md +265 -0
  70. package/.claude/skills/skill-generator/specs/skill-requirements.md +466 -0
  71. package/.claude/skills/skill-generator/templates/autonomous-action.md +517 -0
  72. package/.claude/skills/skill-generator/templates/autonomous-orchestrator.md +276 -0
  73. package/.claude/skills/skill-generator/templates/code-analysis-action.md +503 -0
  74. package/.claude/skills/skill-generator/templates/llm-action.md +355 -0
  75. package/.claude/skills/skill-generator/templates/script-bash.md +277 -0
  76. package/.claude/skills/skill-generator/templates/script-python.md +198 -0
  77. package/.claude/skills/skill-generator/templates/sequential-phase.md +441 -0
  78. package/.claude/skills/skill-generator/templates/skill-md.md +156 -0
  79. package/.claude/workflows/chinese-response.md +15 -28
  80. package/.claude/workflows/cli-templates/prompts/documentation/swagger-api.txt +266 -0
  81. package/.claude/workflows/cli-tools-usage.md +221 -177
  82. package/.claude/workflows/windows-platform.md +13 -10
  83. package/.codex/prompts/issue-execute.md +310 -82
  84. package/.codex/prompts/issue-queue.md +22 -0
  85. package/.codex/prompts/lite-execute.md +36 -11
  86. package/README.md +309 -305
  87. package/ccw/README.md +10 -4
  88. package/ccw/dist/cli.d.ts.map +1 -1
  89. package/ccw/dist/cli.js +4 -1
  90. package/ccw/dist/cli.js.map +1 -1
  91. package/ccw/dist/commands/cli.d.ts.map +1 -1
  92. package/ccw/dist/commands/cli.js +131 -34
  93. package/ccw/dist/commands/cli.js.map +1 -1
  94. package/ccw/dist/commands/issue.d.ts +152 -0
  95. package/ccw/dist/commands/issue.d.ts.map +1 -1
  96. package/ccw/dist/commands/issue.js +550 -85
  97. package/ccw/dist/commands/issue.js.map +1 -1
  98. package/ccw/dist/commands/serve.d.ts +1 -0
  99. package/ccw/dist/commands/serve.d.ts.map +1 -1
  100. package/ccw/dist/commands/serve.js +12 -5
  101. package/ccw/dist/commands/serve.js.map +1 -1
  102. package/ccw/dist/commands/stop.d.ts.map +1 -1
  103. package/ccw/dist/commands/stop.js +29 -5
  104. package/ccw/dist/commands/stop.js.map +1 -1
  105. package/ccw/dist/commands/tool.d.ts.map +1 -1
  106. package/ccw/dist/commands/tool.js +19 -2
  107. package/ccw/dist/commands/tool.js.map +1 -1
  108. package/ccw/dist/commands/view.d.ts +1 -0
  109. package/ccw/dist/commands/view.d.ts.map +1 -1
  110. package/ccw/dist/commands/view.js +10 -3
  111. package/ccw/dist/commands/view.js.map +1 -1
  112. package/ccw/dist/config/cli-settings-manager.d.ts +86 -0
  113. package/ccw/dist/config/cli-settings-manager.d.ts.map +1 -0
  114. package/ccw/dist/config/cli-settings-manager.js +392 -0
  115. package/ccw/dist/config/cli-settings-manager.js.map +1 -0
  116. package/ccw/dist/config/litellm-api-config-manager.d.ts +71 -5
  117. package/ccw/dist/config/litellm-api-config-manager.d.ts.map +1 -1
  118. package/ccw/dist/config/litellm-api-config-manager.js +290 -20
  119. package/ccw/dist/config/litellm-api-config-manager.js.map +1 -1
  120. package/ccw/dist/core/auth/csrf-manager.d.ts +18 -0
  121. package/ccw/dist/core/auth/csrf-manager.d.ts.map +1 -0
  122. package/ccw/dist/core/auth/csrf-manager.js +80 -0
  123. package/ccw/dist/core/auth/csrf-manager.js.map +1 -0
  124. package/ccw/dist/core/auth/csrf-middleware.d.ts +8 -0
  125. package/ccw/dist/core/auth/csrf-middleware.d.ts.map +1 -0
  126. package/ccw/dist/core/auth/csrf-middleware.js +141 -0
  127. package/ccw/dist/core/auth/csrf-middleware.js.map +1 -0
  128. package/ccw/dist/core/auth/middleware.d.ts +15 -0
  129. package/ccw/dist/core/auth/middleware.d.ts.map +1 -0
  130. package/ccw/dist/core/auth/middleware.js +76 -0
  131. package/ccw/dist/core/auth/middleware.js.map +1 -0
  132. package/ccw/dist/core/auth/token-manager.d.ts +41 -0
  133. package/ccw/dist/core/auth/token-manager.d.ts.map +1 -0
  134. package/ccw/dist/core/auth/token-manager.js +171 -0
  135. package/ccw/dist/core/auth/token-manager.js.map +1 -0
  136. package/ccw/dist/core/cache-manager.d.ts +6 -6
  137. package/ccw/dist/core/cache-manager.d.ts.map +1 -1
  138. package/ccw/dist/core/cache-manager.js +70 -48
  139. package/ccw/dist/core/cache-manager.js.map +1 -1
  140. package/ccw/dist/core/claude-freshness.d.ts.map +1 -1
  141. package/ccw/dist/core/claude-freshness.js +23 -3
  142. package/ccw/dist/core/claude-freshness.js.map +1 -1
  143. package/ccw/dist/core/core-memory-store.d.ts.map +1 -1
  144. package/ccw/dist/core/core-memory-store.js +2 -1
  145. package/ccw/dist/core/core-memory-store.js.map +1 -1
  146. package/ccw/dist/core/cors.d.ts +3 -0
  147. package/ccw/dist/core/cors.d.ts.map +1 -0
  148. package/ccw/dist/core/cors.js +10 -0
  149. package/ccw/dist/core/cors.js.map +1 -0
  150. package/ccw/dist/core/dashboard-generator-patch.js +0 -1
  151. package/ccw/dist/core/dashboard-generator-patch.js.map +1 -1
  152. package/ccw/dist/core/dashboard-generator.d.ts.map +1 -1
  153. package/ccw/dist/core/dashboard-generator.js +417 -416
  154. package/ccw/dist/core/dashboard-generator.js.map +1 -1
  155. package/ccw/dist/core/data-aggregator.js +2 -2
  156. package/ccw/dist/core/data-aggregator.js.map +1 -1
  157. package/ccw/dist/core/lite-scanner.d.ts +1 -1
  158. package/ccw/dist/core/lite-scanner.d.ts.map +1 -1
  159. package/ccw/dist/core/lite-scanner.js +130 -127
  160. package/ccw/dist/core/lite-scanner.js.map +1 -1
  161. package/ccw/dist/core/routes/auth-routes.d.ts +12 -0
  162. package/ccw/dist/core/routes/auth-routes.d.ts.map +1 -0
  163. package/ccw/dist/core/routes/auth-routes.js +80 -0
  164. package/ccw/dist/core/routes/auth-routes.js.map +1 -0
  165. package/ccw/dist/core/routes/ccw-routes.d.ts +1 -14
  166. package/ccw/dist/core/routes/ccw-routes.d.ts.map +1 -1
  167. package/ccw/dist/core/routes/ccw-routes.js +9 -4
  168. package/ccw/dist/core/routes/ccw-routes.js.map +1 -1
  169. package/ccw/dist/core/routes/claude-routes.d.ts +1 -14
  170. package/ccw/dist/core/routes/claude-routes.d.ts.map +1 -1
  171. package/ccw/dist/core/routes/claude-routes.js +98 -39
  172. package/ccw/dist/core/routes/claude-routes.js.map +1 -1
  173. package/ccw/dist/core/routes/cli-routes.d.ts +14 -12
  174. package/ccw/dist/core/routes/cli-routes.d.ts.map +1 -1
  175. package/ccw/dist/core/routes/cli-routes.js +122 -43
  176. package/ccw/dist/core/routes/cli-routes.js.map +1 -1
  177. package/ccw/dist/core/routes/cli-settings-routes.d.ts +11 -0
  178. package/ccw/dist/core/routes/cli-settings-routes.d.ts.map +1 -0
  179. package/ccw/dist/core/routes/cli-settings-routes.js +204 -0
  180. package/ccw/dist/core/routes/cli-settings-routes.js.map +1 -0
  181. package/ccw/dist/core/routes/codexlens/config-handlers.d.ts +6 -0
  182. package/ccw/dist/core/routes/codexlens/config-handlers.d.ts.map +1 -0
  183. package/ccw/dist/core/routes/codexlens/config-handlers.js +1195 -0
  184. package/ccw/dist/core/routes/codexlens/config-handlers.js.map +1 -0
  185. package/ccw/dist/core/routes/codexlens/index-handlers.d.ts +10 -0
  186. package/ccw/dist/core/routes/codexlens/index-handlers.d.ts.map +1 -0
  187. package/ccw/dist/core/routes/codexlens/index-handlers.js +322 -0
  188. package/ccw/dist/core/routes/codexlens/index-handlers.js.map +1 -0
  189. package/ccw/dist/core/routes/codexlens/semantic-handlers.d.ts +6 -0
  190. package/ccw/dist/core/routes/codexlens/semantic-handlers.d.ts.map +1 -0
  191. package/ccw/dist/core/routes/codexlens/semantic-handlers.js +865 -0
  192. package/ccw/dist/core/routes/codexlens/semantic-handlers.js.map +1 -0
  193. package/ccw/dist/core/routes/codexlens/utils.d.ts +23 -0
  194. package/ccw/dist/core/routes/codexlens/utils.d.ts.map +1 -0
  195. package/ccw/dist/core/routes/codexlens/utils.js +85 -0
  196. package/ccw/dist/core/routes/codexlens/utils.js.map +1 -0
  197. package/ccw/dist/core/routes/codexlens/watcher-handlers.d.ts +13 -0
  198. package/ccw/dist/core/routes/codexlens/watcher-handlers.d.ts.map +1 -0
  199. package/ccw/dist/core/routes/codexlens/watcher-handlers.js +235 -0
  200. package/ccw/dist/core/routes/codexlens/watcher-handlers.js.map +1 -0
  201. package/ccw/dist/core/routes/codexlens-routes.d.ts +2 -11
  202. package/ccw/dist/core/routes/codexlens-routes.d.ts.map +1 -1
  203. package/ccw/dist/core/routes/codexlens-routes.js +10 -981
  204. package/ccw/dist/core/routes/codexlens-routes.js.map +1 -1
  205. package/ccw/dist/core/routes/discovery-routes.d.ts +1 -35
  206. package/ccw/dist/core/routes/discovery-routes.d.ts.map +1 -1
  207. package/ccw/dist/core/routes/discovery-routes.js +25 -0
  208. package/ccw/dist/core/routes/discovery-routes.js.map +1 -1
  209. package/ccw/dist/core/routes/files-routes.d.ts +1 -14
  210. package/ccw/dist/core/routes/files-routes.d.ts.map +1 -1
  211. package/ccw/dist/core/routes/files-routes.js +57 -14
  212. package/ccw/dist/core/routes/files-routes.js.map +1 -1
  213. package/ccw/dist/core/routes/graph-routes.d.ts +1 -14
  214. package/ccw/dist/core/routes/graph-routes.d.ts.map +1 -1
  215. package/ccw/dist/core/routes/graph-routes.js +36 -37
  216. package/ccw/dist/core/routes/graph-routes.js.map +1 -1
  217. package/ccw/dist/core/routes/help-routes.d.ts +1 -14
  218. package/ccw/dist/core/routes/help-routes.d.ts.map +1 -1
  219. package/ccw/dist/core/routes/help-routes.js +5 -0
  220. package/ccw/dist/core/routes/help-routes.js.map +1 -1
  221. package/ccw/dist/core/routes/hooks-routes.d.ts +4 -14
  222. package/ccw/dist/core/routes/hooks-routes.d.ts.map +1 -1
  223. package/ccw/dist/core/routes/hooks-routes.js +43 -21
  224. package/ccw/dist/core/routes/hooks-routes.js.map +1 -1
  225. package/ccw/dist/core/routes/issue-routes.d.ts +1 -34
  226. package/ccw/dist/core/routes/issue-routes.d.ts.map +1 -1
  227. package/ccw/dist/core/routes/issue-routes.js +24 -0
  228. package/ccw/dist/core/routes/issue-routes.js.map +1 -1
  229. package/ccw/dist/core/routes/litellm-api-routes.d.ts +1 -14
  230. package/ccw/dist/core/routes/litellm-api-routes.d.ts.map +1 -1
  231. package/ccw/dist/core/routes/litellm-api-routes.js +513 -48
  232. package/ccw/dist/core/routes/litellm-api-routes.js.map +1 -1
  233. package/ccw/dist/core/routes/litellm-routes.d.ts +1 -14
  234. package/ccw/dist/core/routes/litellm-routes.d.ts.map +1 -1
  235. package/ccw/dist/core/routes/litellm-routes.js +28 -11
  236. package/ccw/dist/core/routes/litellm-routes.js.map +1 -1
  237. package/ccw/dist/core/routes/mcp-routes.d.ts +1 -14
  238. package/ccw/dist/core/routes/mcp-routes.d.ts.map +1 -1
  239. package/ccw/dist/core/routes/mcp-routes.js +99 -30
  240. package/ccw/dist/core/routes/mcp-routes.js.map +1 -1
  241. package/ccw/dist/core/routes/mcp-templates-db.d.ts.map +1 -1
  242. package/ccw/dist/core/routes/mcp-templates-db.js +30 -31
  243. package/ccw/dist/core/routes/mcp-templates-db.js.map +1 -1
  244. package/ccw/dist/core/routes/memory-routes.d.ts.map +1 -1
  245. package/ccw/dist/core/routes/memory-routes.js +74 -24
  246. package/ccw/dist/core/routes/memory-routes.js.map +1 -1
  247. package/ccw/dist/core/routes/nav-status-routes.d.ts +3 -0
  248. package/ccw/dist/core/routes/nav-status-routes.d.ts.map +1 -0
  249. package/ccw/dist/core/routes/nav-status-routes.js +217 -0
  250. package/ccw/dist/core/routes/nav-status-routes.js.map +1 -0
  251. package/ccw/dist/core/routes/rules-routes.d.ts +1 -14
  252. package/ccw/dist/core/routes/rules-routes.d.ts.map +1 -1
  253. package/ccw/dist/core/routes/rules-routes.js +481 -58
  254. package/ccw/dist/core/routes/rules-routes.js.map +1 -1
  255. package/ccw/dist/core/routes/session-routes.d.ts +1 -14
  256. package/ccw/dist/core/routes/session-routes.d.ts.map +1 -1
  257. package/ccw/dist/core/routes/session-routes.js +15 -3
  258. package/ccw/dist/core/routes/session-routes.js.map +1 -1
  259. package/ccw/dist/core/routes/skills-routes.d.ts +1 -14
  260. package/ccw/dist/core/routes/skills-routes.d.ts.map +1 -1
  261. package/ccw/dist/core/routes/skills-routes.js +394 -112
  262. package/ccw/dist/core/routes/skills-routes.js.map +1 -1
  263. package/ccw/dist/core/routes/status-routes.d.ts +1 -14
  264. package/ccw/dist/core/routes/status-routes.d.ts.map +1 -1
  265. package/ccw/dist/core/routes/status-routes.js +4 -0
  266. package/ccw/dist/core/routes/status-routes.js.map +1 -1
  267. package/ccw/dist/core/routes/system-routes.d.ts +4 -10
  268. package/ccw/dist/core/routes/system-routes.d.ts.map +1 -1
  269. package/ccw/dist/core/routes/system-routes.js +6 -4
  270. package/ccw/dist/core/routes/system-routes.js.map +1 -1
  271. package/ccw/dist/core/routes/types.d.ts +19 -0
  272. package/ccw/dist/core/routes/types.d.ts.map +1 -0
  273. package/ccw/dist/core/routes/types.js +2 -0
  274. package/ccw/dist/core/routes/types.js.map +1 -0
  275. package/ccw/dist/core/server.d.ts.map +1 -1
  276. package/ccw/dist/core/server.js +206 -29
  277. package/ccw/dist/core/server.js.map +1 -1
  278. package/ccw/dist/core/services/api-key-tester.d.ts +42 -0
  279. package/ccw/dist/core/services/api-key-tester.d.ts.map +1 -0
  280. package/ccw/dist/core/services/api-key-tester.js +126 -0
  281. package/ccw/dist/core/services/api-key-tester.js.map +1 -0
  282. package/ccw/dist/core/services/health-check-service.d.ts +88 -0
  283. package/ccw/dist/core/services/health-check-service.d.ts.map +1 -0
  284. package/ccw/dist/core/services/health-check-service.js +293 -0
  285. package/ccw/dist/core/services/health-check-service.js.map +1 -0
  286. package/ccw/dist/core/websocket.d.ts +9 -7
  287. package/ccw/dist/core/websocket.d.ts.map +1 -1
  288. package/ccw/dist/core/websocket.js +9 -4
  289. package/ccw/dist/core/websocket.js.map +1 -1
  290. package/ccw/dist/tools/claude-cli-tools.d.ts +152 -28
  291. package/ccw/dist/tools/claude-cli-tools.d.ts.map +1 -1
  292. package/ccw/dist/tools/claude-cli-tools.js +490 -100
  293. package/ccw/dist/tools/claude-cli-tools.js.map +1 -1
  294. package/ccw/dist/tools/cli-config-manager.d.ts +24 -8
  295. package/ccw/dist/tools/cli-config-manager.d.ts.map +1 -1
  296. package/ccw/dist/tools/cli-config-manager.js +76 -156
  297. package/ccw/dist/tools/cli-config-manager.js.map +1 -1
  298. package/ccw/dist/tools/cli-executor-core.d.ts +85 -0
  299. package/ccw/dist/tools/cli-executor-core.d.ts.map +1 -0
  300. package/ccw/dist/tools/cli-executor-core.js +1310 -0
  301. package/ccw/dist/tools/cli-executor-core.js.map +1 -0
  302. package/ccw/dist/tools/cli-executor-state.d.ts +241 -0
  303. package/ccw/dist/tools/cli-executor-state.d.ts.map +1 -0
  304. package/ccw/dist/tools/cli-executor-state.js +392 -0
  305. package/ccw/dist/tools/cli-executor-state.js.map +1 -0
  306. package/ccw/dist/tools/cli-executor-utils.d.ts +36 -0
  307. package/ccw/dist/tools/cli-executor-utils.d.ts.map +1 -0
  308. package/ccw/dist/tools/cli-executor-utils.js +298 -0
  309. package/ccw/dist/tools/cli-executor-utils.js.map +1 -0
  310. package/ccw/dist/tools/cli-executor.d.ts +3 -377
  311. package/ccw/dist/tools/cli-executor.d.ts.map +1 -1
  312. package/ccw/dist/tools/cli-executor.js +3 -1884
  313. package/ccw/dist/tools/cli-executor.js.map +1 -1
  314. package/ccw/dist/tools/cli-history-store.d.ts +2 -0
  315. package/ccw/dist/tools/cli-history-store.d.ts.map +1 -1
  316. package/ccw/dist/tools/cli-history-store.js.map +1 -1
  317. package/ccw/dist/tools/cli-output-converter.d.ts +192 -0
  318. package/ccw/dist/tools/cli-output-converter.d.ts.map +1 -0
  319. package/ccw/dist/tools/cli-output-converter.js +1047 -0
  320. package/ccw/dist/tools/cli-output-converter.js.map +1 -0
  321. package/ccw/dist/tools/cli-prompt-builder.d.ts +113 -0
  322. package/ccw/dist/tools/cli-prompt-builder.d.ts.map +1 -0
  323. package/ccw/dist/tools/cli-prompt-builder.js +363 -0
  324. package/ccw/dist/tools/cli-prompt-builder.js.map +1 -0
  325. package/ccw/dist/tools/codex-lens.d.ts +15 -1
  326. package/ccw/dist/tools/codex-lens.d.ts.map +1 -1
  327. package/ccw/dist/tools/codex-lens.js +289 -55
  328. package/ccw/dist/tools/codex-lens.js.map +1 -1
  329. package/ccw/dist/tools/detect-changed-modules.d.ts.map +1 -1
  330. package/ccw/dist/tools/detect-changed-modules.js +22 -4
  331. package/ccw/dist/tools/detect-changed-modules.js.map +1 -1
  332. package/ccw/dist/tools/index.d.ts.map +1 -1
  333. package/ccw/dist/tools/index.js +2 -0
  334. package/ccw/dist/tools/index.js.map +1 -1
  335. package/ccw/dist/tools/litellm-client.d.ts.map +1 -1
  336. package/ccw/dist/tools/litellm-client.js +10 -4
  337. package/ccw/dist/tools/litellm-client.js.map +1 -1
  338. package/ccw/dist/tools/litellm-executor.d.ts +2 -4
  339. package/ccw/dist/tools/litellm-executor.d.ts.map +1 -1
  340. package/ccw/dist/tools/litellm-executor.js +39 -8
  341. package/ccw/dist/tools/litellm-executor.js.map +1 -1
  342. package/ccw/dist/tools/native-session-discovery.d.ts +2 -0
  343. package/ccw/dist/tools/native-session-discovery.d.ts.map +1 -1
  344. package/ccw/dist/tools/native-session-discovery.js +197 -1
  345. package/ccw/dist/tools/native-session-discovery.js.map +1 -1
  346. package/ccw/dist/tools/session-manager.d.ts.map +1 -1
  347. package/ccw/dist/tools/session-manager.js +79 -0
  348. package/ccw/dist/tools/session-manager.js.map +1 -1
  349. package/ccw/dist/tools/skill-context-loader.d.ts +15 -0
  350. package/ccw/dist/tools/skill-context-loader.d.ts.map +1 -0
  351. package/ccw/dist/tools/skill-context-loader.js +198 -0
  352. package/ccw/dist/tools/skill-context-loader.js.map +1 -0
  353. package/ccw/dist/tools/smart-search.d.ts +8 -3
  354. package/ccw/dist/tools/smart-search.d.ts.map +1 -1
  355. package/ccw/dist/tools/smart-search.js +378 -75
  356. package/ccw/dist/tools/smart-search.js.map +1 -1
  357. package/ccw/dist/types/cli-settings.d.ts +86 -0
  358. package/ccw/dist/types/cli-settings.d.ts.map +1 -0
  359. package/ccw/dist/types/cli-settings.js +54 -0
  360. package/ccw/dist/types/cli-settings.js.map +1 -0
  361. package/ccw/dist/types/litellm-api-config.d.ts +40 -1
  362. package/ccw/dist/types/litellm-api-config.d.ts.map +1 -1
  363. package/ccw/dist/utils/exec-constants.d.ts +25 -0
  364. package/ccw/dist/utils/exec-constants.d.ts.map +1 -0
  365. package/ccw/dist/utils/exec-constants.js +25 -0
  366. package/ccw/dist/utils/exec-constants.js.map +1 -0
  367. package/ccw/dist/utils/path-resolver.d.ts +1 -0
  368. package/ccw/dist/utils/path-resolver.d.ts.map +1 -1
  369. package/ccw/dist/utils/path-resolver.js +48 -3
  370. package/ccw/dist/utils/path-resolver.js.map +1 -1
  371. package/ccw/dist/utils/path-validator.d.ts.map +1 -1
  372. package/ccw/dist/utils/path-validator.js +25 -6
  373. package/ccw/dist/utils/path-validator.js.map +1 -1
  374. package/ccw/dist/utils/python-utils.d.ts.map +1 -1
  375. package/ccw/dist/utils/python-utils.js +27 -7
  376. package/ccw/dist/utils/python-utils.js.map +1 -1
  377. package/ccw/dist/utils/shell-escape.d.ts +8 -0
  378. package/ccw/dist/utils/shell-escape.d.ts.map +1 -0
  379. package/ccw/dist/utils/shell-escape.js +24 -0
  380. package/ccw/dist/utils/shell-escape.js.map +1 -0
  381. package/ccw/dist/utils/uv-manager.d.ts +167 -0
  382. package/ccw/dist/utils/uv-manager.d.ts.map +1 -0
  383. package/ccw/dist/utils/uv-manager.js +644 -0
  384. package/ccw/dist/utils/uv-manager.js.map +1 -0
  385. package/ccw/src/cli.ts +4 -1
  386. package/ccw/src/commands/cli.ts +132 -34
  387. package/ccw/src/commands/issue.ts +605 -91
  388. package/ccw/src/commands/serve.ts +15 -5
  389. package/ccw/src/commands/stop.ts +32 -5
  390. package/ccw/src/commands/tool.ts +17 -2
  391. package/ccw/src/commands/view.ts +13 -3
  392. package/ccw/src/config/cli-settings-manager.ts +460 -0
  393. package/ccw/src/config/litellm-api-config-manager.ts +392 -57
  394. package/ccw/src/core/auth/csrf-manager.ts +104 -0
  395. package/ccw/src/core/auth/csrf-middleware.ts +159 -0
  396. package/ccw/src/core/auth/middleware.ts +94 -0
  397. package/ccw/src/core/auth/token-manager.ts +219 -0
  398. package/ccw/src/core/cache-manager.ts +64 -52
  399. package/ccw/src/core/claude-freshness.ts +26 -6
  400. package/ccw/src/core/core-memory-store.ts +2 -1
  401. package/ccw/src/core/cors.ts +10 -0
  402. package/ccw/src/core/dashboard-generator-patch.ts +47 -48
  403. package/ccw/src/core/dashboard-generator.ts +797 -744
  404. package/ccw/src/core/data-aggregator.ts +667 -667
  405. package/ccw/src/core/lite-scanner.ts +156 -140
  406. package/ccw/src/core/routes/auth-routes.ts +98 -0
  407. package/ccw/src/core/routes/ccw-routes.ts +10 -20
  408. package/ccw/src/core/routes/claude-routes.ts +101 -51
  409. package/ccw/src/core/routes/cli-routes.ts +152 -55
  410. package/ccw/src/core/routes/cli-settings-routes.ts +232 -0
  411. package/ccw/src/core/routes/codexlens/README.md +37 -0
  412. package/ccw/src/core/routes/codexlens/config-handlers.ts +1269 -0
  413. package/ccw/src/core/routes/codexlens/index-handlers.ts +354 -0
  414. package/ccw/src/core/routes/codexlens/semantic-handlers.ts +931 -0
  415. package/ccw/src/core/routes/codexlens/utils.ts +96 -0
  416. package/ccw/src/core/routes/codexlens/watcher-handlers.ts +265 -0
  417. package/ccw/src/core/routes/codexlens-routes.ts +11 -1044
  418. package/ccw/src/core/routes/discovery-routes.ts +1 -12
  419. package/ccw/src/core/routes/files-routes.ts +112 -40
  420. package/ccw/src/core/routes/graph-routes.ts +39 -46
  421. package/ccw/src/core/routes/help-routes.ts +2 -12
  422. package/ccw/src/core/routes/hooks-routes.ts +83 -44
  423. package/ccw/src/core/routes/issue-routes.ts +1 -12
  424. package/ccw/src/core/routes/litellm-api-routes.ts +574 -60
  425. package/ccw/src/core/routes/litellm-routes.ts +35 -27
  426. package/ccw/src/core/routes/mcp-routes.ts +157 -60
  427. package/ccw/src/core/routes/mcp-routes.ts.backup +549 -550
  428. package/ccw/src/core/routes/mcp-templates-db.ts +267 -268
  429. package/ccw/src/core/routes/memory-routes.ts +76 -22
  430. package/ccw/src/core/routes/nav-status-routes.ts +231 -0
  431. package/ccw/src/core/routes/rules-routes.ts +600 -81
  432. package/ccw/src/core/routes/session-routes.ts +28 -22
  433. package/ccw/src/core/routes/skills-routes.ts +452 -132
  434. package/ccw/src/core/routes/status-routes.ts +1 -12
  435. package/ccw/src/core/routes/system-routes.ts +15 -22
  436. package/ccw/src/core/routes/types.ts +25 -0
  437. package/ccw/src/core/server.ts +657 -468
  438. package/ccw/src/core/services/api-key-tester.ts +160 -0
  439. package/ccw/src/core/services/health-check-service.ts +366 -0
  440. package/ccw/src/core/websocket.ts +20 -12
  441. package/ccw/src/templates/dashboard-css/01-base.css +109 -0
  442. package/ccw/src/templates/dashboard-css/10-cli-status.css +202 -0
  443. package/ccw/src/templates/dashboard-css/21-cli-toolmgmt.css +308 -0
  444. package/ccw/src/templates/dashboard-css/30-core-memory.css +20 -0
  445. package/ccw/src/templates/dashboard-css/31-api-settings.css +751 -14
  446. package/ccw/src/templates/dashboard-css/33-cli-stream-viewer.css +230 -2
  447. package/ccw/src/templates/dashboard-js/api.js +5 -0
  448. package/ccw/src/templates/dashboard-js/components/cli-status.js +279 -107
  449. package/ccw/src/templates/dashboard-js/components/cli-stream-viewer.js +262 -20
  450. package/ccw/src/templates/dashboard-js/components/hook-manager.js +105 -5
  451. package/ccw/src/templates/dashboard-js/components/mcp-manager.js +317 -0
  452. package/ccw/src/templates/dashboard-js/components/navigation.js +45 -0
  453. package/ccw/src/templates/dashboard-js/components/notifications.js +128 -0
  454. package/ccw/src/templates/dashboard-js/i18n.js +4448 -3983
  455. package/ccw/src/templates/dashboard-js/main.js +71 -0
  456. package/ccw/src/templates/dashboard-js/services.js +289 -0
  457. package/ccw/src/templates/dashboard-js/views/api-settings.js +5613 -3361
  458. package/ccw/src/templates/dashboard-js/views/claude-manager.js +1 -7
  459. package/ccw/src/templates/dashboard-js/views/cli-manager.js +581 -87
  460. package/ccw/src/templates/dashboard-js/views/codexlens-manager.js +6101 -1965
  461. package/ccw/src/templates/dashboard-js/views/core-memory.js +129 -20
  462. package/ccw/src/templates/dashboard-js/views/hook-manager.js +17 -3
  463. package/ccw/src/templates/dashboard-js/views/mcp-manager.js +63 -0
  464. package/ccw/src/templates/dashboard-js/views/project-overview.js +182 -37
  465. package/ccw/src/templates/dashboard-js/views/rules-manager.js +26 -3
  466. package/ccw/src/templates/dashboard-js/views/skills-manager.js +2 -42
  467. package/ccw/src/templates/dashboard.html +6 -0
  468. package/ccw/src/tools/README.md +29 -0
  469. package/ccw/src/tools/claude-cli-tools.ts +640 -125
  470. package/ccw/src/tools/cli-config-manager.ts +102 -172
  471. package/ccw/src/tools/cli-executor-core.ts +1533 -0
  472. package/ccw/src/tools/cli-executor-state.ts +560 -0
  473. package/ccw/src/tools/cli-executor-utils.ts +349 -0
  474. package/ccw/src/tools/cli-executor.ts +3 -2309
  475. package/ccw/src/tools/cli-history-store.ts +2 -0
  476. package/ccw/src/tools/cli-output-converter.ts +1237 -0
  477. package/ccw/src/tools/cli-prompt-builder.ts +487 -0
  478. package/ccw/src/tools/codex-lens.ts +324 -59
  479. package/ccw/src/tools/detect-changed-modules.ts +24 -6
  480. package/ccw/src/tools/index.ts +2 -0
  481. package/ccw/src/tools/litellm-client.ts +10 -4
  482. package/ccw/src/tools/litellm-executor.ts +146 -114
  483. package/ccw/src/tools/native-session-discovery.ts +209 -1
  484. package/ccw/src/tools/session-manager.ts +88 -0
  485. package/ccw/src/tools/skill-context-loader.ts +213 -0
  486. package/ccw/src/tools/smart-search.ts +427 -76
  487. package/ccw/src/types/cli-settings.ts +137 -0
  488. package/ccw/src/types/litellm-api-config.ts +55 -1
  489. package/ccw/src/utils/exec-constants.ts +24 -0
  490. package/ccw/src/utils/path-resolver.ts +49 -3
  491. package/ccw/src/utils/path-validator.ts +28 -6
  492. package/ccw/src/utils/python-utils.ts +140 -121
  493. package/ccw/src/utils/shell-escape.ts +30 -0
  494. package/ccw/src/utils/uv-manager.ts +796 -0
  495. package/ccw-litellm/src/ccw_litellm/__pycache__/__init__.cpython-310.pyc +0 -0
  496. package/ccw-litellm/src/ccw_litellm/__pycache__/__init__.cpython-312.pyc +0 -0
  497. package/ccw-litellm/src/ccw_litellm/clients/__pycache__/__init__.cpython-310.pyc +0 -0
  498. package/ccw-litellm/src/ccw_litellm/clients/__pycache__/__init__.cpython-312.pyc +0 -0
  499. package/ccw-litellm/src/ccw_litellm/clients/__pycache__/litellm_embedder.cpython-310.pyc +0 -0
  500. package/ccw-litellm/src/ccw_litellm/clients/__pycache__/litellm_embedder.cpython-312.pyc +0 -0
  501. package/ccw-litellm/src/ccw_litellm/clients/__pycache__/litellm_embedder.cpython-313.pyc +0 -0
  502. package/ccw-litellm/src/ccw_litellm/clients/__pycache__/litellm_llm.cpython-310.pyc +0 -0
  503. package/ccw-litellm/src/ccw_litellm/clients/__pycache__/litellm_llm.cpython-312.pyc +0 -0
  504. package/ccw-litellm/src/ccw_litellm/clients/__pycache__/litellm_llm.cpython-313.pyc +0 -0
  505. package/ccw-litellm/src/ccw_litellm/clients/litellm_embedder.py +270 -251
  506. package/ccw-litellm/src/ccw_litellm/clients/litellm_llm.py +33 -0
  507. package/ccw-litellm/src/ccw_litellm/config/__pycache__/__init__.cpython-310.pyc +0 -0
  508. package/ccw-litellm/src/ccw_litellm/config/__pycache__/__init__.cpython-312.pyc +0 -0
  509. package/ccw-litellm/src/ccw_litellm/config/__pycache__/loader.cpython-310.pyc +0 -0
  510. package/ccw-litellm/src/ccw_litellm/config/__pycache__/loader.cpython-312.pyc +0 -0
  511. package/ccw-litellm/src/ccw_litellm/config/__pycache__/loader.cpython-313.pyc +0 -0
  512. package/ccw-litellm/src/ccw_litellm/config/__pycache__/models.cpython-310.pyc +0 -0
  513. package/ccw-litellm/src/ccw_litellm/config/__pycache__/models.cpython-312.pyc +0 -0
  514. package/ccw-litellm/src/ccw_litellm/config/__pycache__/models.cpython-313.pyc +0 -0
  515. package/ccw-litellm/src/ccw_litellm/config/loader.py +343 -316
  516. package/ccw-litellm/src/ccw_litellm/config/models.py +162 -130
  517. package/ccw-litellm/src/ccw_litellm/interfaces/__pycache__/__init__.cpython-310.pyc +0 -0
  518. package/ccw-litellm/src/ccw_litellm/interfaces/__pycache__/__init__.cpython-312.pyc +0 -0
  519. package/ccw-litellm/src/ccw_litellm/interfaces/__pycache__/embedder.cpython-310.pyc +0 -0
  520. package/ccw-litellm/src/ccw_litellm/interfaces/__pycache__/embedder.cpython-312.pyc +0 -0
  521. package/ccw-litellm/src/ccw_litellm/interfaces/__pycache__/llm.cpython-310.pyc +0 -0
  522. package/ccw-litellm/src/ccw_litellm/interfaces/__pycache__/llm.cpython-312.pyc +0 -0
  523. package/codex-lens/pyproject.toml +43 -0
  524. package/codex-lens/src/codexlens/__pycache__/__init__.cpython-310.pyc +0 -0
  525. package/codex-lens/src/codexlens/__pycache__/__init__.cpython-312.pyc +0 -0
  526. package/codex-lens/src/codexlens/__pycache__/__main__.cpython-310.pyc +0 -0
  527. package/codex-lens/src/codexlens/__pycache__/__main__.cpython-312.pyc +0 -0
  528. package/codex-lens/src/codexlens/__pycache__/config.cpython-310.pyc +0 -0
  529. package/codex-lens/src/codexlens/__pycache__/config.cpython-312.pyc +0 -0
  530. package/codex-lens/src/codexlens/__pycache__/config.cpython-313.pyc +0 -0
  531. package/codex-lens/src/codexlens/__pycache__/entities.cpython-310.pyc +0 -0
  532. package/codex-lens/src/codexlens/__pycache__/entities.cpython-312.pyc +0 -0
  533. package/codex-lens/src/codexlens/__pycache__/entities.cpython-313.pyc +0 -0
  534. package/codex-lens/src/codexlens/__pycache__/env_config.cpython-310.pyc +0 -0
  535. package/codex-lens/src/codexlens/__pycache__/env_config.cpython-312.pyc +0 -0
  536. package/codex-lens/src/codexlens/__pycache__/env_config.cpython-313.pyc +0 -0
  537. package/codex-lens/src/codexlens/__pycache__/errors.cpython-310.pyc +0 -0
  538. package/codex-lens/src/codexlens/__pycache__/errors.cpython-312.pyc +0 -0
  539. package/codex-lens/src/codexlens/cli/__pycache__/__init__.cpython-310.pyc +0 -0
  540. package/codex-lens/src/codexlens/cli/__pycache__/__init__.cpython-312.pyc +0 -0
  541. package/codex-lens/src/codexlens/cli/__pycache__/commands.cpython-310.pyc +0 -0
  542. package/codex-lens/src/codexlens/cli/__pycache__/commands.cpython-312.pyc +0 -0
  543. package/codex-lens/src/codexlens/cli/__pycache__/commands.cpython-313.pyc +0 -0
  544. package/codex-lens/src/codexlens/cli/__pycache__/embedding_manager.cpython-310.pyc +0 -0
  545. package/codex-lens/src/codexlens/cli/__pycache__/embedding_manager.cpython-312.pyc +0 -0
  546. package/codex-lens/src/codexlens/cli/__pycache__/embedding_manager.cpython-313.pyc +0 -0
  547. package/codex-lens/src/codexlens/cli/__pycache__/model_manager.cpython-310.pyc +0 -0
  548. package/codex-lens/src/codexlens/cli/__pycache__/model_manager.cpython-312.pyc +0 -0
  549. package/codex-lens/src/codexlens/cli/__pycache__/model_manager.cpython-313.pyc +0 -0
  550. package/codex-lens/src/codexlens/cli/__pycache__/output.cpython-310.pyc +0 -0
  551. package/codex-lens/src/codexlens/cli/__pycache__/output.cpython-312.pyc +0 -0
  552. package/codex-lens/src/codexlens/cli/commands.py +4416 -2295
  553. package/codex-lens/src/codexlens/cli/embedding_manager.py +777 -15
  554. package/codex-lens/src/codexlens/cli/model_manager.py +676 -0
  555. package/codex-lens/src/codexlens/config.py +356 -12
  556. package/codex-lens/src/codexlens/entities.py +4 -1
  557. package/codex-lens/src/codexlens/env_config.py +304 -0
  558. package/codex-lens/src/codexlens/indexing/__init__.py +23 -1
  559. package/codex-lens/src/codexlens/indexing/__pycache__/__init__.cpython-313.pyc +0 -0
  560. package/codex-lens/src/codexlens/indexing/__pycache__/embedding.cpython-313.pyc +0 -0
  561. package/codex-lens/src/codexlens/indexing/__pycache__/symbol_extractor.cpython-313.pyc +0 -0
  562. package/codex-lens/src/codexlens/indexing/embedding.py +582 -0
  563. package/codex-lens/src/codexlens/indexing/symbol_extractor.py +62 -28
  564. package/codex-lens/src/codexlens/parsers/__pycache__/__init__.cpython-310.pyc +0 -0
  565. package/codex-lens/src/codexlens/parsers/__pycache__/__init__.cpython-312.pyc +0 -0
  566. package/codex-lens/src/codexlens/parsers/__pycache__/factory.cpython-310.pyc +0 -0
  567. package/codex-lens/src/codexlens/parsers/__pycache__/factory.cpython-312.pyc +0 -0
  568. package/codex-lens/src/codexlens/parsers/__pycache__/factory.cpython-313.pyc +0 -0
  569. package/codex-lens/src/codexlens/parsers/__pycache__/tokenizer.cpython-310.pyc +0 -0
  570. package/codex-lens/src/codexlens/parsers/__pycache__/tokenizer.cpython-312.pyc +0 -0
  571. package/codex-lens/src/codexlens/parsers/__pycache__/treesitter_parser.cpython-310.pyc +0 -0
  572. package/codex-lens/src/codexlens/parsers/__pycache__/treesitter_parser.cpython-312.pyc +0 -0
  573. package/codex-lens/src/codexlens/parsers/__pycache__/treesitter_parser.cpython-313.pyc +0 -0
  574. package/codex-lens/src/codexlens/parsers/factory.py +139 -10
  575. package/codex-lens/src/codexlens/parsers/treesitter_parser.py +487 -13
  576. package/codex-lens/src/codexlens/search/__pycache__/__init__.cpython-310.pyc +0 -0
  577. package/codex-lens/src/codexlens/search/__pycache__/__init__.cpython-312.pyc +0 -0
  578. package/codex-lens/src/codexlens/search/__pycache__/binary_searcher.cpython-313.pyc +0 -0
  579. package/codex-lens/src/codexlens/search/__pycache__/chain_search.cpython-310.pyc +0 -0
  580. package/codex-lens/src/codexlens/search/__pycache__/chain_search.cpython-312.pyc +0 -0
  581. package/codex-lens/src/codexlens/search/__pycache__/chain_search.cpython-313.pyc +0 -0
  582. package/codex-lens/src/codexlens/search/__pycache__/enrichment.cpython-313.pyc +0 -0
  583. package/codex-lens/src/codexlens/search/__pycache__/graph_expander.cpython-313.pyc +0 -0
  584. package/codex-lens/src/codexlens/search/__pycache__/hybrid_search.cpython-310.pyc +0 -0
  585. package/codex-lens/src/codexlens/search/__pycache__/hybrid_search.cpython-312.pyc +0 -0
  586. package/codex-lens/src/codexlens/search/__pycache__/hybrid_search.cpython-313.pyc +0 -0
  587. package/codex-lens/src/codexlens/search/__pycache__/ranking.cpython-310.pyc +0 -0
  588. package/codex-lens/src/codexlens/search/__pycache__/ranking.cpython-312.pyc +0 -0
  589. package/codex-lens/src/codexlens/search/__pycache__/ranking.cpython-313.pyc +0 -0
  590. package/codex-lens/src/codexlens/search/binary_searcher.py +277 -0
  591. package/codex-lens/src/codexlens/search/chain_search.py +1652 -8
  592. package/codex-lens/src/codexlens/search/enrichment.py +21 -0
  593. package/codex-lens/src/codexlens/search/graph_expander.py +264 -0
  594. package/codex-lens/src/codexlens/search/hybrid_search.py +772 -37
  595. package/codex-lens/src/codexlens/search/ranking.py +397 -8
  596. package/codex-lens/src/codexlens/semantic/SPLADE_IMPLEMENTATION.md +225 -0
  597. package/codex-lens/src/codexlens/semantic/__pycache__/__init__.cpython-310.pyc +0 -0
  598. package/codex-lens/src/codexlens/semantic/__pycache__/__init__.cpython-312.pyc +0 -0
  599. package/codex-lens/src/codexlens/semantic/__pycache__/ann_index.cpython-310.pyc +0 -0
  600. package/codex-lens/src/codexlens/semantic/__pycache__/ann_index.cpython-312.pyc +0 -0
  601. package/codex-lens/src/codexlens/semantic/__pycache__/ann_index.cpython-313.pyc +0 -0
  602. package/codex-lens/src/codexlens/semantic/__pycache__/base.cpython-310.pyc +0 -0
  603. package/codex-lens/src/codexlens/semantic/__pycache__/base.cpython-312.pyc +0 -0
  604. package/codex-lens/src/codexlens/semantic/__pycache__/chunker.cpython-310.pyc +0 -0
  605. package/codex-lens/src/codexlens/semantic/__pycache__/chunker.cpython-312.pyc +0 -0
  606. package/codex-lens/src/codexlens/semantic/__pycache__/chunker.cpython-313.pyc +0 -0
  607. package/codex-lens/src/codexlens/semantic/__pycache__/embedder.cpython-310.pyc +0 -0
  608. package/codex-lens/src/codexlens/semantic/__pycache__/embedder.cpython-312.pyc +0 -0
  609. package/codex-lens/src/codexlens/semantic/__pycache__/factory.cpython-310.pyc +0 -0
  610. package/codex-lens/src/codexlens/semantic/__pycache__/factory.cpython-312.pyc +0 -0
  611. package/codex-lens/src/codexlens/semantic/__pycache__/factory.cpython-313.pyc +0 -0
  612. package/codex-lens/src/codexlens/semantic/__pycache__/gpu_support.cpython-310.pyc +0 -0
  613. package/codex-lens/src/codexlens/semantic/__pycache__/gpu_support.cpython-312.pyc +0 -0
  614. package/codex-lens/src/codexlens/semantic/__pycache__/gpu_support.cpython-313.pyc +0 -0
  615. package/codex-lens/src/codexlens/semantic/__pycache__/litellm_embedder.cpython-310.pyc +0 -0
  616. package/codex-lens/src/codexlens/semantic/__pycache__/litellm_embedder.cpython-312.pyc +0 -0
  617. package/codex-lens/src/codexlens/semantic/__pycache__/litellm_embedder.cpython-313.pyc +0 -0
  618. package/codex-lens/src/codexlens/semantic/__pycache__/reranker.cpython-313.pyc +0 -0
  619. package/codex-lens/src/codexlens/semantic/__pycache__/splade_encoder.cpython-310.pyc +0 -0
  620. package/codex-lens/src/codexlens/semantic/__pycache__/splade_encoder.cpython-312.pyc +0 -0
  621. package/codex-lens/src/codexlens/semantic/__pycache__/splade_encoder.cpython-313.pyc +0 -0
  622. package/codex-lens/src/codexlens/semantic/__pycache__/vector_store.cpython-310.pyc +0 -0
  623. package/codex-lens/src/codexlens/semantic/__pycache__/vector_store.cpython-312.pyc +0 -0
  624. package/codex-lens/src/codexlens/semantic/__pycache__/vector_store.cpython-313.pyc +0 -0
  625. package/codex-lens/src/codexlens/semantic/ann_index.py +654 -0
  626. package/codex-lens/src/codexlens/semantic/chunker.py +328 -23
  627. package/codex-lens/src/codexlens/semantic/factory.py +63 -3
  628. package/codex-lens/src/codexlens/semantic/gpu_support.py +19 -2
  629. package/codex-lens/src/codexlens/semantic/litellm_embedder.py +144 -144
  630. package/codex-lens/src/codexlens/semantic/reranker/__init__.py +25 -0
  631. package/codex-lens/src/codexlens/semantic/reranker/__pycache__/__init__.cpython-310.pyc +0 -0
  632. package/codex-lens/src/codexlens/semantic/reranker/__pycache__/__init__.cpython-312.pyc +0 -0
  633. package/codex-lens/src/codexlens/semantic/reranker/__pycache__/__init__.cpython-313.pyc +0 -0
  634. package/codex-lens/src/codexlens/semantic/reranker/__pycache__/api_reranker.cpython-310.pyc +0 -0
  635. package/codex-lens/src/codexlens/semantic/reranker/__pycache__/api_reranker.cpython-312.pyc +0 -0
  636. package/codex-lens/src/codexlens/semantic/reranker/__pycache__/api_reranker.cpython-313.pyc +0 -0
  637. package/codex-lens/src/codexlens/semantic/reranker/__pycache__/base.cpython-310.pyc +0 -0
  638. package/codex-lens/src/codexlens/semantic/reranker/__pycache__/base.cpython-312.pyc +0 -0
  639. package/codex-lens/src/codexlens/semantic/reranker/__pycache__/base.cpython-313.pyc +0 -0
  640. package/codex-lens/src/codexlens/semantic/reranker/__pycache__/factory.cpython-310.pyc +0 -0
  641. package/codex-lens/src/codexlens/semantic/reranker/__pycache__/factory.cpython-312.pyc +0 -0
  642. package/codex-lens/src/codexlens/semantic/reranker/__pycache__/factory.cpython-313.pyc +0 -0
  643. package/codex-lens/src/codexlens/semantic/reranker/__pycache__/fastembed_reranker.cpython-310.pyc +0 -0
  644. package/codex-lens/src/codexlens/semantic/reranker/__pycache__/fastembed_reranker.cpython-312.pyc +0 -0
  645. package/codex-lens/src/codexlens/semantic/reranker/__pycache__/fastembed_reranker.cpython-313.pyc +0 -0
  646. package/codex-lens/src/codexlens/semantic/reranker/__pycache__/legacy.cpython-310.pyc +0 -0
  647. package/codex-lens/src/codexlens/semantic/reranker/__pycache__/legacy.cpython-312.pyc +0 -0
  648. package/codex-lens/src/codexlens/semantic/reranker/__pycache__/legacy.cpython-313.pyc +0 -0
  649. package/codex-lens/src/codexlens/semantic/reranker/__pycache__/litellm_reranker.cpython-313.pyc +0 -0
  650. package/codex-lens/src/codexlens/semantic/reranker/__pycache__/onnx_reranker.cpython-310.pyc +0 -0
  651. package/codex-lens/src/codexlens/semantic/reranker/__pycache__/onnx_reranker.cpython-312.pyc +0 -0
  652. package/codex-lens/src/codexlens/semantic/reranker/__pycache__/onnx_reranker.cpython-313.pyc +0 -0
  653. package/codex-lens/src/codexlens/semantic/reranker/api_reranker.py +403 -0
  654. package/codex-lens/src/codexlens/semantic/reranker/base.py +46 -0
  655. package/codex-lens/src/codexlens/semantic/reranker/factory.py +159 -0
  656. package/codex-lens/src/codexlens/semantic/reranker/fastembed_reranker.py +257 -0
  657. package/codex-lens/src/codexlens/semantic/reranker/legacy.py +91 -0
  658. package/codex-lens/src/codexlens/semantic/reranker/litellm_reranker.py +214 -0
  659. package/codex-lens/src/codexlens/semantic/reranker/onnx_reranker.py +268 -0
  660. package/codex-lens/src/codexlens/semantic/splade_encoder.py +567 -0
  661. package/codex-lens/src/codexlens/semantic/vector_store.py +472 -352
  662. package/codex-lens/src/codexlens/storage/__init__.py +3 -0
  663. package/codex-lens/src/codexlens/storage/__pycache__/__init__.cpython-310.pyc +0 -0
  664. package/codex-lens/src/codexlens/storage/__pycache__/__init__.cpython-312.pyc +0 -0
  665. package/codex-lens/src/codexlens/storage/__pycache__/__init__.cpython-313.pyc +0 -0
  666. package/codex-lens/src/codexlens/storage/__pycache__/dir_index.cpython-310.pyc +0 -0
  667. package/codex-lens/src/codexlens/storage/__pycache__/dir_index.cpython-312.pyc +0 -0
  668. package/codex-lens/src/codexlens/storage/__pycache__/dir_index.cpython-313.pyc +0 -0
  669. package/codex-lens/src/codexlens/storage/__pycache__/global_index.cpython-310.pyc +0 -0
  670. package/codex-lens/src/codexlens/storage/__pycache__/global_index.cpython-312.pyc +0 -0
  671. package/codex-lens/src/codexlens/storage/__pycache__/index_tree.cpython-310.pyc +0 -0
  672. package/codex-lens/src/codexlens/storage/__pycache__/index_tree.cpython-312.pyc +0 -0
  673. package/codex-lens/src/codexlens/storage/__pycache__/index_tree.cpython-313.pyc +0 -0
  674. package/codex-lens/src/codexlens/storage/__pycache__/merkle_tree.cpython-313.pyc +0 -0
  675. package/codex-lens/src/codexlens/storage/__pycache__/path_mapper.cpython-310.pyc +0 -0
  676. package/codex-lens/src/codexlens/storage/__pycache__/path_mapper.cpython-312.pyc +0 -0
  677. package/codex-lens/src/codexlens/storage/__pycache__/registry.cpython-310.pyc +0 -0
  678. package/codex-lens/src/codexlens/storage/__pycache__/registry.cpython-312.pyc +0 -0
  679. package/codex-lens/src/codexlens/storage/__pycache__/splade_index.cpython-310.pyc +0 -0
  680. package/codex-lens/src/codexlens/storage/__pycache__/splade_index.cpython-312.pyc +0 -0
  681. package/codex-lens/src/codexlens/storage/__pycache__/splade_index.cpython-313.pyc +0 -0
  682. package/codex-lens/src/codexlens/storage/__pycache__/sqlite_store.cpython-310.pyc +0 -0
  683. package/codex-lens/src/codexlens/storage/__pycache__/sqlite_store.cpython-312.pyc +0 -0
  684. package/codex-lens/src/codexlens/storage/__pycache__/sqlite_store.cpython-313.pyc +0 -0
  685. package/codex-lens/src/codexlens/storage/__pycache__/sqlite_utils.cpython-310.pyc +0 -0
  686. package/codex-lens/src/codexlens/storage/__pycache__/sqlite_utils.cpython-312.pyc +0 -0
  687. package/codex-lens/src/codexlens/storage/__pycache__/vector_meta_store.cpython-310.pyc +0 -0
  688. package/codex-lens/src/codexlens/storage/__pycache__/vector_meta_store.cpython-312.pyc +0 -0
  689. package/codex-lens/src/codexlens/storage/__pycache__/vector_meta_store.cpython-313.pyc +0 -0
  690. package/codex-lens/src/codexlens/storage/dir_index.py +310 -12
  691. package/codex-lens/src/codexlens/storage/index_tree.py +240 -25
  692. package/codex-lens/src/codexlens/storage/merkle_tree.py +136 -0
  693. package/codex-lens/src/codexlens/storage/migrations/__pycache__/__init__.cpython-310.pyc +0 -0
  694. package/codex-lens/src/codexlens/storage/migrations/__pycache__/__init__.cpython-312.pyc +0 -0
  695. package/codex-lens/src/codexlens/storage/migrations/__pycache__/migration_006_enhance_relationships.cpython-313.pyc +0 -0
  696. package/codex-lens/src/codexlens/storage/migrations/__pycache__/migration_007_add_graph_neighbors.cpython-310.pyc +0 -0
  697. package/codex-lens/src/codexlens/storage/migrations/__pycache__/migration_007_add_graph_neighbors.cpython-312.pyc +0 -0
  698. package/codex-lens/src/codexlens/storage/migrations/__pycache__/migration_007_add_graph_neighbors.cpython-313.pyc +0 -0
  699. package/codex-lens/src/codexlens/storage/migrations/__pycache__/migration_008_add_merkle_hashes.cpython-313.pyc +0 -0
  700. package/codex-lens/src/codexlens/storage/migrations/__pycache__/migration_009_add_splade.cpython-313.pyc +0 -0
  701. package/codex-lens/src/codexlens/storage/migrations/__pycache__/migration_010_add_multi_vector_chunks.cpython-313.pyc +0 -0
  702. package/codex-lens/src/codexlens/storage/migrations/migration_006_enhance_relationships.py +37 -0
  703. package/codex-lens/src/codexlens/storage/migrations/migration_007_add_graph_neighbors.py +47 -0
  704. package/codex-lens/src/codexlens/storage/migrations/migration_008_add_merkle_hashes.py +81 -0
  705. package/codex-lens/src/codexlens/storage/migrations/migration_009_add_splade.py +103 -0
  706. package/codex-lens/src/codexlens/storage/migrations/migration_010_add_multi_vector_chunks.py +162 -0
  707. package/codex-lens/src/codexlens/storage/splade_index.py +578 -0
  708. package/codex-lens/src/codexlens/storage/sqlite_store.py +508 -184
  709. package/codex-lens/src/codexlens/storage/vector_meta_store.py +415 -0
  710. package/codex-lens/src/codexlens/watcher/__init__.py +17 -0
  711. package/codex-lens/src/codexlens/watcher/__pycache__/__init__.cpython-310.pyc +0 -0
  712. package/codex-lens/src/codexlens/watcher/__pycache__/__init__.cpython-312.pyc +0 -0
  713. package/codex-lens/src/codexlens/watcher/__pycache__/__init__.cpython-313.pyc +0 -0
  714. package/codex-lens/src/codexlens/watcher/__pycache__/events.cpython-310.pyc +0 -0
  715. package/codex-lens/src/codexlens/watcher/__pycache__/events.cpython-312.pyc +0 -0
  716. package/codex-lens/src/codexlens/watcher/__pycache__/events.cpython-313.pyc +0 -0
  717. package/codex-lens/src/codexlens/watcher/__pycache__/file_watcher.cpython-310.pyc +0 -0
  718. package/codex-lens/src/codexlens/watcher/__pycache__/file_watcher.cpython-312.pyc +0 -0
  719. package/codex-lens/src/codexlens/watcher/__pycache__/file_watcher.cpython-313.pyc +0 -0
  720. package/codex-lens/src/codexlens/watcher/__pycache__/incremental_indexer.cpython-310.pyc +0 -0
  721. package/codex-lens/src/codexlens/watcher/__pycache__/incremental_indexer.cpython-312.pyc +0 -0
  722. package/codex-lens/src/codexlens/watcher/__pycache__/incremental_indexer.cpython-313.pyc +0 -0
  723. package/codex-lens/src/codexlens/watcher/__pycache__/manager.cpython-310.pyc +0 -0
  724. package/codex-lens/src/codexlens/watcher/__pycache__/manager.cpython-312.pyc +0 -0
  725. package/codex-lens/src/codexlens/watcher/__pycache__/manager.cpython-313.pyc +0 -0
  726. package/codex-lens/src/codexlens/watcher/events.py +82 -0
  727. package/codex-lens/src/codexlens/watcher/file_watcher.py +347 -0
  728. package/codex-lens/src/codexlens/watcher/incremental_indexer.py +369 -0
  729. package/codex-lens/src/codexlens/watcher/manager.py +255 -0
  730. package/package.json +4 -1
  731. package/.claude/commands/workflow/docs/analyze.md +0 -1467
  732. package/.claude/commands/workflow/docs/copyright.md +0 -1265
  733. package/.claude/skills/command-guide/SKILL.md +0 -388
  734. package/.claude/skills/command-guide/UPDATE-GUIDELINE.md +0 -592
  735. package/.claude/skills/command-guide/guides/cli-tools-guide.md +0 -410
  736. package/.claude/skills/command-guide/guides/examples.md +0 -537
  737. package/.claude/skills/command-guide/guides/getting-started.md +0 -242
  738. package/.claude/skills/command-guide/guides/implementation-details.md +0 -1010
  739. package/.claude/skills/command-guide/guides/index-structure.md +0 -326
  740. package/.claude/skills/command-guide/guides/troubleshooting.md +0 -92
  741. package/.claude/skills/command-guide/guides/ui-design-workflow-guide.md +0 -316
  742. package/.claude/skills/command-guide/guides/workflow-patterns.md +0 -662
  743. package/.claude/skills/command-guide/reference/agents/action-planning-agent.md +0 -855
  744. package/.claude/skills/command-guide/reference/agents/cli-execution-agent.md +0 -267
  745. package/.claude/skills/command-guide/reference/agents/cli-explore-agent.md +0 -182
  746. package/.claude/skills/command-guide/reference/agents/cli-lite-planning-agent.md +0 -446
  747. package/.claude/skills/command-guide/reference/agents/cli-planning-agent.md +0 -558
  748. package/.claude/skills/command-guide/reference/agents/code-developer.md +0 -311
  749. package/.claude/skills/command-guide/reference/agents/conceptual-planning-agent.md +0 -308
  750. package/.claude/skills/command-guide/reference/agents/context-search-agent.md +0 -581
  751. package/.claude/skills/command-guide/reference/agents/doc-generator.md +0 -330
  752. package/.claude/skills/command-guide/reference/agents/memory-bridge.md +0 -94
  753. package/.claude/skills/command-guide/reference/agents/test-context-search-agent.md +0 -400
  754. package/.claude/skills/command-guide/reference/agents/test-fix-agent.md +0 -344
  755. package/.claude/skills/command-guide/reference/agents/ui-design-agent.md +0 -593
  756. package/.claude/skills/command-guide/reference/agents/universal-executor.md +0 -131
  757. package/.claude/skills/command-guide/reference/commands/cli/cli-init.md +0 -440
  758. package/.claude/skills/command-guide/reference/commands/enhance-prompt.md +0 -93
  759. package/.claude/skills/command-guide/reference/commands/memory/code-map-memory.md +0 -687
  760. package/.claude/skills/command-guide/reference/commands/memory/docs-full-cli.md +0 -471
  761. package/.claude/skills/command-guide/reference/commands/memory/docs-related-cli.md +0 -386
  762. package/.claude/skills/command-guide/reference/commands/memory/docs.md +0 -616
  763. package/.claude/skills/command-guide/reference/commands/memory/load-skill-memory.md +0 -182
  764. package/.claude/skills/command-guide/reference/commands/memory/load.md +0 -240
  765. package/.claude/skills/command-guide/reference/commands/memory/skill-memory.md +0 -525
  766. package/.claude/skills/command-guide/reference/commands/memory/style-skill-memory.md +0 -396
  767. package/.claude/skills/command-guide/reference/commands/memory/tech-research.md +0 -314
  768. package/.claude/skills/command-guide/reference/commands/memory/update-full.md +0 -332
  769. package/.claude/skills/command-guide/reference/commands/memory/update-related.md +0 -332
  770. package/.claude/skills/command-guide/reference/commands/memory/workflow-skill-memory.md +0 -517
  771. package/.claude/skills/command-guide/reference/commands/task/breakdown.md +0 -204
  772. package/.claude/skills/command-guide/reference/commands/task/create.md +0 -152
  773. package/.claude/skills/command-guide/reference/commands/task/execute.md +0 -270
  774. package/.claude/skills/command-guide/reference/commands/task/replan.md +0 -437
  775. package/.claude/skills/command-guide/reference/commands/version.md +0 -254
  776. package/.claude/skills/command-guide/reference/commands/workflow/action-plan-verify.md +0 -447
  777. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/api-designer.md +0 -585
  778. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/artifacts.md +0 -452
  779. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/auto-parallel.md +0 -443
  780. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/data-architect.md +0 -220
  781. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/product-manager.md +0 -200
  782. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/product-owner.md +0 -200
  783. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/scrum-master.md +0 -200
  784. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/subject-matter-expert.md +0 -200
  785. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/synthesis.md +0 -398
  786. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/system-architect.md +0 -387
  787. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/ui-designer.md +0 -221
  788. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/ux-expert.md +0 -221
  789. package/.claude/skills/command-guide/reference/commands/workflow/execute.md +0 -465
  790. package/.claude/skills/command-guide/reference/commands/workflow/init.md +0 -164
  791. package/.claude/skills/command-guide/reference/commands/workflow/lite-execute.md +0 -748
  792. package/.claude/skills/command-guide/reference/commands/workflow/lite-fix.md +0 -664
  793. package/.claude/skills/command-guide/reference/commands/workflow/lite-plan.md +0 -645
  794. package/.claude/skills/command-guide/reference/commands/workflow/plan.md +0 -551
  795. package/.claude/skills/command-guide/reference/commands/workflow/replan.md +0 -515
  796. package/.claude/skills/command-guide/reference/commands/workflow/review-fix.md +0 -606
  797. package/.claude/skills/command-guide/reference/commands/workflow/review-module-cycle.md +0 -765
  798. package/.claude/skills/command-guide/reference/commands/workflow/review-session-cycle.md +0 -776
  799. package/.claude/skills/command-guide/reference/commands/workflow/review.md +0 -298
  800. package/.claude/skills/command-guide/reference/commands/workflow/session/complete.md +0 -547
  801. package/.claude/skills/command-guide/reference/commands/workflow/session/list.md +0 -114
  802. package/.claude/skills/command-guide/reference/commands/workflow/session/resume.md +0 -77
  803. package/.claude/skills/command-guide/reference/commands/workflow/session/start.md +0 -257
  804. package/.claude/skills/command-guide/reference/commands/workflow/tdd-plan.md +0 -460
  805. package/.claude/skills/command-guide/reference/commands/workflow/tdd-verify.md +0 -400
  806. package/.claude/skills/command-guide/reference/commands/workflow/test-cycle-execute.md +0 -498
  807. package/.claude/skills/command-guide/reference/commands/workflow/test-fix-gen.md +0 -699
  808. package/.claude/skills/command-guide/reference/commands/workflow/test-gen.md +0 -529
  809. package/.claude/skills/command-guide/reference/commands/workflow/tools/conflict-resolution.md +0 -766
  810. package/.claude/skills/command-guide/reference/commands/workflow/tools/context-gather.md +0 -433
  811. package/.claude/skills/command-guide/reference/commands/workflow/tools/task-generate-agent.md +0 -487
  812. package/.claude/skills/command-guide/reference/commands/workflow/tools/task-generate-tdd.md +0 -518
  813. package/.claude/skills/command-guide/reference/commands/workflow/tools/tdd-coverage-analysis.md +0 -309
  814. package/.claude/skills/command-guide/reference/commands/workflow/tools/test-concept-enhanced.md +0 -163
  815. package/.claude/skills/command-guide/reference/commands/workflow/tools/test-context-gather.md +0 -232
  816. package/.claude/skills/command-guide/reference/commands/workflow/tools/test-task-generate.md +0 -254
  817. package/.claude/skills/command-guide/reference/commands/workflow/ui-design/animation-extract.md +0 -1150
  818. package/.claude/skills/command-guide/reference/commands/workflow/ui-design/codify-style.md +0 -652
  819. package/.claude/skills/command-guide/reference/commands/workflow/ui-design/design-sync.md +0 -454
  820. package/.claude/skills/command-guide/reference/commands/workflow/ui-design/explore-auto.md +0 -678
  821. package/.claude/skills/command-guide/reference/commands/workflow/ui-design/generate.md +0 -504
  822. package/.claude/skills/command-guide/reference/commands/workflow/ui-design/imitate-auto.md +0 -745
  823. package/.claude/skills/command-guide/reference/commands/workflow/ui-design/import-from-code.md +0 -537
  824. package/.claude/skills/command-guide/reference/commands/workflow/ui-design/layout-extract.md +0 -788
  825. package/.claude/skills/command-guide/reference/commands/workflow/ui-design/reference-page-generator.md +0 -356
  826. package/.claude/skills/command-guide/reference/commands/workflow/ui-design/style-extract.md +0 -773
  827. package/.claude/skills/command-guide/scripts/analyze_commands.py +0 -502
  828. package/.claude/skills/command-guide/scripts/update-index.sh +0 -130
  829. package/.claude/skills/command-guide/templates/issue-bug.md +0 -104
  830. package/.claude/skills/command-guide/templates/issue-diagnosis.md +0 -275
  831. package/.claude/skills/command-guide/templates/issue-feature.md +0 -97
  832. package/.claude/skills/command-guide/templates/issue-question.md +0 -141
@@ -0,0 +1,1269 @@
1
+ /**
2
+ * CodexLens configuration + environment handlers.
3
+ */
4
+
5
+ import {
6
+ bootstrapVenv,
7
+ cancelIndexing,
8
+ checkSemanticStatus,
9
+ checkVenvStatus,
10
+ detectGpuSupport,
11
+ executeCodexLens,
12
+ isIndexingInProgress,
13
+ uninstallCodexLens,
14
+ } from '../../../tools/codex-lens.js';
15
+ import type { RouteContext } from '../types.js';
16
+ import { EXEC_TIMEOUTS } from '../../../utils/exec-constants.js';
17
+ import { extractJSON } from './utils.js';
18
+ import { stopWatcherForUninstall } from './watcher-handlers.js';
19
+
20
+ export async function handleCodexLensConfigRoutes(ctx: RouteContext): Promise<boolean> {
21
+ const { pathname, url, req, res, initialPath, handlePostRequest, broadcastToClients } = ctx;
22
+
23
+ // API: CodexLens Status
24
+ if (pathname === '/api/codexlens/status') {
25
+ const status = await checkVenvStatus();
26
+ res.writeHead(200, { 'Content-Type': 'application/json' });
27
+ res.end(JSON.stringify(status));
28
+ return true;
29
+ }
30
+
31
+ // API: CodexLens Dashboard Init - Aggregated endpoint for page initialization
32
+ if (pathname === '/api/codexlens/dashboard-init') {
33
+ try {
34
+ const venvStatus = await checkVenvStatus();
35
+
36
+ if (!venvStatus.ready) {
37
+ res.writeHead(200, { 'Content-Type': 'application/json' });
38
+ res.end(JSON.stringify({
39
+ installed: false,
40
+ status: venvStatus,
41
+ config: { index_dir: '~/.codexlens/indexes', index_count: 0 },
42
+ semantic: { available: false }
43
+ }));
44
+ return true;
45
+ }
46
+
47
+ // Parallel fetch all initialization data
48
+ const [configResult, statusResult, semanticStatus] = await Promise.all([
49
+ executeCodexLens(['config', '--json']),
50
+ executeCodexLens(['status', '--json']),
51
+ checkSemanticStatus()
52
+ ]);
53
+
54
+ // Parse config
55
+ let config = { index_dir: '~/.codexlens/indexes', index_count: 0 };
56
+ if (configResult.success) {
57
+ try {
58
+ const configData = extractJSON(configResult.output ?? '');
59
+ if (configData.success && configData.result) {
60
+ config.index_dir = configData.result.index_dir || configData.result.index_root || config.index_dir;
61
+ }
62
+ } catch (e: unknown) {
63
+ console.error('[CodexLens] Failed to parse config for dashboard init:', e instanceof Error ? e.message : String(e));
64
+ }
65
+ }
66
+
67
+ // Parse status
68
+ let statusData: any = {};
69
+ if (statusResult.success) {
70
+ try {
71
+ const status = extractJSON(statusResult.output ?? '');
72
+ if (status.success && status.result) {
73
+ config.index_count = status.result.projects_count || 0;
74
+ statusData = status.result;
75
+ }
76
+ } catch (e: unknown) {
77
+ console.error('[CodexLens] Failed to parse status for dashboard init:', e instanceof Error ? e.message : String(e));
78
+ }
79
+ }
80
+
81
+ res.writeHead(200, { 'Content-Type': 'application/json' });
82
+ res.end(JSON.stringify({
83
+ installed: true,
84
+ status: venvStatus,
85
+ config,
86
+ semantic: semanticStatus,
87
+ statusData
88
+ }));
89
+ } catch (err: unknown) {
90
+ res.writeHead(500, { 'Content-Type': 'application/json' });
91
+ res.end(JSON.stringify({ success: false, error: err instanceof Error ? err.message : String(err) }));
92
+ }
93
+ return true;
94
+ }
95
+
96
+ // API: CodexLens Workspace Status - Get FTS and Vector index status for current workspace
97
+ if (pathname === '/api/codexlens/workspace-status') {
98
+ try {
99
+ const venvStatus = await checkVenvStatus();
100
+
101
+ // Default response when not installed
102
+ if (!venvStatus.ready) {
103
+ res.writeHead(200, { 'Content-Type': 'application/json' });
104
+ res.end(JSON.stringify({
105
+ success: true,
106
+ hasIndex: false,
107
+ fts: { percent: 0, indexedFiles: 0, totalFiles: 0 },
108
+ vector: { percent: 0, filesWithEmbeddings: 0, totalFiles: 0, totalChunks: 0 }
109
+ }));
110
+ return true;
111
+ }
112
+
113
+ // Use path from query param, fallback to initialPath
114
+ const projectPath = url.searchParams.get('path') || initialPath;
115
+
116
+ // Get project info using 'projects show' command
117
+ const projectResult = await executeCodexLens(['projects', 'show', projectPath, '--json']);
118
+
119
+ if (!projectResult.success) {
120
+ // No index for this workspace
121
+ res.writeHead(200, { 'Content-Type': 'application/json' });
122
+ res.end(JSON.stringify({
123
+ success: true,
124
+ hasIndex: false,
125
+ fts: { percent: 0, indexedFiles: 0, totalFiles: 0 },
126
+ vector: { percent: 0, filesWithEmbeddings: 0, totalFiles: 0, totalChunks: 0 }
127
+ }));
128
+ return true;
129
+ }
130
+
131
+ // Parse project data
132
+ let projectData: any = null;
133
+ try {
134
+ const parsed = extractJSON(projectResult.output ?? '');
135
+ if (parsed.success && parsed.result) {
136
+ projectData = parsed.result;
137
+ }
138
+ } catch (e: unknown) {
139
+ console.error('[CodexLens] Failed to parse project data:', e instanceof Error ? e.message : String(e));
140
+ }
141
+
142
+ if (!projectData) {
143
+ res.writeHead(200, { 'Content-Type': 'application/json' });
144
+ res.end(JSON.stringify({
145
+ success: true,
146
+ hasIndex: false,
147
+ fts: { percent: 0, indexedFiles: 0, totalFiles: 0 },
148
+ vector: { percent: 0, filesWithEmbeddings: 0, totalFiles: 0, totalChunks: 0 }
149
+ }));
150
+ return true;
151
+ }
152
+
153
+ // Get index status for embeddings coverage using 'index status' command
154
+ const indexStatusResult = await executeCodexLens(['index', 'status', projectPath, '--json']);
155
+
156
+ let embeddingsData: any = null;
157
+ if (indexStatusResult.success && indexStatusResult.output) {
158
+ try {
159
+ const parsed = extractJSON(indexStatusResult.output);
160
+ if (parsed.success && parsed.result?.embeddings) {
161
+ embeddingsData = parsed.result.embeddings;
162
+ }
163
+ } catch (e: unknown) {
164
+ console.error('[CodexLens] Failed to parse index status:', e instanceof Error ? e.message : String(e));
165
+ }
166
+ }
167
+
168
+ // Calculate FTS and Vector percentages
169
+ const totalFiles = projectData.total_files || 0;
170
+ const indexedFiles = projectData.total_files || 0; // All indexed files have FTS
171
+
172
+ // Get embeddings data from index status
173
+ // The response structure is: { total_indexes, indexes_with_embeddings, total_chunks, indexes: [{coverage_percent, total_files, ...}] }
174
+ const indexesWithEmbeddings = embeddingsData?.indexes_with_embeddings || 0;
175
+ const totalChunks = embeddingsData?.total_chunks || 0;
176
+ // coverage_percent is in the indexes array - get the first one (for single project query)
177
+ const indexEntry = embeddingsData?.indexes?.[0];
178
+ const vectorPercent = indexEntry?.coverage_percent || 0;
179
+ const filesWithEmbeddings = indexEntry?.total_files || 0;
180
+
181
+ // FTS percentage (all indexed files have FTS, so it's always 100% if indexed)
182
+ const ftsPercent = totalFiles > 0 ? 100 : 0;
183
+
184
+ res.writeHead(200, { 'Content-Type': 'application/json' });
185
+ res.end(JSON.stringify({
186
+ success: true,
187
+ hasIndex: true,
188
+ path: projectPath,
189
+ fts: {
190
+ percent: ftsPercent,
191
+ indexedFiles,
192
+ totalFiles
193
+ },
194
+ vector: {
195
+ percent: vectorPercent,
196
+ filesWithEmbeddings,
197
+ totalFiles,
198
+ totalChunks
199
+ }
200
+ }));
201
+ } catch (err: unknown) {
202
+ res.writeHead(500, { 'Content-Type': 'application/json' });
203
+ res.end(JSON.stringify({ success: false, error: err instanceof Error ? err.message : String(err) }));
204
+ }
205
+ return true;
206
+ }
207
+
208
+ // API: CodexLens Bootstrap (Install)
209
+ if (pathname === '/api/codexlens/bootstrap' && req.method === 'POST') {
210
+ handlePostRequest(req, res, async () => {
211
+ try {
212
+ const result = await bootstrapVenv();
213
+ if (result.success) {
214
+ const status = await checkVenvStatus();
215
+ broadcastToClients({
216
+ type: 'CODEXLENS_INSTALLED',
217
+ payload: { version: status.version, timestamp: new Date().toISOString() }
218
+ });
219
+ return { success: true, message: 'CodexLens installed successfully', version: status.version };
220
+ } else {
221
+ return { success: false, error: result.error, status: 500 };
222
+ }
223
+ } catch (err) {
224
+ return { success: false, error: err instanceof Error ? err.message : String(err), status: 500 };
225
+ }
226
+ });
227
+ return true;
228
+ }
229
+
230
+ // API: CodexLens Uninstall
231
+ if (pathname === '/api/codexlens/uninstall' && req.method === 'POST') {
232
+ handlePostRequest(req, res, async () => {
233
+ try {
234
+ // Stop watcher if running (to release file handles)
235
+ await stopWatcherForUninstall();
236
+
237
+ if (isIndexingInProgress()) {
238
+ console.log('[CodexLens] Cancelling indexing before uninstall...');
239
+ try {
240
+ cancelIndexing();
241
+ } catch {
242
+ // Ignore errors
243
+ }
244
+ }
245
+
246
+ // Wait a moment for processes to fully exit and release handles
247
+ await new Promise(resolve => setTimeout(resolve, 1000));
248
+
249
+ const result = await uninstallCodexLens();
250
+ if (result.success) {
251
+ broadcastToClients({
252
+ type: 'CODEXLENS_UNINSTALLED',
253
+ payload: { timestamp: new Date().toISOString() }
254
+ });
255
+ return { success: true, message: 'CodexLens uninstalled successfully' };
256
+ } else {
257
+ return { success: false, error: result.error, status: 500 };
258
+ }
259
+ } catch (err) {
260
+ return { success: false, error: err instanceof Error ? err.message : String(err), status: 500 };
261
+ }
262
+ });
263
+ return true;
264
+ }
265
+
266
+ // API: CodexLens Config - GET (Get current configuration with index count)
267
+ if (pathname === '/api/codexlens/config' && req.method === 'GET') {
268
+ try {
269
+ const venvStatus = await checkVenvStatus();
270
+ let responseData = { index_dir: '~/.codexlens/indexes', index_count: 0, api_max_workers: 4, api_batch_size: 8 };
271
+
272
+ // If not installed, return default config without executing CodexLens
273
+ if (!venvStatus.ready) {
274
+ res.writeHead(200, { 'Content-Type': 'application/json' });
275
+ res.end(JSON.stringify(responseData));
276
+ return true;
277
+ }
278
+
279
+ // Use projects list for accurate index_count (same source as /api/codexlens/indexes)
280
+ const [configResult, projectsResult] = await Promise.all([
281
+ executeCodexLens(['config', '--json']),
282
+ executeCodexLens(['projects', 'list', '--json'])
283
+ ]);
284
+
285
+ // Parse config (extract JSON from output that may contain log messages)
286
+ if (configResult.success) {
287
+ try {
288
+ const config = extractJSON(configResult.output ?? '');
289
+ if (config.success && config.result) {
290
+ // CLI returns index_dir (not index_root)
291
+ responseData.index_dir = config.result.index_dir || config.result.index_root || responseData.index_dir;
292
+ // Extract API settings
293
+ if (config.result.api_max_workers !== undefined) {
294
+ responseData.api_max_workers = config.result.api_max_workers;
295
+ }
296
+ if (config.result.api_batch_size !== undefined) {
297
+ responseData.api_batch_size = config.result.api_batch_size;
298
+ }
299
+ }
300
+ } catch (e: unknown) {
301
+ console.error('[CodexLens] Failed to parse config:', e instanceof Error ? e.message : String(e));
302
+ console.error('[CodexLens] Config output:', (configResult.output ?? '').substring(0, 200));
303
+ }
304
+ }
305
+
306
+ // Parse projects list to get index_count (consistent with /api/codexlens/indexes)
307
+ if (projectsResult.success) {
308
+ try {
309
+ const projectsData = extractJSON(projectsResult.output ?? '');
310
+ if (projectsData.success && Array.isArray(projectsData.result)) {
311
+ // Filter out test/temp projects (same logic as /api/codexlens/indexes)
312
+ const validProjects = projectsData.result.filter((project: any) => {
313
+ if (project.source_root && (
314
+ project.source_root.includes('\\Temp\\') ||
315
+ project.source_root.includes('/tmp/') ||
316
+ project.total_files === 0
317
+ )) {
318
+ return false;
319
+ }
320
+ return true;
321
+ });
322
+ responseData.index_count = validProjects.length;
323
+ }
324
+ } catch (e: unknown) {
325
+ console.error('[CodexLens] Failed to parse projects list:', e instanceof Error ? e.message : String(e));
326
+ console.error('[CodexLens] Projects output:', (projectsResult.output ?? '').substring(0, 200));
327
+ }
328
+ }
329
+
330
+ res.writeHead(200, { 'Content-Type': 'application/json' });
331
+ res.end(JSON.stringify(responseData));
332
+ } catch (err: unknown) {
333
+ res.writeHead(500, { 'Content-Type': 'application/json' });
334
+ res.end(JSON.stringify({ error: err instanceof Error ? err.message : String(err) }));
335
+ }
336
+ return true;
337
+ }
338
+
339
+ // API: CodexLens Config - POST (Set configuration)
340
+ if (pathname === '/api/codexlens/config' && req.method === 'POST') {
341
+ handlePostRequest(req, res, async (body: unknown) => {
342
+ const { index_dir, api_max_workers, api_batch_size } = body as {
343
+ index_dir?: unknown;
344
+ api_max_workers?: unknown;
345
+ api_batch_size?: unknown;
346
+ };
347
+
348
+ if (!index_dir) {
349
+ return { success: false, error: 'index_dir is required', status: 400 };
350
+ }
351
+
352
+ // Validate index_dir path
353
+ const indexDirStr = String(index_dir).trim();
354
+
355
+ // Check for dangerous patterns
356
+ if (indexDirStr.includes('\0')) {
357
+ return { success: false, error: 'Invalid path: contains null bytes', status: 400 };
358
+ }
359
+
360
+ // Prevent system root paths and their subdirectories (Windows and Unix)
361
+ const dangerousPaths = ['/', 'C:\\', 'C:/', '/etc', '/usr', '/bin', '/sys', '/proc', '/var',
362
+ 'C:\\Windows', 'C:\\Program Files', 'C:\\Program Files (x86)', 'C:\\System32'];
363
+ const normalizedPath = indexDirStr.replace(/\\/g, '/').toLowerCase();
364
+ for (const dangerous of dangerousPaths) {
365
+ const dangerousLower = dangerous.replace(/\\/g, '/').toLowerCase();
366
+ // Block exact match OR any subdirectory (using startsWith)
367
+ if (normalizedPath === dangerousLower ||
368
+ normalizedPath === dangerousLower + '/' ||
369
+ normalizedPath.startsWith(dangerousLower + '/')) {
370
+ return { success: false, error: 'Invalid path: cannot use system directories or their subdirectories', status: 400 };
371
+ }
372
+ }
373
+
374
+ // Additional check: prevent path traversal attempts
375
+ if (normalizedPath.includes('../') || normalizedPath.includes('/..')) {
376
+ return { success: false, error: 'Invalid path: path traversal not allowed', status: 400 };
377
+ }
378
+
379
+ // Validate api settings
380
+ if (api_max_workers !== undefined) {
381
+ const workers = Number(api_max_workers);
382
+ if (isNaN(workers) || workers < 1 || workers > 32) {
383
+ return { success: false, error: 'api_max_workers must be between 1 and 32', status: 400 };
384
+ }
385
+ }
386
+ if (api_batch_size !== undefined) {
387
+ const batch = Number(api_batch_size);
388
+ if (isNaN(batch) || batch < 1 || batch > 64) {
389
+ return { success: false, error: 'api_batch_size must be between 1 and 64', status: 400 };
390
+ }
391
+ }
392
+
393
+ try {
394
+ // Set index_dir
395
+ const result = await executeCodexLens(['config', 'set', 'index_dir', indexDirStr, '--json']);
396
+ if (!result.success) {
397
+ return { success: false, error: result.error || 'Failed to update index_dir', status: 500 };
398
+ }
399
+
400
+ // Set API settings if provided
401
+ if (api_max_workers !== undefined) {
402
+ await executeCodexLens(['config', 'set', 'api_max_workers', String(api_max_workers), '--json']);
403
+ }
404
+ if (api_batch_size !== undefined) {
405
+ await executeCodexLens(['config', 'set', 'api_batch_size', String(api_batch_size), '--json']);
406
+ }
407
+
408
+ return { success: true, message: 'Configuration updated successfully' };
409
+ } catch (err: unknown) {
410
+ return { success: false, error: err instanceof Error ? err.message : String(err), status: 500 };
411
+ }
412
+ });
413
+ return true;
414
+ }
415
+
416
+ // API: Detect GPU support for semantic search
417
+ if (pathname === '/api/codexlens/gpu/detect' && req.method === 'GET') {
418
+ try {
419
+ const gpuInfo = await detectGpuSupport();
420
+ res.writeHead(200, { 'Content-Type': 'application/json' });
421
+ res.end(JSON.stringify({ success: true, ...gpuInfo }));
422
+ } catch (err: unknown) {
423
+ res.writeHead(500, { 'Content-Type': 'application/json' });
424
+ res.end(JSON.stringify({ success: false, error: err instanceof Error ? err.message : String(err) }));
425
+ }
426
+ return true;
427
+ }
428
+
429
+ // API: List available GPU devices for selection
430
+ if (pathname === '/api/codexlens/gpu/list' && req.method === 'GET') {
431
+ try {
432
+ // Try CodexLens gpu-list first if available
433
+ const venvStatus = await checkVenvStatus();
434
+ if (venvStatus.ready) {
435
+ const result = await executeCodexLens(['gpu-list', '--json']);
436
+ if (result.success) {
437
+ try {
438
+ const parsed = extractJSON(result.output ?? '');
439
+ if (parsed.devices && parsed.devices.length > 0) {
440
+ res.writeHead(200, { 'Content-Type': 'application/json' });
441
+ res.end(JSON.stringify(parsed));
442
+ return true;
443
+ }
444
+ } catch {
445
+ // Fall through to system detection
446
+ }
447
+ }
448
+ }
449
+
450
+ // Fallback: Use system commands to detect GPUs
451
+ const devices: Array<{ name: string; type: string; index: number }> = [];
452
+
453
+ if (process.platform === 'win32') {
454
+ // Windows: Use WMIC to get GPU info
455
+ try {
456
+ const { execSync } = await import('child_process');
457
+ const wmicOutput = execSync('wmic path win32_VideoController get name', {
458
+ encoding: 'utf-8',
459
+ timeout: EXEC_TIMEOUTS.SYSTEM_INFO,
460
+ stdio: ['pipe', 'pipe', 'pipe']
461
+ });
462
+
463
+ const lines = wmicOutput.split('\n')
464
+ .map(line => line.trim())
465
+ .filter(line => line && line !== 'Name');
466
+
467
+ lines.forEach((name, index) => {
468
+ if (name) {
469
+ const isIntegrated = name.toLowerCase().includes('intel') ||
470
+ name.toLowerCase().includes('integrated');
471
+ devices.push({
472
+ name: name,
473
+ type: isIntegrated ? 'integrated' : 'discrete',
474
+ index: index
475
+ });
476
+ }
477
+ });
478
+ } catch (e) {
479
+ console.warn('[CodexLens] WMIC GPU detection failed:', (e as Error).message);
480
+ }
481
+ } else {
482
+ // Linux/Mac: Try nvidia-smi for NVIDIA GPUs
483
+ try {
484
+ const { execSync } = await import('child_process');
485
+ const nvidiaOutput = execSync('nvidia-smi --query-gpu=name --format=csv,noheader', {
486
+ encoding: 'utf-8',
487
+ timeout: EXEC_TIMEOUTS.SYSTEM_INFO,
488
+ stdio: ['pipe', 'pipe', 'pipe']
489
+ });
490
+
491
+ const lines = nvidiaOutput.split('\n').filter(line => line.trim());
492
+ lines.forEach((name, index) => {
493
+ devices.push({
494
+ name: name.trim(),
495
+ type: 'discrete',
496
+ index: index
497
+ });
498
+ });
499
+ } catch {
500
+ // NVIDIA not available, that's fine
501
+ }
502
+ }
503
+
504
+ res.writeHead(200, { 'Content-Type': 'application/json' });
505
+ res.end(JSON.stringify({ success: true, devices: devices, selected_device_id: null }));
506
+ } catch (err: unknown) {
507
+ res.writeHead(500, { 'Content-Type': 'application/json' });
508
+ res.end(JSON.stringify({ success: false, error: err instanceof Error ? err.message : String(err) }));
509
+ }
510
+ return true;
511
+ }
512
+
513
+ // API: Select GPU device for embedding
514
+ if (pathname === '/api/codexlens/gpu/select' && req.method === 'POST') {
515
+ handlePostRequest(req, res, async (body) => {
516
+ const { device_id } = body as { device_id?: unknown };
517
+ const resolvedDeviceId = typeof device_id === 'string' || typeof device_id === 'number' ? device_id : undefined;
518
+
519
+ if (resolvedDeviceId === undefined) {
520
+ return { success: false, error: 'device_id is required', status: 400 };
521
+ }
522
+
523
+ try {
524
+ const result = await executeCodexLens(['gpu-select', String(resolvedDeviceId), '--json']);
525
+ if (result.success) {
526
+ try {
527
+ const parsed = extractJSON(result.output ?? '');
528
+ return parsed;
529
+ } catch {
530
+ return { success: true, message: 'GPU selected', output: result.output };
531
+ }
532
+ } else {
533
+ return { success: false, error: result.error, status: 500 };
534
+ }
535
+ } catch (err: unknown) {
536
+ return { success: false, error: err instanceof Error ? err.message : String(err), status: 500 };
537
+ }
538
+ });
539
+ return true;
540
+ }
541
+
542
+ // API: Reset GPU selection to auto-detection
543
+ if (pathname === '/api/codexlens/gpu/reset' && req.method === 'POST') {
544
+ handlePostRequest(req, res, async () => {
545
+ try {
546
+ const result = await executeCodexLens(['gpu-reset', '--json']);
547
+ if (result.success) {
548
+ try {
549
+ const parsed = extractJSON(result.output ?? '');
550
+ return parsed;
551
+ } catch {
552
+ return { success: true, message: 'GPU selection reset', output: result.output };
553
+ }
554
+ } else {
555
+ return { success: false, error: result.error, status: 500 };
556
+ }
557
+ } catch (err: unknown) {
558
+ return { success: false, error: err instanceof Error ? err.message : String(err), status: 500 };
559
+ }
560
+ });
561
+ return true;
562
+ }
563
+
564
+ // API: CodexLens Model List (list available embedding models)
565
+ if (pathname === '/api/codexlens/models' && req.method === 'GET') {
566
+ try {
567
+ // Check if CodexLens is installed first (without auto-installing)
568
+ const venvStatus = await checkVenvStatus();
569
+ if (!venvStatus.ready) {
570
+ res.writeHead(200, { 'Content-Type': 'application/json' });
571
+ res.end(JSON.stringify({ success: false, error: 'CodexLens not installed' }));
572
+ return true;
573
+ }
574
+ const result = await executeCodexLens(['model-list', '--json']);
575
+ if (result.success) {
576
+ try {
577
+ const parsed = extractJSON(result.output ?? '');
578
+ res.writeHead(200, { 'Content-Type': 'application/json' });
579
+ res.end(JSON.stringify(parsed));
580
+ } catch {
581
+ res.writeHead(200, { 'Content-Type': 'application/json' });
582
+ res.end(JSON.stringify({ success: true, result: { models: [] }, output: result.output }));
583
+ }
584
+ } else {
585
+ res.writeHead(500, { 'Content-Type': 'application/json' });
586
+ res.end(JSON.stringify({ success: false, error: result.error }));
587
+ }
588
+ } catch (err: unknown) {
589
+ res.writeHead(500, { 'Content-Type': 'application/json' });
590
+ res.end(JSON.stringify({ success: false, error: err instanceof Error ? err.message : String(err) }));
591
+ }
592
+ return true;
593
+ }
594
+
595
+ // API: CodexLens Model Download (download embedding model by profile)
596
+ if (pathname === '/api/codexlens/models/download' && req.method === 'POST') {
597
+ handlePostRequest(req, res, async (body) => {
598
+ const { profile } = body as { profile?: unknown };
599
+ const resolvedProfile = typeof profile === 'string' && profile.trim().length > 0 ? profile.trim() : undefined;
600
+
601
+ if (!resolvedProfile) {
602
+ return { success: false, error: 'profile is required', status: 400 };
603
+ }
604
+
605
+ try {
606
+ const result = await executeCodexLens(['model-download', resolvedProfile, '--json'], { timeout: 600000 }); // 10 min for download
607
+ if (result.success) {
608
+ try {
609
+ const parsed = extractJSON(result.output ?? '');
610
+ return { success: true, ...parsed };
611
+ } catch {
612
+ return { success: true, output: result.output };
613
+ }
614
+ } else {
615
+ return { success: false, error: result.error, status: 500 };
616
+ }
617
+ } catch (err: unknown) {
618
+ return { success: false, error: err instanceof Error ? err.message : String(err), status: 500 };
619
+ }
620
+ });
621
+ return true;
622
+ }
623
+
624
+ // API: CodexLens Model Download Custom (download any HuggingFace model)
625
+ if (pathname === '/api/codexlens/models/download-custom' && req.method === 'POST') {
626
+ handlePostRequest(req, res, async (body) => {
627
+ const { model_name, model_type } = body as { model_name?: unknown; model_type?: unknown };
628
+ const resolvedModelName = typeof model_name === 'string' && model_name.trim().length > 0 ? model_name.trim() : undefined;
629
+ const resolvedModelType = typeof model_type === 'string' ? model_type.trim() : 'embedding';
630
+
631
+ if (!resolvedModelName) {
632
+ return { success: false, error: 'model_name is required', status: 400 };
633
+ }
634
+
635
+ // Validate model name format
636
+ if (!resolvedModelName.includes('/')) {
637
+ return { success: false, error: 'Invalid model_name format. Expected: org/model-name', status: 400 };
638
+ }
639
+
640
+ try {
641
+ const result = await executeCodexLens([
642
+ 'model-download-custom', resolvedModelName,
643
+ '--type', resolvedModelType,
644
+ '--json'
645
+ ], { timeout: 600000 }); // 10 min for download
646
+
647
+ if (result.success) {
648
+ try {
649
+ const parsed = extractJSON(result.output ?? '');
650
+ return { success: true, ...parsed };
651
+ } catch {
652
+ return { success: true, output: result.output };
653
+ }
654
+ } else {
655
+ return { success: false, error: result.error, status: 500 };
656
+ }
657
+ } catch (err: unknown) {
658
+ return { success: false, error: err instanceof Error ? err.message : String(err), status: 500 };
659
+ }
660
+ });
661
+ return true;
662
+ }
663
+
664
+ // API: CodexLens Model Delete (delete embedding model by profile)
665
+ if (pathname === '/api/codexlens/models/delete' && req.method === 'POST') {
666
+ handlePostRequest(req, res, async (body) => {
667
+ const { profile } = body as { profile?: unknown };
668
+ const resolvedProfile = typeof profile === 'string' && profile.trim().length > 0 ? profile.trim() : undefined;
669
+
670
+ if (!resolvedProfile) {
671
+ return { success: false, error: 'profile is required', status: 400 };
672
+ }
673
+
674
+ try {
675
+ const result = await executeCodexLens(['model-delete', resolvedProfile, '--json']);
676
+ if (result.success) {
677
+ try {
678
+ const parsed = extractJSON(result.output ?? '');
679
+ return { success: true, ...parsed };
680
+ } catch {
681
+ return { success: true, output: result.output };
682
+ }
683
+ } else {
684
+ return { success: false, error: result.error, status: 500 };
685
+ }
686
+ } catch (err: unknown) {
687
+ return { success: false, error: err instanceof Error ? err.message : String(err), status: 500 };
688
+ }
689
+ });
690
+ return true;
691
+ }
692
+
693
+ // API: CodexLens Model Delete by Path (delete discovered/manually placed model)
694
+ if (pathname === '/api/codexlens/models/delete-path' && req.method === 'POST') {
695
+ handlePostRequest(req, res, async (body) => {
696
+ const { cache_path } = body as { cache_path?: unknown };
697
+ const resolvedPath = typeof cache_path === 'string' && cache_path.trim().length > 0 ? cache_path.trim() : undefined;
698
+
699
+ if (!resolvedPath) {
700
+ return { success: false, error: 'cache_path is required', status: 400 };
701
+ }
702
+
703
+ // Security: Validate that the path is within the HuggingFace cache directory
704
+ const { homedir } = await import('os');
705
+ const { join, resolve, normalize } = await import('path');
706
+ const { rm } = await import('fs/promises');
707
+
708
+ const hfCacheDir = process.env.HF_HOME || join(homedir(), '.cache', 'huggingface');
709
+ const normalizedCachePath = normalize(resolve(resolvedPath));
710
+ const normalizedHfCacheDir = normalize(resolve(hfCacheDir));
711
+
712
+ // Ensure the path is within the HuggingFace cache directory
713
+ if (!normalizedCachePath.startsWith(normalizedHfCacheDir)) {
714
+ return { success: false, error: 'Path must be within the HuggingFace cache directory', status: 400 };
715
+ }
716
+
717
+ // Ensure it's a models-- directory
718
+ const pathParts = normalizedCachePath.split(/[/\\]/);
719
+ const lastPart = pathParts[pathParts.length - 1];
720
+ if (!lastPart.startsWith('models--')) {
721
+ return { success: false, error: 'Path must be a model cache directory (models--*)', status: 400 };
722
+ }
723
+
724
+ try {
725
+ await rm(normalizedCachePath, { recursive: true, force: true });
726
+ return { success: true, message: 'Model deleted successfully', cache_path: normalizedCachePath };
727
+ } catch (err: unknown) {
728
+ return { success: false, error: err instanceof Error ? err.message : String(err), status: 500 };
729
+ }
730
+ });
731
+ return true;
732
+ }
733
+
734
+ // API: CodexLens Model Info (get model info by profile)
735
+ if (pathname === '/api/codexlens/models/info' && req.method === 'GET') {
736
+ const profile = url.searchParams.get('profile');
737
+
738
+ if (!profile) {
739
+ res.writeHead(400, { 'Content-Type': 'application/json' });
740
+ res.end(JSON.stringify({ success: false, error: 'profile parameter is required' }));
741
+ return true;
742
+ }
743
+
744
+ try {
745
+ const result = await executeCodexLens(['model-info', profile, '--json']);
746
+ if (result.success) {
747
+ try {
748
+ const parsed = extractJSON(result.output ?? '');
749
+ res.writeHead(200, { 'Content-Type': 'application/json' });
750
+ res.end(JSON.stringify(parsed));
751
+ } catch {
752
+ res.writeHead(200, { 'Content-Type': 'application/json' });
753
+ res.end(JSON.stringify({ success: false, error: 'Failed to parse response' }));
754
+ }
755
+ } else {
756
+ res.writeHead(500, { 'Content-Type': 'application/json' });
757
+ res.end(JSON.stringify({ success: false, error: result.error }));
758
+ }
759
+ } catch (err: unknown) {
760
+ res.writeHead(500, { 'Content-Type': 'application/json' });
761
+ res.end(JSON.stringify({ success: false, error: err instanceof Error ? err.message : String(err) }));
762
+ }
763
+ return true;
764
+ }
765
+
766
+ // ============================================================
767
+ // ENV FILE MANAGEMENT ENDPOINTS
768
+ // ============================================================
769
+
770
+ // API: Get global env file content
771
+ if (pathname === '/api/codexlens/env' && req.method === 'GET') {
772
+ try {
773
+ const { homedir } = await import('os');
774
+ const { join } = await import('path');
775
+ const { readFile } = await import('fs/promises');
776
+
777
+ const envPath = join(homedir(), '.codexlens', '.env');
778
+ let content = '';
779
+ try {
780
+ content = await readFile(envPath, 'utf-8');
781
+ } catch {
782
+ // File doesn't exist, return empty
783
+ }
784
+
785
+ // Parse env file into key-value pairs (robust parsing)
786
+ const envVars: Record<string, string> = {};
787
+ const lines = content.split('\n');
788
+ for (const line of lines) {
789
+ const trimmed = line.trim();
790
+ // Skip empty lines and comments
791
+ if (!trimmed || trimmed.startsWith('#')) continue;
792
+
793
+ // Find first = that's part of key=value (not in a quote)
794
+ const eqIndex = trimmed.indexOf('=');
795
+ if (eqIndex <= 0) continue;
796
+
797
+ const key = trimmed.substring(0, eqIndex).trim();
798
+ // Validate key format (alphanumeric + underscore)
799
+ if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(key)) continue;
800
+
801
+ let value = trimmed.substring(eqIndex + 1);
802
+
803
+ // Handle quoted values (preserves = inside quotes)
804
+ if (value.startsWith('"')) {
805
+ // Find matching closing quote (handle escaped quotes)
806
+ let end = 1;
807
+ while (end < value.length) {
808
+ if (value[end] === '"' && value[end - 1] !== '\\') break;
809
+ end++;
810
+ }
811
+ value = value.substring(1, end).replace(/\\"/g, '"');
812
+ } else if (value.startsWith("'")) {
813
+ // Single quotes don't support escaping
814
+ const end = value.indexOf("'", 1);
815
+ value = end > 0 ? value.substring(1, end) : value.substring(1);
816
+ } else {
817
+ // Unquoted: trim and take until comment or end
818
+ const commentIndex = value.indexOf(' #');
819
+ if (commentIndex > 0) {
820
+ value = value.substring(0, commentIndex);
821
+ }
822
+ value = value.trim();
823
+ }
824
+
825
+ envVars[key] = value;
826
+ }
827
+
828
+ // Also read settings.json for current configuration
829
+ const settingsPath = join(homedir(), '.codexlens', 'settings.json');
830
+ let settings: Record<string, any> = {};
831
+ try {
832
+ const settingsContent = await readFile(settingsPath, 'utf-8');
833
+ settings = JSON.parse(settingsContent);
834
+ } catch {
835
+ // Settings file doesn't exist or is invalid, use empty
836
+ }
837
+
838
+ // Map settings to env var format for defaults
839
+ const settingsDefaults: Record<string, string> = {};
840
+
841
+ // Embedding settings
842
+ if (settings.embedding?.backend) {
843
+ settingsDefaults['CODEXLENS_EMBEDDING_BACKEND'] = settings.embedding.backend;
844
+ }
845
+ if (settings.embedding?.model) {
846
+ settingsDefaults['CODEXLENS_EMBEDDING_MODEL'] = settings.embedding.model;
847
+ settingsDefaults['LITELLM_EMBEDDING_MODEL'] = settings.embedding.model;
848
+ }
849
+ if (settings.embedding?.use_gpu !== undefined) {
850
+ settingsDefaults['CODEXLENS_USE_GPU'] = String(settings.embedding.use_gpu);
851
+ }
852
+ if (settings.embedding?.strategy) {
853
+ settingsDefaults['CODEXLENS_EMBEDDING_STRATEGY'] = settings.embedding.strategy;
854
+ }
855
+ if (settings.embedding?.cooldown !== undefined) {
856
+ settingsDefaults['CODEXLENS_EMBEDDING_COOLDOWN'] = String(settings.embedding.cooldown);
857
+ }
858
+
859
+ // Reranker settings
860
+ if (settings.reranker?.backend) {
861
+ settingsDefaults['CODEXLENS_RERANKER_BACKEND'] = settings.reranker.backend;
862
+ }
863
+ if (settings.reranker?.model) {
864
+ settingsDefaults['CODEXLENS_RERANKER_MODEL'] = settings.reranker.model;
865
+ settingsDefaults['LITELLM_RERANKER_MODEL'] = settings.reranker.model;
866
+ }
867
+ if (settings.reranker?.enabled !== undefined) {
868
+ settingsDefaults['CODEXLENS_RERANKER_ENABLED'] = String(settings.reranker.enabled);
869
+ }
870
+ if (settings.reranker?.top_k !== undefined) {
871
+ settingsDefaults['CODEXLENS_RERANKER_TOP_K'] = String(settings.reranker.top_k);
872
+ }
873
+
874
+ // API/Concurrency settings
875
+ if (settings.api?.max_workers !== undefined) {
876
+ settingsDefaults['CODEXLENS_API_MAX_WORKERS'] = String(settings.api.max_workers);
877
+ }
878
+ if (settings.api?.batch_size !== undefined) {
879
+ settingsDefaults['CODEXLENS_API_BATCH_SIZE'] = String(settings.api.batch_size);
880
+ }
881
+ // Dynamic batch size settings
882
+ if (settings.api?.batch_size_dynamic !== undefined) {
883
+ settingsDefaults['CODEXLENS_API_BATCH_SIZE_DYNAMIC'] = String(settings.api.batch_size_dynamic);
884
+ }
885
+ if (settings.api?.batch_size_utilization_factor !== undefined) {
886
+ settingsDefaults['CODEXLENS_API_BATCH_SIZE_UTILIZATION'] = String(settings.api.batch_size_utilization_factor);
887
+ }
888
+ if (settings.api?.batch_size_max !== undefined) {
889
+ settingsDefaults['CODEXLENS_API_BATCH_SIZE_MAX'] = String(settings.api.batch_size_max);
890
+ }
891
+ if (settings.api?.chars_per_token_estimate !== undefined) {
892
+ settingsDefaults['CODEXLENS_CHARS_PER_TOKEN'] = String(settings.api.chars_per_token_estimate);
893
+ }
894
+
895
+ // Cascade search settings
896
+ if (settings.cascade?.strategy) {
897
+ settingsDefaults['CODEXLENS_CASCADE_STRATEGY'] = settings.cascade.strategy;
898
+ }
899
+ if (settings.cascade?.coarse_k !== undefined) {
900
+ settingsDefaults['CODEXLENS_CASCADE_COARSE_K'] = String(settings.cascade.coarse_k);
901
+ }
902
+ if (settings.cascade?.fine_k !== undefined) {
903
+ settingsDefaults['CODEXLENS_CASCADE_FINE_K'] = String(settings.cascade.fine_k);
904
+ }
905
+
906
+ // LLM settings
907
+ if (settings.llm?.enabled !== undefined) {
908
+ settingsDefaults['CODEXLENS_LLM_ENABLED'] = String(settings.llm.enabled);
909
+ }
910
+ if (settings.llm?.batch_size !== undefined) {
911
+ settingsDefaults['CODEXLENS_LLM_BATCH_SIZE'] = String(settings.llm.batch_size);
912
+ }
913
+
914
+ res.writeHead(200, { 'Content-Type': 'application/json' });
915
+ res.end(JSON.stringify({
916
+ success: true,
917
+ path: envPath,
918
+ env: envVars,
919
+ raw: content,
920
+ settings: settingsDefaults
921
+ }));
922
+ } catch (err: unknown) {
923
+ res.writeHead(500, { 'Content-Type': 'application/json' });
924
+ res.end(JSON.stringify({ success: false, error: err instanceof Error ? err.message : String(err) }));
925
+ }
926
+ return true;
927
+ }
928
+
929
+ // API: Save global env file content (merge mode - preserves existing values)
930
+ if (pathname === '/api/codexlens/env' && req.method === 'POST') {
931
+ handlePostRequest(req, res, async (body) => {
932
+ const { env } = body as { env: Record<string, string> };
933
+
934
+ if (!env || typeof env !== 'object') {
935
+ return { success: false, error: 'env object is required', status: 400 };
936
+ }
937
+
938
+ try {
939
+ const { homedir } = await import('os');
940
+ const { join, dirname } = await import('path');
941
+ const { writeFile, mkdir, readFile } = await import('fs/promises');
942
+
943
+ const envPath = join(homedir(), '.codexlens', '.env');
944
+ await mkdir(dirname(envPath), { recursive: true });
945
+
946
+ // Read existing env file to preserve custom variables
947
+ let existingEnv: Record<string, string> = {};
948
+ let existingComments: string[] = [];
949
+ try {
950
+ const content = await readFile(envPath, 'utf-8');
951
+ const lines = content.split('\n');
952
+ for (const line of lines) {
953
+ const trimmed = line.trim();
954
+ // Preserve comment lines that aren't our headers
955
+ if (trimmed.startsWith('#') && !trimmed.includes('Managed by CCW')) {
956
+ if (!trimmed.includes('Reranker API') && !trimmed.includes('Embedding API') &&
957
+ !trimmed.includes('LiteLLM Config') && !trimmed.includes('CodexLens Settings') &&
958
+ !trimmed.includes('Other Settings') && !trimmed.includes('CodexLens Environment')) {
959
+ existingComments.push(line);
960
+ }
961
+ }
962
+ if (!trimmed || trimmed.startsWith('#')) continue;
963
+
964
+ // Robust parsing (same as GET handler)
965
+ const eqIndex = trimmed.indexOf('=');
966
+ if (eqIndex <= 0) continue;
967
+
968
+ const key = trimmed.substring(0, eqIndex).trim();
969
+ if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(key)) continue;
970
+
971
+ let value = trimmed.substring(eqIndex + 1);
972
+ if (value.startsWith('"')) {
973
+ let end = 1;
974
+ while (end < value.length) {
975
+ if (value[end] === '"' && value[end - 1] !== '\\') break;
976
+ end++;
977
+ }
978
+ value = value.substring(1, end).replace(/\\"/g, '"');
979
+ } else if (value.startsWith("'")) {
980
+ const end = value.indexOf("'", 1);
981
+ value = end > 0 ? value.substring(1, end) : value.substring(1);
982
+ } else {
983
+ const commentIndex = value.indexOf(' #');
984
+ if (commentIndex > 0) value = value.substring(0, commentIndex);
985
+ value = value.trim();
986
+ }
987
+ existingEnv[key] = value;
988
+ }
989
+ } catch {
990
+ // File doesn't exist, start fresh
991
+ }
992
+
993
+ // Merge: update known keys from payload, preserve unknown keys
994
+ const knownKeys = new Set([
995
+ 'RERANKER_API_KEY', 'RERANKER_API_BASE', 'RERANKER_MODEL',
996
+ 'EMBEDDING_API_KEY', 'EMBEDDING_API_BASE', 'EMBEDDING_MODEL',
997
+ 'LITELLM_API_KEY', 'LITELLM_API_BASE', 'LITELLM_MODEL'
998
+ ]);
999
+
1000
+ // Apply updates from payload
1001
+ for (const [key, value] of Object.entries(env)) {
1002
+ if (value) {
1003
+ existingEnv[key] = value;
1004
+ } else if (knownKeys.has(key)) {
1005
+ // Remove known key if value is empty
1006
+ delete existingEnv[key];
1007
+ }
1008
+ }
1009
+
1010
+ // Build env file content
1011
+ const lines = [
1012
+ '# CodexLens Environment Configuration',
1013
+ '# Managed by CCW Dashboard',
1014
+ ''
1015
+ ];
1016
+
1017
+ // Add preserved custom comments
1018
+ if (existingComments.length > 0) {
1019
+ lines.push(...existingComments, '');
1020
+ }
1021
+
1022
+ // Group by prefix
1023
+ const groups: Record<string, string[]> = {
1024
+ 'RERANKER': [],
1025
+ 'EMBEDDING': [],
1026
+ 'LITELLM': [],
1027
+ 'CODEXLENS': [],
1028
+ 'OTHER': []
1029
+ };
1030
+
1031
+ for (const [key, value] of Object.entries(existingEnv)) {
1032
+ if (!value) continue;
1033
+ // SECURITY: Escape special characters to prevent .env injection
1034
+ const escapedValue = value
1035
+ .replace(/\\/g, '\\\\') // Escape backslashes first
1036
+ .replace(/"/g, '\\"') // Escape double quotes
1037
+ .replace(/\n/g, '\\n') // Escape newlines
1038
+ .replace(/\r/g, '\\r'); // Escape carriage returns
1039
+ const line = `${key}="${escapedValue}"`;
1040
+ if (key.startsWith('RERANKER_')) groups['RERANKER'].push(line);
1041
+ else if (key.startsWith('EMBEDDING_')) groups['EMBEDDING'].push(line);
1042
+ else if (key.startsWith('LITELLM_')) groups['LITELLM'].push(line);
1043
+ else if (key.startsWith('CODEXLENS_')) groups['CODEXLENS'].push(line);
1044
+ else groups['OTHER'].push(line);
1045
+ }
1046
+
1047
+ // Add grouped content
1048
+ if (groups['RERANKER'].length) {
1049
+ lines.push('# Reranker API Configuration');
1050
+ lines.push(...groups['RERANKER'], '');
1051
+ }
1052
+ if (groups['EMBEDDING'].length) {
1053
+ lines.push('# Embedding API Configuration');
1054
+ lines.push(...groups['EMBEDDING'], '');
1055
+ }
1056
+ if (groups['LITELLM'].length) {
1057
+ lines.push('# LiteLLM Configuration');
1058
+ lines.push(...groups['LITELLM'], '');
1059
+ }
1060
+ if (groups['CODEXLENS'].length) {
1061
+ lines.push('# CodexLens Settings');
1062
+ lines.push(...groups['CODEXLENS'], '');
1063
+ }
1064
+ if (groups['OTHER'].length) {
1065
+ lines.push('# Other Settings');
1066
+ lines.push(...groups['OTHER'], '');
1067
+ }
1068
+
1069
+ await writeFile(envPath, lines.join('\n'), 'utf-8');
1070
+
1071
+ // Also update settings.json with mapped values
1072
+ const settingsPath = join(homedir(), '.codexlens', 'settings.json');
1073
+ let settings: Record<string, any> = {};
1074
+ try {
1075
+ const settingsContent = await readFile(settingsPath, 'utf-8');
1076
+ settings = JSON.parse(settingsContent);
1077
+ } catch {
1078
+ // File doesn't exist, create default structure
1079
+ settings = { embedding: {}, reranker: {}, api: {}, cascade: {}, llm: {} };
1080
+ }
1081
+
1082
+ // Map env vars to settings.json structure
1083
+ const envToSettings: Record<string, { path: string[], transform?: (v: string) => any }> = {
1084
+ 'CODEXLENS_EMBEDDING_BACKEND': { path: ['embedding', 'backend'] },
1085
+ 'CODEXLENS_EMBEDDING_MODEL': { path: ['embedding', 'model'] },
1086
+ 'CODEXLENS_USE_GPU': { path: ['embedding', 'use_gpu'], transform: v => v === 'true' },
1087
+ 'CODEXLENS_EMBEDDING_STRATEGY': { path: ['embedding', 'strategy'] },
1088
+ 'CODEXLENS_EMBEDDING_COOLDOWN': { path: ['embedding', 'cooldown'], transform: v => parseFloat(v) },
1089
+ 'CODEXLENS_RERANKER_BACKEND': { path: ['reranker', 'backend'] },
1090
+ 'CODEXLENS_RERANKER_MODEL': { path: ['reranker', 'model'] },
1091
+ 'CODEXLENS_RERANKER_ENABLED': { path: ['reranker', 'enabled'], transform: v => v === 'true' },
1092
+ 'CODEXLENS_RERANKER_TOP_K': { path: ['reranker', 'top_k'], transform: v => parseInt(v, 10) },
1093
+ 'CODEXLENS_API_MAX_WORKERS': { path: ['api', 'max_workers'], transform: v => parseInt(v, 10) },
1094
+ 'CODEXLENS_API_BATCH_SIZE': { path: ['api', 'batch_size'], transform: v => parseInt(v, 10) },
1095
+ 'CODEXLENS_API_BATCH_SIZE_DYNAMIC': { path: ['api', 'batch_size_dynamic'], transform: v => v === 'true' },
1096
+ 'CODEXLENS_API_BATCH_SIZE_UTILIZATION': { path: ['api', 'batch_size_utilization_factor'], transform: v => parseFloat(v) },
1097
+ 'CODEXLENS_API_BATCH_SIZE_MAX': { path: ['api', 'batch_size_max'], transform: v => parseInt(v, 10) },
1098
+ 'CODEXLENS_CHARS_PER_TOKEN': { path: ['api', 'chars_per_token_estimate'], transform: v => parseInt(v, 10) },
1099
+ 'CODEXLENS_CASCADE_STRATEGY': { path: ['cascade', 'strategy'] },
1100
+ 'CODEXLENS_CASCADE_COARSE_K': { path: ['cascade', 'coarse_k'], transform: v => parseInt(v, 10) },
1101
+ 'CODEXLENS_CASCADE_FINE_K': { path: ['cascade', 'fine_k'], transform: v => parseInt(v, 10) },
1102
+ 'CODEXLENS_LLM_ENABLED': { path: ['llm', 'enabled'], transform: v => v === 'true' },
1103
+ 'CODEXLENS_LLM_BATCH_SIZE': { path: ['llm', 'batch_size'], transform: v => parseInt(v, 10) },
1104
+ 'LITELLM_EMBEDDING_MODEL': { path: ['embedding', 'model'] },
1105
+ 'LITELLM_RERANKER_MODEL': { path: ['reranker', 'model'] }
1106
+ };
1107
+
1108
+ // Apply env vars to settings
1109
+ for (const [envKey, value] of Object.entries(env)) {
1110
+ const mapping = envToSettings[envKey];
1111
+ if (mapping && value) {
1112
+ const [section, key] = mapping.path;
1113
+ if (!settings[section]) settings[section] = {};
1114
+ settings[section][key] = mapping.transform ? mapping.transform(value) : value;
1115
+ }
1116
+ }
1117
+
1118
+ // Write updated settings
1119
+ await writeFile(settingsPath, JSON.stringify(settings, null, 2), 'utf-8');
1120
+
1121
+ return {
1122
+ success: true,
1123
+ message: 'Environment and settings configuration saved',
1124
+ path: envPath,
1125
+ settingsPath
1126
+ };
1127
+ } catch (err: unknown) {
1128
+ return { success: false, error: err instanceof Error ? err.message : String(err), status: 500 };
1129
+ }
1130
+ });
1131
+ return true;
1132
+ }
1133
+
1134
+ // ============================================================
1135
+ // IGNORE PATTERNS CONFIGURATION ENDPOINTS
1136
+ // ============================================================
1137
+
1138
+ // API: Get ignore patterns configuration
1139
+ if (pathname === '/api/codexlens/ignore-patterns' && req.method === 'GET') {
1140
+ try {
1141
+ const { homedir } = await import('os');
1142
+ const { join } = await import('path');
1143
+ const { readFile } = await import('fs/promises');
1144
+
1145
+ const settingsPath = join(homedir(), '.codexlens', 'settings.json');
1146
+ let settings: Record<string, any> = {};
1147
+ try {
1148
+ const content = await readFile(settingsPath, 'utf-8');
1149
+ settings = JSON.parse(content);
1150
+ } catch {
1151
+ // File doesn't exist
1152
+ }
1153
+
1154
+ // Default ignore patterns (matching WatcherConfig defaults in events.py)
1155
+ const defaultPatterns = [
1156
+ // Version control
1157
+ '.git', '.svn', '.hg',
1158
+ // Python environments & cache
1159
+ '.venv', 'venv', 'env', '__pycache__', '.pytest_cache', '.mypy_cache', '.ruff_cache',
1160
+ // Node.js
1161
+ 'node_modules', 'bower_components', '.npm', '.yarn',
1162
+ // Build artifacts
1163
+ 'dist', 'build', 'out', 'target', 'bin', 'obj', '_build', 'coverage', 'htmlcov',
1164
+ // IDE & Editor
1165
+ '.idea', '.vscode', '.vs', '.eclipse',
1166
+ // CodexLens internal
1167
+ '.codexlens',
1168
+ // Package manager caches
1169
+ '.cache', '.parcel-cache', '.turbo', '.next', '.nuxt',
1170
+ // Logs & temp
1171
+ 'logs', 'tmp', 'temp',
1172
+ ];
1173
+
1174
+ // Default extension filters for embeddings (files skipped for vector index)
1175
+ const defaultExtensionFilters = [
1176
+ // Lock files (large, repetitive)
1177
+ 'package-lock.json', 'yarn.lock', 'pnpm-lock.yaml', 'composer.lock', 'Gemfile.lock', 'poetry.lock',
1178
+ // Generated/minified
1179
+ '*.min.js', '*.min.css', '*.bundle.js',
1180
+ // Binary-like text
1181
+ '*.svg', '*.map',
1182
+ ];
1183
+
1184
+ res.writeHead(200, { 'Content-Type': 'application/json' });
1185
+ res.end(JSON.stringify({
1186
+ success: true,
1187
+ patterns: settings.ignore_patterns || defaultPatterns,
1188
+ extensionFilters: settings.extension_filters || defaultExtensionFilters,
1189
+ defaults: {
1190
+ patterns: defaultPatterns,
1191
+ extensionFilters: defaultExtensionFilters
1192
+ }
1193
+ }));
1194
+ } catch (err: unknown) {
1195
+ res.writeHead(500, { 'Content-Type': 'application/json' });
1196
+ res.end(JSON.stringify({ success: false, error: err instanceof Error ? err.message : String(err) }));
1197
+ }
1198
+ return true;
1199
+ }
1200
+
1201
+ // API: Save ignore patterns configuration
1202
+ if (pathname === '/api/codexlens/ignore-patterns' && req.method === 'POST') {
1203
+ handlePostRequest(req, res, async (body) => {
1204
+ const { patterns, extensionFilters } = body as {
1205
+ patterns?: string[];
1206
+ extensionFilters?: string[];
1207
+ };
1208
+
1209
+ try {
1210
+ const { homedir } = await import('os');
1211
+ const { join, dirname } = await import('path');
1212
+ const { writeFile, mkdir, readFile } = await import('fs/promises');
1213
+
1214
+ const settingsPath = join(homedir(), '.codexlens', 'settings.json');
1215
+ await mkdir(dirname(settingsPath), { recursive: true });
1216
+
1217
+ // Read existing settings
1218
+ let settings: Record<string, any> = {};
1219
+ try {
1220
+ const content = await readFile(settingsPath, 'utf-8');
1221
+ settings = JSON.parse(content);
1222
+ } catch {
1223
+ // File doesn't exist, start fresh
1224
+ }
1225
+
1226
+ // Validate patterns (alphanumeric, dots, underscores, dashes, asterisks)
1227
+ const validPatternRegex = /^[\w.*\-/]+$/;
1228
+ if (patterns) {
1229
+ const invalidPatterns = patterns.filter(p => !validPatternRegex.test(p));
1230
+ if (invalidPatterns.length > 0) {
1231
+ return {
1232
+ success: false,
1233
+ error: `Invalid patterns: ${invalidPatterns.join(', ')}`,
1234
+ status: 400
1235
+ };
1236
+ }
1237
+ settings.ignore_patterns = patterns;
1238
+ }
1239
+
1240
+ if (extensionFilters) {
1241
+ const invalidFilters = extensionFilters.filter(p => !validPatternRegex.test(p));
1242
+ if (invalidFilters.length > 0) {
1243
+ return {
1244
+ success: false,
1245
+ error: `Invalid extension filters: ${invalidFilters.join(', ')}`,
1246
+ status: 400
1247
+ };
1248
+ }
1249
+ settings.extension_filters = extensionFilters;
1250
+ }
1251
+
1252
+ // Write updated settings
1253
+ await writeFile(settingsPath, JSON.stringify(settings, null, 2), 'utf-8');
1254
+
1255
+ return {
1256
+ success: true,
1257
+ message: 'Ignore patterns saved successfully',
1258
+ patterns: settings.ignore_patterns,
1259
+ extensionFilters: settings.extension_filters
1260
+ };
1261
+ } catch (err: unknown) {
1262
+ return { success: false, error: err instanceof Error ? err.message : String(err), status: 500 };
1263
+ }
1264
+ });
1265
+ return true;
1266
+ }
1267
+
1268
+ return false;
1269
+ }