claude-code-workflow 6.1.4 → 6.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (437) hide show
  1. package/.claude/CLAUDE.md +10 -0
  2. package/.claude/agents/action-planning-agent.md +857 -778
  3. package/.claude/agents/cli-execution-agent.md +266 -269
  4. package/.claude/agents/cli-explore-agent.md +2 -2
  5. package/.claude/agents/cli-lite-planning-agent.md +142 -92
  6. package/.claude/agents/cli-planning-agent.md +4 -4
  7. package/.claude/agents/code-developer.md +7 -6
  8. package/.claude/agents/conceptual-planning-agent.md +2 -2
  9. package/.claude/agents/context-search-agent.md +31 -32
  10. package/.claude/agents/doc-generator.md +4 -4
  11. package/.claude/agents/memory-bridge.md +93 -93
  12. package/.claude/agents/test-context-search-agent.md +8 -7
  13. package/.claude/agents/test-fix-agent.md +7 -6
  14. package/.claude/commands/clean.md +516 -0
  15. package/.claude/commands/memory/compact.md +383 -0
  16. package/.claude/commands/memory/docs-full-cli.md +471 -471
  17. package/.claude/commands/memory/docs-related-cli.md +386 -386
  18. package/.claude/commands/memory/docs.md +615 -615
  19. package/.claude/commands/memory/load.md +5 -5
  20. package/.claude/commands/memory/tech-research-rules.md +310 -0
  21. package/.claude/commands/memory/update-full.md +332 -332
  22. package/.claude/commands/memory/workflow-skill-memory.md +4 -4
  23. package/.claude/commands/task/create.md +151 -151
  24. package/.claude/commands/version.md +254 -254
  25. package/.claude/commands/workflow/brainstorm/api-designer.md +587 -585
  26. package/.claude/commands/workflow/brainstorm/artifacts.md +1 -0
  27. package/.claude/commands/workflow/brainstorm/auto-parallel.md +443 -443
  28. package/.claude/commands/workflow/brainstorm/data-architect.md +220 -220
  29. package/.claude/commands/workflow/brainstorm/product-manager.md +200 -200
  30. package/.claude/commands/workflow/brainstorm/product-owner.md +200 -200
  31. package/.claude/commands/workflow/brainstorm/scrum-master.md +200 -200
  32. package/.claude/commands/workflow/brainstorm/subject-matter-expert.md +200 -200
  33. package/.claude/commands/workflow/brainstorm/system-architect.md +389 -387
  34. package/.claude/commands/workflow/brainstorm/ui-designer.md +221 -221
  35. package/.claude/commands/workflow/brainstorm/ux-expert.md +221 -221
  36. package/.claude/commands/workflow/debug.md +321 -0
  37. package/.claude/commands/workflow/execute.md +13 -0
  38. package/.claude/commands/workflow/init.md +165 -164
  39. package/.claude/commands/workflow/lite-execute.md +119 -13
  40. package/.claude/commands/workflow/lite-fix.md +623 -621
  41. package/.claude/commands/workflow/lite-plan.md +610 -592
  42. package/.claude/commands/workflow/plan.md +5 -5
  43. package/.claude/commands/workflow/review-module-cycle.md +2 -0
  44. package/.claude/commands/workflow/review-session-cycle.md +2 -0
  45. package/.claude/commands/workflow/review.md +297 -291
  46. package/.claude/commands/workflow/session/complete.md +153 -500
  47. package/.claude/commands/workflow/session/list.md +95 -95
  48. package/.claude/commands/workflow/session/resume.md +60 -60
  49. package/.claude/commands/workflow/session/start.md +199 -199
  50. package/.claude/commands/workflow/tdd-plan.md +3 -3
  51. package/.claude/commands/workflow/tdd-verify.md +23 -9
  52. package/.claude/commands/workflow/test-cycle-execute.md +2 -0
  53. package/.claude/commands/workflow/test-fix-gen.md +699 -699
  54. package/.claude/commands/workflow/tools/conflict-resolution.md +104 -18
  55. package/.claude/commands/workflow/tools/context-gather.md +436 -434
  56. package/.claude/commands/workflow/tools/task-generate-agent.md +490 -291
  57. package/.claude/commands/workflow/tools/task-generate-tdd.md +18 -10
  58. package/.claude/commands/workflow/tools/test-concept-enhanced.md +2 -1
  59. package/.claude/commands/workflow/tools/test-context-gather.md +1 -0
  60. package/.claude/commands/workflow/tools/test-task-generate.md +1 -0
  61. package/.claude/commands/workflow/ui-design/import-from-code.md +9 -6
  62. package/.claude/skills/command-guide/SKILL.md +5 -5
  63. package/.claude/skills/command-guide/index/all-commands.json +1 -1
  64. package/.claude/skills/command-guide/index/by-category.json +1 -1
  65. package/.claude/skills/command-guide/index/by-use-case.json +1 -1
  66. package/.claude/skills/command-guide/reference/agents/action-planning-agent.md +857 -778
  67. package/.claude/skills/command-guide/reference/agents/cli-execution-agent.md +266 -269
  68. package/.claude/skills/command-guide/reference/agents/cli-explore-agent.md +2 -2
  69. package/.claude/skills/command-guide/reference/agents/cli-lite-planning-agent.md +142 -92
  70. package/.claude/skills/command-guide/reference/agents/cli-planning-agent.md +4 -4
  71. package/.claude/skills/command-guide/reference/agents/code-developer.md +7 -6
  72. package/.claude/skills/command-guide/reference/agents/conceptual-planning-agent.md +2 -2
  73. package/.claude/skills/command-guide/reference/agents/context-search-agent.md +31 -32
  74. package/.claude/skills/command-guide/reference/agents/doc-generator.md +4 -4
  75. package/.claude/skills/command-guide/reference/agents/memory-bridge.md +93 -93
  76. package/.claude/skills/command-guide/reference/agents/test-context-search-agent.md +8 -7
  77. package/.claude/skills/command-guide/reference/agents/test-fix-agent.md +7 -6
  78. package/.claude/skills/command-guide/reference/commands/memory/docs-full-cli.md +471 -471
  79. package/.claude/skills/command-guide/reference/commands/memory/docs-related-cli.md +386 -386
  80. package/.claude/skills/command-guide/reference/commands/memory/docs.md +17 -16
  81. package/.claude/skills/command-guide/reference/commands/memory/load.md +5 -5
  82. package/.claude/skills/command-guide/reference/commands/memory/tech-research.md +194 -357
  83. package/.claude/skills/command-guide/reference/commands/memory/update-full.md +332 -332
  84. package/.claude/skills/command-guide/reference/commands/memory/workflow-skill-memory.md +4 -4
  85. package/.claude/skills/command-guide/reference/commands/task/create.md +151 -151
  86. package/.claude/skills/command-guide/reference/commands/version.md +254 -254
  87. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/api-designer.md +585 -585
  88. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/auto-parallel.md +443 -443
  89. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/data-architect.md +220 -220
  90. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/product-manager.md +200 -200
  91. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/product-owner.md +200 -200
  92. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/scrum-master.md +200 -200
  93. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/subject-matter-expert.md +200 -200
  94. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/system-architect.md +387 -387
  95. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/ui-designer.md +221 -221
  96. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/ux-expert.md +221 -221
  97. package/.claude/skills/command-guide/reference/commands/workflow/execute.md +25 -20
  98. package/.claude/skills/command-guide/reference/commands/workflow/init.md +164 -164
  99. package/.claude/skills/command-guide/reference/commands/workflow/lite-execute.md +748 -686
  100. package/.claude/skills/command-guide/reference/commands/workflow/lite-fix.md +664 -621
  101. package/.claude/skills/command-guide/reference/commands/workflow/lite-plan.md +645 -592
  102. package/.claude/skills/command-guide/reference/commands/workflow/plan.md +5 -5
  103. package/.claude/skills/command-guide/reference/commands/workflow/review.md +25 -18
  104. package/.claude/skills/command-guide/reference/commands/workflow/session/complete.md +547 -500
  105. package/.claude/skills/command-guide/reference/commands/workflow/session/list.md +45 -27
  106. package/.claude/skills/command-guide/reference/commands/workflow/session/resume.md +35 -19
  107. package/.claude/skills/command-guide/reference/commands/workflow/session/start.md +90 -33
  108. package/.claude/skills/command-guide/reference/commands/workflow/tdd-plan.md +3 -3
  109. package/.claude/skills/command-guide/reference/commands/workflow/tdd-verify.md +23 -9
  110. package/.claude/skills/command-guide/reference/commands/workflow/test-fix-gen.md +699 -699
  111. package/.claude/skills/command-guide/reference/commands/workflow/tools/conflict-resolution.md +103 -17
  112. package/.claude/skills/command-guide/reference/commands/workflow/tools/context-gather.md +434 -434
  113. package/.claude/skills/command-guide/reference/commands/workflow/tools/task-generate-agent.md +487 -291
  114. package/.claude/skills/command-guide/reference/commands/workflow/tools/task-generate-tdd.md +17 -10
  115. package/.claude/skills/command-guide/reference/commands/workflow/tools/test-concept-enhanced.md +1 -1
  116. package/.claude/skills/command-guide/reference/commands/workflow/ui-design/import-from-code.md +6 -6
  117. package/.claude/workflows/chinese-response.md +38 -0
  118. package/.claude/workflows/cli-templates/prompts/rules/rule-api.txt +122 -0
  119. package/.claude/workflows/cli-templates/prompts/rules/rule-components.txt +122 -0
  120. package/.claude/workflows/cli-templates/prompts/rules/rule-config.txt +89 -0
  121. package/.claude/workflows/cli-templates/prompts/rules/rule-core.txt +60 -0
  122. package/.claude/workflows/cli-templates/prompts/rules/rule-patterns.txt +70 -0
  123. package/.claude/workflows/cli-templates/prompts/rules/rule-testing.txt +81 -0
  124. package/.claude/workflows/cli-templates/prompts/rules/tech-rules-agent-prompt.txt +89 -0
  125. package/.claude/workflows/cli-templates/prompts/workflow/gemini-solution-design.txt +131 -131
  126. package/.claude/workflows/cli-templates/prompts/workflow/skill-conflict-patterns.txt +5 -9
  127. package/.claude/workflows/cli-templates/prompts/workflow/skill-lessons-learned.txt +5 -9
  128. package/.claude/workflows/cli-templates/protocols/analysis-protocol.md +112 -0
  129. package/.claude/workflows/cli-templates/protocols/write-protocol.md +201 -0
  130. package/.claude/workflows/cli-templates/schemas/conflict-resolution-schema.json +137 -0
  131. package/.claude/workflows/cli-templates/schemas/debug-log-json-schema.json +127 -0
  132. package/.claude/workflows/cli-templates/schemas/fix-plan-json-schema.json +25 -0
  133. package/.claude/workflows/cli-templates/schemas/plan-json-schema.json +25 -0
  134. package/.claude/workflows/cli-tools-usage.md +526 -0
  135. package/{CLAUDE.md → .claude/workflows/coding-philosophy.md} +24 -45
  136. package/.claude/workflows/context-tools.md +84 -0
  137. package/.claude/workflows/file-modification.md +64 -0
  138. package/.claude/workflows/tool-strategy.md +216 -79
  139. package/.claude/workflows/windows-platform.md +16 -0
  140. package/.claude/workflows/workflow-architecture.md +942 -942
  141. package/.codex/AGENTS.md +63 -330
  142. package/.codex/prompts/debug.md +318 -0
  143. package/.codex/prompts/execute.md +273 -0
  144. package/.codex/prompts/lite-execute.md +164 -0
  145. package/.codex/prompts/lite-plan.md +469 -0
  146. package/.codex/prompts.zip +0 -0
  147. package/.gemini/GEMINI.md +25 -164
  148. package/.qwen/QWEN.md +0 -139
  149. package/README.md +29 -9
  150. package/ccw/README.md +30 -6
  151. package/ccw/bin/ccw-mcp.js +7 -0
  152. package/ccw/bin/ccw.js +9 -9
  153. package/ccw/package.json +65 -47
  154. package/ccw/src/.workflow/.cli-history/history.db +0 -0
  155. package/ccw/src/.workflow/.cli-history/history.db-shm +0 -0
  156. package/ccw/src/.workflow/.cli-history/history.db-wal +0 -0
  157. package/ccw/src/cli.ts +244 -0
  158. package/ccw/src/commands/cli.ts +740 -0
  159. package/ccw/src/commands/core-memory.ts +770 -0
  160. package/ccw/src/commands/hook.ts +315 -0
  161. package/ccw/src/commands/install.ts +519 -0
  162. package/ccw/src/commands/{list.js → list.ts} +1 -1
  163. package/ccw/src/commands/memory.ts +1090 -0
  164. package/ccw/src/commands/{serve.js → serve.ts} +14 -5
  165. package/ccw/src/commands/session-path-resolver.ts +372 -0
  166. package/ccw/src/commands/session.ts +1141 -0
  167. package/ccw/src/commands/{stop.js → stop.ts} +16 -6
  168. package/ccw/src/commands/tool.ts +201 -0
  169. package/ccw/src/commands/{uninstall.js → uninstall.ts} +89 -40
  170. package/ccw/src/commands/{upgrade.js → upgrade.ts} +68 -23
  171. package/ccw/src/commands/{view.js → view.ts} +22 -8
  172. package/ccw/src/config/storage-paths.ts +670 -0
  173. package/ccw/src/core/cache-manager.ts +294 -0
  174. package/ccw/src/core/claude-freshness.ts +319 -0
  175. package/ccw/src/core/core-memory-store.ts +1528 -0
  176. package/ccw/src/core/{dashboard-generator-patch.js → dashboard-generator-patch.ts} +18 -0
  177. package/ccw/src/core/{dashboard-generator.js → dashboard-generator.ts} +69 -12
  178. package/ccw/src/core/data-aggregator.ts +584 -0
  179. package/ccw/src/core/history-importer.ts +625 -0
  180. package/ccw/src/core/{lite-scanner.js → lite-scanner-complete.ts} +162 -66
  181. package/ccw/src/core/lite-scanner.ts +469 -0
  182. package/ccw/src/core/{manifest.js → manifest.ts} +104 -34
  183. package/ccw/src/core/memory-embedder-bridge.ts +262 -0
  184. package/ccw/src/core/memory-store.ts +978 -0
  185. package/ccw/src/core/routes/ccw-routes.ts +96 -0
  186. package/ccw/src/core/routes/claude-routes.ts +1183 -0
  187. package/ccw/src/core/routes/cli-routes.ts +561 -0
  188. package/ccw/src/core/routes/codexlens-routes.ts +806 -0
  189. package/ccw/src/core/routes/core-memory-routes.ts +605 -0
  190. package/ccw/src/core/routes/files-routes.ts +428 -0
  191. package/ccw/src/core/routes/graph-routes.md +164 -0
  192. package/ccw/src/core/routes/graph-routes.ts +626 -0
  193. package/ccw/src/core/routes/help-routes.ts +308 -0
  194. package/ccw/src/core/routes/hooks-routes.ts +405 -0
  195. package/ccw/src/core/routes/mcp-routes.ts +1271 -0
  196. package/ccw/src/core/routes/mcp-routes.ts.backup +550 -0
  197. package/ccw/src/core/routes/mcp-templates-db.ts +268 -0
  198. package/ccw/src/core/routes/memory-routes.ts +1206 -0
  199. package/ccw/src/core/routes/rules-routes.ts +526 -0
  200. package/ccw/src/core/routes/session-routes.ts +467 -0
  201. package/ccw/src/core/routes/skills-routes.ts +599 -0
  202. package/ccw/src/core/routes/status-routes.ts +57 -0
  203. package/ccw/src/core/routes/system-routes.ts +427 -0
  204. package/ccw/src/core/server.ts +431 -0
  205. package/ccw/src/core/session-clustering-service.ts +1258 -0
  206. package/ccw/src/core/session-scanner.ts +283 -0
  207. package/ccw/src/core/websocket.ts +190 -0
  208. package/ccw/src/{index.js → index.ts} +1 -0
  209. package/ccw/src/mcp-server/index.ts +186 -0
  210. package/ccw/src/templates/assets/css/github-dark.min.css +10 -0
  211. package/ccw/src/templates/assets/css/github.min.css +10 -0
  212. package/ccw/src/templates/assets/js/cytoscape.min.js +32 -0
  213. package/ccw/src/templates/assets/js/d3.min.js +2 -0
  214. package/ccw/src/templates/assets/js/highlight.min.js +1244 -0
  215. package/ccw/src/templates/assets/js/lucide.min.js +12 -0
  216. package/ccw/src/templates/assets/js/marked.min.js +69 -0
  217. package/ccw/src/templates/assets/js/tailwind.js +83 -0
  218. package/ccw/src/templates/dashboard-css/01-base.css +11 -0
  219. package/ccw/src/templates/dashboard-css/02-session.css +22 -0
  220. package/ccw/src/templates/dashboard-css/04-lite-tasks.css +10 -0
  221. package/ccw/src/templates/dashboard-css/06-cards.css +10 -4
  222. package/ccw/src/templates/dashboard-css/07-managers.css +1178 -7
  223. package/ccw/src/templates/dashboard-css/09-explorer.css +23 -12
  224. package/ccw/src/templates/dashboard-css/10-cli-status.css +337 -0
  225. package/ccw/src/templates/dashboard-css/11-cli-history.css +271 -0
  226. package/ccw/src/templates/dashboard-css/12-cli-legacy.css +796 -0
  227. package/ccw/src/templates/dashboard-css/13-cli-ccw.css +199 -0
  228. package/ccw/src/templates/dashboard-css/14-cli-modals.css +258 -0
  229. package/ccw/src/templates/dashboard-css/15-cli-endpoints.css +305 -0
  230. package/ccw/src/templates/dashboard-css/16-cli-session.css +241 -0
  231. package/ccw/src/templates/dashboard-css/17-cli-conversation.css +283 -0
  232. package/ccw/src/templates/dashboard-css/18-cli-settings.css +160 -0
  233. package/ccw/src/templates/dashboard-css/19-cli-native-session.css +496 -0
  234. package/ccw/src/templates/dashboard-css/20-cli-taskqueue.css +188 -0
  235. package/ccw/src/templates/dashboard-css/21-cli-toolmgmt.css +310 -0
  236. package/ccw/src/templates/dashboard-css/22-cli-semantic.css +240 -0
  237. package/ccw/src/templates/dashboard-css/23-memory.css +2390 -0
  238. package/ccw/src/templates/dashboard-css/24-prompt-history.css +1089 -0
  239. package/ccw/src/templates/dashboard-css/25-skills-rules.css +326 -0
  240. package/ccw/src/templates/dashboard-css/26-claude-manager.css +908 -0
  241. package/ccw/src/templates/dashboard-css/27-graph-explorer.css +1678 -0
  242. package/ccw/src/templates/dashboard-css/28-mcp-manager.css +748 -0
  243. package/ccw/src/templates/dashboard-css/29-help.css +264 -0
  244. package/ccw/src/templates/dashboard-css/30-core-memory.css +1700 -0
  245. package/ccw/src/templates/dashboard-js/api.js +162 -142
  246. package/ccw/src/templates/dashboard-js/components/carousel.js +4 -4
  247. package/ccw/src/templates/dashboard-js/components/cli-history.js +876 -0
  248. package/ccw/src/templates/dashboard-js/components/cli-status.js +978 -0
  249. package/ccw/src/templates/dashboard-js/components/global-notifications.js +508 -219
  250. package/ccw/src/templates/dashboard-js/components/hook-manager.js +1277 -282
  251. package/ccw/src/templates/dashboard-js/components/index-manager.js +302 -0
  252. package/ccw/src/templates/dashboard-js/components/mcp-manager.js +718 -27
  253. package/ccw/src/templates/dashboard-js/components/modals.js +66 -0
  254. package/ccw/src/templates/dashboard-js/components/navigation.js +80 -12
  255. package/ccw/src/templates/dashboard-js/components/notifications.js +758 -194
  256. package/ccw/src/templates/dashboard-js/components/storage-manager.js +478 -0
  257. package/ccw/src/templates/dashboard-js/components/tabs-other.js +157 -6
  258. package/ccw/src/templates/dashboard-js/components/task-queue-sidebar.js +716 -0
  259. package/ccw/src/templates/dashboard-js/help-i18n.js +272 -0
  260. package/ccw/src/templates/dashboard-js/i18n.js +2807 -0
  261. package/ccw/src/templates/dashboard-js/main.js +15 -0
  262. package/ccw/src/templates/dashboard-js/state.js +243 -42
  263. package/ccw/src/templates/dashboard-js/utils.js +47 -1
  264. package/ccw/src/templates/dashboard-js/views/claude-manager.js +912 -0
  265. package/ccw/src/templates/dashboard-js/views/cli-manager.js +2272 -0
  266. package/ccw/src/templates/dashboard-js/views/codexlens-manager.js +964 -0
  267. package/ccw/src/templates/dashboard-js/views/core-memory-clusters.js +503 -0
  268. package/ccw/src/templates/dashboard-js/views/core-memory.js +782 -0
  269. package/ccw/src/templates/dashboard-js/views/explorer.js +888 -852
  270. package/ccw/src/templates/dashboard-js/views/graph-explorer.js +1157 -0
  271. package/ccw/src/templates/dashboard-js/views/help.js +856 -0
  272. package/ccw/src/templates/dashboard-js/views/history.js +337 -0
  273. package/ccw/src/templates/dashboard-js/views/home.js +61 -15
  274. package/ccw/src/templates/dashboard-js/views/hook-manager.js +311 -43
  275. package/ccw/src/templates/dashboard-js/views/lite-tasks.js +204 -28
  276. package/ccw/src/templates/dashboard-js/views/mcp-manager.js +2187 -411
  277. package/ccw/src/templates/dashboard-js/views/mcp-manager.js.backup +1729 -0
  278. package/ccw/src/templates/dashboard-js/views/mcp-manager.js.new +928 -0
  279. package/ccw/src/templates/dashboard-js/views/memory.js +1221 -0
  280. package/ccw/src/templates/dashboard-js/views/prompt-history.js +713 -0
  281. package/ccw/src/templates/dashboard-js/views/rules-manager.js +828 -0
  282. package/ccw/src/templates/dashboard-js/views/session-detail.js +54 -53
  283. package/ccw/src/templates/dashboard-js/views/skills-manager.js +819 -0
  284. package/ccw/src/templates/dashboard.html +185 -85
  285. package/ccw/src/templates/hooks-config-example.json +60 -0
  286. package/ccw/src/tools/classify-folders.ts +245 -0
  287. package/ccw/src/tools/cli-config-manager.ts +268 -0
  288. package/ccw/src/tools/cli-executor.ts +2014 -0
  289. package/ccw/src/tools/cli-history-store.ts +1195 -0
  290. package/ccw/src/tools/codex-lens.ts +1141 -0
  291. package/ccw/src/tools/{convert-tokens-to-css.js → convert-tokens-to-css.ts} +73 -23
  292. package/ccw/src/tools/core-memory.ts +444 -0
  293. package/ccw/src/tools/detect-changed-modules.ts +325 -0
  294. package/ccw/src/tools/{discover-design-files.js → discover-design-files.ts} +74 -24
  295. package/ccw/src/tools/edit-file.ts +568 -0
  296. package/ccw/src/tools/{generate-module-docs.js → generate-module-docs.ts} +207 -185
  297. package/ccw/src/tools/{get-modules-by-depth.js → get-modules-by-depth.ts} +120 -79
  298. package/ccw/src/tools/index.ts +370 -0
  299. package/ccw/src/tools/native-session-discovery.ts +795 -0
  300. package/ccw/src/tools/notifier.ts +129 -0
  301. package/ccw/src/tools/read-file.ts +410 -0
  302. package/ccw/src/tools/resume-strategy.ts +345 -0
  303. package/ccw/src/tools/session-content-parser.ts +619 -0
  304. package/ccw/src/tools/session-manager.ts +1026 -0
  305. package/ccw/src/tools/smart-context.ts +228 -0
  306. package/ccw/src/tools/smart-search.ts +2065 -0
  307. package/ccw/src/tools/smart-search.ts.backup +1233 -0
  308. package/ccw/src/tools/storage-manager.ts +455 -0
  309. package/ccw/src/tools/write-file.ts +222 -0
  310. package/ccw/src/types/config.ts +11 -0
  311. package/ccw/src/types/index.ts +3 -0
  312. package/ccw/src/types/session.ts +25 -0
  313. package/ccw/src/types/tool.ts +41 -0
  314. package/ccw/src/utils/{browser-launcher.js → browser-launcher.ts} +10 -8
  315. package/ccw/src/utils/file-utils.ts +48 -0
  316. package/ccw/src/utils/{path-resolver.js → path-resolver.ts} +114 -78
  317. package/ccw/src/utils/path-validator.ts +153 -0
  318. package/ccw/src/utils/{ui.js → ui.ts} +32 -25
  319. package/codex-lens/pyproject.toml +48 -0
  320. package/codex-lens/src/codexlens/.workflow/.cli-history/history.db +0 -0
  321. package/codex-lens/src/codexlens/__init__.py +28 -0
  322. package/codex-lens/src/codexlens/__main__.py +14 -0
  323. package/codex-lens/src/codexlens/__pycache__/__init__.cpython-313.pyc +0 -0
  324. package/codex-lens/src/codexlens/__pycache__/__main__.cpython-313.pyc +0 -0
  325. package/codex-lens/src/codexlens/__pycache__/config.cpython-313.pyc +0 -0
  326. package/codex-lens/src/codexlens/__pycache__/entities.cpython-313.pyc +0 -0
  327. package/codex-lens/src/codexlens/__pycache__/errors.cpython-313.pyc +0 -0
  328. package/codex-lens/src/codexlens/cli/__init__.py +27 -0
  329. package/codex-lens/src/codexlens/cli/__pycache__/__init__.cpython-313.pyc +0 -0
  330. package/codex-lens/src/codexlens/cli/__pycache__/commands.cpython-313.pyc +0 -0
  331. package/codex-lens/src/codexlens/cli/__pycache__/embedding_manager.cpython-313.pyc +0 -0
  332. package/codex-lens/src/codexlens/cli/__pycache__/model_manager.cpython-313.pyc +0 -0
  333. package/codex-lens/src/codexlens/cli/__pycache__/output.cpython-313.pyc +0 -0
  334. package/codex-lens/src/codexlens/cli/commands.py +1931 -0
  335. package/codex-lens/src/codexlens/cli/embedding_manager.py +620 -0
  336. package/codex-lens/src/codexlens/cli/model_manager.py +289 -0
  337. package/codex-lens/src/codexlens/cli/output.py +124 -0
  338. package/codex-lens/src/codexlens/config.py +201 -0
  339. package/codex-lens/src/codexlens/entities.py +121 -0
  340. package/codex-lens/src/codexlens/errors.py +55 -0
  341. package/codex-lens/src/codexlens/indexing/README.md +77 -0
  342. package/codex-lens/src/codexlens/indexing/__init__.py +4 -0
  343. package/codex-lens/src/codexlens/indexing/__pycache__/__init__.cpython-313.pyc +0 -0
  344. package/codex-lens/src/codexlens/indexing/__pycache__/symbol_extractor.cpython-313.pyc +0 -0
  345. package/codex-lens/src/codexlens/indexing/symbol_extractor.py +243 -0
  346. package/codex-lens/src/codexlens/parsers/__init__.py +8 -0
  347. package/codex-lens/src/codexlens/parsers/__pycache__/__init__.cpython-313.pyc +0 -0
  348. package/codex-lens/src/codexlens/parsers/__pycache__/encoding.cpython-313.pyc +0 -0
  349. package/codex-lens/src/codexlens/parsers/__pycache__/factory.cpython-313.pyc +0 -0
  350. package/codex-lens/src/codexlens/parsers/__pycache__/tokenizer.cpython-313.pyc +0 -0
  351. package/codex-lens/src/codexlens/parsers/__pycache__/treesitter_parser.cpython-313.pyc +0 -0
  352. package/codex-lens/src/codexlens/parsers/encoding.py +202 -0
  353. package/codex-lens/src/codexlens/parsers/factory.py +256 -0
  354. package/codex-lens/src/codexlens/parsers/tokenizer.py +98 -0
  355. package/codex-lens/src/codexlens/parsers/treesitter_parser.py +335 -0
  356. package/codex-lens/src/codexlens/search/__init__.py +15 -0
  357. package/codex-lens/src/codexlens/search/__pycache__/__init__.cpython-313.pyc +0 -0
  358. package/codex-lens/src/codexlens/search/__pycache__/chain_search.cpython-313.pyc +0 -0
  359. package/codex-lens/src/codexlens/search/__pycache__/enrichment.cpython-313.pyc +0 -0
  360. package/codex-lens/src/codexlens/search/__pycache__/hybrid_search.cpython-313.pyc +0 -0
  361. package/codex-lens/src/codexlens/search/__pycache__/query_parser.cpython-313.pyc +0 -0
  362. package/codex-lens/src/codexlens/search/__pycache__/ranking.cpython-313.pyc +0 -0
  363. package/codex-lens/src/codexlens/search/chain_search.py +647 -0
  364. package/codex-lens/src/codexlens/search/enrichment.py +150 -0
  365. package/codex-lens/src/codexlens/search/hybrid_search.py +313 -0
  366. package/codex-lens/src/codexlens/search/query_parser.py +242 -0
  367. package/codex-lens/src/codexlens/search/ranking.py +274 -0
  368. package/codex-lens/src/codexlens/semantic/__init__.py +39 -0
  369. package/codex-lens/src/codexlens/semantic/__pycache__/__init__.cpython-313.pyc +0 -0
  370. package/codex-lens/src/codexlens/semantic/__pycache__/ann_index.cpython-313.pyc +0 -0
  371. package/codex-lens/src/codexlens/semantic/__pycache__/chunker.cpython-313.pyc +0 -0
  372. package/codex-lens/src/codexlens/semantic/__pycache__/code_extractor.cpython-313.pyc +0 -0
  373. package/codex-lens/src/codexlens/semantic/__pycache__/embedder.cpython-313.pyc +0 -0
  374. package/codex-lens/src/codexlens/semantic/__pycache__/graph_analyzer.cpython-313.pyc +0 -0
  375. package/codex-lens/src/codexlens/semantic/__pycache__/llm_enhancer.cpython-313.pyc +0 -0
  376. package/codex-lens/src/codexlens/semantic/__pycache__/vector_store.cpython-313.pyc +0 -0
  377. package/codex-lens/src/codexlens/semantic/ann_index.py +414 -0
  378. package/codex-lens/src/codexlens/semantic/chunker.py +448 -0
  379. package/codex-lens/src/codexlens/semantic/code_extractor.py +274 -0
  380. package/codex-lens/src/codexlens/semantic/embedder.py +185 -0
  381. package/codex-lens/src/codexlens/semantic/vector_store.py +955 -0
  382. package/codex-lens/src/codexlens/storage/__init__.py +29 -0
  383. package/codex-lens/src/codexlens/storage/__pycache__/__init__.cpython-313.pyc +0 -0
  384. package/codex-lens/src/codexlens/storage/__pycache__/dir_index.cpython-313.pyc +0 -0
  385. package/codex-lens/src/codexlens/storage/__pycache__/file_cache.cpython-313.pyc +0 -0
  386. package/codex-lens/src/codexlens/storage/__pycache__/index_tree.cpython-313.pyc +0 -0
  387. package/codex-lens/src/codexlens/storage/__pycache__/migration_manager.cpython-313.pyc +0 -0
  388. package/codex-lens/src/codexlens/storage/__pycache__/path_mapper.cpython-313.pyc +0 -0
  389. package/codex-lens/src/codexlens/storage/__pycache__/registry.cpython-313.pyc +0 -0
  390. package/codex-lens/src/codexlens/storage/__pycache__/sqlite_store.cpython-313.pyc +0 -0
  391. package/codex-lens/src/codexlens/storage/__pycache__/sqlite_utils.cpython-313.pyc +0 -0
  392. package/codex-lens/src/codexlens/storage/dir_index.py +1850 -0
  393. package/codex-lens/src/codexlens/storage/file_cache.py +32 -0
  394. package/codex-lens/src/codexlens/storage/index_tree.py +776 -0
  395. package/codex-lens/src/codexlens/storage/migration_manager.py +154 -0
  396. package/codex-lens/src/codexlens/storage/migrations/__init__.py +1 -0
  397. package/codex-lens/src/codexlens/storage/migrations/__pycache__/__init__.cpython-313.pyc +0 -0
  398. package/codex-lens/src/codexlens/storage/migrations/__pycache__/migration_001_normalize_keywords.cpython-313.pyc +0 -0
  399. package/codex-lens/src/codexlens/storage/migrations/__pycache__/migration_002_add_token_metadata.cpython-313.pyc +0 -0
  400. package/codex-lens/src/codexlens/storage/migrations/__pycache__/migration_003_code_relationships.cpython-313.pyc +0 -0
  401. package/codex-lens/src/codexlens/storage/migrations/__pycache__/migration_004_dual_fts.cpython-313.pyc +0 -0
  402. package/codex-lens/src/codexlens/storage/migrations/__pycache__/migration_005_cleanup_unused_fields.cpython-313.pyc +0 -0
  403. package/codex-lens/src/codexlens/storage/migrations/migration_001_normalize_keywords.py +123 -0
  404. package/codex-lens/src/codexlens/storage/migrations/migration_002_add_token_metadata.py +48 -0
  405. package/codex-lens/src/codexlens/storage/migrations/migration_004_dual_fts.py +232 -0
  406. package/codex-lens/src/codexlens/storage/migrations/migration_005_cleanup_unused_fields.py +196 -0
  407. package/codex-lens/src/codexlens/storage/path_mapper.py +274 -0
  408. package/codex-lens/src/codexlens/storage/registry.py +670 -0
  409. package/codex-lens/src/codexlens/storage/sqlite_store.py +576 -0
  410. package/codex-lens/src/codexlens/storage/sqlite_utils.py +64 -0
  411. package/package.json +4 -1
  412. package/.claude/commands/memory/tech-research.md +0 -477
  413. package/.claude/scripts/classify-folders.sh +0 -39
  414. package/.claude/scripts/convert_tokens_to_css.sh +0 -229
  415. package/.claude/scripts/detect_changed_modules.sh +0 -161
  416. package/.claude/scripts/discover-design-files.sh +0 -87
  417. package/.claude/scripts/extract-animations.js +0 -243
  418. package/.claude/scripts/extract-computed-styles.js +0 -118
  419. package/.claude/scripts/extract-layout-structure.js +0 -411
  420. package/.claude/scripts/generate_module_docs.sh +0 -717
  421. package/.claude/scripts/get_modules_by_depth.sh +0 -170
  422. package/.claude/scripts/ui-generate-preview.sh +0 -395
  423. package/.claude/scripts/ui-instantiate-prototypes.sh +0 -815
  424. package/.claude/scripts/update_module_claude.sh +0 -337
  425. package/.claude/workflows/context-search-strategy.md +0 -77
  426. package/.claude/workflows/intelligent-tools-strategy.md +0 -662
  427. package/ccw/src/cli.js +0 -119
  428. package/ccw/src/commands/install.js +0 -324
  429. package/ccw/src/commands/tool.js +0 -138
  430. package/ccw/src/core/data-aggregator.js +0 -409
  431. package/ccw/src/core/server.js +0 -2063
  432. package/ccw/src/core/session-scanner.js +0 -235
  433. package/ccw/src/tools/classify-folders.js +0 -204
  434. package/ccw/src/tools/detect-changed-modules.js +0 -288
  435. package/ccw/src/tools/edit-file.js +0 -266
  436. package/ccw/src/tools/index.js +0 -176
  437. package/ccw/src/utils/file-utils.js +0 -48
