mycode-aiagent 0.1.0__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.
- mycode_aiagent-0.1.0/PKG-INFO +341 -0
- mycode_aiagent-0.1.0/README.md +312 -0
- mycode_aiagent-0.1.0/my_code/__init__.py +16 -0
- mycode_aiagent-0.1.0/my_code/__main__.py +4 -0
- mycode_aiagent-0.1.0/my_code/analyzer.py +84 -0
- mycode_aiagent-0.1.0/my_code/backends/__init__.py +33 -0
- mycode_aiagent-0.1.0/my_code/backends/base.py +13 -0
- mycode_aiagent-0.1.0/my_code/backends/claude_backend.py +32 -0
- mycode_aiagent-0.1.0/my_code/backends/mcp_backend.py +14 -0
- mycode_aiagent-0.1.0/my_code/backends/openai_backend.py +33 -0
- mycode_aiagent-0.1.0/my_code/backends/ricky_backend.py +15 -0
- mycode_aiagent-0.1.0/my_code/cli.py +93 -0
- mycode_aiagent-0.1.0/my_code/generator.py +13 -0
- mycode_aiagent-0.1.0/my_code/ricky_client.py +112 -0
- mycode_aiagent-0.1.0/my_code/utils/__init__.py +0 -0
- mycode_aiagent-0.1.0/my_code/utils/prompts.py +58 -0
- mycode_aiagent-0.1.0/mycode_aiagent.egg-info/PKG-INFO +341 -0
- mycode_aiagent-0.1.0/mycode_aiagent.egg-info/SOURCES.txt +23 -0
- mycode_aiagent-0.1.0/mycode_aiagent.egg-info/dependency_links.txt +1 -0
- mycode_aiagent-0.1.0/mycode_aiagent.egg-info/entry_points.txt +2 -0
- mycode_aiagent-0.1.0/mycode_aiagent.egg-info/requires.txt +11 -0
- mycode_aiagent-0.1.0/mycode_aiagent.egg-info/top_level.txt +1 -0
- mycode_aiagent-0.1.0/pyproject.toml +41 -0
- mycode_aiagent-0.1.0/setup.cfg +4 -0
- mycode_aiagent-0.1.0/tests/test_library.py +79 -0
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: mycode-aiagent
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Style-aware code generation — analyze any codebase and generate new code that matches its style
|
|
5
|
+
License: MIT
|
|
6
|
+
Project-URL: Homepage, https://github.com/RyanAbbottData/MyCode
|
|
7
|
+
Project-URL: Repository, https://github.com/RyanAbbottData/MyCode
|
|
8
|
+
Project-URL: Issues, https://github.com/RyanAbbottData/MyCode/issues
|
|
9
|
+
Keywords: code generation,style analysis,llm,ai,developer tools
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Topic :: Software Development :: Code Generators
|
|
18
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
19
|
+
Requires-Python: >=3.10
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
Requires-Dist: requests
|
|
22
|
+
Provides-Extra: claude
|
|
23
|
+
Requires-Dist: anthropic>=0.40; extra == "claude"
|
|
24
|
+
Provides-Extra: openai
|
|
25
|
+
Requires-Dist: openai>=1.0; extra == "openai"
|
|
26
|
+
Provides-Extra: all
|
|
27
|
+
Requires-Dist: anthropic>=0.40; extra == "all"
|
|
28
|
+
Requires-Dist: openai>=1.0; extra == "all"
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
__ __ ____ _
|
|
32
|
+
| \/ |_ _ / ___|___ __| | ___
|
|
33
|
+
| |\/| | | | | | / _ \ / _` |/ _ \
|
|
34
|
+
| | | | |_| | |__| (_) | (_| | __/
|
|
35
|
+
|_| |_|\__, |\____\___/ \__,_|\___|
|
|
36
|
+
|___/
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
> **Style-aware code generation.** Analyze any codebase to extract its coding style, then generate new code that matches it exactly.
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## What it does
|
|
44
|
+
|
|
45
|
+
MyCode learns how a developer or team writes code — naming conventions, type annotation style, import grouping, docstring format, error handling patterns — and uses that style profile to generate new code that feels like it was written by the same hand.
|
|
46
|
+
|
|
47
|
+
It is built to slot into larger agentic systems: the analyzer and generator are clean library functions, and the backend is swappable (local LLM, Claude, or OpenAI).
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## Requirements
|
|
52
|
+
|
|
53
|
+
- Python 3.10+
|
|
54
|
+
- A running AI backend (see [Backends](#backends))
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## Installation
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
# Clone and install in editable mode
|
|
62
|
+
git clone <repo-url>
|
|
63
|
+
cd MyCode
|
|
64
|
+
pip install -e .
|
|
65
|
+
|
|
66
|
+
# For Claude backend support
|
|
67
|
+
pip install -e ".[claude]"
|
|
68
|
+
|
|
69
|
+
# For OpenAI backend support
|
|
70
|
+
pip install -e ".[openai]"
|
|
71
|
+
|
|
72
|
+
# For all backends
|
|
73
|
+
pip install -e ".[all]"
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
The `my-code` CLI command is registered automatically on install.
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## Backends
|
|
81
|
+
|
|
82
|
+
MyCode delegates inference to a pluggable backend. Choose one based on what you have available.
|
|
83
|
+
|
|
84
|
+
| Backend | Flag | Requirement |
|
|
85
|
+
|---|---|---|
|
|
86
|
+
| Local LLM | `--backend llama` (default) | MCP server running at `localhost:8000` |
|
|
87
|
+
| Anthropic Claude | `--backend claude` | `ANTHROPIC_API_KEY` env var or `--api-key` |
|
|
88
|
+
| OpenAI | `--backend openai` | `OPENAI_API_KEY` env var or `--api-key` |
|
|
89
|
+
| Custom MCP server | `--backend mcp` | Any MCP server at `--mcp-url` |
|
|
90
|
+
|
|
91
|
+
### Setting up a local LLM
|
|
92
|
+
|
|
93
|
+
The `llama` backend expects an MCP server at `http://localhost:8000/mcp` that exposes two tools: one for code generation and one for analysis. Any MCP-compatible wrapper around a local model will work. Here is a recommended setup using [llama.cpp](https://github.com/ggerganov/llama.cpp):
|
|
94
|
+
|
|
95
|
+
**1. Download a model**
|
|
96
|
+
|
|
97
|
+
A code-focused model works best. Good options:
|
|
98
|
+
- [CodeLlama-7B-Instruct](https://huggingface.co/TheBloke/CodeLlama-7B-Instruct-GGUF) — fast, runs on most hardware
|
|
99
|
+
- [CodeLlama-13B-Instruct](https://huggingface.co/TheBloke/CodeLlama-13B-Instruct-GGUF) — better quality, needs ~10 GB VRAM
|
|
100
|
+
- [DeepSeek-Coder-6.7B-Instruct](https://huggingface.co/TheBloke/deepseek-coder-6.7B-instruct-GGUF) — strong alternative
|
|
101
|
+
|
|
102
|
+
Download a `.gguf` quantized file (Q4_K_M is a good balance of size and quality).
|
|
103
|
+
|
|
104
|
+
**2. Start the llama.cpp server**
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
# Install llama.cpp (or use a pre-built binary)
|
|
108
|
+
pip install llama-cpp-python[server]
|
|
109
|
+
|
|
110
|
+
# Start the OpenAI-compatible server
|
|
111
|
+
python -m llama_cpp.server \
|
|
112
|
+
--model ./models/codellama-7b-instruct.Q4_K_M.gguf \
|
|
113
|
+
--host 0.0.0.0 \
|
|
114
|
+
--port 8000 \
|
|
115
|
+
--n_ctx 4096
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
**3. Wrap it with an MCP server**
|
|
119
|
+
|
|
120
|
+
The `llama` backend communicates over MCP, not directly with the llama.cpp HTTP API. You need a thin MCP wrapper that exposes two tools:
|
|
121
|
+
- A **code generation tool** (name must not contain `"analyze"`)
|
|
122
|
+
- An **analysis tool** (name must contain `"analyze"`)
|
|
123
|
+
|
|
124
|
+
Both tools accept a `query` string and return the model's completion. A minimal FastMCP wrapper example:
|
|
125
|
+
|
|
126
|
+
```python
|
|
127
|
+
# llm_mcp_server.py
|
|
128
|
+
from fastmcp import FastMCP
|
|
129
|
+
import requests
|
|
130
|
+
|
|
131
|
+
mcp = FastMCP("local-llm")
|
|
132
|
+
LLM_URL = "http://localhost:8000/v1/completions"
|
|
133
|
+
|
|
134
|
+
def _complete(prompt: str) -> str:
|
|
135
|
+
resp = requests.post(LLM_URL, json={
|
|
136
|
+
"prompt": prompt,
|
|
137
|
+
"max_tokens": 1024,
|
|
138
|
+
"temperature": 0.1,
|
|
139
|
+
})
|
|
140
|
+
return resp.json()["choices"][0]["text"]
|
|
141
|
+
|
|
142
|
+
@mcp.tool()
|
|
143
|
+
def generate_code(query: str) -> str:
|
|
144
|
+
return _complete(query)
|
|
145
|
+
|
|
146
|
+
@mcp.tool()
|
|
147
|
+
def analyze_code(query: str) -> str:
|
|
148
|
+
return _complete(query)
|
|
149
|
+
|
|
150
|
+
if __name__ == "__main__":
|
|
151
|
+
mcp.run(transport="streamable-http", host="0.0.0.0", port=8000)
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
pip install fastmcp
|
|
156
|
+
python llm_mcp_server.py
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
**4. Point MyCode at it**
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
my-code --backend llama --ricky-url http://localhost:8000/mcp analyze .
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
Or set a custom URL if your server runs on a different port:
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
my-code --backend llama --ricky-url http://localhost:9000/mcp analyze .
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
## CLI Usage
|
|
174
|
+
|
|
175
|
+
### Step 1 — Analyze a codebase
|
|
176
|
+
|
|
177
|
+
Point MyCode at any directory. It reads every `.py` file and builds a style profile.
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
my-code analyze ./path/to/codebase
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
With verbose output:
|
|
184
|
+
```bash
|
|
185
|
+
my-code analyze ./path/to/codebase --verbose
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
Using a different backend:
|
|
189
|
+
```bash
|
|
190
|
+
my-code --backend claude analyze ./path/to/codebase
|
|
191
|
+
my-code --backend openai --api-key sk-... analyze ./path/to/codebase
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
The profile is saved to `style_profile.json` by default. Specify a different path with `--profile`:
|
|
195
|
+
```bash
|
|
196
|
+
my-code analyze ./path/to/codebase --profile ./profiles/my_team.json
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
### Step 2 — Generate code
|
|
200
|
+
|
|
201
|
+
```bash
|
|
202
|
+
my-code generate "write a function that parses a CSV file and returns a list of dicts"
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
MyCode loads `style_profile.json` and instructs the backend to produce code that matches the analyzed style — naming, annotations, docstrings, structure and all.
|
|
206
|
+
|
|
207
|
+
```bash
|
|
208
|
+
# Use a specific profile
|
|
209
|
+
my-code generate "write a retry decorator" --profile ./profiles/my_team.json
|
|
210
|
+
|
|
211
|
+
# Use Claude to generate
|
|
212
|
+
my-code --backend claude generate "write a binary search function"
|
|
213
|
+
|
|
214
|
+
# Override the model
|
|
215
|
+
my-code --backend claude --model claude-sonnet-4-6 generate "write a rate limiter"
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
---
|
|
219
|
+
|
|
220
|
+
## CLI Reference
|
|
221
|
+
|
|
222
|
+
```
|
|
223
|
+
my-code [OPTIONS] COMMAND
|
|
224
|
+
|
|
225
|
+
Options:
|
|
226
|
+
--backend {llama,claude,openai,mcp} AI backend to use (default: llama)
|
|
227
|
+
--api-key TEXT API key for claude/openai backends
|
|
228
|
+
--model TEXT Override the default model
|
|
229
|
+
--ricky-url TEXT Local LLM MCP server URL (default: http://localhost:8000/mcp)
|
|
230
|
+
--mcp-url TEXT Custom MCP server URL (default: http://localhost:8001/mcp)
|
|
231
|
+
--profile TEXT Path to style profile JSON (default: style_profile.json)
|
|
232
|
+
|
|
233
|
+
Commands:
|
|
234
|
+
analyze PATH Analyze a codebase and write a style profile
|
|
235
|
+
--verbose Print each file as it is analyzed
|
|
236
|
+
|
|
237
|
+
generate TASK Generate code matching the saved style profile
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
---
|
|
241
|
+
|
|
242
|
+
## Python API
|
|
243
|
+
|
|
244
|
+
MyCode is a first-class library. All CLI functionality is available programmatically.
|
|
245
|
+
|
|
246
|
+
```python
|
|
247
|
+
from my_code import StyleAnalyzer, generate_code, make_backend
|
|
248
|
+
from pathlib import Path
|
|
249
|
+
|
|
250
|
+
# Create a backend
|
|
251
|
+
backend = make_backend() # local LLM (default)
|
|
252
|
+
backend = make_backend("claude") # Claude (reads ANTHROPIC_API_KEY)
|
|
253
|
+
backend = make_backend("openai", api_key="sk-...") # OpenAI
|
|
254
|
+
|
|
255
|
+
# Analyze a codebase
|
|
256
|
+
analyzer = StyleAnalyzer(backend)
|
|
257
|
+
profile = analyzer.analyze_codebase(Path("./my_project"), verbose=True)
|
|
258
|
+
|
|
259
|
+
# Save and reload the profile
|
|
260
|
+
StyleAnalyzer.save_profile(profile, Path("style.json"))
|
|
261
|
+
profile = StyleAnalyzer.load_profile(Path("style.json"))
|
|
262
|
+
|
|
263
|
+
# Generate code
|
|
264
|
+
code = generate_code(
|
|
265
|
+
task="write a function that validates an email address",
|
|
266
|
+
backend=backend,
|
|
267
|
+
profile=profile,
|
|
268
|
+
)
|
|
269
|
+
print(code)
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
### Bring your own backend
|
|
273
|
+
|
|
274
|
+
Implement `AIBackend` to connect any model:
|
|
275
|
+
|
|
276
|
+
```python
|
|
277
|
+
from my_code import AIBackend, StyleAnalyzer, generate_code
|
|
278
|
+
|
|
279
|
+
class MyBackend(AIBackend):
|
|
280
|
+
max_file_chars = 4000 # how much of each file to send for analysis
|
|
281
|
+
|
|
282
|
+
def ask_for_code(self, prompt: str) -> str:
|
|
283
|
+
# call your model, return the generated code as a string
|
|
284
|
+
...
|
|
285
|
+
|
|
286
|
+
def ask_to_analyze(self, prompt: str) -> str:
|
|
287
|
+
# call your model, return a JSON string describing the style
|
|
288
|
+
...
|
|
289
|
+
|
|
290
|
+
backend = MyBackend()
|
|
291
|
+
analyzer = StyleAnalyzer(backend)
|
|
292
|
+
profile = analyzer.analyze_codebase(Path("."))
|
|
293
|
+
code = generate_code("write a logging helper", backend, profile)
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
---
|
|
297
|
+
|
|
298
|
+
## Deep Analysis
|
|
299
|
+
|
|
300
|
+
For a richer style profile, `scripts/deep_analyze.py` runs six focused queries (naming, error handling, string formatting, module structure, docstrings, and representative snippets) and synthesizes them into a single detailed profile.
|
|
301
|
+
|
|
302
|
+
```bash
|
|
303
|
+
# Run from the project root; writes style_profile.json
|
|
304
|
+
python scripts/deep_analyze.py
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
This is slower than the standard `analyze` command but produces a more detailed profile, which leads to better code generation.
|
|
308
|
+
|
|
309
|
+
---
|
|
310
|
+
|
|
311
|
+
## Running Tests
|
|
312
|
+
|
|
313
|
+
```bash
|
|
314
|
+
python tests/test_library.py
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
The test suite uses a `MockBackend` so no live AI backend is required. It exercises the full analyze → generate pipeline.
|
|
318
|
+
|
|
319
|
+
---
|
|
320
|
+
|
|
321
|
+
## Project Structure
|
|
322
|
+
|
|
323
|
+
```
|
|
324
|
+
my_code/
|
|
325
|
+
├── analyzer.py # StyleAnalyzer — scans files, builds style profile
|
|
326
|
+
├── generator.py # generate_code() — formats prompt and calls backend
|
|
327
|
+
├── ricky_client.py # Low-level MCP client for the local LLM server
|
|
328
|
+
├── cli.py # CLI entry point (my-code command)
|
|
329
|
+
├── backends/
|
|
330
|
+
│ ├── base.py # AIBackend abstract base class
|
|
331
|
+
│ ├── ricky_backend.py # Local LLM backend (connects via MCP)
|
|
332
|
+
│ ├── claude_backend.py
|
|
333
|
+
│ ├── openai_backend.py
|
|
334
|
+
│ └── mcp_backend.py # Placeholder for custom MCP backends
|
|
335
|
+
└── utils/
|
|
336
|
+
└── prompts.py # Prompt templates for extraction, summary, generation
|
|
337
|
+
scripts/
|
|
338
|
+
└── deep_analyze.py # Multi-query deep style analysis
|
|
339
|
+
tests/
|
|
340
|
+
└── test_library.py # Smoke tests (no live backend required)
|
|
341
|
+
```
|
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
```
|
|
2
|
+
__ __ ____ _
|
|
3
|
+
| \/ |_ _ / ___|___ __| | ___
|
|
4
|
+
| |\/| | | | | | / _ \ / _` |/ _ \
|
|
5
|
+
| | | | |_| | |__| (_) | (_| | __/
|
|
6
|
+
|_| |_|\__, |\____\___/ \__,_|\___|
|
|
7
|
+
|___/
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
> **Style-aware code generation.** Analyze any codebase to extract its coding style, then generate new code that matches it exactly.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## What it does
|
|
15
|
+
|
|
16
|
+
MyCode learns how a developer or team writes code — naming conventions, type annotation style, import grouping, docstring format, error handling patterns — and uses that style profile to generate new code that feels like it was written by the same hand.
|
|
17
|
+
|
|
18
|
+
It is built to slot into larger agentic systems: the analyzer and generator are clean library functions, and the backend is swappable (local LLM, Claude, or OpenAI).
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Requirements
|
|
23
|
+
|
|
24
|
+
- Python 3.10+
|
|
25
|
+
- A running AI backend (see [Backends](#backends))
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Installation
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
# Clone and install in editable mode
|
|
33
|
+
git clone <repo-url>
|
|
34
|
+
cd MyCode
|
|
35
|
+
pip install -e .
|
|
36
|
+
|
|
37
|
+
# For Claude backend support
|
|
38
|
+
pip install -e ".[claude]"
|
|
39
|
+
|
|
40
|
+
# For OpenAI backend support
|
|
41
|
+
pip install -e ".[openai]"
|
|
42
|
+
|
|
43
|
+
# For all backends
|
|
44
|
+
pip install -e ".[all]"
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
The `my-code` CLI command is registered automatically on install.
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## Backends
|
|
52
|
+
|
|
53
|
+
MyCode delegates inference to a pluggable backend. Choose one based on what you have available.
|
|
54
|
+
|
|
55
|
+
| Backend | Flag | Requirement |
|
|
56
|
+
|---|---|---|
|
|
57
|
+
| Local LLM | `--backend llama` (default) | MCP server running at `localhost:8000` |
|
|
58
|
+
| Anthropic Claude | `--backend claude` | `ANTHROPIC_API_KEY` env var or `--api-key` |
|
|
59
|
+
| OpenAI | `--backend openai` | `OPENAI_API_KEY` env var or `--api-key` |
|
|
60
|
+
| Custom MCP server | `--backend mcp` | Any MCP server at `--mcp-url` |
|
|
61
|
+
|
|
62
|
+
### Setting up a local LLM
|
|
63
|
+
|
|
64
|
+
The `llama` backend expects an MCP server at `http://localhost:8000/mcp` that exposes two tools: one for code generation and one for analysis. Any MCP-compatible wrapper around a local model will work. Here is a recommended setup using [llama.cpp](https://github.com/ggerganov/llama.cpp):
|
|
65
|
+
|
|
66
|
+
**1. Download a model**
|
|
67
|
+
|
|
68
|
+
A code-focused model works best. Good options:
|
|
69
|
+
- [CodeLlama-7B-Instruct](https://huggingface.co/TheBloke/CodeLlama-7B-Instruct-GGUF) — fast, runs on most hardware
|
|
70
|
+
- [CodeLlama-13B-Instruct](https://huggingface.co/TheBloke/CodeLlama-13B-Instruct-GGUF) — better quality, needs ~10 GB VRAM
|
|
71
|
+
- [DeepSeek-Coder-6.7B-Instruct](https://huggingface.co/TheBloke/deepseek-coder-6.7B-instruct-GGUF) — strong alternative
|
|
72
|
+
|
|
73
|
+
Download a `.gguf` quantized file (Q4_K_M is a good balance of size and quality).
|
|
74
|
+
|
|
75
|
+
**2. Start the llama.cpp server**
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
# Install llama.cpp (or use a pre-built binary)
|
|
79
|
+
pip install llama-cpp-python[server]
|
|
80
|
+
|
|
81
|
+
# Start the OpenAI-compatible server
|
|
82
|
+
python -m llama_cpp.server \
|
|
83
|
+
--model ./models/codellama-7b-instruct.Q4_K_M.gguf \
|
|
84
|
+
--host 0.0.0.0 \
|
|
85
|
+
--port 8000 \
|
|
86
|
+
--n_ctx 4096
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
**3. Wrap it with an MCP server**
|
|
90
|
+
|
|
91
|
+
The `llama` backend communicates over MCP, not directly with the llama.cpp HTTP API. You need a thin MCP wrapper that exposes two tools:
|
|
92
|
+
- A **code generation tool** (name must not contain `"analyze"`)
|
|
93
|
+
- An **analysis tool** (name must contain `"analyze"`)
|
|
94
|
+
|
|
95
|
+
Both tools accept a `query` string and return the model's completion. A minimal FastMCP wrapper example:
|
|
96
|
+
|
|
97
|
+
```python
|
|
98
|
+
# llm_mcp_server.py
|
|
99
|
+
from fastmcp import FastMCP
|
|
100
|
+
import requests
|
|
101
|
+
|
|
102
|
+
mcp = FastMCP("local-llm")
|
|
103
|
+
LLM_URL = "http://localhost:8000/v1/completions"
|
|
104
|
+
|
|
105
|
+
def _complete(prompt: str) -> str:
|
|
106
|
+
resp = requests.post(LLM_URL, json={
|
|
107
|
+
"prompt": prompt,
|
|
108
|
+
"max_tokens": 1024,
|
|
109
|
+
"temperature": 0.1,
|
|
110
|
+
})
|
|
111
|
+
return resp.json()["choices"][0]["text"]
|
|
112
|
+
|
|
113
|
+
@mcp.tool()
|
|
114
|
+
def generate_code(query: str) -> str:
|
|
115
|
+
return _complete(query)
|
|
116
|
+
|
|
117
|
+
@mcp.tool()
|
|
118
|
+
def analyze_code(query: str) -> str:
|
|
119
|
+
return _complete(query)
|
|
120
|
+
|
|
121
|
+
if __name__ == "__main__":
|
|
122
|
+
mcp.run(transport="streamable-http", host="0.0.0.0", port=8000)
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
pip install fastmcp
|
|
127
|
+
python llm_mcp_server.py
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
**4. Point MyCode at it**
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
my-code --backend llama --ricky-url http://localhost:8000/mcp analyze .
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
Or set a custom URL if your server runs on a different port:
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
my-code --backend llama --ricky-url http://localhost:9000/mcp analyze .
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
## CLI Usage
|
|
145
|
+
|
|
146
|
+
### Step 1 — Analyze a codebase
|
|
147
|
+
|
|
148
|
+
Point MyCode at any directory. It reads every `.py` file and builds a style profile.
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
my-code analyze ./path/to/codebase
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
With verbose output:
|
|
155
|
+
```bash
|
|
156
|
+
my-code analyze ./path/to/codebase --verbose
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
Using a different backend:
|
|
160
|
+
```bash
|
|
161
|
+
my-code --backend claude analyze ./path/to/codebase
|
|
162
|
+
my-code --backend openai --api-key sk-... analyze ./path/to/codebase
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
The profile is saved to `style_profile.json` by default. Specify a different path with `--profile`:
|
|
166
|
+
```bash
|
|
167
|
+
my-code analyze ./path/to/codebase --profile ./profiles/my_team.json
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### Step 2 — Generate code
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
my-code generate "write a function that parses a CSV file and returns a list of dicts"
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
MyCode loads `style_profile.json` and instructs the backend to produce code that matches the analyzed style — naming, annotations, docstrings, structure and all.
|
|
177
|
+
|
|
178
|
+
```bash
|
|
179
|
+
# Use a specific profile
|
|
180
|
+
my-code generate "write a retry decorator" --profile ./profiles/my_team.json
|
|
181
|
+
|
|
182
|
+
# Use Claude to generate
|
|
183
|
+
my-code --backend claude generate "write a binary search function"
|
|
184
|
+
|
|
185
|
+
# Override the model
|
|
186
|
+
my-code --backend claude --model claude-sonnet-4-6 generate "write a rate limiter"
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
## CLI Reference
|
|
192
|
+
|
|
193
|
+
```
|
|
194
|
+
my-code [OPTIONS] COMMAND
|
|
195
|
+
|
|
196
|
+
Options:
|
|
197
|
+
--backend {llama,claude,openai,mcp} AI backend to use (default: llama)
|
|
198
|
+
--api-key TEXT API key for claude/openai backends
|
|
199
|
+
--model TEXT Override the default model
|
|
200
|
+
--ricky-url TEXT Local LLM MCP server URL (default: http://localhost:8000/mcp)
|
|
201
|
+
--mcp-url TEXT Custom MCP server URL (default: http://localhost:8001/mcp)
|
|
202
|
+
--profile TEXT Path to style profile JSON (default: style_profile.json)
|
|
203
|
+
|
|
204
|
+
Commands:
|
|
205
|
+
analyze PATH Analyze a codebase and write a style profile
|
|
206
|
+
--verbose Print each file as it is analyzed
|
|
207
|
+
|
|
208
|
+
generate TASK Generate code matching the saved style profile
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
---
|
|
212
|
+
|
|
213
|
+
## Python API
|
|
214
|
+
|
|
215
|
+
MyCode is a first-class library. All CLI functionality is available programmatically.
|
|
216
|
+
|
|
217
|
+
```python
|
|
218
|
+
from my_code import StyleAnalyzer, generate_code, make_backend
|
|
219
|
+
from pathlib import Path
|
|
220
|
+
|
|
221
|
+
# Create a backend
|
|
222
|
+
backend = make_backend() # local LLM (default)
|
|
223
|
+
backend = make_backend("claude") # Claude (reads ANTHROPIC_API_KEY)
|
|
224
|
+
backend = make_backend("openai", api_key="sk-...") # OpenAI
|
|
225
|
+
|
|
226
|
+
# Analyze a codebase
|
|
227
|
+
analyzer = StyleAnalyzer(backend)
|
|
228
|
+
profile = analyzer.analyze_codebase(Path("./my_project"), verbose=True)
|
|
229
|
+
|
|
230
|
+
# Save and reload the profile
|
|
231
|
+
StyleAnalyzer.save_profile(profile, Path("style.json"))
|
|
232
|
+
profile = StyleAnalyzer.load_profile(Path("style.json"))
|
|
233
|
+
|
|
234
|
+
# Generate code
|
|
235
|
+
code = generate_code(
|
|
236
|
+
task="write a function that validates an email address",
|
|
237
|
+
backend=backend,
|
|
238
|
+
profile=profile,
|
|
239
|
+
)
|
|
240
|
+
print(code)
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
### Bring your own backend
|
|
244
|
+
|
|
245
|
+
Implement `AIBackend` to connect any model:
|
|
246
|
+
|
|
247
|
+
```python
|
|
248
|
+
from my_code import AIBackend, StyleAnalyzer, generate_code
|
|
249
|
+
|
|
250
|
+
class MyBackend(AIBackend):
|
|
251
|
+
max_file_chars = 4000 # how much of each file to send for analysis
|
|
252
|
+
|
|
253
|
+
def ask_for_code(self, prompt: str) -> str:
|
|
254
|
+
# call your model, return the generated code as a string
|
|
255
|
+
...
|
|
256
|
+
|
|
257
|
+
def ask_to_analyze(self, prompt: str) -> str:
|
|
258
|
+
# call your model, return a JSON string describing the style
|
|
259
|
+
...
|
|
260
|
+
|
|
261
|
+
backend = MyBackend()
|
|
262
|
+
analyzer = StyleAnalyzer(backend)
|
|
263
|
+
profile = analyzer.analyze_codebase(Path("."))
|
|
264
|
+
code = generate_code("write a logging helper", backend, profile)
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
---
|
|
268
|
+
|
|
269
|
+
## Deep Analysis
|
|
270
|
+
|
|
271
|
+
For a richer style profile, `scripts/deep_analyze.py` runs six focused queries (naming, error handling, string formatting, module structure, docstrings, and representative snippets) and synthesizes them into a single detailed profile.
|
|
272
|
+
|
|
273
|
+
```bash
|
|
274
|
+
# Run from the project root; writes style_profile.json
|
|
275
|
+
python scripts/deep_analyze.py
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
This is slower than the standard `analyze` command but produces a more detailed profile, which leads to better code generation.
|
|
279
|
+
|
|
280
|
+
---
|
|
281
|
+
|
|
282
|
+
## Running Tests
|
|
283
|
+
|
|
284
|
+
```bash
|
|
285
|
+
python tests/test_library.py
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
The test suite uses a `MockBackend` so no live AI backend is required. It exercises the full analyze → generate pipeline.
|
|
289
|
+
|
|
290
|
+
---
|
|
291
|
+
|
|
292
|
+
## Project Structure
|
|
293
|
+
|
|
294
|
+
```
|
|
295
|
+
my_code/
|
|
296
|
+
├── analyzer.py # StyleAnalyzer — scans files, builds style profile
|
|
297
|
+
├── generator.py # generate_code() — formats prompt and calls backend
|
|
298
|
+
├── ricky_client.py # Low-level MCP client for the local LLM server
|
|
299
|
+
├── cli.py # CLI entry point (my-code command)
|
|
300
|
+
├── backends/
|
|
301
|
+
│ ├── base.py # AIBackend abstract base class
|
|
302
|
+
│ ├── ricky_backend.py # Local LLM backend (connects via MCP)
|
|
303
|
+
│ ├── claude_backend.py
|
|
304
|
+
│ ├── openai_backend.py
|
|
305
|
+
│ └── mcp_backend.py # Placeholder for custom MCP backends
|
|
306
|
+
└── utils/
|
|
307
|
+
└── prompts.py # Prompt templates for extraction, summary, generation
|
|
308
|
+
scripts/
|
|
309
|
+
└── deep_analyze.py # Multi-query deep style analysis
|
|
310
|
+
tests/
|
|
311
|
+
└── test_library.py # Smoke tests (no live backend required)
|
|
312
|
+
```
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
__version__ = "0.1.0"
|
|
2
|
+
|
|
3
|
+
from .analyzer import StyleAnalyzer
|
|
4
|
+
from .generator import generate_code
|
|
5
|
+
from .backends import AIBackend, ClaudeBackend, OpenAIBackend, RickyBackend, MCPBackend, make_backend
|
|
6
|
+
|
|
7
|
+
__all__ = [
|
|
8
|
+
"StyleAnalyzer",
|
|
9
|
+
"generate_code",
|
|
10
|
+
"AIBackend",
|
|
11
|
+
"ClaudeBackend",
|
|
12
|
+
"OpenAIBackend",
|
|
13
|
+
"RickyBackend",
|
|
14
|
+
"MCPBackend",
|
|
15
|
+
"make_backend",
|
|
16
|
+
]
|