cg-code-graph 0.10.1__py3-none-any.whl

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 (174) hide show
  1. cg_code_graph-0.10.1.dist-info/METADATA +678 -0
  2. cg_code_graph-0.10.1.dist-info/RECORD +174 -0
  3. cg_code_graph-0.10.1.dist-info/WHEEL +5 -0
  4. cg_code_graph-0.10.1.dist-info/entry_points.txt +3 -0
  5. cg_code_graph-0.10.1.dist-info/licenses/LICENSE +21 -0
  6. cg_code_graph-0.10.1.dist-info/top_level.txt +1 -0
  7. codegraph/__init__.py +2 -0
  8. codegraph/aitools.py +129 -0
  9. codegraph/apps.py +76 -0
  10. codegraph/blindspots.py +428 -0
  11. codegraph/bridges.py +1701 -0
  12. codegraph/cli.py +725 -0
  13. codegraph/concepts.py +362 -0
  14. codegraph/config.py +559 -0
  15. codegraph/core/__init__.py +0 -0
  16. codegraph/core/cache.py +375 -0
  17. codegraph/core/detect.py +80 -0
  18. codegraph/core/extractors.py +187 -0
  19. codegraph/core/fsutil.py +61 -0
  20. codegraph/core/generated.py +575 -0
  21. codegraph/core/model.py +174 -0
  22. codegraph/core/paths.py +175 -0
  23. codegraph/core/plugin.py +160 -0
  24. codegraph/core/store.py +80 -0
  25. codegraph/core/syntax_errors.py +132 -0
  26. codegraph/coverage.py +928 -0
  27. codegraph/doctor.py +453 -0
  28. codegraph/external.py +613 -0
  29. codegraph/indexer.py +336 -0
  30. codegraph/link.py +434 -0
  31. codegraph/lint_async.py +524 -0
  32. codegraph/mcp_server.py +1303 -0
  33. codegraph/parity.py +473 -0
  34. codegraph/parity_structure.py +307 -0
  35. codegraph/payload.py +321 -0
  36. codegraph/plans.py +1285 -0
  37. codegraph/platform_scan.py +643 -0
  38. codegraph/platforms.py +1369 -0
  39. codegraph/plugins/__init__.py +0 -0
  40. codegraph/plugins/cfamily/__init__.py +0 -0
  41. codegraph/plugins/cfamily/plugin.py +930 -0
  42. codegraph/plugins/cfamily/syntax.py +881 -0
  43. codegraph/plugins/dart/__init__.py +0 -0
  44. codegraph/plugins/dart/bridges.py +345 -0
  45. codegraph/plugins/dart/extractor/bin/extract.dart +717 -0
  46. codegraph/plugins/dart/extractor/pubspec.lock +149 -0
  47. codegraph/plugins/dart/extractor/pubspec.yaml +7 -0
  48. codegraph/plugins/dart/http.py +904 -0
  49. codegraph/plugins/dart/models.py +308 -0
  50. codegraph/plugins/dart/plugin.py +625 -0
  51. codegraph/plugins/dart/program.py +907 -0
  52. codegraph/plugins/django/__init__.py +0 -0
  53. codegraph/plugins/django/extras.py +378 -0
  54. codegraph/plugins/django/models.py +508 -0
  55. codegraph/plugins/django/plugin.py +728 -0
  56. codegraph/plugins/django/schemas.py +339 -0
  57. codegraph/plugins/django/shapes.py +216 -0
  58. codegraph/plugins/django/urls.py +603 -0
  59. codegraph/plugins/express/__init__.py +0 -0
  60. codegraph/plugins/express/plugin.py +428 -0
  61. codegraph/plugins/flutter/__init__.py +0 -0
  62. codegraph/plugins/flutter/plugin.py +538 -0
  63. codegraph/plugins/kotlin/__init__.py +0 -0
  64. codegraph/plugins/kotlin/exact.py +457 -0
  65. codegraph/plugins/kotlin/plugin.py +1961 -0
  66. codegraph/plugins/kotlin/reparse.py +234 -0
  67. codegraph/plugins/laravel/__init__.py +0 -0
  68. codegraph/plugins/laravel/broadcast.py +351 -0
  69. codegraph/plugins/laravel/plugin.py +863 -0
  70. codegraph/plugins/laravel/tests.py +262 -0
  71. codegraph/plugins/laravel/values.py +728 -0
  72. codegraph/plugins/native/__init__.py +0 -0
  73. codegraph/plugins/native/gates.py +286 -0
  74. codegraph/plugins/native/runner.py +183 -0
  75. codegraph/plugins/native/scipread.py +194 -0
  76. codegraph/plugins/native/ts.py +54 -0
  77. codegraph/plugins/nest/__init__.py +0 -0
  78. codegraph/plugins/nest/plugin.py +654 -0
  79. codegraph/plugins/nextjs/__init__.py +0 -0
  80. codegraph/plugins/nextjs/plugin.py +336 -0
  81. codegraph/plugins/nuxt/__init__.py +0 -0
  82. codegraph/plugins/nuxt/plugin.py +308 -0
  83. codegraph/plugins/php/__init__.py +0 -0
  84. codegraph/plugins/php/extractor/composer.json +5 -0
  85. codegraph/plugins/php/extractor/composer.lock +76 -0
  86. codegraph/plugins/php/extractor/extract.php +743 -0
  87. codegraph/plugins/php/gating.py +573 -0
  88. codegraph/plugins/php/plugin.py +668 -0
  89. codegraph/plugins/php/strings.py +197 -0
  90. codegraph/plugins/python/__init__.py +0 -0
  91. codegraph/plugins/python/aitools.py +664 -0
  92. codegraph/plugins/python/external.py +245 -0
  93. codegraph/plugins/python/fields.py +107 -0
  94. codegraph/plugins/python/plugin.py +1733 -0
  95. codegraph/plugins/python/refs.py +485 -0
  96. codegraph/plugins/python/roots.py +412 -0
  97. codegraph/plugins/python/socketio.py +210 -0
  98. codegraph/plugins/python/subproc.py +864 -0
  99. codegraph/plugins/python/tests.py +1040 -0
  100. codegraph/plugins/python/values.py +179 -0
  101. codegraph/plugins/pyweb/__init__.py +0 -0
  102. codegraph/plugins/pyweb/plugin.py +1334 -0
  103. codegraph/plugins/pyweb/values.py +68 -0
  104. codegraph/plugins/rust/__init__.py +0 -0
  105. codegraph/plugins/rust/cargo.py +226 -0
  106. codegraph/plugins/rust/plugin.py +980 -0
  107. codegraph/plugins/rust/syntax.py +678 -0
  108. codegraph/plugins/scip/__init__.py +0 -0
  109. codegraph/plugins/scip/importer.py +129 -0
  110. codegraph/plugins/scip/scip.proto +962 -0
  111. codegraph/plugins/scip/scip_pb2.py +97 -0
  112. codegraph/plugins/stubs/__init__.py +0 -0
  113. codegraph/plugins/stubs/plugins.py +38 -0
  114. codegraph/plugins/swift/__init__.py +0 -0
  115. codegraph/plugins/swift/baseurl.py +109 -0
  116. codegraph/plugins/swift/exact.py +415 -0
  117. codegraph/plugins/swift/indexstore.py +209 -0
  118. codegraph/plugins/swift/packages.py +174 -0
  119. codegraph/plugins/swift/plugin.py +2890 -0
  120. codegraph/plugins/ts/__init__.py +0 -0
  121. codegraph/plugins/ts/baseurl.py +185 -0
  122. codegraph/plugins/ts/extractor/extract.mjs +2652 -0
  123. codegraph/plugins/ts/extractor/fw.mjs +685 -0
  124. codegraph/plugins/ts/extractor/package-lock.json +205 -0
  125. codegraph/plugins/ts/extractor/package.json +9 -0
  126. codegraph/plugins/ts/plugin.py +480 -0
  127. codegraph/plugins/tsweb/__init__.py +0 -0
  128. codegraph/plugins/tsweb/common.py +290 -0
  129. codegraph/plugins/tsweb/data.py +276 -0
  130. codegraph/presets/__init__.py +146 -0
  131. codegraph/presets/c_cpp.yaml +9 -0
  132. codegraph/presets/common.yaml +66 -0
  133. codegraph/presets/dart.yaml +9 -0
  134. codegraph/presets/django-ninja.yaml +15 -0
  135. codegraph/presets/django.yaml +25 -0
  136. codegraph/presets/djangorestframework.yaml +17 -0
  137. codegraph/presets/express.yaml +17 -0
  138. codegraph/presets/kotlin.yaml +11 -0
  139. codegraph/presets/laravel.yaml +40 -0
  140. codegraph/presets/nest.yaml +11 -0
  141. codegraph/presets/nextjs.yaml +15 -0
  142. codegraph/presets/nuxt.yaml +9 -0
  143. codegraph/presets/php.yaml +5 -0
  144. codegraph/presets/python.yaml +10 -0
  145. codegraph/presets/rust.yaml +5 -0
  146. codegraph/presets/swift.yaml +10 -0
  147. codegraph/presets/typescript.yaml +13 -0
  148. codegraph/process_runs.py +328 -0
  149. codegraph/protocols/__init__.py +299 -0
  150. codegraph/protocols/builtin.py +67 -0
  151. codegraph/protocols/matchers.py +144 -0
  152. codegraph/protocols/view.py +334 -0
  153. codegraph/query.py +2089 -0
  154. codegraph/realtime.py +260 -0
  155. codegraph/roundtrip.py +346 -0
  156. codegraph/routes.py +442 -0
  157. codegraph/starters.py +218 -0
  158. codegraph/tests_index.py +117 -0
  159. codegraph/viz/__init__.py +0 -0
  160. codegraph/viz/graph.py +369 -0
  161. codegraph/viz/server.py +198 -0
  162. codegraph/viz/static/app.css +148 -0
  163. codegraph/viz/static/app.js +1082 -0
  164. codegraph/viz/static/index.html +81 -0
  165. codegraph/viz/static/layered.js +237 -0
  166. codegraph/viz/static/vendor/VERSIONS.txt +4 -0
  167. codegraph/viz/static/vendor/cose-base.js +3214 -0
  168. codegraph/viz/static/vendor/cytoscape-fcose.js +1549 -0
  169. codegraph/viz/static/vendor/cytoscape.min.js +31 -0
  170. codegraph/viz/static/vendor/layout-base.js +5230 -0
  171. codegraph/viz/tools/package-lock.json +303 -0
  172. codegraph/viz/tools/package.json +7 -0
  173. codegraph/viz/tools/shoot.mjs +165 -0
  174. codegraph/xcode.py +251 -0
