kirograph 0.16.1 → 0.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (365) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +103 -1605
  3. package/dist/architecture/layers/dart.js +112 -0
  4. package/dist/architecture/layers/dart.js.map +7 -0
  5. package/dist/architecture/layers/index.js +3 -1
  6. package/dist/architecture/layers/index.js.map +2 -2
  7. package/dist/bin/banner.js +74 -6
  8. package/dist/bin/banner.js.map +2 -2
  9. package/dist/bin/commands/affected.js +40 -5
  10. package/dist/bin/commands/affected.js.map +2 -2
  11. package/dist/bin/commands/attack-surface.js +157 -0
  12. package/dist/bin/commands/attack-surface.js.map +7 -0
  13. package/dist/bin/commands/benchmark.js +206 -0
  14. package/dist/bin/commands/benchmark.js.map +7 -0
  15. package/dist/bin/commands/budget.js +70 -0
  16. package/dist/bin/commands/budget.js.map +7 -0
  17. package/dist/bin/commands/communities.js +77 -0
  18. package/dist/bin/commands/communities.js.map +7 -0
  19. package/dist/bin/commands/data.js +665 -0
  20. package/dist/bin/commands/data.js.map +7 -0
  21. package/dist/bin/commands/dep-confusion.js +119 -0
  22. package/dist/bin/commands/dep-confusion.js.map +7 -0
  23. package/dist/bin/commands/export.js +304 -10
  24. package/dist/bin/commands/export.js.map +2 -2
  25. package/dist/bin/commands/flows.js +97 -0
  26. package/dist/bin/commands/flows.js.map +7 -0
  27. package/dist/bin/commands/help.js +386 -100
  28. package/dist/bin/commands/help.js.map +2 -2
  29. package/dist/bin/commands/install.js +90 -8
  30. package/dist/bin/commands/install.js.map +2 -2
  31. package/dist/bin/commands/licenses.js +201 -0
  32. package/dist/bin/commands/licenses.js.map +7 -0
  33. package/dist/bin/commands/reachability.js +160 -0
  34. package/dist/bin/commands/reachability.js.map +7 -0
  35. package/dist/bin/commands/read.js +100 -0
  36. package/dist/bin/commands/read.js.map +7 -0
  37. package/dist/bin/commands/refactor.js +116 -0
  38. package/dist/bin/commands/refactor.js.map +7 -0
  39. package/dist/bin/commands/remediation.js +133 -0
  40. package/dist/bin/commands/remediation.js.map +7 -0
  41. package/dist/bin/commands/sbom.js +76 -0
  42. package/dist/bin/commands/sbom.js.map +7 -0
  43. package/dist/bin/commands/security-ci-report.js +267 -0
  44. package/dist/bin/commands/security-ci-report.js.map +7 -0
  45. package/dist/bin/commands/security-export.js +1349 -0
  46. package/dist/bin/commands/security-export.js.map +7 -0
  47. package/dist/bin/commands/security-flows.js +126 -0
  48. package/dist/bin/commands/security-flows.js.map +7 -0
  49. package/dist/bin/commands/security-secrets.js +170 -0
  50. package/dist/bin/commands/security-secrets.js.map +7 -0
  51. package/dist/bin/commands/security.js +193 -0
  52. package/dist/bin/commands/security.js.map +7 -0
  53. package/dist/bin/commands/staleness.js +144 -0
  54. package/dist/bin/commands/staleness.js.map +7 -0
  55. package/dist/bin/commands/status.js +102 -2
  56. package/dist/bin/commands/status.js.map +2 -2
  57. package/dist/bin/commands/supply-chain.js +138 -0
  58. package/dist/bin/commands/supply-chain.js.map +7 -0
  59. package/dist/bin/commands/uninit.js +109 -60
  60. package/dist/bin/commands/uninit.js.map +2 -2
  61. package/dist/bin/commands/vex.js +76 -0
  62. package/dist/bin/commands/vex.js.map +7 -0
  63. package/dist/bin/commands/vuln-suppress.js +95 -0
  64. package/dist/bin/commands/vuln-suppress.js.map +7 -0
  65. package/dist/bin/commands/vulns.js +382 -0
  66. package/dist/bin/commands/vulns.js.map +7 -0
  67. package/dist/bin/installer/auto-detect.js +125 -0
  68. package/dist/bin/installer/auto-detect.js.map +7 -0
  69. package/dist/bin/installer/cli-agent.js +28 -5
  70. package/dist/bin/installer/cli-agent.js.map +2 -2
  71. package/dist/bin/installer/common.js +47 -0
  72. package/dist/bin/installer/common.js.map +2 -2
  73. package/dist/bin/installer/config-prompt.js +39 -1
  74. package/dist/bin/installer/config-prompt.js.map +2 -2
  75. package/dist/bin/installer/detect.js +309 -0
  76. package/dist/bin/installer/detect.js.map +7 -0
  77. package/dist/bin/installer/index.js +36 -1
  78. package/dist/bin/installer/index.js.map +2 -2
  79. package/dist/bin/installer/instructions.js +195 -3
  80. package/dist/bin/installer/instructions.js.map +2 -2
  81. package/dist/bin/installer/steering.js +440 -0
  82. package/dist/bin/installer/steering.js.map +2 -2
  83. package/dist/bin/installer/targets/aider.js +3 -3
  84. package/dist/bin/installer/targets/aider.js.map +2 -2
  85. package/dist/bin/installer/targets/amp.js +3 -3
  86. package/dist/bin/installer/targets/amp.js.map +2 -2
  87. package/dist/bin/installer/targets/antigravity.js +35 -6
  88. package/dist/bin/installer/targets/antigravity.js.map +2 -2
  89. package/dist/bin/installer/targets/augment.js +3 -3
  90. package/dist/bin/installer/targets/augment.js.map +2 -2
  91. package/dist/bin/installer/targets/claude.js +49 -5
  92. package/dist/bin/installer/targets/claude.js.map +2 -2
  93. package/dist/bin/installer/targets/cline.js +32 -6
  94. package/dist/bin/installer/targets/cline.js.map +2 -2
  95. package/dist/bin/installer/targets/codex.js +64 -12
  96. package/dist/bin/installer/targets/codex.js.map +2 -2
  97. package/dist/bin/installer/targets/continue.js +2 -2
  98. package/dist/bin/installer/targets/continue.js.map +2 -2
  99. package/dist/bin/installer/targets/copilot-cli.js +101 -0
  100. package/dist/bin/installer/targets/copilot-cli.js.map +7 -0
  101. package/dist/bin/installer/targets/copilot.js +31 -5
  102. package/dist/bin/installer/targets/copilot.js.map +2 -2
  103. package/dist/bin/installer/targets/cursor.js +4 -4
  104. package/dist/bin/installer/targets/cursor.js.map +2 -2
  105. package/dist/bin/installer/targets/devin.js +2 -2
  106. package/dist/bin/installer/targets/devin.js.map +2 -2
  107. package/dist/bin/installer/targets/gemini-cli.js +2 -2
  108. package/dist/bin/installer/targets/gemini-cli.js.map +2 -2
  109. package/dist/bin/installer/targets/generic.js +2 -14
  110. package/dist/bin/installer/targets/generic.js.map +2 -2
  111. package/dist/bin/installer/targets/goose.js +3 -3
  112. package/dist/bin/installer/targets/goose.js.map +2 -2
  113. package/dist/bin/installer/targets/index.js +250 -0
  114. package/dist/bin/installer/targets/index.js.map +2 -2
  115. package/dist/bin/installer/targets/junie.js +2 -2
  116. package/dist/bin/installer/targets/junie.js.map +2 -2
  117. package/dist/bin/installer/targets/kilo.js +2 -2
  118. package/dist/bin/installer/targets/kilo.js.map +2 -2
  119. package/dist/bin/installer/targets/kiro.js +3 -3
  120. package/dist/bin/installer/targets/kiro.js.map +2 -2
  121. package/dist/bin/installer/targets/opencode.js +2 -2
  122. package/dist/bin/installer/targets/opencode.js.map +2 -2
  123. package/dist/bin/installer/targets/openhands.js +3 -3
  124. package/dist/bin/installer/targets/openhands.js.map +2 -2
  125. package/dist/bin/installer/targets/qoder.js +91 -0
  126. package/dist/bin/installer/targets/qoder.js.map +7 -0
  127. package/dist/bin/installer/targets/qwen.js +96 -0
  128. package/dist/bin/installer/targets/qwen.js.map +7 -0
  129. package/dist/bin/installer/targets/replit.js +3 -3
  130. package/dist/bin/installer/targets/replit.js.map +2 -2
  131. package/dist/bin/installer/targets/roo.js +2 -2
  132. package/dist/bin/installer/targets/roo.js.map +2 -2
  133. package/dist/bin/installer/targets/tabnine.js +3 -3
  134. package/dist/bin/installer/targets/tabnine.js.map +2 -2
  135. package/dist/bin/installer/targets/trae.js +5 -5
  136. package/dist/bin/installer/targets/trae.js.map +2 -2
  137. package/dist/bin/installer/targets/warp.js +2 -2
  138. package/dist/bin/installer/targets/warp.js.map +2 -2
  139. package/dist/bin/installer/targets/windsurf.js +35 -6
  140. package/dist/bin/installer/targets/windsurf.js.map +2 -2
  141. package/dist/bin/kirograph.js +74 -6
  142. package/dist/bin/kirograph.js.map +3 -3
  143. package/dist/bin/progress.js +30 -0
  144. package/dist/bin/progress.js.map +2 -2
  145. package/dist/compression/naive-cost.js +25 -0
  146. package/dist/compression/naive-cost.js.map +2 -2
  147. package/dist/compression/tracker.js +91 -2
  148. package/dist/compression/tracker.js.map +2 -2
  149. package/dist/compression/types.js.map +1 -1
  150. package/dist/config.js +126 -3
  151. package/dist/config.js.map +2 -2
  152. package/dist/core/pipeline.js +92 -4
  153. package/dist/core/pipeline.js.map +2 -2
  154. package/dist/data/filters.js +105 -0
  155. package/dist/data/filters.js.map +7 -0
  156. package/dist/data/indexer.js +225 -0
  157. package/dist/data/indexer.js.map +7 -0
  158. package/dist/data/linker.js +150 -0
  159. package/dist/data/linker.js.map +7 -0
  160. package/dist/data/lint.js +109 -0
  161. package/dist/data/lint.js.map +7 -0
  162. package/dist/data/parsers/csv.js +132 -0
  163. package/dist/data/parsers/csv.js.map +7 -0
  164. package/dist/data/parsers/excel.js +88 -0
  165. package/dist/data/parsers/excel.js.map +7 -0
  166. package/dist/data/parsers/index.js +79 -0
  167. package/dist/data/parsers/index.js.map +7 -0
  168. package/dist/data/parsers/json-array.js +89 -0
  169. package/dist/data/parsers/json-array.js.map +7 -0
  170. package/dist/data/parsers/jsonl.js +84 -0
  171. package/dist/data/parsers/jsonl.js.map +7 -0
  172. package/dist/data/parsers/parquet.js +95 -0
  173. package/dist/data/parsers/parquet.js.map +7 -0
  174. package/dist/data/profiler.js +182 -0
  175. package/dist/data/profiler.js.map +7 -0
  176. package/dist/data/queries.js +512 -0
  177. package/dist/data/queries.js.map +7 -0
  178. package/dist/data/types.js +17 -0
  179. package/dist/data/types.js.map +7 -0
  180. package/dist/db/data-schema.sql +61 -0
  181. package/dist/db/database.js +67 -5
  182. package/dist/db/database.js.map +2 -2
  183. package/dist/db/memory-schema.sql +5 -1
  184. package/dist/db/schema.sql +3 -1
  185. package/dist/db/security-schema.sql +72 -0
  186. package/dist/extraction/extractor.js +81 -0
  187. package/dist/extraction/extractor.js.map +2 -2
  188. package/dist/extraction/grammars.js +32 -8
  189. package/dist/extraction/grammars.js.map +2 -2
  190. package/dist/extraction/languages.js +43 -1
  191. package/dist/extraction/languages.js.map +2 -2
  192. package/dist/extraction/notebook.js +300 -0
  193. package/dist/extraction/notebook.js.map +7 -0
  194. package/dist/extraction/wasm/tree-sitter-astro.wasm +0 -0
  195. package/dist/extraction/wasm/tree-sitter-gdscript.wasm +0 -0
  196. package/dist/extraction/wasm/tree-sitter-julia.wasm +0 -0
  197. package/dist/extraction/wasm/tree-sitter-nix.wasm +0 -0
  198. package/dist/extraction/wasm/tree-sitter-perl.wasm +0 -0
  199. package/dist/extraction/wasm/tree-sitter-powershell.wasm +0 -0
  200. package/dist/extraction/wasm/tree-sitter-r.wasm +0 -0
  201. package/dist/extraction/wasm/tree-sitter-sql.wasm +0 -0
  202. package/dist/extraction/wasm/tree-sitter-verilog.wasm +0 -0
  203. package/dist/frameworks/flutter.js +130 -0
  204. package/dist/frameworks/flutter.js.map +7 -0
  205. package/dist/frameworks/index.js +7 -1
  206. package/dist/frameworks/index.js.map +3 -3
  207. package/dist/graph/communities.js +317 -0
  208. package/dist/graph/communities.js.map +7 -0
  209. package/dist/graph/flows.js +138 -0
  210. package/dist/graph/flows.js.map +7 -0
  211. package/dist/graph/refactor.js +155 -0
  212. package/dist/graph/refactor.js.map +7 -0
  213. package/dist/index.js +1 -1
  214. package/dist/index.js.map +2 -2
  215. package/dist/mcp/cache.js +172 -0
  216. package/dist/mcp/cache.js.map +7 -0
  217. package/dist/mcp/read-modes.js +295 -0
  218. package/dist/mcp/read-modes.js.map +7 -0
  219. package/dist/mcp/server.js +2 -1
  220. package/dist/mcp/server.js.map +2 -2
  221. package/dist/mcp/tool-names.js +29 -1
  222. package/dist/mcp/tool-names.js.map +2 -2
  223. package/dist/mcp/tools.js +1588 -6
  224. package/dist/mcp/tools.js.map +3 -3
  225. package/dist/memory/database.js +32 -2
  226. package/dist/memory/database.js.map +2 -2
  227. package/dist/memory/types.js.map +1 -1
  228. package/dist/resolution/bridges/android-rn.js +298 -0
  229. package/dist/resolution/bridges/android-rn.js.map +7 -0
  230. package/dist/resolution/bridges/expo-modules.js +155 -0
  231. package/dist/resolution/bridges/expo-modules.js.map +7 -0
  232. package/dist/resolution/bridges/flutter-channel.js +385 -0
  233. package/dist/resolution/bridges/flutter-channel.js.map +7 -0
  234. package/dist/resolution/bridges/index.js +80 -0
  235. package/dist/resolution/bridges/index.js.map +7 -0
  236. package/dist/resolution/bridges/native-events.js +188 -0
  237. package/dist/resolution/bridges/native-events.js.map +7 -0
  238. package/dist/resolution/bridges/native-views.js +244 -0
  239. package/dist/resolution/bridges/native-views.js.map +7 -0
  240. package/dist/resolution/bridges/react-native.js +161 -0
  241. package/dist/resolution/bridges/react-native.js.map +7 -0
  242. package/dist/resolution/bridges/swift-objc.js +227 -0
  243. package/dist/resolution/bridges/swift-objc.js.map +7 -0
  244. package/dist/resolution/bridges/turbomodules.js +216 -0
  245. package/dist/resolution/bridges/turbomodules.js.map +7 -0
  246. package/dist/resolution/index.js +61 -2
  247. package/dist/resolution/index.js.map +2 -2
  248. package/dist/security/attack-surface.js +164 -0
  249. package/dist/security/attack-surface.js.map +7 -0
  250. package/dist/security/context-warnings.js +123 -0
  251. package/dist/security/context-warnings.js.map +7 -0
  252. package/dist/security/context-warnings.test.js +300 -0
  253. package/dist/security/context-warnings.test.js.map +7 -0
  254. package/dist/security/data-flows.js +228 -0
  255. package/dist/security/data-flows.js.map +7 -0
  256. package/dist/security/dep-confusion.js +255 -0
  257. package/dist/security/dep-confusion.js.map +7 -0
  258. package/dist/security/errors.js +51 -0
  259. package/dist/security/errors.js.map +7 -0
  260. package/dist/security/export/fix-suggestions.js +58 -0
  261. package/dist/security/export/fix-suggestions.js.map +7 -0
  262. package/dist/security/export/fix-suggestions.test.js +74 -0
  263. package/dist/security/export/fix-suggestions.test.js.map +7 -0
  264. package/dist/security/export/sbom.js +230 -0
  265. package/dist/security/export/sbom.js.map +7 -0
  266. package/dist/security/export/sbom.test.js +288 -0
  267. package/dist/security/export/sbom.test.js.map +7 -0
  268. package/dist/security/export/serialization.js +142 -0
  269. package/dist/security/export/serialization.js.map +7 -0
  270. package/dist/security/export/serialization.test.js +310 -0
  271. package/dist/security/export/serialization.test.js.map +7 -0
  272. package/dist/security/export/vex.js +220 -0
  273. package/dist/security/export/vex.js.map +7 -0
  274. package/dist/security/export/vex.test.js +278 -0
  275. package/dist/security/export/vex.test.js.map +7 -0
  276. package/dist/security/index.js +67 -0
  277. package/dist/security/index.js.map +7 -0
  278. package/dist/security/integrator-transitives.test.js +359 -0
  279. package/dist/security/integrator-transitives.test.js.map +7 -0
  280. package/dist/security/integrator.js +491 -0
  281. package/dist/security/integrator.js.map +7 -0
  282. package/dist/security/integrator.test.js +237 -0
  283. package/dist/security/integrator.test.js.map +7 -0
  284. package/dist/security/license.js +70 -0
  285. package/dist/security/license.js.map +7 -0
  286. package/dist/security/manifest/adapter.js +243 -0
  287. package/dist/security/manifest/adapter.js.map +7 -0
  288. package/dist/security/manifest/adapter.test.js +272 -0
  289. package/dist/security/manifest/adapter.test.js.map +7 -0
  290. package/dist/security/manifest/parser.js +376 -0
  291. package/dist/security/manifest/parser.js.map +7 -0
  292. package/dist/security/manifest/parser.test.js +110 -0
  293. package/dist/security/manifest/parser.test.js.map +7 -0
  294. package/dist/security/manifest/plugins/cargo.js +233 -0
  295. package/dist/security/manifest/plugins/cargo.js.map +7 -0
  296. package/dist/security/manifest/plugins/cargo.test.js +304 -0
  297. package/dist/security/manifest/plugins/cargo.test.js.map +7 -0
  298. package/dist/security/manifest/plugins/composer.js +152 -0
  299. package/dist/security/manifest/plugins/composer.js.map +7 -0
  300. package/dist/security/manifest/plugins/go.js +146 -0
  301. package/dist/security/manifest/plugins/go.js.map +7 -0
  302. package/dist/security/manifest/plugins/go.test.js +341 -0
  303. package/dist/security/manifest/plugins/go.test.js.map +7 -0
  304. package/dist/security/manifest/plugins/gradle.js +159 -0
  305. package/dist/security/manifest/plugins/gradle.js.map +7 -0
  306. package/dist/security/manifest/plugins/hex.js +159 -0
  307. package/dist/security/manifest/plugins/hex.js.map +7 -0
  308. package/dist/security/manifest/plugins/maven.js +128 -0
  309. package/dist/security/manifest/plugins/maven.js.map +7 -0
  310. package/dist/security/manifest/plugins/maven.test.js +389 -0
  311. package/dist/security/manifest/plugins/maven.test.js.map +7 -0
  312. package/dist/security/manifest/plugins/npm.js +284 -0
  313. package/dist/security/manifest/plugins/npm.js.map +7 -0
  314. package/dist/security/manifest/plugins/npm.test.js +298 -0
  315. package/dist/security/manifest/plugins/npm.test.js.map +7 -0
  316. package/dist/security/manifest/plugins/nuget.js +186 -0
  317. package/dist/security/manifest/plugins/nuget.js.map +7 -0
  318. package/dist/security/manifest/plugins/pip.js +123 -0
  319. package/dist/security/manifest/plugins/pip.js.map +7 -0
  320. package/dist/security/manifest/plugins/pip.test.js +208 -0
  321. package/dist/security/manifest/plugins/pip.test.js.map +7 -0
  322. package/dist/security/manifest/plugins/pubspec.js +212 -0
  323. package/dist/security/manifest/plugins/pubspec.js.map +7 -0
  324. package/dist/security/manifest/plugins/pyproject.js +261 -0
  325. package/dist/security/manifest/plugins/pyproject.js.map +7 -0
  326. package/dist/security/manifest/plugins/rubygems.js +185 -0
  327. package/dist/security/manifest/plugins/rubygems.js.map +7 -0
  328. package/dist/security/manifest/plugins/swift.js +200 -0
  329. package/dist/security/manifest/plugins/swift.js.map +7 -0
  330. package/dist/security/owasp.js +104 -0
  331. package/dist/security/owasp.js.map +7 -0
  332. package/dist/security/pipeline.js +125 -0
  333. package/dist/security/pipeline.js.map +7 -0
  334. package/dist/security/reachability.js +276 -0
  335. package/dist/security/reachability.js.map +7 -0
  336. package/dist/security/reachability.test.js +394 -0
  337. package/dist/security/reachability.test.js.map +7 -0
  338. package/dist/security/remediation.js +126 -0
  339. package/dist/security/remediation.js.map +7 -0
  340. package/dist/security/secrets.js +176 -0
  341. package/dist/security/secrets.js.map +7 -0
  342. package/dist/security/staleness.js +231 -0
  343. package/dist/security/staleness.js.map +7 -0
  344. package/dist/security/supply-chain.js +301 -0
  345. package/dist/security/supply-chain.js.map +7 -0
  346. package/dist/security/suppressions.js +106 -0
  347. package/dist/security/suppressions.js.map +7 -0
  348. package/dist/security/types.js +17 -0
  349. package/dist/security/types.js.map +7 -0
  350. package/dist/security/vuln/client.js +355 -0
  351. package/dist/security/vuln/client.js.map +7 -0
  352. package/dist/security/vuln/client.test.js +288 -0
  353. package/dist/security/vuln/client.test.js.map +7 -0
  354. package/dist/security/vuln/epss-client.js +95 -0
  355. package/dist/security/vuln/epss-client.js.map +7 -0
  356. package/dist/security/vuln/index.js +29 -0
  357. package/dist/security/vuln/index.js.map +7 -0
  358. package/dist/security/vuln/osv-adapter.js +321 -0
  359. package/dist/security/vuln/osv-adapter.js.map +7 -0
  360. package/dist/security/vuln/osv-adapter.test.js +391 -0
  361. package/dist/security/vuln/osv-adapter.test.js.map +7 -0
  362. package/dist/security/vuln/types.js +17 -0
  363. package/dist/security/vuln/types.js.map +7 -0
  364. package/dist/types.js.map +2 -2
  365. package/package.json +5 -2
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/extraction/languages.ts"],
4
- "sourcesContent": ["/**\n * Language detection and tree-sitter grammar mapping\n */\n\nimport type { Language } from '../types';\n\nexport const EXTENSION_MAP: Record<string, Language> = {\n '.ts': 'typescript',\n '.tsx': 'tsx',\n '.js': 'javascript',\n '.jsx': 'jsx',\n '.mjs': 'javascript',\n '.cjs': 'javascript',\n '.py': 'python',\n '.pyw': 'python',\n '.go': 'go',\n '.rs': 'rust',\n '.java': 'java',\n '.c': 'c',\n '.h': 'c',\n '.cpp': 'cpp',\n '.cc': 'cpp',\n '.cxx': 'cpp',\n '.hxx': 'cpp',\n '.hpp': 'cpp',\n '.cs': 'csharp',\n '.php': 'php',\n '.rb': 'ruby',\n '.rake': 'ruby',\n '.swift': 'swift',\n '.kt': 'kotlin',\n '.kts': 'kotlin',\n '.dart': 'dart',\n '.svelte': 'svelte',\n '.pas': 'pascal',\n '.dpr': 'pascal',\n '.dpk': 'pascal',\n '.lpr': 'pascal',\n '.dfm': 'pascal',\n '.fmx': 'pascal',\n '.liquid': 'liquid',\n '.ex': 'elixir',\n '.exs': 'elixir',\n '.scala': 'scala',\n '.sc': 'scala',\n '.sbt': 'scala',\n '.lua': 'lua',\n '.zig': 'zig',\n '.zon': 'zig',\n '.sh': 'bash',\n '.bash': 'bash',\n '.zsh': 'bash',\n '.ml': 'ocaml',\n '.mli': 'ocaml',\n '.elm': 'elm',\n '.sol': 'solidity',\n '.vue': 'vue',\n '.m': 'objc',\n '.yaml': 'yaml',\n '.yml': 'yaml',\n '.tf': 'hcl',\n '.tfvars': 'hcl',\n '.css': 'css',\n '.scss': 'scss',\n '.sass': 'scss',\n '.html': 'html',\n '.htm': 'html',\n};\n\nexport const GRAMMAR_MAP: Record<Language, string> = {\n typescript: 'tree-sitter-typescript',\n tsx: 'tree-sitter-tsx',\n javascript: 'tree-sitter-javascript',\n jsx: 'tree-sitter-javascript',\n python: 'tree-sitter-python',\n go: 'tree-sitter-go',\n rust: 'tree-sitter-rust',\n java: 'tree-sitter-java',\n c: 'tree-sitter-c',\n cpp: 'tree-sitter-cpp',\n csharp: 'tree-sitter-c-sharp',\n php: 'tree-sitter-php',\n ruby: 'tree-sitter-ruby',\n swift: 'tree-sitter-swift',\n kotlin: 'tree-sitter-kotlin',\n dart: 'tree-sitter-dart',\n svelte: 'tree-sitter-svelte',\n elixir: 'tree-sitter-elixir',\n scala: 'tree-sitter-scala',\n lua: 'tree-sitter-lua',\n zig: 'tree-sitter-zig',\n bash: 'tree-sitter-bash',\n ocaml: 'tree-sitter-ocaml',\n elm: 'tree-sitter-elm',\n solidity: 'tree-sitter-solidity',\n vue: 'tree-sitter-vue',\n objc: 'tree-sitter-objc',\n yaml: 'tree-sitter-yaml',\n hcl: 'tree-sitter-hcl',\n css: 'tree-sitter-css',\n scss: 'tree-sitter-scss',\n html: 'tree-sitter-html',\n // Pascal and Liquid require custom WASM not bundled in tree-sitter-wasms\n pascal: '',\n liquid: '',\n unknown: '',\n};\n\nexport function detectLanguage(filePath: string): Language {\n const ext = filePath.slice(filePath.lastIndexOf('.')).toLowerCase();\n return EXTENSION_MAP[ext] ?? 'unknown';\n}\n\nexport function isSupportedLanguage(lang: Language): boolean {\n // All known languages are \"supported\" for indexing purposes.\n // Pascal and Liquid don't have a grammar WASM, so they'll be indexed\n // with empty symbol lists (file tracked but no AST extraction).\n return lang !== 'unknown';\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAMO,MAAM,gBAA0C;AAAA,EACrD,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,OAAO;AAAA,EACP,SAAS;AAAA,EACT,MAAM;AAAA,EACN,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,SAAS;AAAA,EACT,UAAU;AAAA,EACV,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,WAAW;AAAA,EACX,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,WAAW;AAAA,EACX,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,MAAM;AAAA,EACN,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,WAAW;AAAA,EACX,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,SAAS;AAAA,EACT,SAAS;AAAA,EACT,QAAQ;AACV;AAEO,MAAM,cAAwC;AAAA,EACnD,YAAY;AAAA,EACZ,KAAK;AAAA,EACL,YAAY;AAAA,EACZ,KAAK;AAAA,EACL,QAAQ;AAAA,EACR,IAAI;AAAA,EACJ,MAAM;AAAA,EACN,MAAM;AAAA,EACN,GAAG;AAAA,EACH,KAAK;AAAA,EACL,QAAQ;AAAA,EACR,KAAK;AAAA,EACL,MAAM;AAAA,EACN,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,KAAK;AAAA,EACL,KAAK;AAAA,EACL,MAAM;AAAA,EACN,OAAO;AAAA,EACP,KAAK;AAAA,EACL,UAAU;AAAA,EACV,KAAK;AAAA,EACL,MAAM;AAAA,EACN,MAAM;AAAA,EACN,KAAK;AAAA,EACL,KAAK;AAAA,EACL,MAAM;AAAA,EACN,MAAM;AAAA;AAAA,EAEN,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,SAAS;AACX;AAEO,SAAS,eAAe,UAA4B;AACzD,QAAM,MAAM,SAAS,MAAM,SAAS,YAAY,GAAG,CAAC,EAAE,YAAY;AAClE,SAAO,cAAc,GAAG,KAAK;AAC/B;AAEO,SAAS,oBAAoB,MAAyB;AAI3D,SAAO,SAAS;AAClB;",
4
+ "sourcesContent": ["/**\n * Language detection and tree-sitter grammar mapping\n */\n\nimport type { Language } from '../types';\n\nexport const EXTENSION_MAP: Record<string, Language> = {\n '.ts': 'typescript',\n '.tsx': 'tsx',\n '.js': 'javascript',\n '.jsx': 'jsx',\n '.mjs': 'javascript',\n '.cjs': 'javascript',\n '.py': 'python',\n '.pyw': 'python',\n '.go': 'go',\n '.rs': 'rust',\n '.java': 'java',\n '.c': 'c',\n '.h': 'c',\n '.cpp': 'cpp',\n '.cc': 'cpp',\n '.cxx': 'cpp',\n '.hxx': 'cpp',\n '.hpp': 'cpp',\n '.cs': 'csharp',\n '.php': 'php',\n '.rb': 'ruby',\n '.rake': 'ruby',\n '.swift': 'swift',\n '.kt': 'kotlin',\n '.kts': 'kotlin',\n '.dart': 'dart',\n '.svelte': 'svelte',\n '.pas': 'pascal',\n '.dpr': 'pascal',\n '.dpk': 'pascal',\n '.lpr': 'pascal',\n '.dfm': 'pascal',\n '.fmx': 'pascal',\n '.liquid': 'liquid',\n '.ex': 'elixir',\n '.exs': 'elixir',\n '.scala': 'scala',\n '.sc': 'scala',\n '.sbt': 'scala',\n '.lua': 'lua',\n '.zig': 'zig',\n '.zon': 'zig',\n '.sh': 'bash',\n '.bash': 'bash',\n '.zsh': 'bash',\n '.ml': 'ocaml',\n '.mli': 'ocaml',\n '.elm': 'elm',\n '.sol': 'solidity',\n '.vue': 'vue',\n '.m': 'objc',\n '.yaml': 'yaml',\n '.yml': 'yaml',\n '.tf': 'hcl',\n '.tfvars': 'hcl',\n '.css': 'css',\n '.scss': 'scss',\n '.sass': 'scss',\n '.html': 'html',\n '.htm': 'html',\n '.ipynb': 'jupyter',\n // ReScript\n '.res': 'rescript',\n '.resi': 'rescript',\n // SQL\n '.sql': 'sql',\n // R\n '.r': 'r',\n '.R': 'r',\n // Julia\n '.jl': 'julia',\n // PowerShell\n '.ps1': 'powershell',\n '.psm1': 'powershell',\n '.psd1': 'powershell',\n // Perl\n '.pl': 'perl',\n '.pm': 'perl',\n // Astro\n '.astro': 'astro',\n // GDScript (Godot)\n '.gd': 'gdscript',\n // Nix\n '.nix': 'nix',\n // Verilog / SystemVerilog (.v is Verilog, not Vim script)\n '.v': 'verilog',\n '.sv': 'verilog',\n '.svh': 'verilog',\n};\n\nexport const GRAMMAR_MAP: Record<Language, string> = {\n typescript: 'tree-sitter-typescript',\n tsx: 'tree-sitter-tsx',\n javascript: 'tree-sitter-javascript',\n jsx: 'tree-sitter-javascript',\n python: 'tree-sitter-python',\n go: 'tree-sitter-go',\n rust: 'tree-sitter-rust',\n java: 'tree-sitter-java',\n c: 'tree-sitter-c',\n cpp: 'tree-sitter-cpp',\n csharp: 'tree-sitter-c-sharp',\n php: 'tree-sitter-php',\n ruby: 'tree-sitter-ruby',\n swift: 'tree-sitter-swift',\n kotlin: 'tree-sitter-kotlin',\n dart: 'tree-sitter-dart',\n svelte: 'tree-sitter-svelte',\n elixir: 'tree-sitter-elixir',\n scala: 'tree-sitter-scala',\n lua: 'tree-sitter-lua',\n zig: 'tree-sitter-zig',\n bash: 'tree-sitter-bash',\n ocaml: 'tree-sitter-ocaml',\n elm: 'tree-sitter-elm',\n solidity: 'tree-sitter-solidity',\n vue: 'tree-sitter-vue',\n objc: 'tree-sitter-objc',\n yaml: 'tree-sitter-yaml',\n hcl: 'tree-sitter-hcl',\n css: 'tree-sitter-css',\n scss: 'tree-sitter-scss',\n html: 'tree-sitter-html',\n // Pascal and Liquid require custom WASM not bundled in tree-sitter-wasms\n pascal: '',\n liquid: '',\n // Jupyter notebooks are parsed via the notebook extractor (Python grammar on extracted code cells)\n jupyter: '',\n // ReScript: WASM available in tree-sitter-wasms\n rescript: 'tree-sitter-rescript',\n // Languages with WASMs TBD \u2014 files tracked, symbol extraction pending WASM compilation\n sql: 'tree-sitter-sql',\n r: 'tree-sitter-r',\n julia: 'tree-sitter-julia',\n powershell: 'tree-sitter-powershell',\n perl: 'tree-sitter-perl',\n astro: 'tree-sitter-astro',\n gdscript: 'tree-sitter-gdscript',\n nix: 'tree-sitter-nix',\n verilog: 'tree-sitter-verilog',\n unknown: '',\n};\n\nexport function detectLanguage(filePath: string): Language {\n const ext = filePath.slice(filePath.lastIndexOf('.')).toLowerCase();\n return EXTENSION_MAP[ext] ?? 'unknown';\n}\n\nexport function isSupportedLanguage(lang: Language): boolean {\n // All known languages are \"supported\" for indexing purposes.\n // Pascal and Liquid don't have a grammar WASM, so they'll be indexed\n // with empty symbol lists (file tracked but no AST extraction).\n return lang !== 'unknown';\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAMO,MAAM,gBAA0C;AAAA,EACrD,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,OAAO;AAAA,EACP,SAAS;AAAA,EACT,MAAM;AAAA,EACN,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,SAAS;AAAA,EACT,UAAU;AAAA,EACV,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,WAAW;AAAA,EACX,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,WAAW;AAAA,EACX,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,MAAM;AAAA,EACN,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,WAAW;AAAA,EACX,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,SAAS;AAAA,EACT,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,UAAU;AAAA;AAAA,EAEV,QAAQ;AAAA,EACR,SAAS;AAAA;AAAA,EAET,QAAQ;AAAA;AAAA,EAER,MAAM;AAAA,EACN,MAAM;AAAA;AAAA,EAEN,OAAO;AAAA;AAAA,EAEP,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,SAAS;AAAA;AAAA,EAET,OAAO;AAAA,EACP,OAAO;AAAA;AAAA,EAEP,UAAU;AAAA;AAAA,EAEV,OAAO;AAAA;AAAA,EAEP,QAAQ;AAAA;AAAA,EAER,MAAM;AAAA,EACN,OAAO;AAAA,EACP,QAAQ;AACV;AAEO,MAAM,cAAwC;AAAA,EACnD,YAAY;AAAA,EACZ,KAAK;AAAA,EACL,YAAY;AAAA,EACZ,KAAK;AAAA,EACL,QAAQ;AAAA,EACR,IAAI;AAAA,EACJ,MAAM;AAAA,EACN,MAAM;AAAA,EACN,GAAG;AAAA,EACH,KAAK;AAAA,EACL,QAAQ;AAAA,EACR,KAAK;AAAA,EACL,MAAM;AAAA,EACN,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,KAAK;AAAA,EACL,KAAK;AAAA,EACL,MAAM;AAAA,EACN,OAAO;AAAA,EACP,KAAK;AAAA,EACL,UAAU;AAAA,EACV,KAAK;AAAA,EACL,MAAM;AAAA,EACN,MAAM;AAAA,EACN,KAAK;AAAA,EACL,KAAK;AAAA,EACL,MAAM;AAAA,EACN,MAAM;AAAA;AAAA,EAEN,QAAQ;AAAA,EACR,QAAQ;AAAA;AAAA,EAER,SAAS;AAAA;AAAA,EAET,UAAU;AAAA;AAAA,EAEV,KAAK;AAAA,EACL,GAAG;AAAA,EACH,OAAO;AAAA,EACP,YAAY;AAAA,EACZ,MAAM;AAAA,EACN,OAAO;AAAA,EACP,UAAU;AAAA,EACV,KAAK;AAAA,EACL,SAAS;AAAA,EACT,SAAS;AACX;AAEO,SAAS,eAAe,UAA4B;AACzD,QAAM,MAAM,SAAS,MAAM,SAAS,YAAY,GAAG,CAAC,EAAE,YAAY;AAClE,SAAO,cAAc,GAAG,KAAK;AAC/B;AAEO,SAAS,oBAAoB,MAAyB;AAI3D,SAAO,SAAS;AAClB;",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,300 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+ var notebook_exports = {};
30
+ __export(notebook_exports, {
31
+ extractNotebook: () => extractNotebook
32
+ });
33
+ module.exports = __toCommonJS(notebook_exports);
34
+ var path = __toESM(require("path"));
35
+ var fs = __toESM(require("fs"));
36
+ var crypto = __toESM(require("crypto"));
37
+ var import_extractor = require("./extractor");
38
+ var import_grammars = require("./grammars");
39
+ async function extractNotebook(filePath, projectRoot, content) {
40
+ let raw;
41
+ try {
42
+ if (content !== void 0) {
43
+ raw = typeof content === "string" ? content : content.toString("utf8");
44
+ } else {
45
+ raw = fs.readFileSync(filePath, "utf8");
46
+ }
47
+ } catch {
48
+ return null;
49
+ }
50
+ const contentHash = crypto.createHash("sha256").update(raw).digest("hex");
51
+ const fileSize = Buffer.byteLength(raw, "utf8");
52
+ const relPath = path.relative(projectRoot, filePath).replace(/\\/g, "/");
53
+ let notebook;
54
+ try {
55
+ notebook = JSON.parse(raw);
56
+ } catch {
57
+ return { filePath: relPath, language: "jupyter", contentHash, fileSize, nodes: [], edges: [], unresolvedRefs: [] };
58
+ }
59
+ const cells = notebook.cells ?? [];
60
+ const codeCells = cells.filter((c) => c.cell_type === "code");
61
+ if (codeCells.length === 0) {
62
+ return { filePath: relPath, language: "jupyter", contentHash, fileSize, nodes: [], edges: [], unresolvedRefs: [] };
63
+ }
64
+ const cellOffsets = [];
65
+ const codeChunks = [];
66
+ let currentLine = 1;
67
+ for (let i = 0; i < codeCells.length; i++) {
68
+ const cell = codeCells[i];
69
+ const cellSource = (cell.source ?? []).join("");
70
+ const cellCode = cellSource.endsWith("\n") ? cellSource : cellSource + "\n";
71
+ cellOffsets.push({ startLine: currentLine });
72
+ codeChunks.push(cellCode);
73
+ const cellLineCount = cellCode.split("\n").length - 1;
74
+ currentLine += cellLineCount + (i < codeCells.length - 1 ? 1 : 0);
75
+ }
76
+ const concatenated = codeChunks.join("\n");
77
+ await (0, import_grammars.initGrammars)();
78
+ const parser = await (0, import_grammars.getParser)("python");
79
+ if (!parser) {
80
+ return { filePath: relPath, language: "jupyter", contentHash, fileSize, nodes: [], edges: [], unresolvedRefs: [] };
81
+ }
82
+ const tree = parser.parse(concatenated);
83
+ const nodes = [];
84
+ const edges = [];
85
+ const unresolvedRefs = [];
86
+ const now = Date.now();
87
+ walkPythonTree(tree.rootNode, concatenated, relPath, nodes, edges, unresolvedRefs, now, cellOffsets, codeChunks);
88
+ return { filePath: relPath, language: "jupyter", contentHash, fileSize, nodes, edges, unresolvedRefs };
89
+ }
90
+ const TRANSPARENT_TYPES = /* @__PURE__ */ new Set([
91
+ "export_statement",
92
+ "program",
93
+ "source_file",
94
+ "module",
95
+ "translation_unit"
96
+ ]);
97
+ const PYTHON_IMPORT_TYPES = /* @__PURE__ */ new Set([
98
+ "import_statement",
99
+ "import_from_statement"
100
+ ]);
101
+ const PYTHON_KIND_MAP = {
102
+ function_definition: "function",
103
+ class_definition: "class",
104
+ assignment: "variable"
105
+ };
106
+ const CALL_NODE_TYPES = /* @__PURE__ */ new Set(["call"]);
107
+ function remapLine(lineInConcat, cellOffsets, codeChunks) {
108
+ let cellIdx = 0;
109
+ for (let i = cellOffsets.length - 1; i >= 0; i--) {
110
+ if (lineInConcat >= cellOffsets[i].startLine) {
111
+ cellIdx = i;
112
+ break;
113
+ }
114
+ }
115
+ const posInCell = lineInConcat - cellOffsets[cellIdx].startLine;
116
+ return cellOffsets[cellIdx].startLine + posInCell;
117
+ }
118
+ function walkPythonTree(node, source, filePath, nodes, edges, unresolvedRefs, now, cellOffsets, codeChunks, parentId) {
119
+ if (TRANSPARENT_TYPES.has(node.type)) {
120
+ for (let i = 0; i < node.childCount; i++) {
121
+ walkPythonTree(node.child(i), source, filePath, nodes, edges, unresolvedRefs, now, cellOffsets, codeChunks, parentId);
122
+ }
123
+ return;
124
+ }
125
+ if (PYTHON_IMPORT_TYPES.has(node.type)) {
126
+ const modulePath = extractPythonImportSource(node, source);
127
+ if (modulePath) {
128
+ const rawLine = node.startPosition.row + 1;
129
+ const line = remapLine(rawLine, cellOffsets, codeChunks);
130
+ const id = (0, import_extractor.makeNodeId)(filePath, "import", modulePath, line);
131
+ nodes.push({
132
+ id,
133
+ kind: "import",
134
+ name: modulePath,
135
+ qualifiedName: `${filePath}::import:${modulePath}`,
136
+ filePath,
137
+ language: "jupyter",
138
+ startLine: line,
139
+ endLine: remapLine(node.endPosition.row + 1, cellOffsets, codeChunks),
140
+ startColumn: node.startPosition.column,
141
+ endColumn: node.endPosition.column,
142
+ updatedAt: now
143
+ });
144
+ unresolvedRefs.push({ sourceId: id, refName: modulePath, refKind: "import", line, column: node.startPosition.column });
145
+ }
146
+ return;
147
+ }
148
+ let kind = PYTHON_KIND_MAP[node.type] ?? null;
149
+ if (kind) {
150
+ const name = extractPythonName(node, source, kind);
151
+ if (name) {
152
+ const rawStartLine = node.startPosition.row + 1;
153
+ const rawEndLine = node.endPosition.row + 1;
154
+ const startLine = remapLine(rawStartLine, cellOffsets, codeChunks);
155
+ const endLine = remapLine(rawEndLine, cellOffsets, codeChunks);
156
+ const id = (0, import_extractor.makeNodeId)(filePath, kind, name, startLine);
157
+ const visibility = extractPythonVisibility(name);
158
+ const graphNode = {
159
+ id,
160
+ kind,
161
+ name,
162
+ qualifiedName: `${filePath}::${name}`,
163
+ filePath,
164
+ language: "jupyter",
165
+ startLine,
166
+ endLine,
167
+ startColumn: node.startPosition.column,
168
+ endColumn: node.endPosition.column,
169
+ docstring: extractPythonDocstring(node, source),
170
+ signature: extractPythonSignature(node, source, kind),
171
+ visibility,
172
+ isExported: false,
173
+ updatedAt: now
174
+ };
175
+ nodes.push(graphNode);
176
+ if (parentId) {
177
+ edges.push({ source: parentId, target: id, kind: "contains" });
178
+ }
179
+ collectPythonCallRefs(node, source, id, unresolvedRefs, cellOffsets, codeChunks);
180
+ for (let i = 0; i < node.childCount; i++) {
181
+ walkPythonTree(node.child(i), source, filePath, nodes, edges, unresolvedRefs, now, cellOffsets, codeChunks, id);
182
+ }
183
+ return;
184
+ }
185
+ }
186
+ for (let i = 0; i < node.childCount; i++) {
187
+ walkPythonTree(node.child(i), source, filePath, nodes, edges, unresolvedRefs, now, cellOffsets, codeChunks, parentId);
188
+ }
189
+ }
190
+ function extractPythonImportSource(node, source) {
191
+ if (node.type === "import_from_statement") {
192
+ for (let i = 0; i < node.childCount; i++) {
193
+ const child = node.child(i);
194
+ if (child.type === "dotted_name" || child.type === "relative_import") {
195
+ return source.slice(child.startIndex, child.endIndex);
196
+ }
197
+ }
198
+ }
199
+ if (node.type === "import_statement") {
200
+ for (let i = 0; i < node.childCount; i++) {
201
+ const child = node.child(i);
202
+ if (child.type === "dotted_name") {
203
+ return source.slice(child.startIndex, child.endIndex);
204
+ }
205
+ }
206
+ }
207
+ return null;
208
+ }
209
+ function extractPythonName(node, source, kind) {
210
+ if (kind === "variable" && node.type === "assignment") {
211
+ const left = node.child(0);
212
+ if (left && left.type === "identifier") {
213
+ return source.slice(left.startIndex, left.endIndex);
214
+ }
215
+ return null;
216
+ }
217
+ for (let i = 0; i < node.childCount; i++) {
218
+ const child = node.child(i);
219
+ if (child.type === "identifier") {
220
+ return source.slice(child.startIndex, child.endIndex);
221
+ }
222
+ }
223
+ return null;
224
+ }
225
+ function extractPythonVisibility(name) {
226
+ if (name.startsWith("__")) return "private";
227
+ if (name.startsWith("_")) return "protected";
228
+ return "public";
229
+ }
230
+ function extractPythonDocstring(node, source) {
231
+ const commentTypes = /* @__PURE__ */ new Set(["comment"]);
232
+ const commentLines = [];
233
+ let sibling = node.previousNamedSibling;
234
+ while (sibling && commentTypes.has(sibling.type)) {
235
+ commentLines.unshift(source.slice(sibling.startIndex, sibling.endIndex));
236
+ sibling = sibling.previousNamedSibling;
237
+ }
238
+ if (commentLines.length === 0) return void 0;
239
+ const cleaned = commentLines.join("\n").replace(/^#\s?/gm, "").trim();
240
+ return cleaned.length > 0 ? cleaned : void 0;
241
+ }
242
+ function extractPythonSignature(node, source, kind) {
243
+ if (kind === "function" || kind === "method") {
244
+ const text2 = source.slice(node.startIndex, node.endIndex);
245
+ const bodyStart = text2.search(/\s*:\s*\n/);
246
+ const header = bodyStart > 0 ? text2.slice(0, bodyStart).trim() : text2.split("\n")[0].trim();
247
+ return header.length > 150 ? header.slice(0, 150) + "\u2026" : header || void 0;
248
+ }
249
+ const text = source.slice(node.startIndex, node.endIndex);
250
+ const firstLine = text.split("\n")[0].trim();
251
+ return firstLine.length > 120 ? firstLine.slice(0, 120) + "\u2026" : firstLine || void 0;
252
+ }
253
+ function collectPythonCallRefs(node, source, sourceId, unresolvedRefs, cellOffsets, codeChunks) {
254
+ walkForPythonCalls(node, source, sourceId, unresolvedRefs, cellOffsets, codeChunks);
255
+ }
256
+ function walkForPythonCalls(node, source, sourceId, unresolvedRefs, cellOffsets, codeChunks) {
257
+ if (CALL_NODE_TYPES.has(node.type)) {
258
+ const calleeName = extractPythonCallName(node, source);
259
+ if (calleeName) {
260
+ const rawLine = node.startPosition.row + 1;
261
+ const line = remapLine(rawLine, cellOffsets, codeChunks);
262
+ unresolvedRefs.push({
263
+ sourceId,
264
+ refName: calleeName,
265
+ refKind: "function",
266
+ line,
267
+ column: node.startPosition.column
268
+ });
269
+ }
270
+ }
271
+ for (let i = 0; i < node.childCount; i++) {
272
+ walkForPythonCalls(node.child(i), source, sourceId, unresolvedRefs, cellOffsets, codeChunks);
273
+ }
274
+ }
275
+ function extractPythonCallName(node, source) {
276
+ for (const field of ["function", "method"]) {
277
+ const f = node.childForFieldName?.(field);
278
+ if (f) {
279
+ const t = f.type;
280
+ if (t === "identifier" || t === "name") {
281
+ const text = source.slice(f.startIndex, f.endIndex).trim();
282
+ if (text && /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(text)) return text;
283
+ }
284
+ }
285
+ }
286
+ const funcNode = node.child(0);
287
+ if (funcNode) {
288
+ const rawName = source.slice(funcNode.startIndex, funcNode.endIndex).split("(")[0].trim();
289
+ if (rawName && rawName.length < 100) {
290
+ const calleeName = rawName.split(".").pop().trim();
291
+ if (calleeName && /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(calleeName)) return calleeName;
292
+ }
293
+ }
294
+ return null;
295
+ }
296
+ // Annotate the CommonJS export names for ESM import in node:
297
+ 0 && (module.exports = {
298
+ extractNotebook
299
+ });
300
+ //# sourceMappingURL=notebook.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/extraction/notebook.ts"],
4
+ "sourcesContent": ["/**\n * Notebook extractor for Jupyter (.ipynb) files.\n * Parses the JSON notebook format, extracts code cells, concatenates them,\n * runs the Python tree-sitter parser, and adjusts line numbers so they\n * reflect the position of each cell within the notebook.\n */\n\nimport * as path from 'path';\nimport * as fs from 'fs';\nimport * as crypto from 'crypto';\nimport type { Node, Edge } from '../types';\nimport type { ExtractedFile, UnresolvedRef } from './extractor';\nimport { makeNodeId } from './extractor';\nimport { initGrammars, getParser } from './grammars';\n\ninterface NotebookCell {\n cell_type: string;\n source: string[];\n}\n\ninterface NotebookMetadata {\n kernelspec?: { language?: string };\n language_info?: { name?: string };\n}\n\ninterface NotebookJson {\n metadata?: NotebookMetadata;\n cells?: NotebookCell[];\n}\n\n/** Each code cell mapped to its starting line in the concatenated source */\ninterface CellOffset {\n /** 1-based starting line of this cell in the concatenated code string */\n startLine: number;\n}\n\n/**\n * Extract symbols from a Jupyter notebook file.\n * Concatenates all code cells, parses with the Python grammar,\n * and adjusts node line numbers to match cell positions.\n */\nexport async function extractNotebook(\n filePath: string,\n projectRoot: string,\n content?: Buffer | string\n): Promise<ExtractedFile | null> {\n let raw: string;\n try {\n if (content !== undefined) {\n raw = typeof content === 'string' ? content : content.toString('utf8');\n } else {\n raw = fs.readFileSync(filePath, 'utf8');\n }\n } catch {\n return null;\n }\n\n const contentHash = crypto.createHash('sha256').update(raw).digest('hex');\n const fileSize = Buffer.byteLength(raw, 'utf8');\n const relPath = path.relative(projectRoot, filePath).replace(/\\\\/g, '/');\n\n let notebook: NotebookJson;\n try {\n notebook = JSON.parse(raw);\n } catch {\n // Not valid JSON \u2014 return file tracked with no symbols\n return { filePath: relPath, language: 'jupyter', contentHash, fileSize, nodes: [], edges: [], unresolvedRefs: [] };\n }\n\n const cells: NotebookCell[] = notebook.cells ?? [];\n const codeCells = cells.filter((c) => c.cell_type === 'code');\n\n if (codeCells.length === 0) {\n return { filePath: relPath, language: 'jupyter', contentHash, fileSize, nodes: [], edges: [], unresolvedRefs: [] };\n }\n\n // Build concatenated source and track the starting line of each cell\n const cellOffsets: CellOffset[] = [];\n const codeChunks: string[] = [];\n let currentLine = 1; // 1-based\n\n for (let i = 0; i < codeCells.length; i++) {\n const cell = codeCells[i];\n const cellSource = (cell.source ?? []).join('');\n // Ensure each cell ends with a newline so cells don't bleed into each other\n const cellCode = cellSource.endsWith('\\n') ? cellSource : cellSource + '\\n';\n cellOffsets.push({ startLine: currentLine });\n codeChunks.push(cellCode);\n // Number of lines contributed by this cell's code\n const cellLineCount = cellCode.split('\\n').length - 1; // trailing \\n creates empty last entry\n // Advance by cell lines; join('\\n') adds one extra separator line between cells\n currentLine += cellLineCount + (i < codeCells.length - 1 ? 1 : 0);\n }\n\n const concatenated = codeChunks.join('\\n');\n\n // Load Python parser and parse concatenated source\n await initGrammars();\n const parser = await getParser('python');\n if (!parser) {\n // Python grammar unavailable \u2014 return file node with no symbols\n return { filePath: relPath, language: 'jupyter', contentHash, fileSize, nodes: [], edges: [], unresolvedRefs: [] };\n }\n\n const tree = parser.parse(concatenated);\n\n const nodes: Node[] = [];\n const edges: Edge[] = [];\n const unresolvedRefs: UnresolvedRef[] = [];\n const now = Date.now();\n\n // We reuse the same AST walking logic from extractor.ts but with 'python' language.\n // Import walkTree-equivalent logic inline to avoid circular imports by using the\n // exported makeNodeId and reimporting the walk from extractor indirectly.\n // Instead, we call extractFile on the concatenated source as a virtual Python file\n // and then remap file paths and languages back.\n //\n // To avoid code duplication we use a direct re-export path: import the internal\n // walkTree equivalent by parsing via a private helper below.\n\n walkPythonTree(tree.rootNode, concatenated, relPath, nodes, edges, unresolvedRefs, now, cellOffsets, codeChunks);\n\n return { filePath: relPath, language: 'jupyter', contentHash, fileSize, nodes, edges, unresolvedRefs };\n}\n\n// \u2500\u2500 Transparent node types (same as extractor.ts) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nconst TRANSPARENT_TYPES = new Set([\n 'export_statement', 'program', 'source_file', 'module', 'translation_unit',\n]);\n\n// \u2500\u2500 Import node types relevant to Python \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nconst PYTHON_IMPORT_TYPES = new Set([\n 'import_statement',\n 'import_from_statement',\n]);\n\n// \u2500\u2500 KIND_MAP subset for Python \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\ntype NodeKindLocal = Node['kind'];\n\nconst PYTHON_KIND_MAP: Record<string, NodeKindLocal> = {\n function_definition: 'function',\n class_definition: 'class',\n assignment: 'variable',\n};\n\n// \u2500\u2500 CALL_NODE_TYPES for Python \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nconst CALL_NODE_TYPES = new Set(['call']);\n\n// \u2500\u2500 Line offset helper \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Given a 1-based line number within the concatenated source, return the\n * corrected 1-based line number relative to the notebook.\n *\n * The concatenated source is built as:\n * cell[0]\\n cell[1]\\n cell[2]\\n ...\n * where cell[i] starts at cellOffsets[i].startLine (1-based) within the concatenation.\n *\n * Each cell chunk in codeChunks already ends with \\n; cells are separated by an\n * extra \\n (the join('\\n') adds one extra newline between chunks).\n *\n * We build a lookup of the absolute start lines in the concatenated string by\n * re-counting: cell 0 starts at line 1; cell 1 starts at line (lines-in-cell-0 + 1 + 1),\n * etc. (The +1 accounts for the join separator).\n *\n * For simplicity we use the pre-computed cellOffsets directly \u2014 they track the\n * cumulative line position in the concatenated string at each cell boundary.\n */\nfunction remapLine(lineInConcat: number, cellOffsets: CellOffset[], codeChunks: string[]): number {\n // cellOffsets[i].startLine is the 1-based line of cell i in the concatenated string\n // (built with join('\\n') which adds +1 separator line between cells).\n // We need to find which cell this line belongs to.\n //\n // Rebuild absolute offsets accounting for the '\\n' separator added by join:\n // cell 0: lines [offset0, offset0 + cellLines0 - 1]\n // separator line: offset0 + cellLines0\n // cell 1: offset0 + cellLines0 + 1\n // etc.\n //\n // cellOffsets already accounts for this (built with currentLine += cellLines + 1\n // because codeChunks.join('\\n') adds a newline between chunks).\n\n let cellIdx = 0;\n for (let i = cellOffsets.length - 1; i >= 0; i--) {\n if (lineInConcat >= cellOffsets[i].startLine) {\n cellIdx = i;\n break;\n }\n }\n // Position within the cell (0-based)\n const posInCell = lineInConcat - cellOffsets[cellIdx].startLine;\n // Return 1-based position within notebook (cell starts at cellOffsets[cellIdx].startLine\n // which IS the 1-based line in the notebook for cell 0 = line 1)\n return cellOffsets[cellIdx].startLine + posInCell;\n}\n\n// \u2500\u2500 Python-specific AST walker \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction walkPythonTree(\n node: any,\n source: string,\n filePath: string,\n nodes: Node[],\n edges: Edge[],\n unresolvedRefs: UnresolvedRef[],\n now: number,\n cellOffsets: CellOffset[],\n codeChunks: string[],\n parentId?: string\n): void {\n if (TRANSPARENT_TYPES.has(node.type)) {\n for (let i = 0; i < node.childCount; i++) {\n walkPythonTree(node.child(i), source, filePath, nodes, edges, unresolvedRefs, now, cellOffsets, codeChunks, parentId);\n }\n return;\n }\n\n if (PYTHON_IMPORT_TYPES.has(node.type)) {\n const modulePath = extractPythonImportSource(node, source);\n if (modulePath) {\n const rawLine = node.startPosition.row + 1;\n const line = remapLine(rawLine, cellOffsets, codeChunks);\n const id = makeNodeId(filePath, 'import', modulePath, line);\n nodes.push({\n id,\n kind: 'import',\n name: modulePath,\n qualifiedName: `${filePath}::import:${modulePath}`,\n filePath,\n language: 'jupyter',\n startLine: line,\n endLine: remapLine(node.endPosition.row + 1, cellOffsets, codeChunks),\n startColumn: node.startPosition.column,\n endColumn: node.endPosition.column,\n updatedAt: now,\n });\n unresolvedRefs.push({ sourceId: id, refName: modulePath, refKind: 'import', line, column: node.startPosition.column });\n }\n return;\n }\n\n let kind: NodeKindLocal | null = PYTHON_KIND_MAP[node.type] ?? null;\n\n if (kind) {\n const name = extractPythonName(node, source, kind);\n if (name) {\n const rawStartLine = node.startPosition.row + 1;\n const rawEndLine = node.endPosition.row + 1;\n const startLine = remapLine(rawStartLine, cellOffsets, codeChunks);\n const endLine = remapLine(rawEndLine, cellOffsets, codeChunks);\n const id = makeNodeId(filePath, kind, name, startLine);\n const visibility = extractPythonVisibility(name);\n\n const graphNode: Node = {\n id,\n kind,\n name,\n qualifiedName: `${filePath}::${name}`,\n filePath,\n language: 'jupyter',\n startLine,\n endLine,\n startColumn: node.startPosition.column,\n endColumn: node.endPosition.column,\n docstring: extractPythonDocstring(node, source),\n signature: extractPythonSignature(node, source, kind),\n visibility,\n isExported: false,\n updatedAt: now,\n };\n nodes.push(graphNode);\n\n if (parentId) {\n edges.push({ source: parentId, target: id, kind: 'contains' });\n }\n\n collectPythonCallRefs(node, source, id, unresolvedRefs, cellOffsets, codeChunks);\n\n for (let i = 0; i < node.childCount; i++) {\n walkPythonTree(node.child(i), source, filePath, nodes, edges, unresolvedRefs, now, cellOffsets, codeChunks, id);\n }\n return;\n }\n }\n\n for (let i = 0; i < node.childCount; i++) {\n walkPythonTree(node.child(i), source, filePath, nodes, edges, unresolvedRefs, now, cellOffsets, codeChunks, parentId);\n }\n}\n\n// \u2500\u2500 Python helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction extractPythonImportSource(node: any, source: string): string | null {\n if (node.type === 'import_from_statement') {\n for (let i = 0; i < node.childCount; i++) {\n const child = node.child(i);\n if (child.type === 'dotted_name' || child.type === 'relative_import') {\n return source.slice(child.startIndex, child.endIndex);\n }\n }\n }\n if (node.type === 'import_statement') {\n for (let i = 0; i < node.childCount; i++) {\n const child = node.child(i);\n if (child.type === 'dotted_name') {\n return source.slice(child.startIndex, child.endIndex);\n }\n }\n }\n return null;\n}\n\nfunction extractPythonName(node: any, source: string, kind: NodeKindLocal): string | null {\n if (kind === 'variable' && node.type === 'assignment') {\n const left = node.child(0);\n if (left && left.type === 'identifier') {\n return source.slice(left.startIndex, left.endIndex);\n }\n return null;\n }\n for (let i = 0; i < node.childCount; i++) {\n const child = node.child(i);\n if (child.type === 'identifier') {\n return source.slice(child.startIndex, child.endIndex);\n }\n }\n return null;\n}\n\nfunction extractPythonVisibility(name: string): Node['visibility'] {\n if (name.startsWith('__')) return 'private';\n if (name.startsWith('_')) return 'protected';\n return 'public';\n}\n\nfunction extractPythonDocstring(node: any, source: string): string | undefined {\n const commentTypes = new Set(['comment']);\n const commentLines: string[] = [];\n let sibling = node.previousNamedSibling;\n while (sibling && commentTypes.has(sibling.type)) {\n commentLines.unshift(source.slice(sibling.startIndex, sibling.endIndex));\n sibling = sibling.previousNamedSibling;\n }\n if (commentLines.length === 0) return undefined;\n const cleaned = commentLines.join('\\n').replace(/^#\\s?/gm, '').trim();\n return cleaned.length > 0 ? cleaned : undefined;\n}\n\nfunction extractPythonSignature(node: any, source: string, kind: NodeKindLocal): string | undefined {\n if (kind === 'function' || kind === 'method') {\n const text = source.slice(node.startIndex, node.endIndex);\n const bodyStart = text.search(/\\s*:\\s*\\n/);\n const header = bodyStart > 0 ? text.slice(0, bodyStart).trim() : text.split('\\n')[0].trim();\n return header.length > 150 ? header.slice(0, 150) + '\u2026' : header || undefined;\n }\n const text = source.slice(node.startIndex, node.endIndex);\n const firstLine = text.split('\\n')[0].trim();\n return firstLine.length > 120 ? firstLine.slice(0, 120) + '\u2026' : firstLine || undefined;\n}\n\nfunction collectPythonCallRefs(\n node: any,\n source: string,\n sourceId: string,\n unresolvedRefs: UnresolvedRef[],\n cellOffsets: CellOffset[],\n codeChunks: string[]\n): void {\n walkForPythonCalls(node, source, sourceId, unresolvedRefs, cellOffsets, codeChunks);\n}\n\nfunction walkForPythonCalls(\n node: any,\n source: string,\n sourceId: string,\n unresolvedRefs: UnresolvedRef[],\n cellOffsets: CellOffset[],\n codeChunks: string[]\n): void {\n if (CALL_NODE_TYPES.has(node.type)) {\n const calleeName = extractPythonCallName(node, source);\n if (calleeName) {\n const rawLine = node.startPosition.row + 1;\n const line = remapLine(rawLine, cellOffsets, codeChunks);\n unresolvedRefs.push({\n sourceId,\n refName: calleeName,\n refKind: 'function',\n line,\n column: node.startPosition.column,\n });\n }\n }\n for (let i = 0; i < node.childCount; i++) {\n walkForPythonCalls(node.child(i), source, sourceId, unresolvedRefs, cellOffsets, codeChunks);\n }\n}\n\nfunction extractPythonCallName(node: any, source: string): string | null {\n for (const field of ['function', 'method']) {\n const f = node.childForFieldName?.(field);\n if (f) {\n const t = f.type;\n if (t === 'identifier' || t === 'name') {\n const text = source.slice(f.startIndex, f.endIndex).trim();\n if (text && /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(text)) return text;\n }\n }\n }\n const funcNode = node.child(0);\n if (funcNode) {\n const rawName = source.slice(funcNode.startIndex, funcNode.endIndex).split('(')[0].trim();\n if (rawName && rawName.length < 100) {\n const calleeName = rawName.split('.').pop()!.trim();\n if (calleeName && /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(calleeName)) return calleeName;\n }\n }\n return null;\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["text"]
7
+ }
@@ -0,0 +1,130 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var flutter_exports = {};
20
+ __export(flutter_exports, {
21
+ flutterResolver: () => flutterResolver
22
+ });
23
+ module.exports = __toCommonJS(flutter_exports);
24
+ const flutterResolver = {
25
+ name: "flutter",
26
+ detect(context) {
27
+ const pubspec = context.readFile("pubspec.yaml");
28
+ if (pubspec) {
29
+ if (pubspec.includes("flutter:") || pubspec.includes("flutter_hooks:") || pubspec.includes("flutter_riverpod:")) {
30
+ return true;
31
+ }
32
+ }
33
+ for (const file of context.getAllFiles()) {
34
+ if (file.startsWith("lib/") && file.endsWith(".dart")) return true;
35
+ }
36
+ return false;
37
+ },
38
+ resolve(ref, context) {
39
+ if (/(?:Page|Screen|View|Widget)$/.test(ref.referenceName) && /^[A-Z]/.test(ref.referenceName)) {
40
+ for (const file of context.getAllFiles()) {
41
+ if (!file.endsWith(".dart")) continue;
42
+ const node = context.getNodesInFile(file).find(
43
+ (n) => n.name === ref.referenceName && (n.kind === "component" || n.kind === "class")
44
+ );
45
+ if (node) return { original: ref, targetNodeId: node.id, confidence: 0.8, resolvedBy: "framework" };
46
+ }
47
+ }
48
+ return null;
49
+ },
50
+ extractNodes(filePath, content) {
51
+ if (!filePath.endsWith(".dart")) return [];
52
+ const nodes = [];
53
+ const now = Date.now();
54
+ const materialRoutesPattern = /routes\s*:\s*\{([^}]+)\}/gs;
55
+ let routesBlock;
56
+ while ((routesBlock = materialRoutesPattern.exec(content)) !== null) {
57
+ const block = routesBlock[1];
58
+ const entryPattern = /['"]([^'"]+)['"]\s*:/g;
59
+ let entry;
60
+ while ((entry = entryPattern.exec(block)) !== null) {
61
+ const routePath = entry[1];
62
+ const line = content.slice(0, routesBlock.index).split("\n").length;
63
+ nodes.push({
64
+ id: `route:${filePath}:${routePath}:${line}`,
65
+ kind: "route",
66
+ name: routePath,
67
+ qualifiedName: `${filePath}::route:${routePath}`,
68
+ filePath,
69
+ startLine: line,
70
+ endLine: line,
71
+ startColumn: 0,
72
+ endColumn: entry[0].length,
73
+ language: "dart",
74
+ updatedAt: now
75
+ });
76
+ }
77
+ }
78
+ const goRoutePattern = /GoRoute\s*\([^)]*path\s*:\s*['"]([^'"]+)['"]/g;
79
+ let goMatch;
80
+ while ((goMatch = goRoutePattern.exec(content)) !== null) {
81
+ const routePath = goMatch[1];
82
+ const line = content.slice(0, goMatch.index).split("\n").length;
83
+ const id = `route:${filePath}:${routePath}:${line}`;
84
+ if (!nodes.some((n) => n.id === id)) {
85
+ nodes.push({
86
+ id,
87
+ kind: "route",
88
+ name: routePath,
89
+ qualifiedName: `${filePath}::route:${routePath}`,
90
+ filePath,
91
+ startLine: line,
92
+ endLine: line,
93
+ startColumn: 0,
94
+ endColumn: goMatch[0].length,
95
+ language: "dart",
96
+ updatedAt: now
97
+ });
98
+ }
99
+ }
100
+ const autoRoutePattern = /@RoutePage\(\s*\)\s*\n(?:\s*\n)*\s*class\s+(\w+)/g;
101
+ let autoMatch;
102
+ while ((autoMatch = autoRoutePattern.exec(content)) !== null) {
103
+ const widgetName = autoMatch[1];
104
+ const line = content.slice(0, autoMatch.index).split("\n").length;
105
+ const routePath = "/" + widgetName.replace(/(?:Page|Screen|View)$/, "").replace(/([A-Z])/g, (_, c, i) => (i > 0 ? "-" : "") + c.toLowerCase());
106
+ const id = `route:${filePath}:${routePath}:${line}`;
107
+ if (!nodes.some((n) => n.id === id)) {
108
+ nodes.push({
109
+ id,
110
+ kind: "route",
111
+ name: routePath,
112
+ qualifiedName: `${filePath}::route:${routePath}`,
113
+ filePath,
114
+ startLine: line,
115
+ endLine: line,
116
+ startColumn: 0,
117
+ endColumn: autoMatch[0].length,
118
+ language: "dart",
119
+ updatedAt: now
120
+ });
121
+ }
122
+ }
123
+ return nodes;
124
+ }
125
+ };
126
+ // Annotate the CommonJS export names for ESM import in node:
127
+ 0 && (module.exports = {
128
+ flutterResolver
129
+ });
130
+ //# sourceMappingURL=flutter.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/frameworks/flutter.ts"],
4
+ "sourcesContent": ["/**\n * Flutter Framework Resolver\n *\n * Detects Flutter projects and extracts route nodes from:\n * - MaterialApp(routes: {'/path': (ctx) => MyPage()})\n * - MaterialApp.router(routerConfig: GoRouter(...))\n * - GoRouter(routes: [GoRoute(path: '/path', builder: ...)])\n * - AutoRoute annotations: @RoutePage() on widget classes\n */\n\nimport type { Node } from '../types';\nimport type { FrameworkResolver, UnresolvedRef, ResolvedRef, ResolutionContext } from './types';\n\nexport const flutterResolver: FrameworkResolver = {\n name: 'flutter',\n\n detect(context: ResolutionContext): boolean {\n // Primary signal: pubspec.yaml with a flutter dependency/section\n const pubspec = context.readFile('pubspec.yaml');\n if (pubspec) {\n if (pubspec.includes('flutter:') || pubspec.includes('flutter_hooks:') || pubspec.includes('flutter_riverpod:')) {\n return true;\n }\n }\n // Secondary signal: lib/ directory contains .dart files\n for (const file of context.getAllFiles()) {\n if (file.startsWith('lib/') && file.endsWith('.dart')) return true;\n }\n return false;\n },\n\n resolve(ref: UnresolvedRef, context: ResolutionContext): ResolvedRef | null {\n // Resolve widget references (names ending with Page, Screen, View, Widget)\n if (/(?:Page|Screen|View|Widget)$/.test(ref.referenceName) && /^[A-Z]/.test(ref.referenceName)) {\n for (const file of context.getAllFiles()) {\n if (!file.endsWith('.dart')) continue;\n const node = context.getNodesInFile(file).find(\n n => n.name === ref.referenceName && (n.kind === 'component' || n.kind === 'class')\n );\n if (node) return { original: ref, targetNodeId: node.id, confidence: 0.8, resolvedBy: 'framework' };\n }\n }\n return null;\n },\n\n extractNodes(filePath: string, content: string): Node[] {\n if (!filePath.endsWith('.dart')) return [];\n const nodes: Node[] = [];\n const now = Date.now();\n\n // 1. MaterialApp static routes map: '/path': (ctx) => WidgetName()\n const materialRoutesPattern = /routes\\s*:\\s*\\{([^}]+)\\}/gs;\n let routesBlock: RegExpExecArray | null;\n while ((routesBlock = materialRoutesPattern.exec(content)) !== null) {\n const block = routesBlock[1]!;\n const entryPattern = /['\"]([^'\"]+)['\"]\\s*:/g;\n let entry: RegExpExecArray | null;\n while ((entry = entryPattern.exec(block)) !== null) {\n const routePath = entry[1]!;\n const line = content.slice(0, routesBlock.index).split('\\n').length;\n nodes.push({\n id: `route:${filePath}:${routePath}:${line}`,\n kind: 'route',\n name: routePath,\n qualifiedName: `${filePath}::route:${routePath}`,\n filePath,\n startLine: line,\n endLine: line,\n startColumn: 0,\n endColumn: entry[0].length,\n language: 'dart',\n updatedAt: now,\n });\n }\n }\n\n // 2. GoRouter GoRoute(path: '/path', ...) declarations\n const goRoutePattern = /GoRoute\\s*\\([^)]*path\\s*:\\s*['\"]([^'\"]+)['\"]/g;\n let goMatch: RegExpExecArray | null;\n while ((goMatch = goRoutePattern.exec(content)) !== null) {\n const routePath = goMatch[1]!;\n const line = content.slice(0, goMatch.index).split('\\n').length;\n // Avoid duplicates from the routes:{} pass above\n const id = `route:${filePath}:${routePath}:${line}`;\n if (!nodes.some(n => n.id === id)) {\n nodes.push({\n id,\n kind: 'route',\n name: routePath,\n qualifiedName: `${filePath}::route:${routePath}`,\n filePath,\n startLine: line,\n endLine: line,\n startColumn: 0,\n endColumn: goMatch[0].length,\n language: 'dart',\n updatedAt: now,\n });\n }\n }\n\n // 3. AutoRoute @RoutePage() annotation \u2014 mark the annotated class as a routed page\n const autoRoutePattern = /@RoutePage\\(\\s*\\)\\s*\\n(?:\\s*\\n)*\\s*class\\s+(\\w+)/g;\n let autoMatch: RegExpExecArray | null;\n while ((autoMatch = autoRoutePattern.exec(content)) !== null) {\n const widgetName = autoMatch[1]!;\n const line = content.slice(0, autoMatch.index).split('\\n').length;\n // Derive a conventional route path from the class name (e.g. LoginPage \u2192 /login)\n const routePath = '/' + widgetName.replace(/(?:Page|Screen|View)$/, '').replace(/([A-Z])/g, (_, c, i) => (i > 0 ? '-' : '') + c.toLowerCase());\n const id = `route:${filePath}:${routePath}:${line}`;\n if (!nodes.some(n => n.id === id)) {\n nodes.push({\n id,\n kind: 'route',\n name: routePath,\n qualifiedName: `${filePath}::route:${routePath}`,\n filePath,\n startLine: line,\n endLine: line,\n startColumn: 0,\n endColumn: autoMatch[0].length,\n language: 'dart',\n updatedAt: now,\n });\n }\n }\n\n return nodes;\n },\n};\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -41,6 +41,7 @@ __export(frameworks_exports, {
41
41
  expressResolver: () => import_express.expressResolver,
42
42
  fastapiResolver: () => import_python.fastapiResolver,
43
43
  flaskResolver: () => import_python.flaskResolver,
44
+ flutterResolver: () => import_flutter.flutterResolver,
44
45
  getAllFrameworkResolvers: () => getAllFrameworkResolvers,
45
46
  getFrameworkResolver: () => getFrameworkResolver,
46
47
  goResolver: () => import_go.goResolver,
@@ -95,6 +96,7 @@ var import_docker = require("./docker");
95
96
  var import_ansible = require("./ansible");
96
97
  var import_angular = require("./angular");
97
98
  var import_amplify = require("./amplify");
99
+ var import_flutter = require("./flutter");
98
100
  var import_react2 = require("./react");
99
101
  var import_svelte2 = require("./svelte");
100
102
  var import_express2 = require("./express");
@@ -119,6 +121,7 @@ var import_docker2 = require("./docker");
119
121
  var import_ansible2 = require("./ansible");
120
122
  var import_angular2 = require("./angular");
121
123
  var import_amplify2 = require("./amplify");
124
+ var import_flutter2 = require("./flutter");
122
125
  const FRAMEWORK_RESOLVERS = [
123
126
  // PHP
124
127
  import_laravel2.laravelResolver,
@@ -167,7 +170,9 @@ const FRAMEWORK_RESOLVERS = [
167
170
  import_kubernetes2.kubernetesResolver,
168
171
  import_docker2.dockerComposeResolver,
169
172
  // Configuration Management
170
- import_ansible2.ansibleResolver
173
+ import_ansible2.ansibleResolver,
174
+ // Dart / Flutter
175
+ import_flutter2.flutterResolver
171
176
  ];
172
177
  function getAllFrameworkResolvers() {
173
178
  return FRAMEWORK_RESOLVERS;
@@ -293,6 +298,7 @@ async function detectFromPackageJson(projectRoot) {
293
298
  expressResolver,
294
299
  fastapiResolver,
295
300
  flaskResolver,
301
+ flutterResolver,
296
302
  getAllFrameworkResolvers,
297
303
  getFrameworkResolver,
298
304
  goResolver,