codebookx 3.0.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.
codebookx/llm.py ADDED
@@ -0,0 +1,73 @@
1
+ import json
2
+ import re
3
+ import requests
4
+ from typing import Optional, Tuple
5
+ from tqdm import tqdm
6
+
7
+ def check_server(base_url: str) -> tuple[bool, Optional[str]]:
8
+ """Check if an LLM server is running and return (is_running, model_name)."""
9
+
10
+ try:
11
+ r = requests.get(f"{base_url.rstrip('/')}/models", timeout=3)
12
+ if r.status_code == 200:
13
+ data = r.json()
14
+ models = data.get("data", [])
15
+ if models:
16
+ model_name = models[0].get("id", "unknown")
17
+ return True, model_name
18
+ return True, None
19
+ except Exception:
20
+ pass
21
+ return False, None
22
+
23
+ def strip_think_tokens(text: str) -> str:
24
+ """Remove <think>...</think> blocks (used by reasoning models like DeepSeek-R1)."""
25
+ return re.sub(r"<think>.*?</think>", "", text, flags=re.DOTALL).strip()
26
+
27
+ def stream_chat_completion(url: str, model: str, messages: list, temperature: float = 0.3, max_tokens: int = 4096) -> str:
28
+ """Send messages to LM Studio and stream the response, returning the full text."""
29
+ try:
30
+ response = requests.post(
31
+ f"{url.rstrip('/')}/chat/completions",
32
+ json={
33
+ "model": model,
34
+ "messages": messages,
35
+ "temperature": temperature,
36
+ "max_tokens": max_tokens,
37
+ "stream": True,
38
+ },
39
+ stream=True,
40
+ timeout=(10, 60),
41
+ )
42
+ response.raise_for_status()
43
+
44
+ full_text_chunks = []
45
+ content_type = response.headers.get("content-type", "")
46
+
47
+ if "application/json" in content_type:
48
+ data = response.json()
49
+ full_text = data["choices"][0]["message"]["content"]
50
+ print(full_text)
51
+ return strip_think_tokens(full_text)
52
+ else:
53
+ for line in response.iter_lines():
54
+ if not line:
55
+ continue
56
+ line = line.decode("utf-8") if isinstance(line, bytes) else line
57
+ if line.startswith("data: "):
58
+ line = line[6:]
59
+ if line == "[DONE]":
60
+ break
61
+ try:
62
+ chunk = json.loads(line)
63
+ delta = chunk["choices"][0]["delta"].get("content", "")
64
+ if delta:
65
+ print(delta, end="", flush=True)
66
+ full_text_chunks.append(delta)
67
+ except (json.JSONDecodeError, KeyError, IndexError):
68
+ continue
69
+ print()
70
+ return strip_think_tokens("".join(full_text_chunks))
71
+ except Exception as e:
72
+ print(f"\n[Error: {e}]")
73
+ return f"[Error: {e}]"
codebookx/prompts.py ADDED
@@ -0,0 +1,43 @@
1
+ PCTF_SYSTEM_PROMPT = """You are a Senior Software Architect. You are given details about a codebase and must explain it to a product manager who has zero technical knowledge. Use simple language, real-world analogies (like a restaurant kitchen or a library), and avoid jargon.
2
+
3
+ You MUST output your response exactly in the following Markdown format:
4
+
5
+ # Codebase Teardown
6
+
7
+ ## Elevator Pitch
8
+ [2-3 sentences explaining what this project does and why it exists]
9
+
10
+ ## Architecture Blueprint
11
+ | Folder | Purpose |
12
+ |--------|---------|
13
+ | [folder path] | [plain English purpose] |
14
+
15
+ ## Core Features
16
+ - **[Feature 1]**: [Brief description]
17
+ - **[Feature 2]**: [Brief description]
18
+
19
+ ## High-Level Architecture
20
+ [A few paragraphs describing how the system is structured, layered, or how data flows through it, using analogies.]
21
+ """
22
+
23
+ AATD_SYSTEM_PROMPT = """You are a Senior Developer breaking down a feature for a junior AI assistant.
24
+ You MUST output a JSON array of tasks. Each task object MUST have:
25
+ - task_id: number
26
+ - title: short string
27
+ - purpose: string
28
+ - file_path_hint: string
29
+ - function_or_component: string
30
+ - input_output: string
31
+ - constraints: string
32
+ - relevant_context: string
33
+ - copy_paste_prompt: a complete self-contained prompt for the AI to execute only this task.
34
+ """
35
+
36
+ ENHANCE_SYSTEM_PROMPT = """You are an expert Prompt Engineer and Senior Architect.
37
+ Your goal is to take a simple feature request and turn it into a high-context, detailed prompt for an AI coding tool like Cursor or Copilot.
38
+ Incorporate file paths, symbol names, and architectural constraints provided in the context.
39
+ """
40
+
41
+ QA_SYSTEM_PROMPT = """You are a senior engineer who knows this codebase inside out.
42
+ Answer the user's question concisely. Reference specific files and symbols when relevant.
43
+ If you're not sure, say so — don't make things up."""
@@ -0,0 +1,153 @@
1
+ from flask import Flask, jsonify, request, current_app, send_from_directory
2
+ from pathlib import Path
3
+ import sqlite3
4
+ import os
5
+
6
+ app = Flask(__name__)
7
+
8
+ @app.route("/static/<path:filename>")
9
+ def static_files(filename):
10
+ return send_from_directory(
11
+ os.path.join(os.path.dirname(__file__), "static"), filename
12
+ )
13
+
14
+ @app.route("/graph")
15
+ def graph_view():
16
+ return """<!DOCTYPE html>
17
+ <html lang="en">
18
+ <head><meta charset="UTF-8"><title>Codebase Knowledge Graph</title>
19
+ <style>
20
+ body { margin: 0; font-family: sans-serif; overflow: hidden; }
21
+ #legend { position: absolute; top: 10px; left: 10px; background: rgba(255,255,255,0.9); padding: 8px 14px; border-radius: 6px; font-size: 12px; }
22
+ #legend span { display: inline-block; width: 12px; height: 12px; border-radius: 50%; margin-right: 4px; }
23
+ .link { stroke: #999; stroke-opacity: 0.5; }
24
+ .link.CALLS { stroke: #4caf50; }
25
+ .link.IMPORTS { stroke: #2196f3; }
26
+ .link.CONTAINS { stroke: #ff9800; }
27
+ </style>
28
+ </head>
29
+ <body>
30
+ <div id="legend">
31
+ <div><span style="background:#4caf50"></span> CALLS</div>
32
+ <div><span style="background:#2196f3"></span> IMPORTS</div>
33
+ <div><span style="background:#ff9800"></span> CONTAINS</div>
34
+ </div>
35
+ <div id="graph"></div>
36
+ <script src="/static/d3.min.js"></script>
37
+ <script>
38
+ const W = window.innerWidth, H = window.innerHeight;
39
+ const svg = d3.select("#graph").append("svg").attr("width", W).attr("height", H);
40
+ const defs = svg.append("defs");
41
+ defs.append("marker").attr("id", "arrow").attr("viewBox", "0 -5 10 10").attr("refX", 20).attr("refY", 0)
42
+ .append("path").attr("d", "M0,-5L10,0L0,5").attr("fill", "#999");
43
+
44
+ Promise.all([
45
+ fetch("/api/symbols?limit=200").then(r => r.json()),
46
+ fetch("/api/relations").then(r => r.json())
47
+ ]).then(([data, relations]) => {
48
+ const symbols = data.symbols;
49
+ const total = data.total;
50
+ if (total > symbols.length) {
51
+ d3.select("#legend").append("p").attr("style", "color:red;font-weight:bold;margin-top:8px")
52
+ .text(`⚠️ Showing ${symbols.length} of ${total} symbols`);
53
+ }
54
+ const nodes = symbols.map(s => ({id: s.id, name: s.name}));
55
+ const nodeIds = new Set(nodes.map(n => n.id));
56
+ const links = relations.filter(r => nodeIds.has(r.from_id) && nodeIds.has(r.to_id))
57
+ .map(r => ({ source: r.from_id, target: r.to_id, type: r.type }));
58
+ const sim = d3.forceSimulation(nodes)
59
+ .force("link", d3.forceLink(links).id(d => d.id).distance(120))
60
+ .force("charge", d3.forceManyBody().strength(-300))
61
+ .force("center", d3.forceCenter(W/2, H/2));
62
+ const link = svg.selectAll(".link").data(links).join("line")
63
+ .attr("class", d => `link ${d.type}`)
64
+ .attr("marker-end", "url(#arrow)");
65
+ const node = svg.selectAll(".node").data(nodes).join("g").attr("class", "node")
66
+ .call(d3.drag().on("start", (e,d) => { if(!e.active) sim.alphaTarget(0.3).restart(); d.fx = d.x; d.fy = d.y; })
67
+ .on("drag", (e,d) => { d.fx = e.x; d.fy = e.y; })
68
+ .on("end", (e,d) => { if(!e.active) sim.alphaTarget(0); d.fx = null; d.fy = null; }));
69
+ node.append("circle").attr("r", 7).attr("fill", "#69b3a2").attr("stroke", "#333").attr("stroke-width", 1.5);
70
+ node.append("text").attr("dx", 12).attr("dy", 4).style("font-size", "11px").text(d => d.name);
71
+ sim.on("tick", () => {
72
+ link.attr("x1", d => d.source.x).attr("y1", d => d.source.y)
73
+ .attr("x2", d => d.target.x).attr("y2", d => d.target.y);
74
+ node.attr("transform", d => `translate(${d.x},${d.y})`);
75
+ });
76
+ });
77
+ </script>
78
+ </body></html>"""
79
+
80
+ def get_db_connection():
81
+ db_path = current_app.config.get('DB_PATH')
82
+ if not db_path:
83
+ db_path = Path(".codebook_cache.db").resolve()
84
+ conn = sqlite3.connect(db_path)
85
+ conn.row_factory = sqlite3.Row
86
+ return conn
87
+
88
+ @app.route("/")
89
+ def index():
90
+ db_path = current_app.config.get('DB_PATH', 'Not set (using default)')
91
+ rows_html = ""
92
+ try:
93
+ conn = get_db_connection()
94
+ relations = conn.execute("""
95
+ SELECT s1.name as source_name, r.type, s2.name as target_name
96
+ FROM relations r
97
+ JOIN symbols s1 ON r.source_id = s1.id
98
+ JOIN symbols s2 ON r.target_id = s2.id
99
+ LIMIT 100
100
+ """).fetchall()
101
+ conn.close()
102
+ for r in relations:
103
+ d = dict(r)
104
+ rows_html += f"<tr><td>{d['source_name']}</td><td>{d['type']}</td><td>{d['target_name']}</td></tr>\n"
105
+ except Exception:
106
+ rows_html = "<tr><td colspan='3'>No relations found. Run 'codebookx analyze' first.</td></tr>"
107
+
108
+ return f"""<h1>Codebase-X Knowledge Graph Viewer</h1>
109
+ <p>Database: {db_path}</p>
110
+ <p>API endpoints: /api/files, /api/symbols, /api/relations</p>
111
+ <p>🚀 <strong><a href="/graph">View Interactive Knowledge Graph</a></strong></p>
112
+ <h2>🔗 Relations</h2>
113
+ <table border="1"><tr><th>Source Symbol</th><th>Type</th><th>Target Symbol</th></tr>
114
+ {rows_html}</table>
115
+ <p>💡 <strong>CONTAINS</strong> means a file includes a symbol.
116
+ <strong>CALLS</strong> and <strong>IMPORTS</strong> show cross-file dependencies.</p>"""
117
+
118
+ @app.route("/api/relations")
119
+ def get_relations():
120
+ try:
121
+ conn = get_db_connection()
122
+ relations = conn.execute("SELECT * FROM relations LIMIT 500").fetchall()
123
+ conn.close()
124
+ return jsonify([dict(r) for r in relations])
125
+ except Exception as e:
126
+ return jsonify({"error": str(e)}), 500
127
+
128
+ @app.route("/api/files")
129
+ def get_files():
130
+ try:
131
+ conn = get_db_connection()
132
+ files = conn.execute("SELECT * FROM files").fetchall()
133
+ conn.close()
134
+ return jsonify([dict(f) for f in files])
135
+ except Exception as e:
136
+ return jsonify({"error": str(e)}), 500
137
+
138
+ @app.route("/api/symbols")
139
+ def get_symbols():
140
+ try:
141
+ limit = request.args.get("limit", 100, type=int)
142
+ limit = min(limit, 200)
143
+ conn = get_db_connection()
144
+ total = conn.execute("SELECT COUNT(*) FROM symbols").fetchone()[0]
145
+ symbols = conn.execute("SELECT * FROM symbols LIMIT ?", (limit,)).fetchall()
146
+ conn.close()
147
+ return jsonify({"symbols": [dict(s) for s in symbols], "total": total})
148
+ except Exception as e:
149
+ return jsonify({"error": str(e)}), 500
150
+
151
+ def run_server(port=8050, db_path=".codebook_cache.db"):
152
+ app.config['DB_PATH'] = Path(db_path).resolve()
153
+ app.run(host="127.0.0.1", port=port)
@@ -0,0 +1,115 @@
1
+ Metadata-Version: 2.4
2
+ Name: codebookx
3
+ Version: 3.0.0
4
+ Summary: Codebase-X: Production-grade, offline code comprehension and AI-tasking platform
5
+ Author-email: Satvik Jain <klickbae8yt@gmail.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/satvikjain/codebook
8
+ Requires-Python: >=3.10
9
+ Description-Content-Type: text/markdown
10
+ License-File: NOTICE.md
11
+ Requires-Dist: requests>=2.28.0
12
+ Requires-Dist: tqdm>=4.64.0
13
+ Requires-Dist: questionary>=2.0.0
14
+ Requires-Dist: tomli>=2.0.0; python_version < "3.11"
15
+ Provides-Extra: ui
16
+ Requires-Dist: flask>=2.0.0; extra == "ui"
17
+ Provides-Extra: dev
18
+ Requires-Dist: black; extra == "dev"
19
+ Requires-Dist: ruff; extra == "dev"
20
+ Requires-Dist: tree-sitter; extra == "dev"
21
+ Dynamic: license-file
22
+
23
+ # Codebase-X
24
+
25
+ **The Intelligent AI Assistant for Your Entire Codebase.**
26
+
27
+ Codebase-X is a production-grade, offline platform designed to give you total control over your code. By building a deep, persistent Knowledge Graph of your repository, Codebase-X enables advanced architectural analysis, atomic task decomposition, and prompt engineering—all while keeping your data 100% private and local.
28
+
29
+ ---
30
+
31
+ ## 🗺️ User Journey
32
+
33
+ 1. **`codebookx analyze`**: Scan your repository to build a Knowledge Graph and architectural teardown.
34
+ 2. **`codebookx view`**: Launch the interactive Knowledge Graph browser to explore your code visually.
35
+ 3. **`codebookx ask "..."`**: Ask technical questions about your codebase, powered by the Knowledge Graph context.
36
+
37
+ ---
38
+
39
+ ## 🚀 Core Capabilities
40
+
41
+ ### 🏛️ Codebase Teardown (Analyze)
42
+ Stop guessing how your system works. Codebase-X scans your entire repository to generate a high-level architectural blueprint.
43
+ * **Elevator Pitch:** Get an instant summary of any project.
44
+ * **Architecture Blueprint:** Automatically mapped folder roles and purposes.
45
+ * **Data Flow:** Understand how the core components of your system interact.
46
+ ```bash
47
+ codebookx analyze
48
+ ```
49
+
50
+ ### 🔨 Atomic Task Decomposition (Decompose)
51
+ Break complex features into small, manageable pieces. Codebase-X analyzes your feature request against your actual codebase to produce a series of atomic tasks.
52
+ * **AI-Ready:** Each task includes a "copy-paste" prompt specifically designed for AI coding assistants.
53
+ * **Context-Aware:** Tasks reference the exact files and symbols needed.
54
+ ```bash
55
+ codebookx decompose "Add a user settings page"
56
+ ```
57
+
58
+ ### ✨ Prompt Enhancement (Enhance)
59
+ Stop writing vague prompts. The Prompt Enhancer uses the Knowledge Graph to inject relevant file paths, function signatures, and dependencies into your request, creating a high-context prompt that gets it right the first time.
60
+ ```bash
61
+ codebookx enhance "Refactor the authentication flow"
62
+ ```
63
+
64
+ ### 🕸️ Knowledge Graph Browser (View)
65
+ Explore your code visually. Launch an interactive local web UI to traverse your project's dependency graph, find symbols, and manage your AI tasks.
66
+ * **Visual Map:** Interactive D3.js force-directed graph available at `/graph`.
67
+ * **Relations:** Track CALLS, IMPORTS, and CONTAINS relationships cross-file.
68
+ ```bash
69
+ codebookx view
70
+ ```
71
+
72
+ ### ❓ Technical Q&A (Ask)
73
+ Knowledge Graph-backed Q&A for your codebase. Answers are saved automatically.
74
+ ```bash
75
+ # Single question
76
+ codebookx ask "How is the authentication handled in this project?"
77
+
78
+ # Interactive chat mode (multi-turn, context carry-over)
79
+ codebookx ask -c "Walk me through the data flow"
80
+
81
+ # Save Q&A logs to a custom directory
82
+ codebookx ask "What does run_ask do?" --dir ~/my-notes
83
+ ```
84
+ * **Auto-save:** Every Q&A and chat session is saved to `ask_history/` by default (`--dir` to override, or set `CODEBOOK_ASK_DIR` env var).
85
+ * **Chat mode (`-c`):** Multi-turn conversation with full context carry-over. Each turn is saved incrementally — no history lost on crash.
86
+
87
+ ---
88
+
89
+ ## 🛠️ Getting Started
90
+
91
+ **1. Install**
92
+ ```bash
93
+ pip install .
94
+ ```
95
+
96
+ **2. Local LLM Setup**
97
+ Codebase-X is designed to work with **LM Studio**, **Ollama**, or any OpenAI-compatible local server. Ensure your server is running.
98
+
99
+ **3. Initial Analysis**
100
+ Scan your repository to build the Knowledge Graph:
101
+ ```bash
102
+ codebookx analyze
103
+ ```
104
+
105
+ ---
106
+
107
+ ## 🔒 Privacy & Performance
108
+ * **100% Offline:** Your code never leaves your machine. No cloud APIs, no subscriptions.
109
+ * **Persistent Indexing:** Uses a lightning-fast SQLite-backed Knowledge Graph with hash-based caching.
110
+ * **Multi-Language:** Deep support for Python, TypeScript, JavaScript, and more.
111
+
112
+ ---
113
+
114
+ ## 📄 License
115
+ Codebase-X is released under the MIT License.
@@ -0,0 +1,17 @@
1
+ codebookx/__init__.py,sha256=EPmgXOdWKks5S__ZMH7Nu6xpAeVrZpfxaFy4pykuyeI,22
2
+ codebookx/cli.py,sha256=hV-9ojUJSgP6pqqNwVryo4iWgSU79biE6pcK_lQdQ4M,4098
3
+ codebookx/core.py,sha256=yIK2RZJ7fEZq0KFz2u05ZaIYKIHsZOObAIT3Wolk6sI,21756
4
+ codebookx/llm.py,sha256=IsvZ4BRv0crS0iMusynMuoOqYBGb3ZpPZe1Jkz5LcVo,2685
5
+ codebookx/prompts.py,sha256=hiNh2NZ079n-vAB0bITOrclN9VS2GNXqijsEBMPk9A8,1824
6
+ codebookx/engine/graph.py,sha256=aI496ZO9WJQeB5a_Ox-T7WNZTE53RaP5_Q1xiYvSeeI,5921
7
+ codebookx/engine/indexer.py,sha256=E8r-hcmKoZ4veXP7TGIi-jZxw-U1N1P_W_Vr4cE6OoA,5584
8
+ codebookx/engine/parser.py,sha256=sxd2tFiNA_mBB8XQS3sFkUbMC8dvOXHPgDAGjDCsXws,12548
9
+ codebookx/engine/vendor/claude_mem_lite.py,sha256=IUFxGF_2VmmoYJn6i9NH3YevBDJ5zTSXWLHhgxh57tU,1655
10
+ codebookx/engine/vendor/repomix_lite.py,sha256=84he25PLhK0qa7gpX8y2mjnwk7-S4H6laGavDAYxa7o,1235
11
+ codebookx/webapp/app.py,sha256=LpED173MMldRrh1iVBCF1OtQ983irsOFQ3P2h8bnVs4,6266
12
+ codebookx-3.0.0.dist-info/licenses/NOTICE.md,sha256=_uMKd-2xfoO8XRxtunU0jvlJx1BYlPjAsn_oHT9gKew,775
13
+ codebookx-3.0.0.dist-info/METADATA,sha256=mRT8BaA_zOkwkSPqUYQiwIDjJEJtzzNoiQvbuXnWIDE,4506
14
+ codebookx-3.0.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
15
+ codebookx-3.0.0.dist-info/entry_points.txt,sha256=A6ijqPE8joUoN_a45-J0zZ2n86JpjnlVDoI5G70Couw,79
16
+ codebookx-3.0.0.dist-info/top_level.txt,sha256=su_fZ6tEsa4GWjZFsinfGAqXtrXlU0YHVNnpUNaxh2E,10
17
+ codebookx-3.0.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (82.0.1)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,3 @@
1
+ [console_scripts]
2
+ codebook = codebookx.cli:main
3
+ codebookx = codebookx.cli:main
@@ -0,0 +1,20 @@
1
+ # NOTICE
2
+
3
+ Codebase-X includes code from the following open-source projects, used under their respective licenses:
4
+
5
+ 1. **GitNexus** (https://github.com/abhigyanpatwari/GitNexus)
6
+ - License: Apache License 2.0
7
+ - Adapted modules: AST parsing, symbol extraction logic.
8
+ - Original copyright (c) 2024 Abhigyan Patwari.
9
+
10
+ 2. **claude-mem** (https://github.com/thedotmack/claude-mem)
11
+ - License: MIT License
12
+ - Adapted modules: Structural skeleton extraction.
13
+ - Original copyright (c) 2024 thedotmack.
14
+
15
+ 3. **repomix** (https://github.com/yamadashy/repomix)
16
+ - License: MIT License
17
+ - Adapted logic: File packing algorithm.
18
+ - Original copyright (c) 2024 yamadashy.
19
+
20
+ All original copyright notices have been preserved in the adapted source files where applicable.
@@ -0,0 +1 @@
1
+ codebookx