@@ -0,0 +1,174 @@
1
+ cg_code_graph-0.10.1.dist-info/licenses/LICENSE,sha256=yCxPvuJnAuaFMhQ981siWjB2Gntd4PGMISBr3wFcPmA,1071
2
+ codegraph/__init__.py,sha256=fLdO0rp1R5Eb98wCakFij9fCaDjb-rd35zrlRYkwIdo,84
3
+ codegraph/aitools.py,sha256=RZWesED1Oc4QlF4kOkQOn_m41cvDOtIQMyBPWIy59mc,7804
4
+ codegraph/apps.py,sha256=dLvcO5ILmYeo3Ns_4Xg3yAjCwqV3Z5ovuNHZRSX_OTc,4348
5
+ codegraph/blindspots.py,sha256=ZkVGmSABczuvYEHEDPvMdMPtFeV1OcQHv8mPD6OTifI,21098
6
+ codegraph/bridges.py,sha256=ukvAl30Jj8x-g137ixw_hzTaBN9l4Jt_SDQncHVncjk,91347
7
+ codegraph/cli.py,sha256=UtnPQtxa3kYLGFVvDgTm36iFuzlVYnRGUQHdfAgFLcA,49913
8
+ codegraph/concepts.py,sha256=cBAj33qSYtMUKOgSSejOL-xnzbqgZm_ZbxuQXTkYFSk,19511
9
+ codegraph/config.py,sha256=FKf_EEybctooXtmfBEh1k3gpJ9IVh6a40tzmqLRXoaE,29425
10
+ codegraph/coverage.py,sha256=616XJYSoRa8k7MdsxtgYRuttRtcX8dkO71vNvfDWoC4,49392
11
+ codegraph/doctor.py,sha256=bwGXYNtBJq3NBNsFC6j5buxFDEvdxMq0zm-096A7acU,24788
12
+ codegraph/external.py,sha256=W1HSmj9JTWO_IkLOdmpibnuQyh9rYAmz16lfL41UeiE,35092
13
+ codegraph/indexer.py,sha256=0sKlydwu0eRzTjb-8B-hv08FMdj_ixbT2fdtU4W4z8M,18637
14
+ codegraph/link.py,sha256=mUU4zfnQat11z_uZKzp7MV9AQ6fe7S1uNf-3MB4pA_E,25596
15
+ codegraph/lint_async.py,sha256=MG0JB-RB-FaZotqCSl6tWhjZd8VsMsjbFb53H6KneCU,29665
16
+ codegraph/mcp_server.py,sha256=-c6ULQ_EF40Hho0onPcLeaHT8nVpZJXl451wUeorkbQ,79303
17
+ codegraph/parity.py,sha256=D-QBHn8aDoTu9nHJAbsWowGM3TJ4jA9DHPPkVdW8XwA,23558
18
+ codegraph/parity_structure.py,sha256=QxhZ8hgE599Fq8Sqa0cio8aFm8jaySZ9YRDLKlIG7tw,14897
19
+ codegraph/payload.py,sha256=1mS9t59qY0gEeibfDBP97PK9_6XC2_p7WASgWGUI4ag,19174
20
+ codegraph/plans.py,sha256=_mKMXXNW6BkMkKYYFgfszHjKG__hmT6qnY99k9zYsbE,70803
21
+ codegraph/platform_scan.py,sha256=oHWAoLyMCqWUZC1nGvnAlgj1zjqd_OnfjK3LIlQgjmE,23527
22
+ codegraph/platforms.py,sha256=XAW-csPFpXdTcFcY5v36h_a-ze7UscyVJfYfFNcjECk,74758
23
+ codegraph/process_runs.py,sha256=6wJhSeu15QYStjtqy-X08VwLz8FAAZWQOvE7rYKvw5Y,15881
24
+ codegraph/query.py,sha256=AsRvzOy3TDA_KPTpzlDvmFssJpN26X4_tmz0fwO3w2A,113921
25
+ codegraph/realtime.py,sha256=Qb8HkWY4zbETE3VqBd_3Ae73Y6In5L2FoxeQu5cVUkk,14458
26
+ codegraph/roundtrip.py,sha256=ixfVYHghUvlqaRhSB63pziqilNm-rDAslDi9OCjKL8E,17795
27
+ codegraph/routes.py,sha256=VRxGgGhYxjBueAwpuGVT0ky2Adv_bc8slJHHyhQB7WA,25842
28
+ codegraph/starters.py,sha256=__ZfO2z02Lj29vdhO44GOGqxyCz1CKGsgvzlM3iLNLg,9734
29
+ codegraph/tests_index.py,sha256=FDENNeoRgF3M7kP4tHZozeT9lC_LINhZce_0N5MXLGY,5528
30
+ codegraph/xcode.py,sha256=YkMOIb2dq2vMb6FNs8i3WUn3zRqP-JsFolXcE7ZGHpI,10838
31
+ codegraph/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
32
+ codegraph/core/cache.py,sha256=MpjzaslQmnkykTNkaK481AV5FYIb51_UjI-lAkhf_BE,13872
33
+ codegraph/core/detect.py,sha256=kV3B3UdWB6sFNiQekeESRfuybrn0HasUwY1tnnlttQw,3400
34
+ codegraph/core/extractors.py,sha256=qW0pFZ5uuDEyMToLObgkCZ4WlfRBQdLBCvCaLUNBF_c,7429
35
+ codegraph/core/fsutil.py,sha256=mYlAxhIDFFFWkAFg71n2XdggpfSPICotQB1fQnyOsNk,2390
36
+ codegraph/core/generated.py,sha256=-KP_NS4r1_MBTDAD-9OoZ4FAZl0SFfYII0-VEgch2CI,29147
37
+ codegraph/core/model.py,sha256=0aGpRdJRMv22qzTaADVY5xzQFsK0_3XgZiMqHahhJK4,11634
38
+ codegraph/core/paths.py,sha256=mWAi6aaxZWvK8Zfo76hL_HYv3La-QoPnwrwo2Kouzy8,9539
39
+ codegraph/core/plugin.py,sha256=rsOAEltfnr7RI1PkwKUiEBxih7EZnnXicYoS84BLAlc,6336
40
+ codegraph/core/store.py,sha256=RtnVgFTE7fYwcgJcU3Xn7Xe2APANL8OIzo02iiwGGFg,3830
41
+ codegraph/core/syntax_errors.py,sha256=heY_C3HPY3MmlHU8-GWFS1etdQ8lfU0g2ykj382_SKM,7118
42
+ codegraph/plugins/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
43
+ codegraph/plugins/cfamily/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
44
+ codegraph/plugins/cfamily/plugin.py,sha256=eBAcS2UAohzNwpPXwwYKGpnvvCXzknlT-SMPhhZshSg,47037
45
+ codegraph/plugins/cfamily/syntax.py,sha256=lxb4rXjP5N0ctDHDL6R-zbfhf42bFRIoR7U3QhGZZBY,45743
46
+ codegraph/plugins/dart/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
47
+ codegraph/plugins/dart/bridges.py,sha256=HGEcZO2-vShzRQ10FHBFBBllOTVpyqar5Ka-1--vbxU,15778
48
+ codegraph/plugins/dart/http.py,sha256=OBGr2BsdDB2kPzBL2gaECxjPcJRxzm5K5ZgOXxpHZRc,45892
49
+ codegraph/plugins/dart/models.py,sha256=idBW5qKmioMR2X4Nk8el5mVZzWSurekeyZT0WctrvNw,14449
50
+ codegraph/plugins/dart/plugin.py,sha256=Mnu52AlTXvxQSUCVis6rHBIWddvqf_r7lwJtQcIYTZo,33400
51
+ codegraph/plugins/dart/program.py,sha256=49Z7OgITtJOsq9w6leKEiqZCubQYGlHOpv-cfPA-Pog,38080
52
+ codegraph/plugins/dart/extractor/pubspec.lock,sha256=MYPqGt6oUbFKsLfMHz4pr0Y5EVpZQcqLpyznzE9oZq0,4206
53
+ codegraph/plugins/dart/extractor/pubspec.yaml,sha256=-TgmeDHNkFsZriLlO7hARCOy-PRLOIVLfrUc_ZjZE6M,219
54
+ codegraph/plugins/dart/extractor/bin/extract.dart,sha256=2tzSQvC0KV8LZpdasnRUiYze0BGzl5S2ts17hrx4ywg,30552
55
+ codegraph/plugins/django/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
56
+ codegraph/plugins/django/extras.py,sha256=PEAMWpBzEHCUihCBVsq1KuFn6QSbZoYeMSu1kI-N1b8,20521
57
+ codegraph/plugins/django/models.py,sha256=G1b7ZSgmxsWrZbRjNF5LXdnCHQ0mP5KCFHuROPlwkyQ,27022
58
+ codegraph/plugins/django/plugin.py,sha256=R_wDiIyHJG66W45c9T-tMeKaEsKQputSq05bCDcA3Z8,41085
59
+ codegraph/plugins/django/schemas.py,sha256=iHSlUePSzxtgqX-AfJU6uf--mEPkZqxPb9bKf6px5-A,18369
60
+ codegraph/plugins/django/shapes.py,sha256=cedy6_q-1P18Erpy6qpqRaIpeoaXM7JNrcvZQCcFbP4,12220
61
+ codegraph/plugins/django/urls.py,sha256=AXa9ouMDJQAla5GVBPw0lHZnf7p7GUokyHT95QQsSNY,30333
62
+ codegraph/plugins/express/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
63
+ codegraph/plugins/express/plugin.py,sha256=yqeasEnb2b3z19vmeE27BLIrBbft_S436NeFEM2QIgw,22967
64
+ codegraph/plugins/flutter/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
65
+ codegraph/plugins/flutter/plugin.py,sha256=jtJ_wYDCwSlj4Qes1S52y0GkAAgSxVHjP5ni7gKDkQk,30538
66
+ codegraph/plugins/kotlin/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
67
+ codegraph/plugins/kotlin/exact.py,sha256=zeJl3gD7MWrDLFOTDpEgEiZqcvHJLojQEnS72pfWUj8,23584
68
+ codegraph/plugins/kotlin/plugin.py,sha256=cpg7xhETnnXxzpxoj-lwufEeDaq7lxKCZx56XoVJZmk,109791
69
+ codegraph/plugins/kotlin/reparse.py,sha256=yRsmIiWelv4tLoMQxIb4eNqzWQWx4NKIonTmJRukNKw,9989
70
+ codegraph/plugins/laravel/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
71
+ codegraph/plugins/laravel/broadcast.py,sha256=ZM20u_H87NwqjLe7hGJ09Vbv1rTakKn3TBad4CuX35U,19464
72
+ codegraph/plugins/laravel/plugin.py,sha256=8U4pNw-ZVishrktk0EhA3plKwXOgEN1mWzRi5C8_PQU,49518
73
+ codegraph/plugins/laravel/tests.py,sha256=P7aqY2AGAkv2nNvTNh_gy9axNkqDgjUyBCf2F-IT1SU,13611
74
+ codegraph/plugins/laravel/values.py,sha256=q22fWUkA_XGIVlLZgJkIWpiI7_IvPChzrsng8fQ-HDU,36402
75
+ codegraph/plugins/native/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
76
+ codegraph/plugins/native/gates.py,sha256=l0V8qNOm9s9iuSStOED1ek-ZME_flVzvCxoANDMVmDE,10141
77
+ codegraph/plugins/native/runner.py,sha256=ih8X2-H3tBdW_3fUdvIGdaBr6As6lO7OFfjyo7E840o,7867
78
+ codegraph/plugins/native/scipread.py,sha256=DcuwvNmOyU1HnxDMVUeqQmo5A-a-GzBemyZbD6uAG7c,7643
79
+ codegraph/plugins/native/ts.py,sha256=h9sEK9ON8fntMTz-zr-zQ4Zaf7kGC5qB77BwSIyUEZQ,1783
80
+ codegraph/plugins/nest/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
81
+ codegraph/plugins/nest/plugin.py,sha256=8xa-pr3Fo788gDhofoIlU-Hc6d-34kKmCCmiIWfKFiI,37581
82
+ codegraph/plugins/nextjs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
83
+ codegraph/plugins/nextjs/plugin.py,sha256=grGMtSWQcNUyAWv6j2G9Uaj5XQRUftPaFuU7uX3bvbU,17067
84
+ codegraph/plugins/nuxt/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
85
+ codegraph/plugins/nuxt/plugin.py,sha256=JfPFYT3M0R3eHCMZHndNmzYjYEOkXCncixR0qLxR3Ic,15865
86
+ codegraph/plugins/php/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
87
+ codegraph/plugins/php/gating.py,sha256=8JXOEAan2QeljTlNTV8eySYFu7g4ry5gogvB0qaflm0,22169
88
+ codegraph/plugins/php/plugin.py,sha256=iu2iRls6u581ywEmmEKCS-yoGQfzEoGgf155xLgELok,31172
89
+ codegraph/plugins/php/strings.py,sha256=GDFKRbDBp6Fox0oqaGgsVhH3IJntl1LeB0XY3vTCdx0,7385
90
+ codegraph/plugins/php/extractor/composer.json,sha256=7onx7HgBH9O38z14ZOaRKYllhzlWLMXUBtr0UQY1eNQ,62
91
+ codegraph/plugins/php/extractor/composer.lock,sha256=NKLF6eqhUUIyNLSxZ7wTySz5LskJ8HcQyYERydI0VvM,2455
92
+ codegraph/plugins/php/extractor/extract.php,sha256=q8yRiSAlVtFrOlH5U5DwHyx8wy3pgjtS0e290sy7Awg,44587
93
+ codegraph/plugins/python/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
94
+ codegraph/plugins/python/aitools.py,sha256=W3-29u-9v7kBdNnx1hQrxpHptehEgyW1HSXesUK3KZY,36531
95
+ codegraph/plugins/python/external.py,sha256=BJ5_MKdymd8u7v2LbC1JysgVetL1CjMbuHipOMNu4is,13479
96
+ codegraph/plugins/python/fields.py,sha256=6RSgZHXhkOyB-75R_V8UTshkwI1eAJN-f2xIkMCU1KU,5322
97
+ codegraph/plugins/python/plugin.py,sha256=znQxjaHWzgVWdinrNjf_GWKlWX0Azm7xsS2e8-aJH3U,83522
98
+ codegraph/plugins/python/refs.py,sha256=oaHTLcL9FK_lSn0ifispnM3oddGtp3Qsx0N-lcC7ArQ,23989
99
+ codegraph/plugins/python/roots.py,sha256=DooXRmnT2zfTJhGcul6sgHVt5dhhzNZ4EZmE4YXthsU,20313
100
+ codegraph/plugins/python/socketio.py,sha256=KM-Dk2s6GkPhv3uC-oCeayPGxw_Po5j0uDjV0LT-pIg,9145
101
+ codegraph/plugins/python/subproc.py,sha256=hDU9RGVx_ywqt7v5v8moeXMgK2IiI-UVrxUu1Z1lyJE,45016
102
+ codegraph/plugins/python/tests.py,sha256=eI90GD9R7cwVv2QiIwsCySrW3O5l6pCkLiU6ghEcaUY,53764
103
+ codegraph/plugins/python/values.py,sha256=6jq5mggMhpOOJRp-XATTXTlYAQ7f4NU1pehanJEEvFs,8714
104
+ codegraph/plugins/pyweb/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
105
+ codegraph/plugins/pyweb/plugin.py,sha256=UZLN8vgGhVyWjktZqTUMDKe5ZoEOAFofzWKtMwn71ss,71382
106
+ codegraph/plugins/pyweb/values.py,sha256=IwF8_0qYWFlnGeDi0nZ4haoyLo7E-oSLY-92yF0EI-Q,3004
107
+ codegraph/plugins/rust/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
108
+ codegraph/plugins/rust/cargo.py,sha256=x50BDQmOKhPE-zpqL8ndJXHxRNdM7FUm2AuNXBdhLig,9329
109
+ codegraph/plugins/rust/plugin.py,sha256=68AiF2-9vpEnA9VMYsd7RQXRzIRUdTfIK1gY8VKAPsw,51086
110
+ codegraph/plugins/rust/syntax.py,sha256=GFJk7BXGRTq0QBdL-naVKaWOQMysCdHXH5-y4kvCx7o,35296
111
+ codegraph/plugins/scip/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
112
+ codegraph/plugins/scip/importer.py,sha256=DSNQHuaCifNivlHG35E6Lf-OQJLWZNc0w8wFtERc3Ug,5283
113
+ codegraph/plugins/scip/scip.proto,sha256=s4Ahtl75DLv2r5yCn_dRkoWa2bXaBUOe8VS-pM6yvwM,35781
114
+ codegraph/plugins/scip/scip_pb2.py,sha256=cMjo1YhOpPspmTvO0owZIs14CtYXeTmBNmzCzp8CUKk,16842
115
+ codegraph/plugins/stubs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
116
+ codegraph/plugins/stubs/plugins.py,sha256=T-CrNeHmMFeM9sqZv8Is8QTDq69RLu4pT0AhGqfmYh8,1844
117
+ codegraph/plugins/swift/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
118
+ codegraph/plugins/swift/baseurl.py,sha256=EN6mf6qzuwHXoVRSdRyCUwiRjTm0iuqh_6WndyTNvcE,5492
119
+ codegraph/plugins/swift/exact.py,sha256=t7MTVCOaElw42aiqz1fB828gmviRRieAJLuUO8IgYqA,21785
120
+ codegraph/plugins/swift/indexstore.py,sha256=Wqy4sZIbCCFh3YVybYkh9vNtbGkHdXLRHMAb9gFqgos,9011
121
+ codegraph/plugins/swift/packages.py,sha256=suVodi3wngNRLt_FMVfyBRGI8e3fbS59ersS9acKmcA,7902
122
+ codegraph/plugins/swift/plugin.py,sha256=8YtUi96AQVPoTMp0b9w7RymWdXR5STPXn4F8Ld7z1HA,161122
123
+ codegraph/plugins/ts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
124
+ codegraph/plugins/ts/baseurl.py,sha256=_G1bKhwx21GxCKOKckrb1ACrKDr0KlmgHQimryAG3RE,7198
125
+ codegraph/plugins/ts/plugin.py,sha256=PJHhYmF8fiTGo5EKNFHHMTXqFzAB8pFUZqACxuoPfxM,27797
126
+ codegraph/plugins/ts/extractor/extract.mjs,sha256=8iu6_XI_jxT0Uc4cpVN1w3ZcaJPYUvB6GCGDO5nqCas,165118
127
+ codegraph/plugins/ts/extractor/fw.mjs,sha256=k-HGRO2G4Y2HWscvpB4g_20whM13JqjdCk877bUWwfE,43827
128
+ codegraph/plugins/ts/extractor/package-lock.json,sha256=K4tCaYBOAzOLvbsAP0lo60JkTHktZN8trPe1gindV14,7753
129
+ codegraph/plugins/ts/extractor/package.json,sha256=JJA8I1THmwEl2cbg0SZ34MSweH8qdxXXUt9d13JJ_ms,164
130
+ codegraph/plugins/tsweb/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
131
+ codegraph/plugins/tsweb/common.py,sha256=DY4X_3TB3rTDCFl-Ohv3te1YI3XDgttJ22RsMdECYNI,11548
132
+ codegraph/plugins/tsweb/data.py,sha256=8iuZb3SmtFcsaoeai1_T7shiD5AaVtqRZKybhlS12Ho,16109
133
+ codegraph/presets/__init__.py,sha256=t4BbTMvB-5-3KXmPHA7beZ8a1FRCO_5sgg9MB8RnfRE,6334
134
+ codegraph/presets/c_cpp.yaml,sha256=Z2ga8yxMygjw63j__kx9Tv3v9vpUICdweVK7nhmW32U,644
135
+ codegraph/presets/common.yaml,sha256=hryctTOHS_zZB3rsSf0jKk-vwSYjWIhRyKC1O_To--A,4041
136
+ codegraph/presets/dart.yaml,sha256=L2euBg4LgvhSloy6UjolyThP_SPkXyXnCEiH1u7zXhU,535
137
+ codegraph/presets/django-ninja.yaml,sha256=2yeNmrbULpzsWjWX8Gxvzj-FOJSPGY1gSjd6O1q4ifQ,798
138
+ codegraph/presets/django.yaml,sha256=7vGX75GIzFO2Zay1hPV7xsku-l007kh_s-MZ9ze-QZE,1970
139
+ codegraph/presets/djangorestframework.yaml,sha256=AB3pHSYUag9wlG8yZC_9RACS9cjBOMVIh1vuUV0EFaE,1288
140
+ codegraph/presets/express.yaml,sha256=zYPSiBXEG5L4LxbVOZ64ArDssrcwjZVUy1z-JcTtdUs,1045
141
+ codegraph/presets/kotlin.yaml,sha256=Nw9ogp_WAW4CWNv5O4LjAbyLDRjt951ffs6Gv0hcxWo,689
142
+ codegraph/presets/laravel.yaml,sha256=M82eiasS4iOIB-AUAmr-SNZHbiK75RPhJyUODXq2cJs,3531
143
+ codegraph/presets/nest.yaml,sha256=EOdMO9F2_GT0FRr7Dju3excgXSX7nD3lH8ZbIpUkIw4,701
144
+ codegraph/presets/nextjs.yaml,sha256=eKoTi5MH6BjpEY21W59WFkr6ntYyqlVMkg_yig92SXk,1100
145
+ codegraph/presets/nuxt.yaml,sha256=ctKXNp1ef6arv4XCeH2GIYIos1Ii_qmiAId7f5p1hw4,495
146
+ codegraph/presets/php.yaml,sha256=L9_sphQdAsdNtop0Xfuc2zCZWTTSKIRaIP2JdU00M4A,265
147
+ codegraph/presets/python.yaml,sha256=OaspOfJ4dh6qNVjOWZVEjwVXxSqMJnXu0G5w1DMtkWQ,665
148
+ codegraph/presets/rust.yaml,sha256=Mcn3AsX8qvXKsh4D-euocFMMd-DomYn65kuxoOUOe6o,202
149
+ codegraph/presets/swift.yaml,sha256=OVvfMxIYTfhn7h1JB4YYj9pOQYD7W8wg92mw9tK5TWA,574
150
+ codegraph/presets/typescript.yaml,sha256=7nH5s2A2TproF0ulBmqIspoFOSxd2kJ-hG7VMmyon0Q,944
151
+ codegraph/protocols/__init__.py,sha256=Db-fbunvJOzSyHldXdmoYFbYQ-X6HWaN_viRSgLWRHc,15650
152
+ codegraph/protocols/builtin.py,sha256=Q58l5HbYmC4rxOo52fwcpHjkHDi1y6ZJi4MBK522GpE,5809
153
+ codegraph/protocols/matchers.py,sha256=Ym5IXJ65dDHrzmMDvGkT8tmyIMGGJKg9j_bhiRMP3ps,6182
154
+ codegraph/protocols/view.py,sha256=npQ6sJm5Ea0jhKb3cnot1jbJIG67rHaNgjE4618ogXg,19807
155
+ codegraph/viz/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
156
+ codegraph/viz/graph.py,sha256=ru31BBWGy42j5VVF5vz92Pg3r6yikfO7R-7FLFIUt8M,19316
157
+ codegraph/viz/server.py,sha256=CAC0RhqJTBA4FBfmY1sSktGmfe5aeZa41z9ZfszUJA0,10066
158
+ codegraph/viz/static/app.css,sha256=27H0-WQEp72EKOaRbzTRQlWy4qKnNwaXEMMw0jr2kZk,15756
159
+ codegraph/viz/static/app.js,sha256=gb3mDJLjoRY2AZVqdchdnurnWy_vk42EWO2Kzik7q7Q,75426
160
+ codegraph/viz/static/index.html,sha256=KHyS9yhCLbDHh4NqbgUIdJJOfqDSRqNdr-5uLIIhvI4,6135
161
+ codegraph/viz/static/layered.js,sha256=xdLFNtgH_UqVEZ833LTYMzeAopa-n0LIEkqvIupqvBU,12991
162
+ codegraph/viz/static/vendor/VERSIONS.txt,sha256=iog0BVRUEiE7Wmvs9EWGyVzPC0dJN-3Ay_Rbf9o-P4I,89
163
+ codegraph/viz/static/vendor/cose-base.js,sha256=fK6VCb02I1pjqF5xyNn6LNC8HQwezFtac3l2850EDd8,118906
164
+ codegraph/viz/static/vendor/cytoscape-fcose.js,sha256=SxyrIY10mWqlnNhHP5I5zGOYuMF3TYTX5ZrZpolZy1c,57239
165
+ codegraph/viz/static/vendor/cytoscape.min.js,sha256=XztbUpVG1a8fxWKFkK8DO3RRGltveJ9fRoKEWGMii5E,435503
166
+ codegraph/viz/static/vendor/layout-base.js,sha256=7BWrXfmvPyBwj0-quZSsz5HNpxhIzVuxCiNDLMULZ0U,147958
167
+ codegraph/viz/tools/package-lock.json,sha256=w5RXxZ5IWiYK2mDFLWlONv8zttjjqchDBIxAVAlQrS8,10915
168
+ codegraph/viz/tools/package.json,sha256=A03HUX_je5qCUxVleTuE6W9BlLEtMm3O5tvPeLFFnAQ,237
169
+ codegraph/viz/tools/shoot.mjs,sha256=CGk6neJMoQld6p63maI-o_12eP57PFqzDa5dvErnPAQ,11634
170
+ cg_code_graph-0.10.1.dist-info/METADATA,sha256=5qfsoieqA0o__vZbQNUChpPBasyiyheax7FaaXnL56s,56469
171
+ cg_code_graph-0.10.1.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
172
+ cg_code_graph-0.10.1.dist-info/entry_points.txt,sha256=0kTuX0ciCnAlfHHv4vbwD5w_IGhYojd67hO8TxaylNk,77
173
+ cg_code_graph-0.10.1.dist-info/top_level.txt,sha256=RqBj9sPbifZTb9aeHtnbxTgKJvfHIQdmYE1Brv8Wdkg,10
174
+ cg_code_graph-0.10.1.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (84.0.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,3 @@
1
+ [console_scripts]
2
+ cg = codegraph.cli:main
3
+ cg-mcp = codegraph.mcp_server:main
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 cyberchronos00
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1 @@
1
+ codegraph
codegraph/__init__.py ADDED
@@ -0,0 +1,2 @@
1
+ """code-graph: deterministic code knowledge graph (beta)."""
2
+ __version__ = "0.10.1"
codegraph/aitools.py ADDED
@@ -0,0 +1,129 @@
1
+ """`cg tools` / MCP `llm_tools` (#66): LLM tools and MCP primitives (#31 endpoints of the llm_tool / mcp_tool /
2
+ mcp_resource / mcp_prompt protocols) with their handlers, the tables a handler writes or reads (depth-limited), the
3
+ agents offering them and who invokes them; agents; agent loops dispatching by a runtime name (dynamic_dispatch).
4
+
5
+ Flags per tool: the #31 checks (no_receiver: offered to the model / called by a client, no handler; no_sender: a
6
+ handler nothing offers or calls) plus name_collision (two handlers for one name in one toolset)."""
7
+ from __future__ import annotations
8
+
9
+ import fnmatch
10
+ import json
11
+ from collections import defaultdict
12
+
13
+ AI_PROTOCOLS = ("llm_tool", "mcp_tool", "mcp_resource", "mcp_prompt")
14
+
15
+
16
+ def _reach_tables(st, fn, depth=3):
17
+ seen, frontier, out = {fn}, [fn], set()
18
+ for _ in range(depth):
19
+ nxt = []
20
+ for s in frontier:
21
+ for r in st.q("SELECT dst, kind FROM edges WHERE src=? AND kind IN ('CALLS','WRITES_TABLE','READS_TABLE','INSTANTIATES')", (s,)):
22
+ if r["dst"].startswith("table:"):
23
+ out.add(f"{r['dst'][6:]} ({'write' if r['kind'] == 'WRITES_TABLE' else 'read'})")
24
+ elif r["dst"] not in seen:
25
+ seen.add(r["dst"]); nxt.append(r["dst"])
26
+ frontier = nxt
27
+ return sorted(out)
28
+
29
+
30
+ def tools(st, pattern: str | None = None, framework: str | None = None, unmatched: bool = False, agent: str | None = None,
31
+ max_items: int = 200) -> dict:
32
+ from .protocols.view import protocols
33
+ eps = []
34
+ for p in AI_PROTOCOLS:
35
+ eps += protocols(st, protocol=p, max_items=100000)["endpoints"]
36
+ attrs = {r["id"]: json.loads(r["attrs"] or "{}") for r in
37
+ st.q("SELECT id, attrs FROM nodes WHERE kind='endpoint' AND id LIKE 'endpoint:llm_tool:%' OR id LIKE 'endpoint:mcp_%'")}
38
+ agents = defaultdict(list)
39
+ agent_rows = {r["id"]: r for r in st.q("SELECT id, name, file, line, attrs FROM nodes WHERE kind='agent'")}
40
+ for r in st.q("SELECT src, dst FROM edges WHERE kind='OFFERS_TOOL'"):
41
+ agents[r["dst"]].append(agent_rows[r["src"]]["name"] if r["src"] in agent_rows else r["src"])
42
+ out = []
43
+ summary = defaultdict(lambda: defaultdict(int))
44
+ for e in eps:
45
+ a = attrs.get(e["id"], {})
46
+ fw = a.get("framework") or ("mcp" if e["protocol"].startswith("mcp_") else "custom")
47
+ e = {**e, "framework": fw, "agents": sorted(set(agents.get(e["id"], []))),
48
+ "description": a.get("description"), "params": a.get("params"), "schema_source": a.get("schema_source"),
49
+ "toolset": a.get("toolset")}
50
+ per_file = defaultdict(set) # one toolset ~ one module: the same name in separate examples is no collision
51
+ for r in e["receivers"]:
52
+ per_file[(r.get("at") or "").rsplit(":", 1)[0]].add(r["handler"])
53
+ if any(len(v) > 1 for v in per_file.values()) and e["protocol"] != "mcp_resource":
54
+ e["checks"] = [*e["checks"], "name_collision"]
55
+ s = summary[f"{e['protocol']}/{fw}"]
56
+ s["tools"] += 1
57
+ s["handled"] += bool(e["receivers"])
58
+ s["offered_or_called"] += bool(e["senders"] or e["matches"])
59
+ for c in e["checks"]:
60
+ s[c] += 1
61
+ if framework and fw != framework:
62
+ continue
63
+ if agent and not any(fnmatch.fnmatchcase(x, agent) or agent in x for x in e["agents"]):
64
+ continue
65
+ if unmatched and not e["checks"]:
66
+ continue
67
+ if pattern and not (fnmatch.fnmatchcase(e["name"], pattern) or pattern.lower() in e["name"].lower() or e["id"] == pattern):
68
+ continue
69
+ out.append(e)
70
+ for e in out[:max_items]:
71
+ e["reaches_tables"] = sorted({t for r in e["receivers"] for t in _reach_tables(st, r["handler"])})
72
+ dyn = []
73
+ for r in st.q("SELECT id, file, attrs FROM nodes WHERE attrs LIKE '%llm_dynamic_dispatch%'"):
74
+ for d in json.loads(r["attrs"]).get("llm_dynamic_dispatch", []):
75
+ dyn.append({"fn": r["id"], "at": f"{r['file']}:{d['line']}", "expr": d["expr"]})
76
+ ags = []
77
+ for aid, r in sorted(agent_rows.items()):
78
+ aa = json.loads(r["attrs"] or "{}")
79
+ ags.append({"id": aid, "name": r["name"], "at": f"{r['file']}:{r['line']}", "framework": aa.get("framework"),
80
+ "model": aa.get("model"), "tools": [x["dst"] for x in st.q("SELECT dst FROM edges WHERE src=? AND kind='OFFERS_TOOL'", (aid,))],
81
+ "handoffs": [x["dst"] for x in st.q("SELECT dst FROM edges WHERE src=? AND kind='HANDS_OFF_TO'", (aid,))]})
82
+ models = []
83
+ for r in st.q("SELECT id, file, attrs FROM nodes WHERE attrs LIKE '%llm_calls%'"):
84
+ for c in json.loads(r["attrs"]).get("llm_calls", []):
85
+ models.append({"fn": r["id"], "at": f"{r['file']}:{c.get('line')}", **{k: v for k, v in c.items() if k != "line"}})
86
+ return {"summary": {k: dict(v) for k, v in sorted(summary.items())}, "tools": out[:max_items], "selected": len(out),
87
+ "agents": ags, "dynamic_dispatch": dyn, "model_calls": models,
88
+ "filters": {"pattern": pattern, "framework": framework, "unmatched": unmatched, "agent": agent}}
89
+
90
+
91
+ def render_tools(res: dict, max_items: int = 60) -> str:
92
+ if not res["summary"] and not res["agents"] and not res["dynamic_dispatch"]:
93
+ return "no LLM tools, MCP servers or agents in this graph (see docs/ai-tools.md for the frameworks covered)"
94
+ L = [f"{'protocol/framework':28} {'tools':>6} {'handled':>8} {'offered':>8} checks"]
95
+ for k, s in res["summary"].items():
96
+ ck = ", ".join(f"{c} {n}" for c, n in s.items() if c not in ("tools", "handled", "offered_or_called")) or "-"
97
+ L.append(f"{k:28} {s['tools']:>6} {s['handled']:>8} {s['offered_or_called']:>8} {ck}")
98
+ if any(res["filters"].values()) or res["selected"] <= 30:
99
+ L.append("")
100
+ for e in res["tools"][:max_items]:
101
+ fl = f" ! {', '.join(e['checks'])}" if e["checks"] else ""
102
+ L.append(f"[{e['protocol']}] {e['name']} ({e['framework']}{', ' + e['schema_source'] if e.get('schema_source') else ''}){fl}")
103
+ for r in e["receivers"]:
104
+ L.append(f" handler {r['handler'].split(':', 1)[1]} @ {r['at']} [{r['confidence']}]")
105
+ for s in e["senders"]:
106
+ L.append(f" {'offered' if e['protocol'] == 'llm_tool' else 'called'} by {s['fn'].split(':', 1)[1]} @ {s['at']} [{s['confidence']}]")
107
+ for m in e["matches"]:
108
+ L.append(f" {'<-' if m.get('dir') == 'in' else '->'} {m['endpoint']} [{m.get('confidence')}]")
109
+ if e["agents"]:
110
+ L.append(f" agents {', '.join(e['agents'])}")
111
+ if e.get("reaches_tables"):
112
+ L.append(f" tables {', '.join(e['reaches_tables'])}")
113
+ if res["selected"] > max_items:
114
+ L.append(f"... {res['selected'] - max_items} more")
115
+ if res["agents"]:
116
+ L.append("")
117
+ L.append("agents:")
118
+ for a in res["agents"][:max_items]:
119
+ L.append(f" {a['name']} ({a['framework']}{', model ' + a['model'] if a.get('model') else ''}) @ {a['at']}: "
120
+ f"{len(a['tools'])} tools{', hands off to ' + ', '.join(h.split(':', 1)[1] for h in a['handoffs']) if a['handoffs'] else ''}")
121
+ if res["dynamic_dispatch"]:
122
+ L.append("")
123
+ L.append("dynamic_dispatch (tool chosen by a runtime name; not linked):")
124
+ for d in res["dynamic_dispatch"][:max_items]:
125
+ L.append(f" {d['fn'].split(':', 1)[1]} @ {d['at']}: {d['expr']}")
126
+ if res["model_calls"]:
127
+ L.append("")
128
+ L.append(f"model calls: {len(res['model_calls'])} (" + ", ".join(sorted({f"{m.get('provider')}:{m.get('model') or m.get('base_url')}" for m in res['model_calls']}))[:300] + ")")
129
+ return "\n".join(L)
codegraph/apps.py ADDED
@@ -0,0 +1,76 @@
1
+ """Monorepo apps (`.cg.yaml` `apps`): one `cg index <root>` indexes every app and links every frontend / backend pair.
2
+
3
+ apps:
4
+ - {name: api, root: apps/api, role: backend}
5
+ - {name: web, root: apps/web, role: frontend, links: [api]} # links: the backends it calls (default: all)
6
+
7
+ `cg index <root> --db out/mono.db` writes `out/mono.<app>.db` per app and `out/mono.<frontend>+<backend>.db` per link
8
+ pair, the same graphs `cg index <app root>` and `cg link` give one by one. `out/mono.db` itself is the combined graph
9
+ of the first pair (in config order); without a frontend it is the first app's graph. Each app is indexed with its own
10
+ `.cg.yaml` (at the app root), like a separate checkout."""
11
+ from __future__ import annotations
12
+
13
+ import shutil
14
+ import time
15
+ from pathlib import Path
16
+
17
+ from .config import ConfigError, app_pairs
18
+
19
+
20
+ def app_dbs(db: str | Path, apps: list[dict]) -> tuple[dict, dict]:
21
+ """(app name -> DB path, (frontend, backend) -> combined DB path) next to `db`."""
22
+ db = Path(db)
23
+ stem = db.name[:-3] if db.name.endswith(".db") else db.name
24
+ per_app = {a["name"]: db.parent / f"{stem}.{a['name']}.db" for a in apps}
25
+ pairs = {(f["name"], b["name"]): db.parent / f"{stem}.{f['name']}+{b['name']}.db" for f, b in app_pairs(apps)}
26
+ return per_app, pairs
27
+
28
+
29
+ def index_apps(root: str | Path, db: str | Path, cfg: dict, scip=None, python_roots=None,
30
+ include_generated: bool = False) -> dict:
31
+ """Index each app of `cfg["apps"]` and link each pair; returns a summary (per-app and per-pair stats)."""
32
+ from .indexer import index_project
33
+ from .link import link
34
+ t0 = time.time()
35
+ root = Path(root).resolve()
36
+ apps = cfg["apps"]
37
+ fname = cfg.get("file", ".cg.yaml")
38
+ for a in apps:
39
+ d = root / a["root"] if a["root"] else root
40
+ if not d.is_dir():
41
+ raise ConfigError(f"{fname}: apps[{a['name']}].root: {a['root']!r} is not a directory under {root.name}")
42
+ per_app, pairs = app_dbs(db, apps)
43
+ Path(db).parent.mkdir(parents=True, exist_ok=True)
44
+ out = {"project": root.name, "config": fname, "apps": [], "links": []}
45
+ for a in apps:
46
+ st = index_project(root / a["root"] if a["root"] else root, per_app[a["name"]], a["name"], scip,
47
+ python_roots=python_roots, include_generated=include_generated)
48
+ out["apps"].append({"name": a["name"], "root": a["root"] or ".", "role": a["role"], "db": str(per_app[a["name"]]),
49
+ "nodes": st.get("nodes"), "edges": st.get("edges"), "index_seconds": st.get("index_seconds"),
50
+ "frameworks": sorted(((st.get("presets") or {}).get("frameworks") or {}))})
51
+ for (fn, bn), path in pairs.items():
52
+ res = link(str(per_app[bn]), str(per_app[fn]), str(path), backend_name=bn, frontend_name=fn)
53
+ s = res["stats"]
54
+ out["links"].append({"frontend": fn, "backend": bn, "db": str(path), "endpoints": s.get("endpoints"),
55
+ "endpoints_matched": s.get("endpoints_matched"), "call_sites": s.get("call_sites"),
56
+ "call_sites_matched": s.get("call_sites_matched"), "link_seconds": s.get("link_seconds")})
57
+ first = next(iter(pairs.values()), None) or per_app[apps[0]["name"]]
58
+ shutil.copyfile(first, db)
59
+ out["db"] = str(db)
60
+ out["db_is"] = (f"combined graph {next(iter(pairs))[0]} + {next(iter(pairs))[1]}" if pairs
61
+ else f"graph of app {apps[0]['name']}")
62
+ out["index_seconds"] = round(time.time() - t0, 2)
63
+ return out
64
+
65
+
66
+ def render(summary: dict) -> str:
67
+ lines = [f"apps of {summary['project']} ({summary['config']}): {len(summary['apps'])} indexed, "
68
+ f"{len(summary['links'])} linked in {summary['index_seconds']} s"]
69
+ for a in summary["apps"]:
70
+ lines.append(f" {a['name']:<16} {a['role']:<8} {a['root']:<28} {a['nodes']} nodes, {a['edges']} edges, "
71
+ f"{a['index_seconds']} s -> {Path(a['db']).name}")
72
+ for ln in summary["links"]:
73
+ lines.append(f" {ln['frontend']} -> {ln['backend']}: {ln['endpoints_matched']}/{ln['endpoints']} endpoints, "
74
+ f"{ln['call_sites_matched']}/{ln['call_sites']} call sites matched -> {Path(ln['db']).name}")
75
+ lines.append(f" {Path(summary['db']).name}: {summary['db_is']}")
76
+ return "\n".join(lines)