codegraph-cli-ai 0.1.6__tar.gz → 0.1.8__tar.gz
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.
- codegraph_cli_ai-0.1.8/MANIFEST.in +1 -0
- codegraph_cli_ai-0.1.8/PKG-INFO +225 -0
- codegraph_cli_ai-0.1.8/README.md +207 -0
- {codegraph_cli_ai-0.1.6 → codegraph_cli_ai-0.1.8}/codegraph/cli.py +121 -11
- codegraph_cli_ai-0.1.8/codegraph/graph/builder.py +190 -0
- codegraph_cli_ai-0.1.8/codegraph/parsers/database_parser.py +25 -0
- codegraph_cli_ai-0.1.8/codegraph/parsers/image_parser.py +39 -0
- codegraph_cli_ai-0.1.8/codegraph/parsers/multimodal_parser.py +86 -0
- codegraph_cli_ai-0.1.8/codegraph/parsers/pdf_parser.py +43 -0
- {codegraph_cli_ai-0.1.6 → codegraph_cli_ai-0.1.8}/codegraph/parsers/python_parser.py +13 -1
- codegraph_cli_ai-0.1.8/codegraph_cli_ai.egg-info/PKG-INFO +225 -0
- {codegraph_cli_ai-0.1.6 → codegraph_cli_ai-0.1.8}/codegraph_cli_ai.egg-info/SOURCES.txt +5 -0
- {codegraph_cli_ai-0.1.6 → codegraph_cli_ai-0.1.8}/pyproject.toml +1 -1
- codegraph_cli_ai-0.1.6/MANIFEST.in +0 -1
- codegraph_cli_ai-0.1.6/PKG-INFO +0 -17
- codegraph_cli_ai-0.1.6/codegraph/graph/builder.py +0 -110
- codegraph_cli_ai-0.1.6/codegraph_cli_ai.egg-info/PKG-INFO +0 -17
- {codegraph_cli_ai-0.1.6 → codegraph_cli_ai-0.1.8}/codegraph_cli_ai.egg-info/dependency_links.txt +0 -0
- {codegraph_cli_ai-0.1.6 → codegraph_cli_ai-0.1.8}/codegraph_cli_ai.egg-info/entry_points.txt +0 -0
- {codegraph_cli_ai-0.1.6 → codegraph_cli_ai-0.1.8}/codegraph_cli_ai.egg-info/requires.txt +0 -0
- {codegraph_cli_ai-0.1.6 → codegraph_cli_ai-0.1.8}/codegraph_cli_ai.egg-info/top_level.txt +0 -0
- {codegraph_cli_ai-0.1.6 → codegraph_cli_ai-0.1.8}/setup.cfg +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
include README.md
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: codegraph-cli-ai
|
|
3
|
+
Version: 0.1.8
|
|
4
|
+
Summary: CLI tool to analyze codebases and visualize knowledge graphs using AST
|
|
5
|
+
Author: Aditya Jogdand
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/AdityaJogdand/codegraph-ai
|
|
8
|
+
Keywords: code-analysis,ast,graph,cli,developer-tools
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
11
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
+
Classifier: Operating System :: OS Independent
|
|
13
|
+
Requires-Python: >=3.9
|
|
14
|
+
Description-Content-Type: text/markdown
|
|
15
|
+
Requires-Dist: typer>=0.9.0
|
|
16
|
+
Requires-Dist: networkx>=3.0
|
|
17
|
+
Requires-Dist: pyvis>=0.3.2
|
|
18
|
+
|
|
19
|
+
# CodeGraph AI
|
|
20
|
+
|
|
21
|
+
**CodeGraph AI** is a CLI tool that analyzes your Python codebase and visualizes it as an interactive knowledge graph.
|
|
22
|
+
|
|
23
|
+
It helps developers understand:
|
|
24
|
+
|
|
25
|
+
* Code structure
|
|
26
|
+
* Function call relationships
|
|
27
|
+
* File dependencies
|
|
28
|
+
* Overall architecture
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## Features
|
|
33
|
+
|
|
34
|
+
* AST-based parsing of Python code
|
|
35
|
+
* Function call graph generation
|
|
36
|
+
* Dependency graph (imports)
|
|
37
|
+
* Interactive visualization in browser
|
|
38
|
+
* Focus on specific files
|
|
39
|
+
* Hide external libraries (stdlib & third-party)
|
|
40
|
+
* Fast CLI-based workflow
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Installation
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
pip install codegraph-ai
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## Quick Start
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
codegraph index
|
|
56
|
+
codegraph plot
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## Commands
|
|
62
|
+
|
|
63
|
+
### 1. Index your codebase
|
|
64
|
+
|
|
65
|
+
Scan and build the graph:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
codegraph index
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Index a specific folder:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
codegraph index path/to/your/project
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
### 2. Visualize the graph
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
codegraph plot
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
This opens an interactive graph in your browser.
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## Advanced Usage
|
|
90
|
+
|
|
91
|
+
### Hide external libraries
|
|
92
|
+
|
|
93
|
+
Removes standard library and third-party dependencies from the graph:
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
codegraph plot --hide-external
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
### Focus on a specific file
|
|
102
|
+
|
|
103
|
+
Shows only a file and its direct relationships:
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
codegraph plot --focus cli.py
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
### Filter by node type
|
|
112
|
+
|
|
113
|
+
Show only certain types of nodes:
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
codegraph plot --level file
|
|
117
|
+
codegraph plot --level function
|
|
118
|
+
codegraph plot --level class
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
### Filter by edge type
|
|
124
|
+
|
|
125
|
+
Show only specific relationships:
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
codegraph plot --edge-type calls
|
|
129
|
+
codegraph plot --edge-type imports
|
|
130
|
+
codegraph plot --edge-type contains
|
|
131
|
+
codegraph plot --edge-type all
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
### Combine filters
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
codegraph plot --focus cli.py --hide-external --edge-type calls
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
## How It Works
|
|
145
|
+
|
|
146
|
+
1. Parses Python files using AST
|
|
147
|
+
2. Extracts:
|
|
148
|
+
|
|
149
|
+
* Functions
|
|
150
|
+
* Classes
|
|
151
|
+
* Imports
|
|
152
|
+
* Function calls
|
|
153
|
+
3. Builds a directed knowledge graph
|
|
154
|
+
4. Renders it as an interactive visualization
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
## Graph Semantics
|
|
159
|
+
|
|
160
|
+
### Node Types
|
|
161
|
+
|
|
162
|
+
| Type | Description |
|
|
163
|
+
| -------- | ------------------- |
|
|
164
|
+
| File | Python file |
|
|
165
|
+
| Function | Function or method |
|
|
166
|
+
| Class | Class definition |
|
|
167
|
+
| Module | External dependency |
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
### Edge Types
|
|
172
|
+
|
|
173
|
+
| Relation | Meaning |
|
|
174
|
+
| ---------- | ------------------------------- |
|
|
175
|
+
| contains | File/Class contains function |
|
|
176
|
+
| calls | Function calls another function |
|
|
177
|
+
| imports | File imports module |
|
|
178
|
+
| defined_in | Function belongs to file |
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
## Output Files
|
|
183
|
+
|
|
184
|
+
After indexing:
|
|
185
|
+
|
|
186
|
+
```
|
|
187
|
+
.codegraph/graph.json
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
After visualization:
|
|
191
|
+
|
|
192
|
+
```
|
|
193
|
+
graph.html
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
---
|
|
197
|
+
|
|
198
|
+
## Example Workflow
|
|
199
|
+
|
|
200
|
+
```bash
|
|
201
|
+
codegraph index
|
|
202
|
+
codegraph plot --hide-external
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
---
|
|
206
|
+
|
|
207
|
+
## Use Cases
|
|
208
|
+
|
|
209
|
+
* Understand large codebases quickly
|
|
210
|
+
* Visualize architecture
|
|
211
|
+
* Debug dependencies
|
|
212
|
+
* Explore function interactions
|
|
213
|
+
* Prepare for refactoring
|
|
214
|
+
|
|
215
|
+
---
|
|
216
|
+
|
|
217
|
+
## Author
|
|
218
|
+
|
|
219
|
+
Aditya Jogdand
|
|
220
|
+
|
|
221
|
+
---
|
|
222
|
+
|
|
223
|
+
## License
|
|
224
|
+
|
|
225
|
+
MIT License
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
# CodeGraph AI
|
|
2
|
+
|
|
3
|
+
**CodeGraph AI** is a CLI tool that analyzes your Python codebase and visualizes it as an interactive knowledge graph.
|
|
4
|
+
|
|
5
|
+
It helps developers understand:
|
|
6
|
+
|
|
7
|
+
* Code structure
|
|
8
|
+
* Function call relationships
|
|
9
|
+
* File dependencies
|
|
10
|
+
* Overall architecture
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Features
|
|
15
|
+
|
|
16
|
+
* AST-based parsing of Python code
|
|
17
|
+
* Function call graph generation
|
|
18
|
+
* Dependency graph (imports)
|
|
19
|
+
* Interactive visualization in browser
|
|
20
|
+
* Focus on specific files
|
|
21
|
+
* Hide external libraries (stdlib & third-party)
|
|
22
|
+
* Fast CLI-based workflow
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Installation
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
pip install codegraph-ai
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## Quick Start
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
codegraph index
|
|
38
|
+
codegraph plot
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Commands
|
|
44
|
+
|
|
45
|
+
### 1. Index your codebase
|
|
46
|
+
|
|
47
|
+
Scan and build the graph:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
codegraph index
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Index a specific folder:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
codegraph index path/to/your/project
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
### 2. Visualize the graph
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
codegraph plot
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
This opens an interactive graph in your browser.
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## Advanced Usage
|
|
72
|
+
|
|
73
|
+
### Hide external libraries
|
|
74
|
+
|
|
75
|
+
Removes standard library and third-party dependencies from the graph:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
codegraph plot --hide-external
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
### Focus on a specific file
|
|
84
|
+
|
|
85
|
+
Shows only a file and its direct relationships:
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
codegraph plot --focus cli.py
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
### Filter by node type
|
|
94
|
+
|
|
95
|
+
Show only certain types of nodes:
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
codegraph plot --level file
|
|
99
|
+
codegraph plot --level function
|
|
100
|
+
codegraph plot --level class
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
### Filter by edge type
|
|
106
|
+
|
|
107
|
+
Show only specific relationships:
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
codegraph plot --edge-type calls
|
|
111
|
+
codegraph plot --edge-type imports
|
|
112
|
+
codegraph plot --edge-type contains
|
|
113
|
+
codegraph plot --edge-type all
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
### Combine filters
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
codegraph plot --focus cli.py --hide-external --edge-type calls
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
## How It Works
|
|
127
|
+
|
|
128
|
+
1. Parses Python files using AST
|
|
129
|
+
2. Extracts:
|
|
130
|
+
|
|
131
|
+
* Functions
|
|
132
|
+
* Classes
|
|
133
|
+
* Imports
|
|
134
|
+
* Function calls
|
|
135
|
+
3. Builds a directed knowledge graph
|
|
136
|
+
4. Renders it as an interactive visualization
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
## Graph Semantics
|
|
141
|
+
|
|
142
|
+
### Node Types
|
|
143
|
+
|
|
144
|
+
| Type | Description |
|
|
145
|
+
| -------- | ------------------- |
|
|
146
|
+
| File | Python file |
|
|
147
|
+
| Function | Function or method |
|
|
148
|
+
| Class | Class definition |
|
|
149
|
+
| Module | External dependency |
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
### Edge Types
|
|
154
|
+
|
|
155
|
+
| Relation | Meaning |
|
|
156
|
+
| ---------- | ------------------------------- |
|
|
157
|
+
| contains | File/Class contains function |
|
|
158
|
+
| calls | Function calls another function |
|
|
159
|
+
| imports | File imports module |
|
|
160
|
+
| defined_in | Function belongs to file |
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
## Output Files
|
|
165
|
+
|
|
166
|
+
After indexing:
|
|
167
|
+
|
|
168
|
+
```
|
|
169
|
+
.codegraph/graph.json
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
After visualization:
|
|
173
|
+
|
|
174
|
+
```
|
|
175
|
+
graph.html
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
|
|
180
|
+
## Example Workflow
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
codegraph index
|
|
184
|
+
codegraph plot --hide-external
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
## Use Cases
|
|
190
|
+
|
|
191
|
+
* Understand large codebases quickly
|
|
192
|
+
* Visualize architecture
|
|
193
|
+
* Debug dependencies
|
|
194
|
+
* Explore function interactions
|
|
195
|
+
* Prepare for refactoring
|
|
196
|
+
|
|
197
|
+
---
|
|
198
|
+
|
|
199
|
+
## Author
|
|
200
|
+
|
|
201
|
+
Aditya Jogdand
|
|
202
|
+
|
|
203
|
+
---
|
|
204
|
+
|
|
205
|
+
## License
|
|
206
|
+
|
|
207
|
+
MIT License
|
|
@@ -9,6 +9,7 @@ import networkx as nx
|
|
|
9
9
|
from pathlib import Path
|
|
10
10
|
from typing import Optional
|
|
11
11
|
from codegraph.parsers.python_parser import PythonParser
|
|
12
|
+
from codegraph.parsers.multimodal_parser import MultiModalParser
|
|
12
13
|
from codegraph.graph.builder import GraphBuilder
|
|
13
14
|
|
|
14
15
|
app = typer.Typer()
|
|
@@ -20,6 +21,23 @@ def main():
|
|
|
20
21
|
pass
|
|
21
22
|
|
|
22
23
|
|
|
24
|
+
IGNORE_DIRS = {
|
|
25
|
+
"venv", ".venv", "env", "bin", "Scripts",
|
|
26
|
+
".git", "__pycache__", "node_modules", ".codegraph"
|
|
27
|
+
}
|
|
28
|
+
IGNORE_FILES = {"graph.json", ".DS_Store"}
|
|
29
|
+
IGNORE_EXTENSIONS = {".pyc", ".log", ".pyo", ".pyd"}
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def is_virtualenv(path: Path) -> bool:
|
|
33
|
+
"""Detect if a directory is a virtual environment based on its structure."""
|
|
34
|
+
return (
|
|
35
|
+
(path / "pyvenv.cfg").exists()
|
|
36
|
+
or (path / "bin" / "python").exists()
|
|
37
|
+
or (path / "Scripts" / "python.exe").exists()
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
|
|
23
41
|
@app.command()
|
|
24
42
|
def index(
|
|
25
43
|
path: str = typer.Argument(".", help="Path to the repo or folder to index")
|
|
@@ -32,31 +50,81 @@ def index(
|
|
|
32
50
|
raise typer.Exit(code=1)
|
|
33
51
|
|
|
34
52
|
typer.echo(f"Indexing: {root}\n")
|
|
35
|
-
|
|
53
|
+
|
|
54
|
+
# Phase A: Identify top-level custom virtualenvs
|
|
55
|
+
venv_dirs = set()
|
|
56
|
+
for item in root.iterdir():
|
|
57
|
+
if item.is_dir() and is_virtualenv(item):
|
|
58
|
+
venv_dirs.add(item)
|
|
59
|
+
|
|
60
|
+
# Phase B: Filtered Scan
|
|
61
|
+
all_files = []
|
|
62
|
+
for p in root.rglob("*"):
|
|
63
|
+
if not p.is_file():
|
|
64
|
+
continue
|
|
65
|
+
|
|
66
|
+
# 1. Skip if any parent directory is in IGNORE_DIRS
|
|
67
|
+
if any(part in IGNORE_DIRS for part in p.parts):
|
|
68
|
+
continue
|
|
69
|
+
|
|
70
|
+
# 2. Skip if inside a detected custom venv
|
|
71
|
+
if any(v_dir in p.parents for v_dir in venv_dirs):
|
|
72
|
+
continue
|
|
73
|
+
|
|
74
|
+
# 3. Skip if filename is ignored
|
|
75
|
+
if p.name in IGNORE_FILES:
|
|
76
|
+
continue
|
|
77
|
+
|
|
78
|
+
# 4. Skip if extension is ignored
|
|
79
|
+
if p.suffix.lower() in IGNORE_EXTENSIONS:
|
|
80
|
+
continue
|
|
81
|
+
|
|
82
|
+
all_files.append(p)
|
|
83
|
+
|
|
84
|
+
py_files = [f for f in all_files if f.suffix == ".py"]
|
|
85
|
+
asset_exts = {
|
|
86
|
+
".csv", ".json", ".db", ".sqlite",
|
|
87
|
+
".pdf",
|
|
88
|
+
".png", ".jpg", ".jpeg"
|
|
89
|
+
}
|
|
90
|
+
asset_files = [f for f in all_files if f.suffix.lower() in asset_exts]
|
|
36
91
|
|
|
37
|
-
if not py_files:
|
|
38
|
-
typer.echo("No
|
|
92
|
+
if not py_files and not asset_files:
|
|
93
|
+
typer.echo("No supported files found (everything might be ignored).")
|
|
39
94
|
raise typer.Exit()
|
|
40
95
|
|
|
41
|
-
typer.echo(f"Found {len(py_files)} Python file(s)\n")
|
|
96
|
+
typer.echo(f"Found {len(py_files)} Python file(s) and {len(asset_files)} asset(s)\n")
|
|
42
97
|
|
|
43
98
|
# Step 1 — Parse
|
|
44
|
-
|
|
99
|
+
py_parser = PythonParser()
|
|
100
|
+
mm_parser = MultiModalParser()
|
|
101
|
+
|
|
45
102
|
parsed_files = []
|
|
103
|
+
parsed_assets = []
|
|
46
104
|
failed_files = []
|
|
47
105
|
|
|
106
|
+
# Parse Python files
|
|
48
107
|
for filepath in py_files:
|
|
49
|
-
result =
|
|
108
|
+
result = py_parser.parse_file(str(filepath))
|
|
50
109
|
if result.errors:
|
|
51
110
|
failed_files.append((str(filepath), result.errors))
|
|
52
111
|
else:
|
|
53
|
-
typer.echo(f" ✔ {filepath.relative_to(root)}")
|
|
112
|
+
typer.echo(f" ✔ [code] {filepath.relative_to(root)}")
|
|
54
113
|
parsed_files.append(result)
|
|
55
114
|
|
|
115
|
+
# Parse assets
|
|
116
|
+
for filepath in asset_files:
|
|
117
|
+
try:
|
|
118
|
+
asset = mm_parser.parse(str(filepath))
|
|
119
|
+
typer.echo(f" ✔ [asset] {filepath.relative_to(root)}")
|
|
120
|
+
parsed_assets.append(asset)
|
|
121
|
+
except Exception as e:
|
|
122
|
+
failed_files.append((str(filepath), [str(e)]))
|
|
123
|
+
|
|
56
124
|
# Step 2 — Build graph
|
|
57
125
|
typer.echo("\nBuilding graph...")
|
|
58
126
|
builder = GraphBuilder()
|
|
59
|
-
builder.build(parsed_files)
|
|
127
|
+
builder.build(parsed_files, parsed_assets)
|
|
60
128
|
summary = builder.summary()
|
|
61
129
|
|
|
62
130
|
# Step 3 — Save to .codegraph/graph.json
|
|
@@ -163,9 +231,13 @@ def _build_premium_html(G: nx.DiGraph) -> str:
|
|
|
163
231
|
STYLES = {
|
|
164
232
|
"file": {"color": "#4A90E2", "shape": "diamond", "size": 28, "font_color": "#ffffff"},
|
|
165
233
|
"class": {"color": "#F5A623", "shape": "hexagon", "size": 24, "font_color": "#ffffff"},
|
|
166
|
-
"function": {"color": "#50C878", "shape": "dot",
|
|
167
|
-
"method": {"color": "#7ED6A8", "shape": "dot",
|
|
234
|
+
"function": {"color": "#50C878", "shape": "dot", "size": 16, "font_color": "#ffffff"},
|
|
235
|
+
"method": {"color": "#7ED6A8", "shape": "dot", "size": 14, "font_color": "#ffffff"},
|
|
168
236
|
"module": {"color": "#B0BEC5", "shape": "box", "size": 14, "font_color": "#ffffff"},
|
|
237
|
+
"dataset": {"color": "#FFD700", "shape": "diamond", "size": 22, "font_color": "#ffffff"},
|
|
238
|
+
"database": {"color": "#FF69B4", "shape": "database", "size": 24, "font_color": "#ffffff"},
|
|
239
|
+
"document": {"color": "#9B59B6", "shape": "diamond", "size": 24, "font_color": "#ffffff"},
|
|
240
|
+
"image": {"color": "#5DADE2", "shape": "diamond", "size": 24, "font_color": "#ffffff"},
|
|
169
241
|
}
|
|
170
242
|
|
|
171
243
|
EDGE_COLORS = {
|
|
@@ -173,6 +245,8 @@ def _build_premium_html(G: nx.DiGraph) -> str:
|
|
|
173
245
|
"calls": "#50C878",
|
|
174
246
|
"imports": "#B0BEC5",
|
|
175
247
|
"defined_in": "#E8E8E8",
|
|
248
|
+
"uses": "#FFD700",
|
|
249
|
+
"references": "#9B59B6",
|
|
176
250
|
}
|
|
177
251
|
|
|
178
252
|
nodes_js = []
|
|
@@ -188,10 +262,41 @@ def _build_premium_html(G: nx.DiGraph) -> str:
|
|
|
188
262
|
|
|
189
263
|
# Tooltip
|
|
190
264
|
tooltip_parts = [f"<b>{label}</b>", f"Kind: {kind}"]
|
|
191
|
-
if attrs.get("
|
|
265
|
+
if attrs.get("filename"):
|
|
266
|
+
tooltip_parts.append(f"File: {attrs['filename']}")
|
|
267
|
+
elif attrs.get("file"):
|
|
192
268
|
tooltip_parts.append(f"File: {attrs['file'].replace('file:', '')}")
|
|
193
269
|
if attrs.get("cls"):
|
|
194
270
|
tooltip_parts.append(f"Class: {attrs['cls']}")
|
|
271
|
+
|
|
272
|
+
# MultiModal Metadata for tooltips
|
|
273
|
+
metadata = attrs.get("metadata", {})
|
|
274
|
+
if kind == "dataset":
|
|
275
|
+
if "columns" in metadata: tooltip_parts.append(f"Columns: {', '.join(metadata['columns'])}")
|
|
276
|
+
if "keys" in metadata: tooltip_parts.append(f"Keys: {', '.join(metadata['keys'])}")
|
|
277
|
+
elif kind == "database":
|
|
278
|
+
if "tables" in metadata: tooltip_parts.append(f"Tables: {', '.join(metadata['tables'])}")
|
|
279
|
+
elif kind == "document":
|
|
280
|
+
if "num_pages" in metadata: tooltip_parts.append(f"Pages: {metadata['num_pages']}")
|
|
281
|
+
if "text_preview" in metadata: tooltip_parts.append(f"<br>Preview: <i>{metadata['text_preview']}</i>")
|
|
282
|
+
elif kind == "image":
|
|
283
|
+
if "text" in metadata and metadata["text"]: tooltip_parts.append(f"<br>OCR Text: <i>{metadata['text']}</i>")
|
|
284
|
+
|
|
285
|
+
# Add metadata for datasets/databases
|
|
286
|
+
metadata = attrs.get("metadata", {})
|
|
287
|
+
if metadata:
|
|
288
|
+
if "columns" in metadata:
|
|
289
|
+
cols = ", ".join(metadata["columns"][:5])
|
|
290
|
+
if len(metadata["columns"]) > 5: cols += "..."
|
|
291
|
+
tooltip_parts.append(f"Columns: {cols}")
|
|
292
|
+
if "tables" in metadata:
|
|
293
|
+
tbls = ", ".join(metadata["tables"])
|
|
294
|
+
tooltip_parts.append(f"Tables: {tbls}")
|
|
295
|
+
if "keys" in metadata:
|
|
296
|
+
keys = ", ".join(metadata["keys"][:5])
|
|
297
|
+
if len(metadata["keys"]) > 5: keys += "..."
|
|
298
|
+
tooltip_parts.append(f"Keys: {keys}")
|
|
299
|
+
|
|
195
300
|
if external:
|
|
196
301
|
tooltip_parts.append("<i>external</i>")
|
|
197
302
|
tooltip = "<br>".join(tooltip_parts)
|
|
@@ -337,10 +442,15 @@ def _build_premium_html(G: nx.DiGraph) -> str:
|
|
|
337
442
|
<div class="legend-item"><div class="legend-dot" style="background:#50C878"></div>Function</div>
|
|
338
443
|
<div class="legend-item"><div class="legend-dot" style="background:#7ED6A8"></div>Method</div>
|
|
339
444
|
<div class="legend-item"><div class="legend-dot" style="background:#B0BEC5;border-radius:2px"></div>Module</div>
|
|
445
|
+
<div class="legend-item"><div class="legend-dot" style="background:#FFD700;clip-path:polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%)"></div>Dataset</div>
|
|
446
|
+
<div class="legend-item"><div class="legend-dot" style="background:#FF69B4;border-radius:2px"></div>Database</div>
|
|
447
|
+
<div class="legend-item"><div class="legend-dot" style="background:#9B59B6;clip-path:polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%)"></div>Document</div>
|
|
448
|
+
<div class="legend-item"><div class="legend-dot" style="background:#5DADE2;clip-path:polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%)"></div>Image</div>
|
|
340
449
|
<span style="font-size:11px; color:#546E7A; font-weight: 700; margin-left:12px; margin-right:4px; letter-spacing: 0.05em;">EDGES</span>
|
|
341
450
|
<div class="legend-item"><div style="width:20px;height:2px;background:#4A90E2;opacity:0.6"></div>contains</div>
|
|
342
451
|
<div class="legend-item"><div style="width:20px;height:2px;background:#50C878;opacity:0.6"></div>calls</div>
|
|
343
452
|
<div class="legend-item"><div style="width:20px;height:1px;background:#B0BEC5;border-top:1px dashed #B0BEC5"></div>imports</div>
|
|
453
|
+
<div class="legend-item"><div style="width:20px;height:2px;background:#FFD700;opacity:0.6"></div>uses</div>
|
|
344
454
|
</div>
|
|
345
455
|
|
|
346
456
|
<div id="graph-container">
|