ai-first-cli 1.2.3 → 1.3.1

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 (467) hide show
  1. package/.github/workflows/publish.yml +4 -1
  2. package/CHANGELOG.md +292 -6
  3. package/README.md +24 -4
  4. package/dist/analyzers/symbols.d.ts.map +1 -1
  5. package/dist/analyzers/symbols.js +9 -7
  6. package/dist/analyzers/symbols.js.map +1 -1
  7. package/dist/analyzers/techStack.d.ts.map +1 -1
  8. package/dist/analyzers/techStack.js +198 -3
  9. package/dist/analyzers/techStack.js.map +1 -1
  10. package/dist/commands/ai-first.d.ts.map +1 -1
  11. package/dist/commands/ai-first.js +14 -13
  12. package/dist/commands/ai-first.js.map +1 -1
  13. package/dist/core/analysis/architectureDetector.d.ts +37 -0
  14. package/dist/core/analysis/architectureDetector.d.ts.map +1 -0
  15. package/dist/core/analysis/architectureDetector.js +316 -0
  16. package/dist/core/analysis/architectureDetector.js.map +1 -0
  17. package/dist/core/analysis/callGraphBuilder.d.ts +37 -0
  18. package/dist/core/analysis/callGraphBuilder.d.ts.map +1 -0
  19. package/dist/core/analysis/callGraphBuilder.js +101 -0
  20. package/dist/core/analysis/callGraphBuilder.js.map +1 -0
  21. package/dist/core/analysis/dependencyAnalyzer.d.ts +45 -0
  22. package/dist/core/analysis/dependencyAnalyzer.d.ts.map +1 -0
  23. package/dist/core/analysis/dependencyAnalyzer.js +98 -0
  24. package/dist/core/analysis/dependencyAnalyzer.js.map +1 -0
  25. package/dist/core/analysis/index.d.ts +5 -0
  26. package/dist/core/analysis/index.d.ts.map +1 -0
  27. package/dist/core/analysis/index.js +5 -0
  28. package/dist/core/analysis/index.js.map +1 -0
  29. package/dist/core/analysis/inheritanceAnalyzer.d.ts +35 -0
  30. package/dist/core/analysis/inheritanceAnalyzer.d.ts.map +1 -0
  31. package/dist/core/analysis/inheritanceAnalyzer.js +115 -0
  32. package/dist/core/analysis/inheritanceAnalyzer.js.map +1 -0
  33. package/dist/core/ccp.d.ts.map +1 -1
  34. package/dist/core/ccp.js +3 -2
  35. package/dist/core/ccp.js.map +1 -1
  36. package/dist/core/generation/aiContextGenerator.d.ts +71 -0
  37. package/dist/core/generation/aiContextGenerator.d.ts.map +1 -0
  38. package/dist/core/generation/aiContextGenerator.js +217 -0
  39. package/dist/core/generation/aiContextGenerator.js.map +1 -0
  40. package/dist/core/generation/architectureGenerator.d.ts +17 -0
  41. package/dist/core/generation/architectureGenerator.d.ts.map +1 -0
  42. package/dist/core/generation/architectureGenerator.js +160 -0
  43. package/dist/core/generation/architectureGenerator.js.map +1 -0
  44. package/dist/core/generation/flowGenerator.d.ts +52 -0
  45. package/dist/core/generation/flowGenerator.d.ts.map +1 -0
  46. package/dist/core/generation/flowGenerator.js +164 -0
  47. package/dist/core/generation/flowGenerator.js.map +1 -0
  48. package/dist/core/generation/index.d.ts +4 -0
  49. package/dist/core/generation/index.d.ts.map +1 -0
  50. package/dist/core/generation/index.js +4 -0
  51. package/dist/core/generation/index.js.map +1 -0
  52. package/dist/core/hierarchyGenerator.d.ts.map +1 -1
  53. package/dist/core/hierarchyGenerator.js +3 -2
  54. package/dist/core/hierarchyGenerator.js.map +1 -1
  55. package/dist/core/parsers/index.d.ts +20 -0
  56. package/dist/core/parsers/index.d.ts.map +1 -0
  57. package/dist/core/parsers/index.js +76 -0
  58. package/dist/core/parsers/index.js.map +1 -0
  59. package/dist/core/parsers/pythonParser.d.ts +37 -0
  60. package/dist/core/parsers/pythonParser.d.ts.map +1 -0
  61. package/dist/core/parsers/pythonParser.js +229 -0
  62. package/dist/core/parsers/pythonParser.js.map +1 -0
  63. package/dist/core/parsers/typescriptParser.d.ts +54 -0
  64. package/dist/core/parsers/typescriptParser.d.ts.map +1 -0
  65. package/dist/core/parsers/typescriptParser.js +291 -0
  66. package/dist/core/parsers/typescriptParser.js.map +1 -0
  67. package/dist/core/pipeline.d.ts +42 -0
  68. package/dist/core/pipeline.d.ts.map +1 -0
  69. package/dist/core/pipeline.js +172 -0
  70. package/dist/core/pipeline.js.map +1 -0
  71. package/dist/core/semanticContexts.js +1 -1
  72. package/dist/core/semanticContexts.js.map +1 -1
  73. package/dist/utils/constants.d.ts +46 -0
  74. package/dist/utils/constants.d.ts.map +1 -0
  75. package/dist/utils/constants.js +67 -0
  76. package/dist/utils/constants.js.map +1 -0
  77. package/package.json +1 -1
  78. package/run-all-tests.sh +184 -0
  79. package/src/analyzers/symbols.ts +12 -7
  80. package/src/analyzers/techStack.ts +203 -3
  81. package/src/commands/ai-first.ts +14 -13
  82. package/src/core/analysis/architectureDetector.ts +487 -0
  83. package/src/core/analysis/callGraphBuilder.ts +158 -0
  84. package/src/core/analysis/dependencyAnalyzer.ts +167 -0
  85. package/src/core/analysis/index.ts +28 -0
  86. package/src/core/analysis/inheritanceAnalyzer.ts +169 -0
  87. package/src/core/ccp.ts +3 -2
  88. package/src/core/generation/aiContextGenerator.ts +335 -0
  89. package/src/core/generation/architectureGenerator.ts +200 -0
  90. package/src/core/generation/flowGenerator.ts +238 -0
  91. package/src/core/generation/index.ts +16 -0
  92. package/src/core/hierarchyGenerator.ts +3 -2
  93. package/src/core/parsers/index.ts +99 -0
  94. package/src/core/parsers/pythonParser.ts +302 -0
  95. package/src/core/parsers/typescriptParser.ts +445 -0
  96. package/src/core/pipeline.ts +241 -0
  97. package/src/core/semanticContexts.ts +1 -1
  98. package/src/utils/constants.ts +78 -0
  99. package/test-ai-context-understanding.sh +21 -0
  100. package/test_adapters.mjs +11 -11
  101. package/tests/analysis.test.ts +283 -0
  102. package/tests/architectureDetector.test.ts +137 -0
  103. package/tests/generation.test.ts +216 -0
  104. package/tests/parserRegistry.test.ts +139 -0
  105. package/tests/pipeline.integration.test.ts +245 -0
  106. package/tests/pythonParser.test.ts +210 -0
  107. package/tests/typescriptParser.test.ts +197 -0
  108. package/.ai-dev/index.db +0 -0
  109. package/BUGS.md +0 -455
  110. package/PLAN_MEJORAS.md +0 -216
  111. package/STATUS_ADAPTADORES +0 -126
  112. package/TEST_RESULTS_PHASE1.md +0 -420
  113. package/ai/dependencies.json +0 -15
  114. package/ai/graph/knowledge-graph.json +0 -12
  115. package/ai-context/ai_context.md +0 -130
  116. package/ai-context/ai_rules.md +0 -54
  117. package/ai-context/architecture.md +0 -136
  118. package/ai-context/cache.json +0 -2349
  119. package/ai-context/ccp/jira-123/context.json +0 -7
  120. package/ai-context/context/features/commands.json +0 -18
  121. package/ai-context/context/features/src.json +0 -61
  122. package/ai-context/context/features/test-projects.json +0 -69
  123. package/ai-context/context/flows/account.json +0 -9
  124. package/ai-context/context/flows/ai-first.json +0 -9
  125. package/ai-context/context/flows/api.json +0 -9
  126. package/ai-context/context/flows/auth.json +0 -13
  127. package/ai-context/context/flows/category.json +0 -12
  128. package/ai-context/context/flows/comment.json +0 -16
  129. package/ai-context/context/flows/dashboard.json +0 -9
  130. package/ai-context/context/flows/doctor.json +0 -9
  131. package/ai-context/context/flows/explore.json +0 -9
  132. package/ai-context/context/flows/login.json +0 -9
  133. package/ai-context/context/flows/opportunity.json +0 -9
  134. package/ai-context/context/flows/post.json +0 -18
  135. package/ai-context/context/flows/routes.json +0 -19
  136. package/ai-context/context/flows/user.json +0 -20
  137. package/ai-context/context/flows/users.json +0 -9
  138. package/ai-context/context/flows/views.json +0 -14
  139. package/ai-context/context/repo.json +0 -56
  140. package/ai-context/context/utils.json +0 -7
  141. package/ai-context/conventions.md +0 -53
  142. package/ai-context/dependencies.json +0 -2978
  143. package/ai-context/embeddings.json +0 -23828
  144. package/ai-context/entrypoints.md +0 -42
  145. package/ai-context/files.json +0 -2944
  146. package/ai-context/git/commit-activity.json +0 -8646
  147. package/ai-context/git/recent-features.json +0 -1
  148. package/ai-context/git/recent-files.json +0 -52
  149. package/ai-context/git/recent-flows.json +0 -1
  150. package/ai-context/graph/knowledge-graph.json +0 -44129
  151. package/ai-context/graph/module-graph.json +0 -866
  152. package/ai-context/graph/symbol-graph.json +0 -200622
  153. package/ai-context/graph/symbol-references.json +0 -6778
  154. package/ai-context/hierarchy.json +0 -20
  155. package/ai-context/index-state.json +0 -4487
  156. package/ai-context/index.db +0 -0
  157. package/ai-context/modules.json +0 -933
  158. package/ai-context/project.json +0 -30
  159. package/ai-context/repo_map.json +0 -9116
  160. package/ai-context/repo_map.md +0 -2061
  161. package/ai-context/schema.json +0 -5
  162. package/ai-context/summary.md +0 -47
  163. package/ai-context/symbols.json +0 -65351
  164. package/ai-context/tech_stack.md +0 -47
  165. package/ai-context/tools.json +0 -10
  166. package/test-projects/django-app/.ai-dev/index.db +0 -0
  167. package/test-projects/django-app/ai-context/ai_context.md +0 -92
  168. package/test-projects/django-app/ai-context/ai_rules.md +0 -47
  169. package/test-projects/django-app/ai-context/architecture.md +0 -57
  170. package/test-projects/django-app/ai-context/cache.json +0 -169
  171. package/test-projects/django-app/ai-context/context/flows/views.json +0 -10
  172. package/test-projects/django-app/ai-context/conventions.md +0 -51
  173. package/test-projects/django-app/ai-context/dependencies.json +0 -312
  174. package/test-projects/django-app/ai-context/entrypoints.md +0 -4
  175. package/test-projects/django-app/ai-context/files.json +0 -209
  176. package/test-projects/django-app/ai-context/graph/knowledge-graph.json +0 -36
  177. package/test-projects/django-app/ai-context/graph/module-graph.json +0 -145
  178. package/test-projects/django-app/ai-context/graph/symbol-graph.json +0 -1488
  179. package/test-projects/django-app/ai-context/graph/symbol-references.json +0 -1
  180. package/test-projects/django-app/ai-context/index-state.json +0 -294
  181. package/test-projects/django-app/ai-context/index.db +0 -0
  182. package/test-projects/django-app/ai-context/modules.json +0 -35
  183. package/test-projects/django-app/ai-context/project.json +0 -11
  184. package/test-projects/django-app/ai-context/repo_map.json +0 -412
  185. package/test-projects/django-app/ai-context/repo_map.md +0 -105
  186. package/test-projects/django-app/ai-context/schema.json +0 -5
  187. package/test-projects/django-app/ai-context/summary.md +0 -15
  188. package/test-projects/django-app/ai-context/symbols.json +0 -1
  189. package/test-projects/django-app/ai-context/tech_stack.md +0 -32
  190. package/test-projects/django-app/ai-context/tools.json +0 -10
  191. package/test-projects/express-api/ai-context/ai_context.md +0 -112
  192. package/test-projects/express-api/ai-context/ai_rules.md +0 -50
  193. package/test-projects/express-api/ai-context/architecture.md +0 -62
  194. package/test-projects/express-api/ai-context/context/features/controllers.json +0 -13
  195. package/test-projects/express-api/ai-context/context/features/services.json +0 -13
  196. package/test-projects/express-api/ai-context/context/flows/auth.json +0 -12
  197. package/test-projects/express-api/ai-context/context/flows/user.json +0 -13
  198. package/test-projects/express-api/ai-context/conventions.md +0 -51
  199. package/test-projects/express-api/ai-context/dependencies.json +0 -54
  200. package/test-projects/express-api/ai-context/entrypoints.md +0 -17
  201. package/test-projects/express-api/ai-context/modules.json +0 -30
  202. package/test-projects/express-api/ai-context/project.json +0 -15
  203. package/test-projects/express-api/ai-context/repo_map.json +0 -100
  204. package/test-projects/express-api/ai-context/repo_map.md +0 -36
  205. package/test-projects/express-api/ai-context/schema.json +0 -5
  206. package/test-projects/express-api/ai-context/summary.md +0 -14
  207. package/test-projects/express-api/ai-context/symbols.json +0 -7
  208. package/test-projects/express-api/ai-context/tech_stack.md +0 -38
  209. package/test-projects/express-api/ai-context/tools.json +0 -10
  210. package/test-projects/fastapi-app/.ai-dev/index.db +0 -0
  211. package/test-projects/fastapi-app/ai-context/ai_context.md +0 -89
  212. package/test-projects/fastapi-app/ai-context/ai_rules.md +0 -47
  213. package/test-projects/fastapi-app/ai-context/architecture.md +0 -39
  214. package/test-projects/fastapi-app/ai-context/cache.json +0 -125
  215. package/test-projects/fastapi-app/ai-context/conventions.md +0 -51
  216. package/test-projects/fastapi-app/ai-context/dependencies.json +0 -244
  217. package/test-projects/fastapi-app/ai-context/entrypoints.md +0 -4
  218. package/test-projects/fastapi-app/ai-context/files.json +0 -154
  219. package/test-projects/fastapi-app/ai-context/graph/knowledge-graph.json +0 -15
  220. package/test-projects/fastapi-app/ai-context/graph/module-graph.json +0 -78
  221. package/test-projects/fastapi-app/ai-context/graph/symbol-graph.json +0 -1724
  222. package/test-projects/fastapi-app/ai-context/graph/symbol-references.json +0 -51
  223. package/test-projects/fastapi-app/ai-context/index-state.json +0 -217
  224. package/test-projects/fastapi-app/ai-context/index.db +0 -0
  225. package/test-projects/fastapi-app/ai-context/modules.json +0 -16
  226. package/test-projects/fastapi-app/ai-context/project.json +0 -9
  227. package/test-projects/fastapi-app/ai-context/repo_map.json +0 -298
  228. package/test-projects/fastapi-app/ai-context/repo_map.md +0 -74
  229. package/test-projects/fastapi-app/ai-context/schema.json +0 -5
  230. package/test-projects/fastapi-app/ai-context/summary.md +0 -12
  231. package/test-projects/fastapi-app/ai-context/symbols.json +0 -1
  232. package/test-projects/fastapi-app/ai-context/tech_stack.md +0 -32
  233. package/test-projects/fastapi-app/ai-context/tools.json +0 -10
  234. package/test-projects/flask-app/.ai-dev/index.db +0 -0
  235. package/test-projects/flask-app/ai-context/ai_context.md +0 -94
  236. package/test-projects/flask-app/ai-context/ai_rules.md +0 -47
  237. package/test-projects/flask-app/ai-context/architecture.md +0 -49
  238. package/test-projects/flask-app/ai-context/cache.json +0 -157
  239. package/test-projects/flask-app/ai-context/context/features/app.json +0 -25
  240. package/test-projects/flask-app/ai-context/context/flows/routes.json +0 -14
  241. package/test-projects/flask-app/ai-context/conventions.md +0 -51
  242. package/test-projects/flask-app/ai-context/dependencies.json +0 -298
  243. package/test-projects/flask-app/ai-context/entrypoints.md +0 -4
  244. package/test-projects/flask-app/ai-context/files.json +0 -194
  245. package/test-projects/flask-app/ai-context/graph/knowledge-graph.json +0 -60
  246. package/test-projects/flask-app/ai-context/graph/module-graph.json +0 -95
  247. package/test-projects/flask-app/ai-context/graph/symbol-graph.json +0 -1448
  248. package/test-projects/flask-app/ai-context/graph/symbol-references.json +0 -45
  249. package/test-projects/flask-app/ai-context/index-state.json +0 -273
  250. package/test-projects/flask-app/ai-context/index.db +0 -0
  251. package/test-projects/flask-app/ai-context/modules.json +0 -21
  252. package/test-projects/flask-app/ai-context/project.json +0 -13
  253. package/test-projects/flask-app/ai-context/repo_map.json +0 -400
  254. package/test-projects/flask-app/ai-context/repo_map.md +0 -98
  255. package/test-projects/flask-app/ai-context/schema.json +0 -5
  256. package/test-projects/flask-app/ai-context/summary.md +0 -13
  257. package/test-projects/flask-app/ai-context/symbols.json +0 -1
  258. package/test-projects/flask-app/ai-context/tech_stack.md +0 -32
  259. package/test-projects/flask-app/ai-context/tools.json +0 -10
  260. package/test-projects/laravel-app/.ai-dev/index.db +0 -0
  261. package/test-projects/laravel-app/ai-context/ai_context.md +0 -97
  262. package/test-projects/laravel-app/ai-context/ai_rules.md +0 -47
  263. package/test-projects/laravel-app/ai-context/architecture.md +0 -60
  264. package/test-projects/laravel-app/ai-context/cache.json +0 -161
  265. package/test-projects/laravel-app/ai-context/context/features/app.json +0 -21
  266. package/test-projects/laravel-app/ai-context/context/flows/.json +0 -9
  267. package/test-projects/laravel-app/ai-context/context/flows/category.json +0 -12
  268. package/test-projects/laravel-app/ai-context/context/flows/comment.json +0 -12
  269. package/test-projects/laravel-app/ai-context/context/flows/post.json +0 -12
  270. package/test-projects/laravel-app/ai-context/context/flows/unnamed.json +0 -9
  271. package/test-projects/laravel-app/ai-context/conventions.md +0 -51
  272. package/test-projects/laravel-app/ai-context/dependencies.json +0 -6
  273. package/test-projects/laravel-app/ai-context/entrypoints.md +0 -4
  274. package/test-projects/laravel-app/ai-context/files.json +0 -199
  275. package/test-projects/laravel-app/ai-context/graph/knowledge-graph.json +0 -98
  276. package/test-projects/laravel-app/ai-context/graph/module-graph.json +0 -30
  277. package/test-projects/laravel-app/ai-context/graph/symbol-graph.json +0 -5
  278. package/test-projects/laravel-app/ai-context/graph/symbol-references.json +0 -1
  279. package/test-projects/laravel-app/ai-context/index-state.json +0 -280
  280. package/test-projects/laravel-app/ai-context/index.db +0 -0
  281. package/test-projects/laravel-app/ai-context/modules.json +0 -29
  282. package/test-projects/laravel-app/ai-context/project.json +0 -17
  283. package/test-projects/laravel-app/ai-context/repo_map.json +0 -419
  284. package/test-projects/laravel-app/ai-context/repo_map.md +0 -106
  285. package/test-projects/laravel-app/ai-context/schema.json +0 -5
  286. package/test-projects/laravel-app/ai-context/summary.md +0 -15
  287. package/test-projects/laravel-app/ai-context/symbols.json +0 -1
  288. package/test-projects/laravel-app/ai-context/tech_stack.md +0 -34
  289. package/test-projects/laravel-app/ai-context/tools.json +0 -10
  290. package/test-projects/nestjs-backend/.ai-dev/index.db +0 -0
  291. package/test-projects/nestjs-backend/ai-context/ai_context.md +0 -111
  292. package/test-projects/nestjs-backend/ai-context/ai_rules.md +0 -52
  293. package/test-projects/nestjs-backend/ai-context/architecture.md +0 -49
  294. package/test-projects/nestjs-backend/ai-context/cache.json +0 -169
  295. package/test-projects/nestjs-backend/ai-context/context/features/src.json +0 -23
  296. package/test-projects/nestjs-backend/ai-context/context/flows/auth.controller.json +0 -14
  297. package/test-projects/nestjs-backend/ai-context/context/flows/auth.json +0 -10
  298. package/test-projects/nestjs-backend/ai-context/context/flows/users..json +0 -10
  299. package/test-projects/nestjs-backend/ai-context/context/flows/users.controller.json +0 -14
  300. package/test-projects/nestjs-backend/ai-context/context/flows/users.json +0 -10
  301. package/test-projects/nestjs-backend/ai-context/conventions.md +0 -52
  302. package/test-projects/nestjs-backend/ai-context/dependencies.json +0 -152
  303. package/test-projects/nestjs-backend/ai-context/entrypoints.md +0 -18
  304. package/test-projects/nestjs-backend/ai-context/files.json +0 -209
  305. package/test-projects/nestjs-backend/ai-context/graph/knowledge-graph.json +0 -132
  306. package/test-projects/nestjs-backend/ai-context/graph/module-graph.json +0 -29
  307. package/test-projects/nestjs-backend/ai-context/graph/symbol-graph.json +0 -304
  308. package/test-projects/nestjs-backend/ai-context/graph/symbol-references.json +0 -5
  309. package/test-projects/nestjs-backend/ai-context/index-state.json +0 -294
  310. package/test-projects/nestjs-backend/ai-context/index.db +0 -0
  311. package/test-projects/nestjs-backend/ai-context/modules.json +0 -19
  312. package/test-projects/nestjs-backend/ai-context/project.json +0 -18
  313. package/test-projects/nestjs-backend/ai-context/repo_map.json +0 -427
  314. package/test-projects/nestjs-backend/ai-context/repo_map.md +0 -104
  315. package/test-projects/nestjs-backend/ai-context/schema.json +0 -5
  316. package/test-projects/nestjs-backend/ai-context/summary.md +0 -13
  317. package/test-projects/nestjs-backend/ai-context/symbols.json +0 -1
  318. package/test-projects/nestjs-backend/ai-context/tech_stack.md +0 -38
  319. package/test-projects/nestjs-backend/ai-context/tools.json +0 -10
  320. package/test-projects/python-cli/.ai-dev/index.db +0 -0
  321. package/test-projects/python-cli/ai-context/ai_context.md +0 -95
  322. package/test-projects/python-cli/ai-context/ai_rules.md +0 -47
  323. package/test-projects/python-cli/ai-context/architecture.md +0 -55
  324. package/test-projects/python-cli/ai-context/cache.json +0 -149
  325. package/test-projects/python-cli/ai-context/context/features/cli.json +0 -16
  326. package/test-projects/python-cli/ai-context/context/flows/list_.json +0 -9
  327. package/test-projects/python-cli/ai-context/context/flows/remove_.json +0 -9
  328. package/test-projects/python-cli/ai-context/conventions.md +0 -51
  329. package/test-projects/python-cli/ai-context/dependencies.json +0 -66
  330. package/test-projects/python-cli/ai-context/entrypoints.md +0 -4
  331. package/test-projects/python-cli/ai-context/files.json +0 -184
  332. package/test-projects/python-cli/ai-context/graph/knowledge-graph.json +0 -83
  333. package/test-projects/python-cli/ai-context/graph/module-graph.json +0 -31
  334. package/test-projects/python-cli/ai-context/graph/symbol-graph.json +0 -358
  335. package/test-projects/python-cli/ai-context/graph/symbol-references.json +0 -11
  336. package/test-projects/python-cli/ai-context/index-state.json +0 -259
  337. package/test-projects/python-cli/ai-context/index.db +0 -0
  338. package/test-projects/python-cli/ai-context/modules.json +0 -21
  339. package/test-projects/python-cli/ai-context/project.json +0 -15
  340. package/test-projects/python-cli/ai-context/repo_map.json +0 -367
  341. package/test-projects/python-cli/ai-context/repo_map.md +0 -93
  342. package/test-projects/python-cli/ai-context/schema.json +0 -5
  343. package/test-projects/python-cli/ai-context/summary.md +0 -14
  344. package/test-projects/python-cli/ai-context/symbols.json +0 -1
  345. package/test-projects/python-cli/ai-context/tech_stack.md +0 -32
  346. package/test-projects/python-cli/ai-context/tools.json +0 -10
  347. package/test-projects/rails-app/.ai-dev/index.db +0 -0
  348. package/test-projects/rails-app/ai-context/ai_context.md +0 -94
  349. package/test-projects/rails-app/ai-context/ai_rules.md +0 -47
  350. package/test-projects/rails-app/ai-context/architecture.md +0 -49
  351. package/test-projects/rails-app/ai-context/cache.json +0 -193
  352. package/test-projects/rails-app/ai-context/context/features/app.json +0 -24
  353. package/test-projects/rails-app/ai-context/context/features/config.json +0 -13
  354. package/test-projects/rails-app/ai-context/context/flows/application.json +0 -9
  355. package/test-projects/rails-app/ai-context/context/flows/application_.json +0 -9
  356. package/test-projects/rails-app/ai-context/context/flows/comments.json +0 -11
  357. package/test-projects/rails-app/ai-context/context/flows/comments_.json +0 -11
  358. package/test-projects/rails-app/ai-context/context/flows/posts.json +0 -11
  359. package/test-projects/rails-app/ai-context/context/flows/posts_.json +0 -11
  360. package/test-projects/rails-app/ai-context/context/flows/routes.json +0 -9
  361. package/test-projects/rails-app/ai-context/context/flows/users.json +0 -11
  362. package/test-projects/rails-app/ai-context/context/flows/users_.json +0 -11
  363. package/test-projects/rails-app/ai-context/conventions.md +0 -51
  364. package/test-projects/rails-app/ai-context/dependencies.json +0 -6
  365. package/test-projects/rails-app/ai-context/entrypoints.md +0 -4
  366. package/test-projects/rails-app/ai-context/files.json +0 -239
  367. package/test-projects/rails-app/ai-context/graph/knowledge-graph.json +0 -130
  368. package/test-projects/rails-app/ai-context/graph/module-graph.json +0 -27
  369. package/test-projects/rails-app/ai-context/graph/symbol-graph.json +0 -5
  370. package/test-projects/rails-app/ai-context/graph/symbol-references.json +0 -1
  371. package/test-projects/rails-app/ai-context/index-state.json +0 -336
  372. package/test-projects/rails-app/ai-context/index.db +0 -0
  373. package/test-projects/rails-app/ai-context/modules.json +0 -26
  374. package/test-projects/rails-app/ai-context/project.json +0 -22
  375. package/test-projects/rails-app/ai-context/repo_map.json +0 -486
  376. package/test-projects/rails-app/ai-context/repo_map.md +0 -117
  377. package/test-projects/rails-app/ai-context/schema.json +0 -5
  378. package/test-projects/rails-app/ai-context/summary.md +0 -13
  379. package/test-projects/rails-app/ai-context/symbols.json +0 -1
  380. package/test-projects/rails-app/ai-context/tech_stack.md +0 -32
  381. package/test-projects/rails-app/ai-context/tools.json +0 -10
  382. package/test-projects/react-app/.ai-dev/index.db +0 -0
  383. package/test-projects/react-app/ai-context/ai_context.md +0 -96
  384. package/test-projects/react-app/ai-context/ai_rules.md +0 -49
  385. package/test-projects/react-app/ai-context/architecture.md +0 -39
  386. package/test-projects/react-app/ai-context/cache.json +0 -153
  387. package/test-projects/react-app/ai-context/context/features/src.json +0 -18
  388. package/test-projects/react-app/ai-context/context/flows/UsersPage.json +0 -14
  389. package/test-projects/react-app/ai-context/context/flows/dashboard.json +0 -9
  390. package/test-projects/react-app/ai-context/context/flows/login.json +0 -9
  391. package/test-projects/react-app/ai-context/context/flows/users.json +0 -9
  392. package/test-projects/react-app/ai-context/conventions.md +0 -52
  393. package/test-projects/react-app/ai-context/dependencies.json +0 -128
  394. package/test-projects/react-app/ai-context/entrypoints.md +0 -4
  395. package/test-projects/react-app/ai-context/files.json +0 -189
  396. package/test-projects/react-app/ai-context/graph/knowledge-graph.json +0 -112
  397. package/test-projects/react-app/ai-context/graph/module-graph.json +0 -31
  398. package/test-projects/react-app/ai-context/graph/symbol-graph.json +0 -868
  399. package/test-projects/react-app/ai-context/graph/symbol-references.json +0 -31
  400. package/test-projects/react-app/ai-context/index-state.json +0 -266
  401. package/test-projects/react-app/ai-context/index.db +0 -0
  402. package/test-projects/react-app/ai-context/modules.json +0 -17
  403. package/test-projects/react-app/ai-context/project.json +0 -16
  404. package/test-projects/react-app/ai-context/repo_map.json +0 -391
  405. package/test-projects/react-app/ai-context/repo_map.md +0 -94
  406. package/test-projects/react-app/ai-context/schema.json +0 -5
  407. package/test-projects/react-app/ai-context/summary.md +0 -13
  408. package/test-projects/react-app/ai-context/symbols.json +0 -1
  409. package/test-projects/react-app/ai-context/tech_stack.md +0 -39
  410. package/test-projects/react-app/ai-context/tools.json +0 -10
  411. package/test-projects/salesforce-cli/.ai-dev/index.db +0 -0
  412. package/test-projects/salesforce-cli/ai-context/ai_context.md +0 -89
  413. package/test-projects/salesforce-cli/ai-context/ai_rules.md +0 -47
  414. package/test-projects/salesforce-cli/ai-context/architecture.md +0 -39
  415. package/test-projects/salesforce-cli/ai-context/cache.json +0 -125
  416. package/test-projects/salesforce-cli/ai-context/context/features/force-app.json +0 -14
  417. package/test-projects/salesforce-cli/ai-context/context/flows/account.json +0 -9
  418. package/test-projects/salesforce-cli/ai-context/context/flows/opportunity.json +0 -9
  419. package/test-projects/salesforce-cli/ai-context/conventions.md +0 -51
  420. package/test-projects/salesforce-cli/ai-context/dependencies.json +0 -6
  421. package/test-projects/salesforce-cli/ai-context/entrypoints.md +0 -4
  422. package/test-projects/salesforce-cli/ai-context/files.json +0 -154
  423. package/test-projects/salesforce-cli/ai-context/graph/knowledge-graph.json +0 -64
  424. package/test-projects/salesforce-cli/ai-context/graph/module-graph.json +0 -13
  425. package/test-projects/salesforce-cli/ai-context/graph/symbol-graph.json +0 -148
  426. package/test-projects/salesforce-cli/ai-context/graph/symbol-references.json +0 -1
  427. package/test-projects/salesforce-cli/ai-context/index-state.json +0 -217
  428. package/test-projects/salesforce-cli/ai-context/index.db +0 -0
  429. package/test-projects/salesforce-cli/ai-context/modules.json +0 -12
  430. package/test-projects/salesforce-cli/ai-context/project.json +0 -14
  431. package/test-projects/salesforce-cli/ai-context/repo_map.json +0 -328
  432. package/test-projects/salesforce-cli/ai-context/repo_map.md +0 -80
  433. package/test-projects/salesforce-cli/ai-context/schema.json +0 -5
  434. package/test-projects/salesforce-cli/ai-context/summary.md +0 -13
  435. package/test-projects/salesforce-cli/ai-context/symbols.json +0 -1
  436. package/test-projects/salesforce-cli/ai-context/tech_stack.md +0 -31
  437. package/test-projects/salesforce-cli/ai-context/tools.json +0 -10
  438. package/test-projects/spring-boot-app/.ai-dev/index.db +0 -0
  439. package/test-projects/spring-boot-app/ai-context/ai_context.md +0 -91
  440. package/test-projects/spring-boot-app/ai-context/ai_rules.md +0 -48
  441. package/test-projects/spring-boot-app/ai-context/architecture.md +0 -39
  442. package/test-projects/spring-boot-app/ai-context/cache.json +0 -173
  443. package/test-projects/spring-boot-app/ai-context/context/features/src.json +0 -26
  444. package/test-projects/spring-boot-app/ai-context/context/flows/PostController.json +0 -19
  445. package/test-projects/spring-boot-app/ai-context/context/flows/UserController.json +0 -19
  446. package/test-projects/spring-boot-app/ai-context/context/flows/comment.json +0 -11
  447. package/test-projects/spring-boot-app/ai-context/context/flows/post.json +0 -14
  448. package/test-projects/spring-boot-app/ai-context/context/flows/user.json +0 -14
  449. package/test-projects/spring-boot-app/ai-context/conventions.md +0 -52
  450. package/test-projects/spring-boot-app/ai-context/dependencies.json +0 -326
  451. package/test-projects/spring-boot-app/ai-context/entrypoints.md +0 -4
  452. package/test-projects/spring-boot-app/ai-context/files.json +0 -214
  453. package/test-projects/spring-boot-app/ai-context/graph/knowledge-graph.json +0 -231
  454. package/test-projects/spring-boot-app/ai-context/graph/module-graph.json +0 -22
  455. package/test-projects/spring-boot-app/ai-context/graph/symbol-graph.json +0 -794
  456. package/test-projects/spring-boot-app/ai-context/graph/symbol-references.json +0 -70
  457. package/test-projects/spring-boot-app/ai-context/index-state.json +0 -301
  458. package/test-projects/spring-boot-app/ai-context/index.db +0 -0
  459. package/test-projects/spring-boot-app/ai-context/modules.json +0 -21
  460. package/test-projects/spring-boot-app/ai-context/project.json +0 -17
  461. package/test-projects/spring-boot-app/ai-context/repo_map.json +0 -461
  462. package/test-projects/spring-boot-app/ai-context/repo_map.md +0 -109
  463. package/test-projects/spring-boot-app/ai-context/schema.json +0 -5
  464. package/test-projects/spring-boot-app/ai-context/summary.md +0 -12
  465. package/test-projects/spring-boot-app/ai-context/symbols.json +0 -1
  466. package/test-projects/spring-boot-app/ai-context/tech_stack.md +0 -32
  467. package/test-projects/spring-boot-app/ai-context/tools.json +0 -10