@@ -0,0 +1,202 @@
1
+ """Optional encoding detection module for CodexLens.
2
+
3
+ Provides automatic encoding detection with graceful fallback to UTF-8.
4
+ Install with: pip install codexlens[encoding]
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import logging
10
+ from pathlib import Path
11
+ from typing import Tuple, Optional
12
+
13
+ log = logging.getLogger(__name__)
14
+
15
+ # Feature flag for encoding detection availability
16
+ ENCODING_DETECTION_AVAILABLE = False
17
+ _import_error: Optional[str] = None
18
+
19
+
20
+ def _detect_chardet_backend() -> Tuple[bool, Optional[str]]:
21
+ """Detect if chardet or charset-normalizer is available."""
22
+ try:
23
+ import chardet
24
+ return True, None
25
+ except ImportError:
26
+ pass
27
+
28
+ try:
29
+ from charset_normalizer import from_bytes
30
+ return True, None
31
+ except ImportError:
32
+ pass
33
+
34
+ return False, "chardet not available. Install with: pip install codexlens[encoding]"
35
+
36
+
37
+ # Initialize on module load
38
+ ENCODING_DETECTION_AVAILABLE, _import_error = _detect_chardet_backend()
39
+
40
+
41
+ def check_encoding_available() -> Tuple[bool, Optional[str]]:
42
+ """Check if encoding detection dependencies are available.
43
+
44
+ Returns:
45
+ Tuple of (available, error_message)
46
+ """
47
+ return ENCODING_DETECTION_AVAILABLE, _import_error
48
+
49
+
50
+ def detect_encoding(content_bytes: bytes, confidence_threshold: float = 0.7) -> str:
51
+ """Detect encoding from file content bytes.
52
+
53
+ Uses chardet or charset-normalizer with configurable confidence threshold.
54
+ Falls back to UTF-8 if confidence is too low or detection unavailable.
55
+
56
+ Args:
57
+ content_bytes: Raw file content as bytes
58
+ confidence_threshold: Minimum confidence (0.0-1.0) to accept detection
59
+
60
+ Returns:
61
+ Detected encoding name (e.g., 'utf-8', 'iso-8859-1', 'gbk')
62
+ Returns 'utf-8' as fallback if detection fails or confidence too low
63
+ """
64
+ if not ENCODING_DETECTION_AVAILABLE:
65
+ log.debug("Encoding detection not available, using UTF-8 fallback")
66
+ return "utf-8"
67
+
68
+ if not content_bytes:
69
+ return "utf-8"
70
+
71
+ try:
72
+ # Try chardet first
73
+ try:
74
+ import chardet
75
+ result = chardet.detect(content_bytes)
76
+ encoding = result.get("encoding")
77
+ confidence = result.get("confidence", 0.0)
78
+
79
+ if encoding and confidence >= confidence_threshold:
80
+ log.debug(f"Detected encoding: {encoding} (confidence: {confidence:.2f})")
81
+ # Normalize encoding name: replace underscores with hyphens
82
+ return encoding.lower().replace('_', '-')
83
+ else:
84
+ log.debug(
85
+ f"Low confidence encoding detection: {encoding} "
86
+ f"(confidence: {confidence:.2f}), using UTF-8 fallback"
87
+ )
88
+ return "utf-8"
89
+ except ImportError:
90
+ pass
91
+
92
+ # Fallback to charset-normalizer
93
+ try:
94
+ from charset_normalizer import from_bytes
95
+ results = from_bytes(content_bytes)
96
+ if results:
97
+ best = results.best()
98
+ if best and best.encoding:
99
+ log.debug(f"Detected encoding via charset-normalizer: {best.encoding}")
100
+ # Normalize encoding name: replace underscores with hyphens
101
+ return best.encoding.lower().replace('_', '-')
102
+ except ImportError:
103
+ pass
104
+
105
+ except Exception as e:
106
+ log.warning(f"Encoding detection failed: {e}, using UTF-8 fallback")
107
+
108
+ return "utf-8"
109
+
110
+
111
+ def read_file_safe(
112
+ path: Path | str,
113
+ confidence_threshold: float = 0.7,
114
+ max_detection_bytes: int = 100_000
115
+ ) -> Tuple[str, str]:
116
+ """Read file with automatic encoding detection and safe decoding.
117
+
118
+ Reads file bytes, detects encoding, and decodes with error replacement
119
+ to preserve file structure even with encoding issues.
120
+
121
+ Args:
122
+ path: Path to file to read
123
+ confidence_threshold: Minimum confidence for encoding detection
124
+ max_detection_bytes: Maximum bytes to use for encoding detection (default 100KB)
125
+
126
+ Returns:
127
+ Tuple of (content, detected_encoding)
128
+ - content: Decoded file content (with � for unmappable bytes)
129
+ - detected_encoding: Detected encoding name
130
+
131
+ Raises:
132
+ OSError: If file cannot be read
133
+ IsADirectoryError: If path is a directory
134
+ """
135
+ file_path = Path(path) if isinstance(path, str) else path
136
+
137
+ # Read file bytes
138
+ try:
139
+ content_bytes = file_path.read_bytes()
140
+ except Exception as e:
141
+ log.error(f"Failed to read file {file_path}: {e}")
142
+ raise
143
+
144
+ # Detect encoding from first N bytes for performance
145
+ detection_sample = content_bytes[:max_detection_bytes] if len(content_bytes) > max_detection_bytes else content_bytes
146
+ encoding = detect_encoding(detection_sample, confidence_threshold)
147
+
148
+ # Decode with error replacement to preserve structure
149
+ try:
150
+ content = content_bytes.decode(encoding, errors='replace')
151
+ log.debug(f"Successfully decoded {file_path} using {encoding}")
152
+ return content, encoding
153
+ except Exception as e:
154
+ # Final fallback to UTF-8 with replacement
155
+ log.warning(f"Failed to decode {file_path} with {encoding}, using UTF-8: {e}")
156
+ content = content_bytes.decode('utf-8', errors='replace')
157
+ return content, 'utf-8'
158
+
159
+
160
+ def is_binary_file(path: Path | str, sample_size: int = 8192) -> bool:
161
+ """Check if file is likely binary by sampling first bytes.
162
+
163
+ Uses heuristic: if >30% of sample bytes are null or non-text, consider binary.
164
+
165
+ Args:
166
+ path: Path to file to check
167
+ sample_size: Number of bytes to sample (default 8KB)
168
+
169
+ Returns:
170
+ True if file appears to be binary, False otherwise
171
+ """
172
+ file_path = Path(path) if isinstance(path, str) else path
173
+
174
+ try:
175
+ with file_path.open('rb') as f:
176
+ sample = f.read(sample_size)
177
+
178
+ if not sample:
179
+ return False
180
+
181
+ # Count null bytes and non-printable characters
182
+ null_count = sample.count(b'\x00')
183
+ non_text_count = sum(1 for byte in sample if byte < 0x20 and byte not in (0x09, 0x0a, 0x0d))
184
+
185
+ # If >30% null bytes or >50% non-text, consider binary
186
+ null_ratio = null_count / len(sample)
187
+ non_text_ratio = non_text_count / len(sample)
188
+
189
+ return null_ratio > 0.3 or non_text_ratio > 0.5
190
+
191
+ except Exception as e:
192
+ log.debug(f"Binary check failed for {file_path}: {e}, assuming text")
193
+ return False
194
+
195
+
196
+ __all__ = [
197
+ "ENCODING_DETECTION_AVAILABLE",
198
+ "check_encoding_available",
199
+ "detect_encoding",
200
+ "read_file_safe",
201
+ "is_binary_file",
202
+ ]
@@ -0,0 +1,256 @@
1
+ """Parser factory for CodexLens.
2
+
3
+ Python and JavaScript/TypeScript parsing use Tree-Sitter grammars when
4
+ available. Regex fallbacks are retained to preserve the existing parser
5
+ interface and behavior in minimal environments.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import re
11
+ from dataclasses import dataclass
12
+ from pathlib import Path
13
+ from typing import Dict, List, Optional, Protocol
14
+
15
+ from codexlens.config import Config
16
+ from codexlens.entities import IndexedFile, Symbol
17
+ from codexlens.parsers.treesitter_parser import TreeSitterSymbolParser
18
+
19
+
20
+ class Parser(Protocol):
21
+ def parse(self, text: str, path: Path) -> IndexedFile: ...
22
+
23
+
24
+ @dataclass
25
+ class SimpleRegexParser:
26
+ language_id: str
27
+
28
+ def parse(self, text: str, path: Path) -> IndexedFile:
29
+ # Try tree-sitter first for supported languages
30
+ if self.language_id in {"python", "javascript", "typescript"}:
31
+ ts_parser = TreeSitterSymbolParser(self.language_id, path)
32
+ if ts_parser.is_available():
33
+ symbols = ts_parser.parse_symbols(text)
34
+ if symbols is not None:
35
+ return IndexedFile(
36
+ path=str(path.resolve()),
37
+ language=self.language_id,
38
+ symbols=symbols,
39
+ chunks=[],
40
+ )
41
+
42
+ # Fallback to regex parsing
43
+ if self.language_id == "python":
44
+ symbols = _parse_python_symbols_regex(text)
45
+ elif self.language_id in {"javascript", "typescript"}:
46
+ symbols = _parse_js_ts_symbols_regex(text)
47
+ elif self.language_id == "java":
48
+ symbols = _parse_java_symbols(text)
49
+ elif self.language_id == "go":
50
+ symbols = _parse_go_symbols(text)
51
+ elif self.language_id == "markdown":
52
+ symbols = _parse_markdown_symbols(text)
53
+ elif self.language_id == "text":
54
+ symbols = _parse_text_symbols(text)
55
+ else:
56
+ symbols = _parse_generic_symbols(text)
57
+
58
+ return IndexedFile(
59
+ path=str(path.resolve()),
60
+ language=self.language_id,
61
+ symbols=symbols,
62
+ chunks=[],
63
+ )
64
+
65
+
66
+ class ParserFactory:
67
+ def __init__(self, config: Config) -> None:
68
+ self.config = config
69
+ self._parsers: Dict[str, Parser] = {}
70
+
71
+ def get_parser(self, language_id: str) -> Parser:
72
+ if language_id not in self._parsers:
73
+ self._parsers[language_id] = SimpleRegexParser(language_id)
74
+ return self._parsers[language_id]
75
+
76
+
77
+ # Regex-based fallback parsers
78
+ _PY_CLASS_RE = re.compile(r"^\s*class\s+([A-Za-z_]\w*)\b")
79
+ _PY_DEF_RE = re.compile(r"^\s*(?:async\s+)?def\s+([A-Za-z_]\w*)\s*\(")
80
+
81
+
82
+
83
+
84
+ def _parse_python_symbols(text: str) -> List[Symbol]:
85
+ """Parse Python symbols, using tree-sitter if available, regex fallback."""
86
+ ts_parser = TreeSitterSymbolParser("python")
87
+ if ts_parser.is_available():
88
+ symbols = ts_parser.parse_symbols(text)
89
+ if symbols is not None:
90
+ return symbols
91
+ return _parse_python_symbols_regex(text)
92
+
93
+
94
+ def _parse_js_ts_symbols(
95
+ text: str,
96
+ language_id: str = "javascript",
97
+ path: Optional[Path] = None,
98
+ ) -> List[Symbol]:
99
+ """Parse JS/TS symbols, using tree-sitter if available, regex fallback."""
100
+ ts_parser = TreeSitterSymbolParser(language_id, path)
101
+ if ts_parser.is_available():
102
+ symbols = ts_parser.parse_symbols(text)
103
+ if symbols is not None:
104
+ return symbols
105
+ return _parse_js_ts_symbols_regex(text)
106
+
107
+
108
+ def _parse_python_symbols_regex(text: str) -> List[Symbol]:
109
+ symbols: List[Symbol] = []
110
+ current_class_indent: Optional[int] = None
111
+ for i, line in enumerate(text.splitlines(), start=1):
112
+ class_match = _PY_CLASS_RE.match(line)
113
+ if class_match:
114
+ current_class_indent = len(line) - len(line.lstrip(" "))
115
+ symbols.append(Symbol(name=class_match.group(1), kind="class", range=(i, i)))
116
+ continue
117
+ def_match = _PY_DEF_RE.match(line)
118
+ if def_match:
119
+ indent = len(line) - len(line.lstrip(" "))
120
+ kind = "method" if current_class_indent is not None and indent > current_class_indent else "function"
121
+ symbols.append(Symbol(name=def_match.group(1), kind=kind, range=(i, i)))
122
+ continue
123
+ if current_class_indent is not None:
124
+ indent = len(line) - len(line.lstrip(" "))
125
+ if line.strip() and indent <= current_class_indent:
126
+ current_class_indent = None
127
+ return symbols
128
+
129
+
130
+ _JS_FUNC_RE = re.compile(r"^\s*(?:export\s+)?(?:async\s+)?function\s+([A-Za-z_$][\w$]*)\s*\(")
131
+ _JS_CLASS_RE = re.compile(r"^\s*(?:export\s+)?class\s+([A-Za-z_$][\w$]*)\b")
132
+ _JS_ARROW_RE = re.compile(
133
+ r"^\s*(?:export\s+)?(?:const|let|var)\s+([A-Za-z_$][\w$]*)\s*=\s*(?:async\s*)?\(?[^)]*\)?\s*=>"
134
+ )
135
+ _JS_METHOD_RE = re.compile(r"^\s+(?:async\s+)?([A-Za-z_$][\w$]*)\s*\([^)]*\)\s*\{")
136
+
137
+
138
+ def _parse_js_ts_symbols_regex(text: str) -> List[Symbol]:
139
+ symbols: List[Symbol] = []
140
+ in_class = False
141
+ class_brace_depth = 0
142
+ brace_depth = 0
143
+
144
+ for i, line in enumerate(text.splitlines(), start=1):
145
+ brace_depth += line.count("{") - line.count("}")
146
+
147
+ class_match = _JS_CLASS_RE.match(line)
148
+ if class_match:
149
+ symbols.append(Symbol(name=class_match.group(1), kind="class", range=(i, i)))
150
+ in_class = True
151
+ class_brace_depth = brace_depth
152
+ continue
153
+
154
+ if in_class and brace_depth < class_brace_depth:
155
+ in_class = False
156
+
157
+ func_match = _JS_FUNC_RE.match(line)
158
+ if func_match:
159
+ symbols.append(Symbol(name=func_match.group(1), kind="function", range=(i, i)))
160
+ continue
161
+
162
+ arrow_match = _JS_ARROW_RE.match(line)
163
+ if arrow_match:
164
+ symbols.append(Symbol(name=arrow_match.group(1), kind="function", range=(i, i)))
165
+ continue
166
+
167
+ if in_class:
168
+ method_match = _JS_METHOD_RE.match(line)
169
+ if method_match:
170
+ name = method_match.group(1)
171
+ if name != "constructor":
172
+ symbols.append(Symbol(name=name, kind="method", range=(i, i)))
173
+
174
+ return symbols
175
+
176
+
177
+ _JAVA_CLASS_RE = re.compile(r"^\s*(?:public\s+)?class\s+([A-Za-z_]\w*)\b")
178
+ _JAVA_METHOD_RE = re.compile(
179
+ r"^\s*(?:public|private|protected|static|\s)+[\w<>\[\]]+\s+([A-Za-z_]\w*)\s*\("
180
+ )
181
+
182
+
183
+ def _parse_java_symbols(text: str) -> List[Symbol]:
184
+ symbols: List[Symbol] = []
185
+ for i, line in enumerate(text.splitlines(), start=1):
186
+ class_match = _JAVA_CLASS_RE.match(line)
187
+ if class_match:
188
+ symbols.append(Symbol(name=class_match.group(1), kind="class", range=(i, i)))
189
+ continue
190
+ method_match = _JAVA_METHOD_RE.match(line)
191
+ if method_match:
192
+ symbols.append(Symbol(name=method_match.group(1), kind="method", range=(i, i)))
193
+ return symbols
194
+
195
+
196
+ _GO_FUNC_RE = re.compile(r"^\s*func\s+(?:\([^)]+\)\s+)?([A-Za-z_]\w*)\s*\(")
197
+ _GO_TYPE_RE = re.compile(r"^\s*type\s+([A-Za-z_]\w*)\s+(?:struct|interface)\b")
198
+
199
+
200
+ def _parse_go_symbols(text: str) -> List[Symbol]:
201
+ symbols: List[Symbol] = []
202
+ for i, line in enumerate(text.splitlines(), start=1):
203
+ type_match = _GO_TYPE_RE.match(line)
204
+ if type_match:
205
+ symbols.append(Symbol(name=type_match.group(1), kind="class", range=(i, i)))
206
+ continue
207
+ func_match = _GO_FUNC_RE.match(line)
208
+ if func_match:
209
+ symbols.append(Symbol(name=func_match.group(1), kind="function", range=(i, i)))
210
+ return symbols
211
+
212
+
213
+ _GENERIC_DEF_RE = re.compile(r"^\s*(?:def|function|func)\s+([A-Za-z_]\w*)\b")
214
+ _GENERIC_CLASS_RE = re.compile(r"^\s*(?:class|struct|interface)\s+([A-Za-z_]\w*)\b")
215
+
216
+
217
+ def _parse_generic_symbols(text: str) -> List[Symbol]:
218
+ symbols: List[Symbol] = []
219
+ for i, line in enumerate(text.splitlines(), start=1):
220
+ class_match = _GENERIC_CLASS_RE.match(line)
221
+ if class_match:
222
+ symbols.append(Symbol(name=class_match.group(1), kind="class", range=(i, i)))
223
+ continue
224
+ def_match = _GENERIC_DEF_RE.match(line)
225
+ if def_match:
226
+ symbols.append(Symbol(name=def_match.group(1), kind="function", range=(i, i)))
227
+ return symbols
228
+
229
+
230
+ # Markdown heading regex: # Heading, ## Heading, etc.
231
+ _MD_HEADING_RE = re.compile(r"^(#{1,6})\s+(.+)$")
232
+
233
+
234
+ def _parse_markdown_symbols(text: str) -> List[Symbol]:
235
+ """Parse Markdown headings as symbols.
236
+
237
+ Extracts # headings as 'section' symbols with heading level as kind suffix.
238
+ """
239
+ symbols: List[Symbol] = []
240
+ for i, line in enumerate(text.splitlines(), start=1):
241
+ heading_match = _MD_HEADING_RE.match(line)
242
+ if heading_match:
243
+ level = len(heading_match.group(1))
244
+ title = heading_match.group(2).strip()
245
+ # Use 'section' kind with level indicator
246
+ kind = f"h{level}"
247
+ symbols.append(Symbol(name=title, kind=kind, range=(i, i)))
248
+ return symbols
249
+
250
+
251
+ def _parse_text_symbols(text: str) -> List[Symbol]:
252
+ """Parse plain text files - no symbols, just index content."""
253
+ # Text files don't have structured symbols, return empty list
254
+ # The file content will still be indexed for FTS search
255
+ return []
256
+
@@ -0,0 +1,98 @@
1
+ """Token counting utilities for CodexLens.
2
+
3
+ Provides accurate token counting using tiktoken with character count fallback.
4
+ """
5
+
6
+ from __future__ import annotations
7
+
8
+ from typing import Optional
9
+
10
+ try:
11
+ import tiktoken
12
+ TIKTOKEN_AVAILABLE = True
13
+ except ImportError:
14
+ TIKTOKEN_AVAILABLE = False
15
+
16
+
17
+ class Tokenizer:
18
+ """Token counter with tiktoken primary and character count fallback."""
19
+
20
+ def __init__(self, encoding_name: str = "cl100k_base") -> None:
21
+ """Initialize tokenizer.
22
+
23
+ Args:
24
+ encoding_name: Tiktoken encoding name (default: cl100k_base for GPT-4)
25
+ """
26
+ self._encoding: Optional[object] = None
27
+ self._encoding_name = encoding_name
28
+
29
+ if TIKTOKEN_AVAILABLE:
30
+ try:
31
+ self._encoding = tiktoken.get_encoding(encoding_name)
32
+ except Exception:
33
+ # Fallback to character counting if encoding fails
34
+ self._encoding = None
35
+
36
+ def count_tokens(self, text: str) -> int:
37
+ """Count tokens in text.
38
+
39
+ Uses tiktoken if available, otherwise falls back to character count / 4.
40
+
41
+ Args:
42
+ text: Text to count tokens for
43
+
44
+ Returns:
45
+ Estimated token count
46
+ """
47
+ if not text:
48
+ return 0
49
+
50
+ if self._encoding is not None:
51
+ try:
52
+ return len(self._encoding.encode(text)) # type: ignore[attr-defined]
53
+ except Exception:
54
+ # Fall through to character count fallback
55
+ pass
56
+
57
+ # Fallback: rough estimate using character count
58
+ # Average of ~4 characters per token for English text
59
+ return max(1, len(text) // 4)
60
+
61
+ def is_using_tiktoken(self) -> bool:
62
+ """Check if tiktoken is being used.
63
+
64
+ Returns:
65
+ True if tiktoken is available and initialized
66
+ """
67
+ return self._encoding is not None
68
+
69
+
70
+ # Global default tokenizer instance
71
+ _default_tokenizer: Optional[Tokenizer] = None
72
+
73
+
74
+ def get_default_tokenizer() -> Tokenizer:
75
+ """Get the global default tokenizer instance.
76
+
77
+ Returns:
78
+ Shared Tokenizer instance
79
+ """
80
+ global _default_tokenizer
81
+ if _default_tokenizer is None:
82
+ _default_tokenizer = Tokenizer()
83
+ return _default_tokenizer
84
+
85
+
86
+ def count_tokens(text: str, tokenizer: Optional[Tokenizer] = None) -> int:
87
+ """Count tokens in text using default or provided tokenizer.
88
+
89
+ Args:
90
+ text: Text to count tokens for
91
+ tokenizer: Optional tokenizer instance (uses default if None)
92
+
93
+ Returns:
94
+ Estimated token count
95
+ """
96
+ if tokenizer is None:
97
+ tokenizer = get_default_tokenizer()
98
+ return tokenizer.count_tokens(text)