codebrain 0.1.0__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.
- codebrain/__init__.py +3 -0
- codebrain/__main__.py +6 -0
- codebrain/agent_bridge.py +162 -0
- codebrain/analyzer.py +943 -0
- codebrain/api.py +578 -0
- codebrain/api_models.py +102 -0
- codebrain/cli.py +1927 -0
- codebrain/comprehension.py +1939 -0
- codebrain/config.py +46 -0
- codebrain/context.py +276 -0
- codebrain/export.py +334 -0
- codebrain/graph/__init__.py +0 -0
- codebrain/graph/query.py +656 -0
- codebrain/graph/schema.py +113 -0
- codebrain/graph/store.py +295 -0
- codebrain/hook_runner.py +71 -0
- codebrain/hooks.py +107 -0
- codebrain/indexer.py +450 -0
- codebrain/llm.py +676 -0
- codebrain/logging.py +42 -0
- codebrain/mcp_server.py +1635 -0
- codebrain/memory/__init__.py +5 -0
- codebrain/memory/store.py +270 -0
- codebrain/parser/__init__.py +0 -0
- codebrain/parser/base.py +27 -0
- codebrain/parser/config_parser.py +228 -0
- codebrain/parser/models.py +44 -0
- codebrain/parser/python_parser.py +658 -0
- codebrain/parser/registry.py +144 -0
- codebrain/parser/typescript_parser.py +1189 -0
- codebrain/parser/typescript_treesitter.py +535 -0
- codebrain/py.typed +0 -0
- codebrain/resolver.py +171 -0
- codebrain/settings.py +88 -0
- codebrain/utils.py +59 -0
- codebrain/validator.py +563 -0
- codebrain/watcher/__init__.py +0 -0
- codebrain/watcher/file_watcher.py +173 -0
- codebrain-0.1.0.dist-info/METADATA +360 -0
- codebrain-0.1.0.dist-info/RECORD +44 -0
- codebrain-0.1.0.dist-info/WHEEL +5 -0
- codebrain-0.1.0.dist-info/entry_points.txt +6 -0
- codebrain-0.1.0.dist-info/licenses/LICENSE +21 -0
- codebrain-0.1.0.dist-info/top_level.txt +1 -0
codebrain/__init__.py
ADDED
codebrain/__main__.py
ADDED
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
"""Agent bridge — makes LLM agents aware of CodeBrain.
|
|
2
|
+
|
|
3
|
+
Generates:
|
|
4
|
+
- CLAUDE.md with codebase context for Claude Code
|
|
5
|
+
- .codebrain/context.json for any agent to consume
|
|
6
|
+
- MCP server configuration snippet
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import json
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
|
|
14
|
+
from codebrain.comprehension import ComprehensionEngine
|
|
15
|
+
from codebrain.config import CODEBRAIN_DIR, DB_FILENAME
|
|
16
|
+
from codebrain.graph.store import GraphStore
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def generate_claude_md(repo_root: Path) -> str:
|
|
20
|
+
"""Generate a CLAUDE.md file with codebase structural context.
|
|
21
|
+
|
|
22
|
+
This file is automatically read by Claude Code at session start,
|
|
23
|
+
giving the agent instant structural knowledge.
|
|
24
|
+
"""
|
|
25
|
+
db_path = repo_root / CODEBRAIN_DIR / DB_FILENAME
|
|
26
|
+
if not db_path.exists():
|
|
27
|
+
return "# CodeBrain not initialized. Run `brain init` first.\n"
|
|
28
|
+
|
|
29
|
+
with GraphStore(db_path) as store:
|
|
30
|
+
comp = ComprehensionEngine(store)
|
|
31
|
+
overview = comp.system_overview()
|
|
32
|
+
hotspots = comp.risk_hotspots(top_n=10)
|
|
33
|
+
|
|
34
|
+
stats = overview["stats"]
|
|
35
|
+
lines: list[str] = []
|
|
36
|
+
|
|
37
|
+
lines.append("# Codebase Structure (auto-generated by CodeBrain)")
|
|
38
|
+
lines.append("")
|
|
39
|
+
|
|
40
|
+
# Structural safety gate — MUST be first so the agent reads it
|
|
41
|
+
lines.append("## Structural Safety Gate")
|
|
42
|
+
lines.append("")
|
|
43
|
+
lines.append("Before writing any file that modifies existing functions, classes, or methods,")
|
|
44
|
+
lines.append("call the `propose_change` MCP tool with the file path and full new content.")
|
|
45
|
+
lines.append("")
|
|
46
|
+
lines.append("- **SAFE**: proceed with writing")
|
|
47
|
+
lines.append("- **CAUTION**: review the warnings, fix if needed, then write")
|
|
48
|
+
lines.append("- **UNSAFE**: do NOT write. Fix the violations first.")
|
|
49
|
+
lines.append("")
|
|
50
|
+
lines.append("Do not skip this step. It prevents you from breaking callers in other files.")
|
|
51
|
+
lines.append("")
|
|
52
|
+
|
|
53
|
+
lines.append(f"**{stats['files']} files, {stats['nodes']} symbols, {stats['edges']} edges**")
|
|
54
|
+
lines.append("")
|
|
55
|
+
|
|
56
|
+
# Packages
|
|
57
|
+
lines.append("## Packages")
|
|
58
|
+
for name, info in overview["packages"].items():
|
|
59
|
+
doc = f" - {info['docstring']}" if info["docstring"] else ""
|
|
60
|
+
deps = f" (depends on: {', '.join(info['depends_on'])})" if info["depends_on"] else ""
|
|
61
|
+
lines.append(f"- **{name}**: {info['file_count']} files, {info['node_count']} symbols{doc}{deps}")
|
|
62
|
+
lines.append("")
|
|
63
|
+
|
|
64
|
+
# Entry points
|
|
65
|
+
if overview["entry_points"]:
|
|
66
|
+
lines.append("## Entry Points")
|
|
67
|
+
for ep in overview["entry_points"]:
|
|
68
|
+
lines.append(f"- `{ep['file_path']}:{ep['line']}`")
|
|
69
|
+
lines.append("")
|
|
70
|
+
|
|
71
|
+
# Risk hotspots
|
|
72
|
+
if hotspots:
|
|
73
|
+
lines.append("## High-Impact Symbols (change with care)")
|
|
74
|
+
for h in hotspots[:10]:
|
|
75
|
+
lines.append(f"- `{h['name']}` ({h['type']}) in `{h['file_path']}` - {h['direct_dependents']} dependents, affects {h['affected_files']} files")
|
|
76
|
+
lines.append("")
|
|
77
|
+
|
|
78
|
+
# MCP instructions
|
|
79
|
+
lines.append("## CodeBrain Tools")
|
|
80
|
+
lines.append("")
|
|
81
|
+
lines.append("This repo has a CodeBrain knowledge graph. Use these CLI commands instead of grepping:")
|
|
82
|
+
lines.append("- `brain search <name>` - find symbols by name")
|
|
83
|
+
lines.append("- `brain context <name> --json` - get full structural context for a symbol")
|
|
84
|
+
lines.append("- `brain impact <name> --json` - see what breaks if a symbol changes")
|
|
85
|
+
lines.append("- `brain validate <file> --json` - validate a file change against the graph")
|
|
86
|
+
lines.append("- `brain module <file> --json` - understand a module's role and dependencies")
|
|
87
|
+
lines.append("- `brain overview --json` - system-level codebase overview")
|
|
88
|
+
lines.append("- `brain hotspots --json` - find riskiest symbols")
|
|
89
|
+
lines.append("")
|
|
90
|
+
lines.append("**Always run `brain validate <file> --json` after modifying a file.**")
|
|
91
|
+
lines.append("")
|
|
92
|
+
|
|
93
|
+
return "\n".join(lines)
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def generate_context_json(repo_root: Path) -> dict:
|
|
97
|
+
"""Generate .codebrain/context.json for any agent to consume.
|
|
98
|
+
|
|
99
|
+
This is a structured representation of the codebase that can be
|
|
100
|
+
injected into any LLM's context.
|
|
101
|
+
"""
|
|
102
|
+
db_path = repo_root / CODEBRAIN_DIR / DB_FILENAME
|
|
103
|
+
if not db_path.exists():
|
|
104
|
+
return {"error": "CodeBrain not initialized"}
|
|
105
|
+
|
|
106
|
+
with GraphStore(db_path) as store:
|
|
107
|
+
comp = ComprehensionEngine(store)
|
|
108
|
+
overview = comp.system_overview()
|
|
109
|
+
hotspots = comp.risk_hotspots(top_n=15)
|
|
110
|
+
|
|
111
|
+
from codebrain.analyzer import StructuralAnalyzer
|
|
112
|
+
analyzer = StructuralAnalyzer(store)
|
|
113
|
+
layers = analyzer.detect_layers()
|
|
114
|
+
|
|
115
|
+
return {
|
|
116
|
+
"codebrain_version": "0.1.0",
|
|
117
|
+
"overview": overview,
|
|
118
|
+
"risk_hotspots": hotspots,
|
|
119
|
+
"architectural_layers": layers,
|
|
120
|
+
"instructions": {
|
|
121
|
+
"before_modifying": "Run `brain validate <file> --json` to check impact.",
|
|
122
|
+
"to_understand_symbol": "Run `brain context <name> --json` instead of reading source.",
|
|
123
|
+
"to_find_code": "Run `brain search <query> --json` instead of grepping.",
|
|
124
|
+
},
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def generate_mcp_config(repo_root: Path) -> dict:
|
|
129
|
+
"""Generate MCP server configuration for claude_desktop_config.json."""
|
|
130
|
+
return {
|
|
131
|
+
"codebrain": {
|
|
132
|
+
"command": "python",
|
|
133
|
+
"args": ["-m", "codebrain.mcp_server"],
|
|
134
|
+
"cwd": str(repo_root),
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def write_agent_files(repo_root: Path) -> list[str]:
|
|
140
|
+
"""Write all agent integration files. Returns list of files written."""
|
|
141
|
+
written: list[str] = []
|
|
142
|
+
|
|
143
|
+
# CLAUDE.md at repo root
|
|
144
|
+
claude_md = repo_root / "CLAUDE.md"
|
|
145
|
+
content = generate_claude_md(repo_root)
|
|
146
|
+
claude_md.write_text(content, encoding="utf-8")
|
|
147
|
+
written.append(str(claude_md))
|
|
148
|
+
|
|
149
|
+
# context.json inside .codebrain/
|
|
150
|
+
ctx_path = repo_root / CODEBRAIN_DIR / "context.json"
|
|
151
|
+
ctx_path.parent.mkdir(parents=True, exist_ok=True)
|
|
152
|
+
ctx_data = generate_context_json(repo_root)
|
|
153
|
+
ctx_path.write_text(json.dumps(ctx_data, indent=2), encoding="utf-8")
|
|
154
|
+
written.append(str(ctx_path))
|
|
155
|
+
|
|
156
|
+
# MCP config snippet
|
|
157
|
+
mcp_path = repo_root / CODEBRAIN_DIR / "mcp_config.json"
|
|
158
|
+
mcp_data = generate_mcp_config(repo_root)
|
|
159
|
+
mcp_path.write_text(json.dumps(mcp_data, indent=2), encoding="utf-8")
|
|
160
|
+
written.append(str(mcp_path))
|
|
161
|
+
|
|
162
|
+
return written
|