@@ -0,0 +1,238 @@
1
+ export interface EnrichedFlow {
2
+ name: string;
3
+ entrypoint: string;
4
+ type: string;
5
+ responsibility: string;
6
+ files: Array<{
7
+ path: string;
8
+ responsibility: string;
9
+ symbols: string[];
10
+ }>;
11
+ layers: string[];
12
+ dependencies: {
13
+ imports: string[];
14
+ calls: string[];
15
+ implementsInterfaces: string[];
16
+ };
17
+ complexity: "low" | "medium" | "high";
18
+ depth: number;
19
+ }
20
+
21
+ export class FlowGenerator {
22
+ generateFlows(
23
+ entryPoints: string[],
24
+ symbols: Array<{
25
+ id: string;
26
+ name: string;
27
+ type: string;
28
+ file: string;
29
+ }>,
30
+ dependencyGraph: {
31
+ edges: Array<{ from: string; to: string; type: string }>;
32
+ },
33
+ callGraph: {
34
+ edges: Array<{ caller: string; callee: string }>;
35
+ },
36
+ inheritanceGraph: {
37
+ edges: Array<{ child: string; parent: string; type: string }>;
38
+ }
39
+ ): EnrichedFlow[] {
40
+ const flows: EnrichedFlow[] = [];
41
+
42
+ for (const entryPoint of entryPoints) {
43
+ const flow = this.analyzeFlow(
44
+ entryPoint,
45
+ symbols,
46
+ dependencyGraph,
47
+ callGraph,
48
+ inheritanceGraph
49
+ );
50
+ flows.push(flow);
51
+ }
52
+
53
+ return flows;
54
+ }
55
+
56
+ private analyzeFlow(
57
+ entryPoint: string,
58
+ symbols: Array<{
59
+ id: string;
60
+ name: string;
61
+ type: string;
62
+ file: string;
63
+ }>,
64
+ dependencyGraph: {
65
+ edges: Array<{ from: string; to: string; type: string }>;
66
+ },
67
+ callGraph: {
68
+ edges: Array<{ caller: string; callee: string }>;
69
+ },
70
+ inheritanceGraph: {
71
+ edges: Array<{ child: string; parent: string; type: string }>;
72
+ }
73
+ ): EnrichedFlow {
74
+ const entrySymbol = symbols.find((s) => s.id === entryPoint);
75
+ const visited = new Set<string>();
76
+ const files = new Map<string, string[]>();
77
+ const layers = new Set<string>();
78
+
79
+ const traverse = (symbolId: string, depth: number = 0) => {
80
+ if (visited.has(symbolId) || depth > 10) return;
81
+ visited.add(symbolId);
82
+
83
+ const symbol = symbols.find((s) => s.id === symbolId);
84
+ if (symbol) {
85
+ const fileSymbols = files.get(symbol.file) || [];
86
+ fileSymbols.push(symbol.name);
87
+ files.set(symbol.file, fileSymbols);
88
+
89
+ const layer = this.detectLayer(symbol);
90
+ if (layer) layers.add(layer);
91
+ }
92
+
93
+ const outgoingCalls = callGraph.edges.filter((e) => e.caller === symbolId);
94
+ for (const call of outgoingCalls) {
95
+ traverse(call.callee, depth + 1);
96
+ }
97
+
98
+ const outgoingDeps = dependencyGraph.edges.filter(
99
+ (e) => e.from === symbolId && e.type === "import"
100
+ );
101
+ for (const dep of outgoingDeps) {
102
+ if (symbols.some((s) => s.id === dep.to)) {
103
+ traverse(dep.to, depth + 1);
104
+ }
105
+ }
106
+ };
107
+
108
+ traverse(entryPoint);
109
+
110
+ const imports = dependencyGraph.edges
111
+ .filter((e) => e.from === entryPoint && e.type === "import")
112
+ .map((e) => e.to);
113
+
114
+ const calls = callGraph.edges
115
+ .filter((e) => e.caller === entryPoint)
116
+ .map((e) => e.callee);
117
+
118
+ const implementsInterfaces = inheritanceGraph.edges
119
+ .filter((e) => e.child === entryPoint && e.type === "implements")
120
+ .map((e) => e.parent);
121
+
122
+ return {
123
+ name: entrySymbol?.name || entryPoint.split("#")[1] || "unknown",
124
+ entrypoint: entryPoint,
125
+ type: this.classifyFlowType(entrySymbol),
126
+ responsibility: this.inferResponsibility(entrySymbol),
127
+ files: Array.from(files.entries()).map(([path, syms]) => ({
128
+ path,
129
+ responsibility: this.describeFile(path, syms),
130
+ symbols: syms,
131
+ })),
132
+ layers: Array.from(layers),
133
+ dependencies: {
134
+ imports: [...new Set(imports)],
135
+ calls: [...new Set(calls)],
136
+ implementsInterfaces: [...new Set(implementsInterfaces)],
137
+ },
138
+ complexity: this.calculateComplexity(visited.size, files.size),
139
+ depth: visited.size,
140
+ };
141
+ }
142
+
143
+ private detectLayer(symbol: {
144
+ name: string;
145
+ file: string;
146
+ }): string | null {
147
+ const name = symbol.name.toLowerCase();
148
+ const file = symbol.file.toLowerCase();
149
+
150
+ if (
151
+ name.includes("controller") ||
152
+ name.includes("route") ||
153
+ name.includes("handler") ||
154
+ file.includes("controller") ||
155
+ file.includes("routes")
156
+ ) {
157
+ return "api";
158
+ }
159
+ if (
160
+ name.includes("service") ||
161
+ name.includes("usecase") ||
162
+ file.includes("service") ||
163
+ file.includes("usecase")
164
+ ) {
165
+ return "service";
166
+ }
167
+ if (
168
+ name.includes("repository") ||
169
+ name.includes("model") ||
170
+ file.includes("repository") ||
171
+ file.includes("model")
172
+ ) {
173
+ return "data";
174
+ }
175
+ if (name.includes("component") || file.includes("component")) {
176
+ return "ui";
177
+ }
178
+ return null;
179
+ }
180
+
181
+ private classifyFlowType(symbol?: {
182
+ name: string;
183
+ type: string;
184
+ }): string {
185
+ if (!symbol) return "unknown";
186
+
187
+ const name = symbol.name.toLowerCase();
188
+
189
+ if (name.includes("auth")) return "Authentication Flow";
190
+ if (name.includes("user")) return "User Management Flow";
191
+ if (name.includes("payment")) return "Payment Processing Flow";
192
+ if (name.includes("order")) return "Order Processing Flow";
193
+ if (name.includes("notification")) return "Notification Flow";
194
+ if (name.includes("report")) return "Reporting Flow";
195
+ if (symbol.type === "function") return "API Endpoint";
196
+ if (symbol.type === "class") return "Service Handler";
197
+
198
+ return "Business Flow";
199
+ }
200
+
201
+ private inferResponsibility(symbol?: { name: string }): string {
202
+ if (!symbol) return "Unknown responsibility";
203
+
204
+ const name = symbol.name.toLowerCase();
205
+
206
+ if (name.includes("create")) return "Creation and initialization";
207
+ if (name.includes("get") || name.includes("find")) return "Data retrieval";
208
+ if (name.includes("update")) return "Data modification";
209
+ if (name.includes("delete") || name.includes("remove")) return "Data deletion";
210
+ if (name.includes("validate")) return "Data validation";
211
+ if (name.includes("process")) return "Business logic processing";
212
+ if (name.includes("handle")) return "Event/request handling";
213
+
214
+ return `Manages ${symbol.name} operations`;
215
+ }
216
+
217
+ private describeFile(path: string, symbols: string[]): string {
218
+ if (path.includes("controller")) return "API endpoint definitions";
219
+ if (path.includes("service")) return "Business logic implementation";
220
+ if (path.includes("repository")) return "Data access layer";
221
+ if (path.includes("model")) return "Data models and entities";
222
+ if (path.includes("route")) return "URL routing configuration";
223
+ if (path.includes("middleware")) return "Request/response middleware";
224
+ if (path.includes("component")) return "UI component";
225
+ return `Contains ${symbols.length} symbols`;
226
+ }
227
+
228
+ private calculateComplexity(
229
+ symbolCount: number,
230
+ fileCount: number
231
+ ): "low" | "medium" | "high" {
232
+ if (symbolCount < 5 && fileCount <= 2) return "low";
233
+ if (symbolCount > 15 || fileCount > 5) return "high";
234
+ return "medium";
235
+ }
236
+ }
237
+
238
+ export const flowGenerator = new FlowGenerator();
@@ -0,0 +1,16 @@
1
+ export {
2
+ AIContextGenerator,
3
+ aiContextGenerator,
4
+ type EnrichedContext,
5
+ } from "./aiContextGenerator.js";
6
+
7
+ export {
8
+ FlowGenerator,
9
+ flowGenerator,
10
+ type EnrichedFlow,
11
+ } from "./flowGenerator.js";
12
+
13
+ export {
14
+ ArchitectureGenerator,
15
+ architectureGenerator,
16
+ } from "./architectureGenerator.js";
@@ -1,6 +1,7 @@
1
1
  import fs from "fs";
2
2
  import path from "path";
3
3
  import { readFile, DEFAULT_EXCLUDE_PATTERNS, getAllFiles as scanFiles, getRelativePath } from "../utils/fileUtils.js";
4
+ import { AI_CONTEXT_DIR, getHierarchyPath } from "../utils/constants.js";
4
5
 
5
6
  /**
6
7
  * Hierarchy result
@@ -299,11 +300,11 @@ function summarizeFile(filePath: string, content: string): string {
299
300
  */
300
301
  export async function generateHierarchy(
301
302
  rootDir: string,
302
- outputPath: string = "ai/hierarchy.json"
303
+ outputPath: string = getHierarchyPath(rootDir)
303
304
  ): Promise<HierarchyResult> {
304
305
  try {
305
306
  // Get all files
306
- const allFiles = scanFiles(rootDir, [...DEFAULT_EXCLUDE_PATTERNS, "ai", "node_modules"]);
307
+ const allFiles = scanFiles(rootDir, [...DEFAULT_EXCLUDE_PATTERNS, AI_CONTEXT_DIR, "ai", "node_modules"]);
307
308
 
308
309
  // Get files for analysis
309
310
  const files: { path: string; relativePath: string }[] = [];
@@ -0,0 +1,99 @@
1
+ import { typescriptParser, ParsedFile as ParsedTSFile } from "./typescriptParser.js";
2
+ import { pythonParser, ParsedPythonFile } from "./pythonParser.js";
3
+ import type { Symbol as CodeSymbol } from "../../analyzers/symbols.js";
4
+
5
+ export type ParsedResult = ParsedTSFile | ParsedPythonFile;
6
+
7
+ export interface BaseParser {
8
+ parseFile(filePath: string, sourceText: string): ParsedResult;
9
+ }
10
+
11
+ export class ParserRegistry {
12
+ private parsers: Map<string, BaseParser> = new Map();
13
+
14
+ constructor() {
15
+ this.registerParsers();
16
+ }
17
+
18
+ private registerParsers(): void {
19
+ this.parsers.set(".ts", typescriptParser);
20
+ this.parsers.set(".tsx", typescriptParser);
21
+ this.parsers.set(".js", typescriptParser);
22
+ this.parsers.set(".jsx", typescriptParser);
23
+ this.parsers.set(".mjs", typescriptParser);
24
+ this.parsers.set(".cjs", typescriptParser);
25
+
26
+ this.parsers.set(".py", pythonParser);
27
+ this.parsers.set(".pyw", pythonParser);
28
+ }
29
+
30
+ getParser(extension: string): BaseParser | undefined {
31
+ return this.parsers.get(extension.toLowerCase());
32
+ }
33
+
34
+ hasParser(extension: string): boolean {
35
+ return this.parsers.has(extension.toLowerCase());
36
+ }
37
+
38
+ getSupportedExtensions(): string[] {
39
+ return Array.from(this.parsers.keys());
40
+ }
41
+
42
+ parse(filePath: string, sourceText: string, extension?: string): ParsedResult | null {
43
+ const ext = extension || this.getExtension(filePath);
44
+ const parser = this.getParser(ext);
45
+
46
+ if (!parser) {
47
+ return null;
48
+ }
49
+
50
+ try {
51
+ return parser.parseFile(filePath, sourceText);
52
+ } catch {
53
+ return null;
54
+ }
55
+ }
56
+
57
+ private getExtension(filePath: string): string {
58
+ const lastDot = filePath.lastIndexOf(".");
59
+ if (lastDot === -1) return "";
60
+ return filePath.slice(lastDot);
61
+ }
62
+ }
63
+
64
+ export const parserRegistry = new ParserRegistry();
65
+
66
+ export function createSymbolFromParsed(
67
+ parsed: ParsedResult,
68
+ filePath: string
69
+ ): CodeSymbol[] {
70
+ const symbols: CodeSymbol[] = [];
71
+
72
+ if ("symbols" in parsed) {
73
+ for (const sym of parsed.symbols) {
74
+ symbols.push({
75
+ id: `${filePath}#${sym.name}`,
76
+ name: sym.name,
77
+ type: sym.type as CodeSymbol['type'],
78
+ file: filePath,
79
+ line: sym.line,
80
+ export: sym.isExported ?? false,
81
+ });
82
+
83
+ if ('members' in sym && sym.members) {
84
+ for (const member of sym.members) {
85
+ symbols.push({
86
+ id: `${filePath}#${sym.name}.${member.name}`,
87
+ name: `${sym.name}.${member.name}`,
88
+ type: member.type as CodeSymbol['type'],
89
+ file: filePath,
90
+ line: member.line,
91
+ export: false,
92
+ });
93
+ }
94
+ }
95
+ }
96
+ }
97
+
98
+ return symbols;
99
+ }
@@ -0,0 +1,302 @@
1
+ export interface PythonSymbol {
2
+ name: string;
3
+ type: "class" | "function" | "method" | "variable" | "import";
4
+ line: number;
5
+ decorators?: string[];
6
+ parameters?: {
7
+ name: string;
8
+ type?: string;
9
+ default?: string;
10
+ }[];
11
+ inheritance?: string[];
12
+ docstring?: string;
13
+ isAsync?: boolean;
14
+ isExported?: boolean;
15
+ }
16
+
17
+ export interface ParsedPythonFile {
18
+ filePath: string;
19
+ symbols: PythonSymbol[];
20
+ imports: {
21
+ module: string;
22
+ names?: string[];
23
+ alias?: string;
24
+ isFromImport: boolean;
25
+ }[];
26
+ }
27
+
28
+ export class PythonParser {
29
+ parseFile(filePath: string, sourceText: string): ParsedPythonFile {
30
+ const lines = sourceText.split("\n");
31
+ const symbols: PythonSymbol[] = [];
32
+ const imports: ParsedPythonFile["imports"] = [];
33
+
34
+ let currentClass: PythonSymbol | null = null;
35
+ let i = 0;
36
+
37
+ while (i < lines.length) {
38
+ const line = lines[i];
39
+ const trimmedLine = line.trim();
40
+ const lineNumber = i + 1;
41
+
42
+ // Skip empty lines and comments
43
+ if (!trimmedLine || trimmedLine.startsWith("#")) {
44
+ i++;
45
+ continue;
46
+ }
47
+
48
+ // Parse imports
49
+ if (trimmedLine.startsWith("import ") || trimmedLine.startsWith("from ")) {
50
+ const importInfo = this.parseImport(trimmedLine);
51
+ if (importInfo) {
52
+ imports.push(importInfo);
53
+ }
54
+ i++;
55
+ continue;
56
+ }
57
+
58
+ // Check for decorators
59
+ const decorators: string[] = [];
60
+ let j = i;
61
+ while (j < lines.length && lines[j].trim().startsWith("@")) {
62
+ decorators.push(lines[j].trim().substring(1).split("(")[0]);
63
+ j++;
64
+ }
65
+
66
+ if (decorators.length > 0) {
67
+ i = j;
68
+ const nextLine = lines[i]?.trim() || "";
69
+
70
+ // Class with decorators
71
+ if (nextLine.startsWith("class ")) {
72
+ const classSymbol = this.parseClass(nextLine, lineNumber, decorators, lines, i);
73
+ if (classSymbol) {
74
+ symbols.push(classSymbol);
75
+ currentClass = classSymbol;
76
+ }
77
+ i = this.findClassEnd(lines, i);
78
+ continue;
79
+ }
80
+
81
+ // Function with decorators
82
+ if (nextLine.startsWith("def ") || nextLine.startsWith("async def ")) {
83
+ const funcSymbol = this.parseFunction(nextLine, lineNumber, decorators);
84
+ if (funcSymbol) {
85
+ if (currentClass && this.isMethodOfClass(funcSymbol.name, lines, i, currentClass)) {
86
+ funcSymbol.type = "method";
87
+ }
88
+ symbols.push(funcSymbol);
89
+ }
90
+ }
91
+
92
+ i++;
93
+ continue;
94
+ }
95
+
96
+ // Parse class
97
+ if (trimmedLine.startsWith("class ")) {
98
+ const classSymbol = this.parseClass(trimmedLine, lineNumber, [], lines, i);
99
+ if (classSymbol) {
100
+ symbols.push(classSymbol);
101
+ currentClass = classSymbol;
102
+ }
103
+ i = this.findClassEnd(lines, i);
104
+ continue;
105
+ }
106
+
107
+ // Parse function
108
+ if (trimmedLine.startsWith("def ") || trimmedLine.startsWith("async def ")) {
109
+ const funcSymbol = this.parseFunction(trimmedLine, lineNumber, []);
110
+ if (funcSymbol) {
111
+ if (currentClass && this.isMethodOfClass(funcSymbol.name, lines, i, currentClass)) {
112
+ funcSymbol.type = "method";
113
+ }
114
+ symbols.push(funcSymbol);
115
+ }
116
+ i++;
117
+ continue;
118
+ }
119
+
120
+ // Detect class end by indentation
121
+ if (currentClass && !line.startsWith(" ") && !line.startsWith("\t") && trimmedLine) {
122
+ currentClass = null;
123
+ }
124
+
125
+ i++;
126
+ }
127
+
128
+ return {
129
+ filePath,
130
+ symbols,
131
+ imports,
132
+ };
133
+ }
134
+
135
+ private parseImport(line: string): ParsedPythonFile["imports"][0] | null {
136
+ // from module import name1, name2
137
+ const fromMatch = line.match(/from\s+(\S+)\s+import\s+(.+)/);
138
+ if (fromMatch) {
139
+ const module = fromMatch[1];
140
+ const namesPart = fromMatch[2];
141
+ const names = namesPart.split(",").map(n => n.trim().split(" ")[0]);
142
+ return { module, names, isFromImport: true };
143
+ }
144
+
145
+ // import module or import module as alias
146
+ const importMatch = line.match(/import\s+(.+)/);
147
+ if (importMatch) {
148
+ const modules = importMatch[1].split(",").map(m => {
149
+ const parts = m.trim().split(/\s+as\s+/);
150
+ return { module: parts[0], alias: parts[1] };
151
+ });
152
+ return { module: modules[0].module, alias: modules[0].alias, isFromImport: false };
153
+ }
154
+
155
+ return null;
156
+ }
157
+
158
+ private parseClass(
159
+ line: string,
160
+ lineNumber: number,
161
+ decorators: string[],
162
+ lines: string[],
163
+ startIndex: number
164
+ ): PythonSymbol | null {
165
+ const match = line.match(/class\s+(\w+)(?:\(([^)]+)\))?/);
166
+ if (!match) return null;
167
+
168
+ const name = match[1];
169
+ const inheritance = match[2] ? match[2].split(",").map(s => s.trim()) : [];
170
+
171
+ // Extract docstring
172
+ const docstring = this.extractDocstring(lines, startIndex);
173
+
174
+ return {
175
+ name,
176
+ type: "class",
177
+ line: lineNumber,
178
+ decorators: decorators.length > 0 ? decorators : undefined,
179
+ inheritance: inheritance.length > 0 ? inheritance : undefined,
180
+ docstring,
181
+ isExported: true,
182
+ };
183
+ }
184
+
185
+ private parseFunction(
186
+ line: string,
187
+ lineNumber: number,
188
+ decorators: string[]
189
+ ): PythonSymbol | null {
190
+ const isAsync = line.startsWith("async ");
191
+ const defKeyword = isAsync ? "async def" : "def";
192
+ const match = line.match(new RegExp(`${defKeyword}\\s+(\\w+)\\s*\\(([^)]*)\\)`));
193
+
194
+ if (!match) return null;
195
+
196
+ const name = match[1];
197
+ const paramsStr = match[2];
198
+ const parameters = this.parseParameters(paramsStr);
199
+
200
+ return {
201
+ name,
202
+ type: "function",
203
+ line: lineNumber,
204
+ decorators: decorators.length > 0 ? decorators : undefined,
205
+ parameters: parameters.length > 0 ? parameters : [],
206
+ isAsync,
207
+ isExported: true,
208
+ };
209
+ }
210
+
211
+ private parseParameters(paramsStr: string): { name: string; type?: string; default?: string }[] {
212
+ if (!paramsStr.trim()) return [];
213
+
214
+ return paramsStr.split(",").map(param => {
215
+ const trimmed = param.trim();
216
+ if (!trimmed || trimmed === "self" || trimmed === "cls") return null;
217
+
218
+ // Handle type hints and defaults
219
+ const parts = trimmed.split("=");
220
+ const nameAndType = parts[0].trim();
221
+ const defaultValue = parts[1]?.trim();
222
+
223
+ const typeMatch = nameAndType.match(/(.+):\s*(.+)/);
224
+ if (typeMatch) {
225
+ return {
226
+ name: typeMatch[1].trim(),
227
+ type: typeMatch[2].trim(),
228
+ default: defaultValue,
229
+ };
230
+ }
231
+
232
+ return {
233
+ name: nameAndType,
234
+ default: defaultValue,
235
+ };
236
+ }).filter((p): p is NonNullable<typeof p> => p !== null);
237
+ }
238
+
239
+ private extractDocstring(lines: string[], startIndex: number): string | undefined {
240
+ // Look for docstring in next few lines
241
+ for (let i = startIndex + 1; i < Math.min(startIndex + 5, lines.length); i++) {
242
+ const line = lines[i].trim();
243
+ if (line.startsWith('"""') || line.startsWith("'''")) {
244
+ const quote = line.startsWith('"""') ? '"""' : "'''";
245
+ if (line.endsWith(quote) && line.length > 6) {
246
+ return line.slice(3, -3);
247
+ }
248
+ // Multi-line docstring
249
+ let docstring = line.slice(3);
250
+ for (let j = i + 1; j < lines.length; j++) {
251
+ const nextLine = lines[j];
252
+ if (nextLine.includes(quote)) {
253
+ docstring += "\n" + nextLine.slice(0, nextLine.indexOf(quote));
254
+ return docstring.trim();
255
+ }
256
+ docstring += "\n" + nextLine;
257
+ }
258
+ }
259
+ }
260
+ return undefined;
261
+ }
262
+
263
+ private findClassEnd(lines: string[], startIndex: number): number {
264
+ const baseIndent = lines[startIndex].match(/^(\s*)/)?.[1].length || 0;
265
+ let i = startIndex + 1;
266
+
267
+ while (i < lines.length) {
268
+ const line = lines[i];
269
+ const trimmed = line.trim();
270
+
271
+ if (!trimmed || trimmed.startsWith("#")) {
272
+ i++;
273
+ continue;
274
+ }
275
+
276
+ const indent = line.match(/^(\s*)/)?.[1].length || 0;
277
+
278
+ // Check if we've exited the class (less or equal indentation)
279
+ if (indent <= baseIndent && trimmed) {
280
+ // Check if it's a new class or function at same level
281
+ if (trimmed.startsWith("class ") || trimmed.startsWith("def ") || trimmed.startsWith("async def ") || trimmed.startsWith("@")) {
282
+ return i;
283
+ }
284
+ }
285
+
286
+ i++;
287
+ }
288
+
289
+ return i;
290
+ }
291
+
292
+ private isMethodOfClass(funcName: string, lines: string[], funcIndex: number, classSymbol: PythonSymbol): boolean {
293
+ // Check if function is indented within the class
294
+ const classLineIndex = classSymbol.line - 1;
295
+ const classIndent = lines[classLineIndex].match(/^(\s*)/)?.[1].length || 0;
296
+ const funcIndent = lines[funcIndex].match(/^(\s*)/)?.[1].length || 0;
297
+
298
+ return funcIndent > classIndent;
299
+ }
300
+ }
301
+
302
+ export const pythonParser = new PythonParser();