agentic-python-coder 2.2.0__tar.gz → 2.3.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.
- {agentic_python_coder-2.2.0 → agentic_python_coder-2.3.0}/.gitignore +1 -0
- {agentic_python_coder-2.2.0 → agentic_python_coder-2.3.0}/PKG-INFO +31 -15
- {agentic_python_coder-2.2.0 → agentic_python_coder-2.3.0}/README.md +18 -3
- {agentic_python_coder-2.2.0 → agentic_python_coder-2.3.0}/coder/prompts/system.md +3 -15
- {agentic_python_coder-2.2.0 → agentic_python_coder-2.3.0}/coder/prompts/system_todo.md +10 -22
- agentic_python_coder-2.3.0/coder/src/agentic_python_coder/__init__.py +74 -0
- {agentic_python_coder-2.2.0 → agentic_python_coder-2.3.0}/coder/src/agentic_python_coder/agent.py +28 -49
- {agentic_python_coder-2.2.0 → agentic_python_coder-2.3.0}/coder/src/agentic_python_coder/cli.py +17 -7
- agentic_python_coder-2.3.0/coder/src/agentic_python_coder/kernel.py +634 -0
- {agentic_python_coder-2.2.0 → agentic_python_coder-2.3.0}/coder/src/agentic_python_coder/llm.py +4 -1
- agentic_python_coder-2.3.0/coder/src/agentic_python_coder/mcp_server.py +526 -0
- {agentic_python_coder-2.2.0 → agentic_python_coder-2.3.0}/coder/src/agentic_python_coder/runner.py +1 -28
- {agentic_python_coder-2.2.0 → agentic_python_coder-2.3.0}/coder/src/agentic_python_coder/tools.py +1 -44
- {agentic_python_coder-2.2.0 → agentic_python_coder-2.3.0}/coder/tests/test_library_api.py +21 -17
- {agentic_python_coder-2.2.0 → agentic_python_coder-2.3.0}/coder/tests/test_mcp_server.py +109 -20
- {agentic_python_coder-2.2.0 → agentic_python_coder-2.3.0}/coder/tests/test_todo_tool_availability.py +2 -0
- {agentic_python_coder-2.2.0 → agentic_python_coder-2.3.0}/pyproject.toml +13 -12
- agentic_python_coder-2.2.0/coder/src/agentic_python_coder/__init__.py +0 -39
- agentic_python_coder-2.2.0/coder/src/agentic_python_coder/kernel.py +0 -343
- agentic_python_coder-2.2.0/coder/src/agentic_python_coder/mcp_server.py +0 -485
- agentic_python_coder-2.2.0/examples/cpmpy/README.md +0 -69
- agentic_python_coder-2.2.0/examples/cpmpy/cpmpy.md +0 -46
- agentic_python_coder-2.2.0/examples/cpmpy/sample_problems/magic_square.md +0 -46
- agentic_python_coder-2.2.0/examples/cpmpy/sample_problems/n_queens.md +0 -36
- {agentic_python_coder-2.2.0 → agentic_python_coder-2.3.0}/LICENSE +0 -0
- {agentic_python_coder-2.2.0 → agentic_python_coder-2.3.0}/coder/.gitignore +0 -0
- {agentic_python_coder-2.2.0 → agentic_python_coder-2.3.0}/coder/src/agentic_python_coder/examples/__init__.py +0 -0
- {agentic_python_coder-2.2.0 → agentic_python_coder-2.3.0}/coder/src/agentic_python_coder/examples/clingo/README.md +0 -0
- {agentic_python_coder-2.2.0 → agentic_python_coder-2.3.0}/coder/src/agentic_python_coder/examples/clingo/clingo.md +0 -0
- {agentic_python_coder-2.2.0 → agentic_python_coder-2.3.0}/coder/src/agentic_python_coder/examples/clingo/sample_tasks/bird_reasoning.md +0 -0
- {agentic_python_coder-2.2.0 → agentic_python_coder-2.3.0}/coder/src/agentic_python_coder/examples/clingo/sample_tasks/diagnosis.md +0 -0
- {agentic_python_coder-2.2.0 → agentic_python_coder-2.3.0}/coder/src/agentic_python_coder/examples/clingo/sample_tasks/simple_coloring.md +0 -0
- {agentic_python_coder-2.2.0 → agentic_python_coder-2.3.0}/coder/src/agentic_python_coder/examples/clingo/sample_tasks/stable_marriage.md +0 -0
- {agentic_python_coder-2.2.0 → agentic_python_coder-2.3.0}/coder/src/agentic_python_coder/examples/clingo/sample_tasks/sudoku_mini.md +0 -0
- {agentic_python_coder-2.2.0/coder-examples → agentic_python_coder-2.3.0/coder/src/agentic_python_coder/examples}/cpmpy/README.md +0 -0
- {agentic_python_coder-2.2.0/coder-examples → agentic_python_coder-2.3.0/coder/src/agentic_python_coder/examples}/cpmpy/cpmpy.md +0 -0
- {agentic_python_coder-2.2.0/coder-examples → agentic_python_coder-2.3.0/coder/src/agentic_python_coder/examples}/cpmpy/sample_tasks/magic_square.md +0 -0
- {agentic_python_coder-2.2.0/coder-examples → agentic_python_coder-2.3.0/coder/src/agentic_python_coder/examples}/cpmpy/sample_tasks/n_queens.md +0 -0
- {agentic_python_coder-2.2.0 → agentic_python_coder-2.3.0}/coder/src/agentic_python_coder/examples/regex/README.md +0 -0
- {agentic_python_coder-2.2.0 → agentic_python_coder-2.3.0}/coder/src/agentic_python_coder/examples/regex/regex.md +0 -0
- {agentic_python_coder-2.2.0 → agentic_python_coder-2.3.0}/coder/src/agentic_python_coder/examples/regex/sample_tasks/email_extraction.md +0 -0
- {agentic_python_coder-2.2.0 → agentic_python_coder-2.3.0}/coder/src/agentic_python_coder/examples/regex/sample_tasks/phone_validation.md +0 -0
- {agentic_python_coder-2.2.0 → agentic_python_coder-2.3.0}/coder/src/agentic_python_coder/examples/regex/sample_tasks/url_parsing.md +0 -0
- {agentic_python_coder-2.2.0 → agentic_python_coder-2.3.0}/coder/src/agentic_python_coder/models/deepseek31.json +0 -0
- {agentic_python_coder-2.2.0 → agentic_python_coder-2.3.0}/coder/src/agentic_python_coder/models/gemini25.json +0 -0
- {agentic_python_coder-2.2.0 → agentic_python_coder-2.3.0}/coder/src/agentic_python_coder/models/gpt5.json +0 -0
- {agentic_python_coder-2.2.0 → agentic_python_coder-2.3.0}/coder/src/agentic_python_coder/models/grok41.json +0 -0
- {agentic_python_coder-2.2.0 → agentic_python_coder-2.3.0}/coder/src/agentic_python_coder/models/opus45.json +0 -0
- {agentic_python_coder-2.2.0 → agentic_python_coder-2.3.0}/coder/src/agentic_python_coder/models/qwen3.json +0 -0
- {agentic_python_coder-2.2.0 → agentic_python_coder-2.3.0}/coder/src/agentic_python_coder/models/sonnet45.json +0 -0
- {agentic_python_coder-2.2.0 → agentic_python_coder-2.3.0}/coder/src/agentic_python_coder/project_md.py +0 -0
- {agentic_python_coder-2.2.0 → agentic_python_coder-2.3.0}/coder/tests/test_kernel.py +0 -0
- {agentic_python_coder-2.2.0 → agentic_python_coder-2.3.0}/coder/tests/test_todo_flag_integration.py +0 -0
- {agentic_python_coder-2.2.0 → agentic_python_coder-2.3.0}/examples/clingo/README.md +0 -0
- {agentic_python_coder-2.2.0 → agentic_python_coder-2.3.0}/examples/clingo/clingo.md +0 -0
- {agentic_python_coder-2.2.0 → agentic_python_coder-2.3.0}/examples/clingo/sample_tasks/bird_reasoning.md +0 -0
- {agentic_python_coder-2.2.0 → agentic_python_coder-2.3.0}/examples/clingo/sample_tasks/diagnosis.md +0 -0
- {agentic_python_coder-2.2.0 → agentic_python_coder-2.3.0}/examples/clingo/sample_tasks/simple_coloring.md +0 -0
- {agentic_python_coder-2.2.0 → agentic_python_coder-2.3.0}/examples/clingo/sample_tasks/stable_marriage.md +0 -0
- {agentic_python_coder-2.2.0 → agentic_python_coder-2.3.0}/examples/clingo/sample_tasks/sudoku_mini.md +0 -0
- {agentic_python_coder-2.2.0/coder/src/agentic_python_coder → agentic_python_coder-2.3.0}/examples/cpmpy/README.md +0 -0
- {agentic_python_coder-2.2.0/coder/src/agentic_python_coder → agentic_python_coder-2.3.0}/examples/cpmpy/cpmpy.md +0 -0
- {agentic_python_coder-2.2.0/coder/src/agentic_python_coder/examples/cpmpy/sample_tasks → agentic_python_coder-2.3.0/examples/cpmpy/sample_problems}/magic_square.md +0 -0
- {agentic_python_coder-2.2.0/coder/src/agentic_python_coder/examples/cpmpy/sample_tasks → agentic_python_coder-2.3.0/examples/cpmpy/sample_problems}/n_queens.md +0 -0
- {agentic_python_coder-2.2.0 → agentic_python_coder-2.3.0}/examples/regex/README.md +0 -0
- {agentic_python_coder-2.2.0 → agentic_python_coder-2.3.0}/examples/regex/regex.md +0 -0
- {agentic_python_coder-2.2.0 → agentic_python_coder-2.3.0}/examples/regex/sample_tasks/email_extraction.md +0 -0
- {agentic_python_coder-2.2.0 → agentic_python_coder-2.3.0}/examples/regex/sample_tasks/phone_validation.md +0 -0
- {agentic_python_coder-2.2.0 → agentic_python_coder-2.3.0}/examples/regex/sample_tasks/test_email/email_extractor.py +0 -0
- {agentic_python_coder-2.2.0 → agentic_python_coder-2.3.0}/examples/regex/sample_tasks/test_email/extracted_emails.txt +0 -0
- {agentic_python_coder-2.2.0 → agentic_python_coder-2.3.0}/examples/regex/sample_tasks/test_email/text.txt +0 -0
- {agentic_python_coder-2.2.0 → agentic_python_coder-2.3.0}/examples/regex/sample_tasks/url_parsing.md +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agentic-python-coder
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.3.0
|
|
4
4
|
Summary: A lightweight Python coding agent that writes, executes, and iterates on code through natural language instructions
|
|
5
5
|
Author: Stefan Szeider
|
|
6
6
|
License: Apache-2.0
|
|
@@ -14,25 +14,26 @@ Classifier: Programming Language :: Python :: 3.13
|
|
|
14
14
|
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
15
15
|
Classifier: Topic :: Software Development :: Code Generators
|
|
16
16
|
Requires-Python: <3.14,>=3.13
|
|
17
|
-
Requires-Dist: ipykernel>=
|
|
18
|
-
Requires-Dist: jupyter-client>=8.
|
|
19
|
-
Requires-Dist: langchain-anthropic>=1.
|
|
20
|
-
Requires-Dist: langchain-core>=1.
|
|
21
|
-
Requires-Dist: langchain-experimental>=0.4.
|
|
22
|
-
Requires-Dist: langchain-openai>=1.1.
|
|
23
|
-
Requires-Dist:
|
|
17
|
+
Requires-Dist: ipykernel>=7.0.0
|
|
18
|
+
Requires-Dist: jupyter-client>=8.7.0
|
|
19
|
+
Requires-Dist: langchain-anthropic>=1.3.0
|
|
20
|
+
Requires-Dist: langchain-core>=1.2.0
|
|
21
|
+
Requires-Dist: langchain-experimental>=0.4.1
|
|
22
|
+
Requires-Dist: langchain-openai>=1.1.6
|
|
23
|
+
Requires-Dist: langchain>=1.2.0
|
|
24
|
+
Requires-Dist: langgraph>=1.0.5
|
|
24
25
|
Requires-Dist: mcp>=1.0.0
|
|
25
26
|
Requires-Dist: python-dotenv>=1.2.1
|
|
26
27
|
Requires-Dist: pyyaml>=6.0.3
|
|
27
28
|
Requires-Dist: rich>=14.2.0
|
|
28
29
|
Provides-Extra: dev
|
|
29
|
-
Requires-Dist: mypy>=1.19.
|
|
30
|
-
Requires-Dist: ruff>=0.14.
|
|
30
|
+
Requires-Dist: mypy>=1.19.1; extra == 'dev'
|
|
31
|
+
Requires-Dist: ruff>=0.14.10; extra == 'dev'
|
|
31
32
|
Provides-Extra: test
|
|
32
|
-
Requires-Dist: pytest-asyncio>=1.
|
|
33
|
+
Requires-Dist: pytest-asyncio>=1.3.0; extra == 'test'
|
|
33
34
|
Requires-Dist: pytest-cov>=7.0.0; extra == 'test'
|
|
34
35
|
Requires-Dist: pytest-watch>=4.2.0; extra == 'test'
|
|
35
|
-
Requires-Dist: pytest>=9.0.
|
|
36
|
+
Requires-Dist: pytest>=9.0.2; extra == 'test'
|
|
36
37
|
Description-Content-Type: text/markdown
|
|
37
38
|
|
|
38
39
|
# Agentic Python Coder
|
|
@@ -291,17 +292,32 @@ Add to your MCP settings (e.g., `~/.claude/claude_desktop_config.json` or projec
|
|
|
291
292
|
| Tool | Description |
|
|
292
293
|
|------|-------------|
|
|
293
294
|
| `python_exec` | Execute Python code. Auto-starts session if needed. Default 30s timeout. |
|
|
294
|
-
| `python_reset` |
|
|
295
|
-
| `python_status` | Check
|
|
295
|
+
| `python_reset` | Create new kernel (no `kernel_id`) OR reset existing kernel (with `kernel_id`). Optionally install packages. |
|
|
296
|
+
| `python_status` | Check session state: active flag, all active kernel IDs, Python version, packages, variables. |
|
|
296
297
|
| `python_interrupt` | Send interrupt signal to stop long-running code. Session state is preserved. |
|
|
297
298
|
|
|
299
|
+
### Multi-Agent Workflow
|
|
300
|
+
|
|
301
|
+
For parallel agents, each agent gets its own kernel:
|
|
302
|
+
|
|
303
|
+
```
|
|
304
|
+
Agent A Agent B
|
|
305
|
+
──────── ────────
|
|
306
|
+
python_reset() → kernel_id="aaa" python_reset() → kernel_id="bbb"
|
|
307
|
+
python_exec(kernel_id="aaa", ...) python_exec(kernel_id="bbb", ...)
|
|
308
|
+
python_exec(kernel_id="aaa", ...) python_exec(kernel_id="bbb", ...)
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
Simple single-agent use: just call `python_exec()` — the default kernel auto-starts.
|
|
312
|
+
|
|
298
313
|
### Features
|
|
299
314
|
|
|
300
315
|
- **Persistent state**: Variables, imports, and definitions persist across executions
|
|
301
|
-
- **Auto-start**:
|
|
316
|
+
- **Auto-start**: Default session starts automatically on first `python_exec`
|
|
302
317
|
- **Package installation**: Use `python_reset` with `packages` parameter to install dependencies
|
|
303
318
|
- **Timeout handling**: Long-running code times out gracefully (session preserved)
|
|
304
319
|
- **Interrupt support**: Stop runaway code without losing session state
|
|
320
|
+
- **Multi-kernel**: Each `python_reset()` creates an isolated kernel for parallel agents
|
|
305
321
|
|
|
306
322
|
### Usage Tips
|
|
307
323
|
|
|
@@ -254,17 +254,32 @@ Add to your MCP settings (e.g., `~/.claude/claude_desktop_config.json` or projec
|
|
|
254
254
|
| Tool | Description |
|
|
255
255
|
|------|-------------|
|
|
256
256
|
| `python_exec` | Execute Python code. Auto-starts session if needed. Default 30s timeout. |
|
|
257
|
-
| `python_reset` |
|
|
258
|
-
| `python_status` | Check
|
|
257
|
+
| `python_reset` | Create new kernel (no `kernel_id`) OR reset existing kernel (with `kernel_id`). Optionally install packages. |
|
|
258
|
+
| `python_status` | Check session state: active flag, all active kernel IDs, Python version, packages, variables. |
|
|
259
259
|
| `python_interrupt` | Send interrupt signal to stop long-running code. Session state is preserved. |
|
|
260
260
|
|
|
261
|
+
### Multi-Agent Workflow
|
|
262
|
+
|
|
263
|
+
For parallel agents, each agent gets its own kernel:
|
|
264
|
+
|
|
265
|
+
```
|
|
266
|
+
Agent A Agent B
|
|
267
|
+
──────── ────────
|
|
268
|
+
python_reset() → kernel_id="aaa" python_reset() → kernel_id="bbb"
|
|
269
|
+
python_exec(kernel_id="aaa", ...) python_exec(kernel_id="bbb", ...)
|
|
270
|
+
python_exec(kernel_id="aaa", ...) python_exec(kernel_id="bbb", ...)
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
Simple single-agent use: just call `python_exec()` — the default kernel auto-starts.
|
|
274
|
+
|
|
261
275
|
### Features
|
|
262
276
|
|
|
263
277
|
- **Persistent state**: Variables, imports, and definitions persist across executions
|
|
264
|
-
- **Auto-start**:
|
|
278
|
+
- **Auto-start**: Default session starts automatically on first `python_exec`
|
|
265
279
|
- **Package installation**: Use `python_reset` with `packages` parameter to install dependencies
|
|
266
280
|
- **Timeout handling**: Long-running code times out gracefully (session preserved)
|
|
267
281
|
- **Interrupt support**: Stop runaway code without losing session state
|
|
282
|
+
- **Multi-kernel**: Each `python_reset()` creates an isolated kernel for parallel agents
|
|
268
283
|
|
|
269
284
|
### Usage Tips
|
|
270
285
|
|
|
@@ -16,19 +16,12 @@ You have access to these specialized tools:
|
|
|
16
16
|
- Call this ONCE when you have a complete, working solution
|
|
17
17
|
- The code will be saved to {basename}_code.py
|
|
18
18
|
|
|
19
|
-
3. **report_issue**: Provide feedback and summary
|
|
20
|
-
- Use at the end to summarize what was accomplished
|
|
21
|
-
- Report any issues, ambiguities, or difficulties encountered
|
|
22
|
-
- Also report if everything worked perfectly
|
|
23
|
-
- This feedback will be included in the log file
|
|
24
|
-
|
|
25
19
|
## Workflow
|
|
26
20
|
|
|
27
21
|
1. **Understand the Task**: Read the problem in the <task> section carefully
|
|
28
22
|
2. **Plan Your Approach**: Think through the problem and plan your solution strategy
|
|
29
23
|
3. **Develop Solution**: Use python_exec iteratively to build and test
|
|
30
24
|
4. **Save Final Code**: Call save_code with your complete solution
|
|
31
|
-
5. **Provide Feedback**: Use report_issue to summarize and provide feedback
|
|
32
25
|
|
|
33
26
|
## Python Execution Best Practices
|
|
34
27
|
|
|
@@ -68,8 +61,7 @@ Build solutions incrementally:
|
|
|
68
61
|
1. **Focus on the Task**: Complete what's requested, nothing more
|
|
69
62
|
2. **Test Efficiently**: One or two test cases are usually sufficient
|
|
70
63
|
3. **Save Once**: Call save_code only when you have the final code
|
|
71
|
-
4. **
|
|
72
|
-
5. **Stop When Done**: Don't add features not requested
|
|
64
|
+
4. **Stop When Done**: Don't add features not requested
|
|
73
65
|
|
|
74
66
|
## Error Recovery
|
|
75
67
|
|
|
@@ -94,10 +86,6 @@ When finishing:
|
|
|
94
86
|
1. Verify the solution works correctly
|
|
95
87
|
2. Clean the code according to the **Code Cleaning Requirements** above
|
|
96
88
|
3. Call save_code with the complete, cleaned code
|
|
97
|
-
4.
|
|
98
|
-
- Summarize what was accomplished
|
|
99
|
-
- Report any issues, ambiguities, or difficulties encountered
|
|
100
|
-
- Even if everything worked perfectly, report: "All is fine - no issues encountered."
|
|
101
|
-
5. STOP - do not continue unless asked
|
|
89
|
+
4. STOP - do not continue unless asked
|
|
102
90
|
|
|
103
|
-
Your goal is efficient, focused problem-solving.
|
|
91
|
+
Your goal is efficient, focused problem-solving.
|
|
@@ -16,35 +16,28 @@ You have access to these specialized tools:
|
|
|
16
16
|
- Call this ONCE when you have a complete, working solution
|
|
17
17
|
- The code will be saved to {basename}_code.py
|
|
18
18
|
|
|
19
|
-
3. **
|
|
20
|
-
- Use at the end to summarize what was accomplished
|
|
21
|
-
- Report any issues, ambiguities, or difficulties encountered
|
|
22
|
-
- Also report if everything worked perfectly
|
|
23
|
-
- This feedback will be included in the log file
|
|
24
|
-
|
|
25
|
-
4. **todo_write**: MANDATORY task management tool
|
|
19
|
+
3. **todo_write**: MANDATORY task management tool
|
|
26
20
|
- You MUST use this tool after understanding the problem
|
|
27
21
|
- Create a todo list with items appropriate to the problem complexity
|
|
28
22
|
(ranging from 3 simple items to over a dozen for complex problems)
|
|
29
23
|
- Update todo item status as you progress (pending → in_progress → completed)
|
|
30
24
|
- Only ONE todo item can be in_progress at a time
|
|
31
25
|
- Add new todo items if you discover additional work needed
|
|
32
|
-
- Your last
|
|
26
|
+
- Your last two todo items should always be: "Clean final code" and "Save final code"
|
|
33
27
|
|
|
34
28
|
## Workflow
|
|
35
29
|
|
|
36
30
|
1. **Understand the Task**: Read the problem in the <task> section carefully
|
|
37
|
-
2. **Plan Your Approach** (MANDATORY):
|
|
31
|
+
2. **Plan Your Approach** (MANDATORY):
|
|
38
32
|
- Use todo_write to create your todo list based on your understanding
|
|
39
33
|
- The number of todo items should match problem complexity (3-12+ items)
|
|
40
|
-
- Include "Save final code"
|
|
34
|
+
- Include "Save final code" as your last item
|
|
41
35
|
- This demonstrates planning and helps track progress
|
|
42
36
|
3. **Develop Solution**: Use python_exec iteratively to build and test
|
|
43
37
|
- Mark todo items as in_progress when starting them
|
|
44
38
|
- Mark as completed when done
|
|
45
|
-
4. **Clean Final Code**: Clean the code according to Code Cleaning Requirements (
|
|
46
|
-
5. **Save Final Code**: Call save_code with your complete, cleaned solution (
|
|
47
|
-
6. **Provide Feedback**: Use report_issue to summarize and provide feedback (final todo item)
|
|
39
|
+
4. **Clean Final Code**: Clean the code according to Code Cleaning Requirements (second-to-last todo item)
|
|
40
|
+
5. **Save Final Code**: Call save_code with your complete, cleaned solution (final todo item)
|
|
48
41
|
|
|
49
42
|
## Python Execution Best Practices
|
|
50
43
|
|
|
@@ -85,8 +78,7 @@ Build solutions incrementally:
|
|
|
85
78
|
2. **Focus on the Task**: Complete what's requested, nothing more
|
|
86
79
|
3. **Test Efficiently**: One or two test cases are usually sufficient
|
|
87
80
|
4. **Save Once**: Call save_code only when you have the final code
|
|
88
|
-
5. **
|
|
89
|
-
6. **Stop When Done**: Don't add features not requested
|
|
81
|
+
5. **Stop When Done**: Don't add features not requested
|
|
90
82
|
|
|
91
83
|
## Error Recovery
|
|
92
84
|
|
|
@@ -111,13 +103,9 @@ When finishing (these should be your final todo items):
|
|
|
111
103
|
1. Ensure all todo items are marked as completed
|
|
112
104
|
2. Verify the solution works correctly
|
|
113
105
|
3. Clean the code according to the **Code Cleaning Requirements** above
|
|
114
|
-
4. Call save_code with the complete, cleaned code (
|
|
115
|
-
5.
|
|
116
|
-
- Summarize what was accomplished
|
|
117
|
-
- Report any issues, ambiguities, or difficulties encountered
|
|
118
|
-
- Even if everything worked perfectly, report: "All is fine - no issues encountered."
|
|
119
|
-
6. STOP - do not continue unless asked
|
|
106
|
+
4. Call save_code with the complete, cleaned code (final todo item)
|
|
107
|
+
5. STOP - do not continue unless asked
|
|
120
108
|
|
|
121
109
|
Note: Your todo list should show a clear progression from planning through completion.
|
|
122
110
|
|
|
123
|
-
Your goal is efficient, focused problem-solving.
|
|
111
|
+
Your goal is efficient, focused problem-solving.
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"""Python Coding Agent - A minimal coding assistant using LangGraph and OpenRouter."""
|
|
2
|
+
|
|
3
|
+
__version__ = "2.3.0"
|
|
4
|
+
|
|
5
|
+
# High-level API (recommended for most users)
|
|
6
|
+
from agentic_python_coder.runner import solve_task
|
|
7
|
+
|
|
8
|
+
# Lower-level API (for custom workflows)
|
|
9
|
+
from agentic_python_coder.agent import (
|
|
10
|
+
create_coding_agent,
|
|
11
|
+
run_agent,
|
|
12
|
+
get_final_response,
|
|
13
|
+
DEFAULT_STEP_LIMIT,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
# LLM utilities
|
|
17
|
+
from agentic_python_coder.llm import (
|
|
18
|
+
get_openrouter_llm,
|
|
19
|
+
load_model_config,
|
|
20
|
+
list_available_models,
|
|
21
|
+
DEFAULT_MODEL,
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
# Kernel management (multi-kernel API)
|
|
25
|
+
from agentic_python_coder.kernel import (
|
|
26
|
+
# Core functions
|
|
27
|
+
create_kernel,
|
|
28
|
+
execute_in_kernel,
|
|
29
|
+
shutdown_kernel_by_id,
|
|
30
|
+
interrupt_kernel_by_id,
|
|
31
|
+
restart_kernel,
|
|
32
|
+
# Query functions
|
|
33
|
+
list_kernels,
|
|
34
|
+
kernel_exists,
|
|
35
|
+
get_kernel_info,
|
|
36
|
+
shutdown_all_kernels,
|
|
37
|
+
# Backward compat
|
|
38
|
+
get_kernel,
|
|
39
|
+
shutdown_kernel,
|
|
40
|
+
# Constants
|
|
41
|
+
DEFAULT_KERNEL_ID,
|
|
42
|
+
MAX_KERNELS,
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
__all__ = [
|
|
46
|
+
# Version
|
|
47
|
+
"__version__",
|
|
48
|
+
# High-level
|
|
49
|
+
"solve_task",
|
|
50
|
+
# Low-level agent
|
|
51
|
+
"create_coding_agent",
|
|
52
|
+
"run_agent",
|
|
53
|
+
"get_final_response",
|
|
54
|
+
"DEFAULT_STEP_LIMIT",
|
|
55
|
+
# LLM
|
|
56
|
+
"get_openrouter_llm",
|
|
57
|
+
"load_model_config",
|
|
58
|
+
"list_available_models",
|
|
59
|
+
"DEFAULT_MODEL",
|
|
60
|
+
# Kernel management
|
|
61
|
+
"create_kernel",
|
|
62
|
+
"execute_in_kernel",
|
|
63
|
+
"shutdown_kernel_by_id",
|
|
64
|
+
"interrupt_kernel_by_id",
|
|
65
|
+
"restart_kernel",
|
|
66
|
+
"list_kernels",
|
|
67
|
+
"kernel_exists",
|
|
68
|
+
"get_kernel_info",
|
|
69
|
+
"shutdown_all_kernels",
|
|
70
|
+
"get_kernel",
|
|
71
|
+
"shutdown_kernel",
|
|
72
|
+
"DEFAULT_KERNEL_ID",
|
|
73
|
+
"MAX_KERNELS",
|
|
74
|
+
]
|
{agentic_python_coder-2.2.0 → agentic_python_coder-2.3.0}/coder/src/agentic_python_coder/agent.py
RENAMED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
"""ReAct agent for Python coding tasks."""
|
|
2
2
|
|
|
3
|
+
import json
|
|
4
|
+
import os
|
|
5
|
+
import time
|
|
3
6
|
from typing import Dict, Any, List, Optional
|
|
4
7
|
from pathlib import Path
|
|
5
|
-
from
|
|
8
|
+
from langchain.agents import create_agent
|
|
6
9
|
from langgraph.checkpoint.memory import InMemorySaver
|
|
7
10
|
|
|
8
11
|
from agentic_python_coder.llm import get_openrouter_llm
|
|
@@ -10,7 +13,6 @@ from agentic_python_coder.tools import (
|
|
|
10
13
|
todo_write,
|
|
11
14
|
python_exec,
|
|
12
15
|
save_code,
|
|
13
|
-
report_issue,
|
|
14
16
|
working_dir,
|
|
15
17
|
set_task_basename,
|
|
16
18
|
reset_global_state,
|
|
@@ -46,7 +48,7 @@ def create_coding_agent(
|
|
|
46
48
|
working_directory: Directory for file operations
|
|
47
49
|
system_prompt: System prompt as string (takes precedence over path)
|
|
48
50
|
system_prompt_path: Path to system prompt file (used if system_prompt not provided)
|
|
49
|
-
model: Optional model name (
|
|
51
|
+
model: Optional model name (uses configured default if not specified)
|
|
50
52
|
project_prompt: Optional project-specific prompt
|
|
51
53
|
with_packages: Optional list of packages for dynamic mode
|
|
52
54
|
task_content: Task description/content
|
|
@@ -67,8 +69,6 @@ def create_coding_agent(
|
|
|
67
69
|
|
|
68
70
|
# Store packages for kernel initialization
|
|
69
71
|
if with_packages is not None:
|
|
70
|
-
import os
|
|
71
|
-
|
|
72
72
|
os.environ["CODER_WITH_PACKAGES"] = ",".join(with_packages)
|
|
73
73
|
|
|
74
74
|
# Get LLM instance
|
|
@@ -80,9 +80,9 @@ def create_coding_agent(
|
|
|
80
80
|
|
|
81
81
|
# Minimal tool set
|
|
82
82
|
if todo:
|
|
83
|
-
tools = [python_exec, save_code,
|
|
83
|
+
tools = [python_exec, save_code, todo_write]
|
|
84
84
|
else:
|
|
85
|
-
tools = [python_exec, save_code
|
|
85
|
+
tools = [python_exec, save_code]
|
|
86
86
|
|
|
87
87
|
# Build combined prompt
|
|
88
88
|
prompts = []
|
|
@@ -109,15 +109,13 @@ def create_coding_agent(
|
|
|
109
109
|
|
|
110
110
|
# Create the agent with memory
|
|
111
111
|
checkpointer = InMemorySaver()
|
|
112
|
-
agent =
|
|
113
|
-
llm, tools,
|
|
112
|
+
agent = create_agent(
|
|
113
|
+
llm, tools, system_prompt=combined_prompt, checkpointer=checkpointer
|
|
114
114
|
)
|
|
115
115
|
|
|
116
116
|
# Store metadata for run_agent to use
|
|
117
117
|
agent._coder_metadata = {
|
|
118
118
|
"working_directory": working_directory,
|
|
119
|
-
"with_packages": with_packages,
|
|
120
|
-
"task_basename": task_basename,
|
|
121
119
|
}
|
|
122
120
|
|
|
123
121
|
return agent
|
|
@@ -127,24 +125,21 @@ def _print_tool_progress(tool_name: str, args: dict):
|
|
|
127
125
|
"""Print progress info for a tool call."""
|
|
128
126
|
if tool_name == "python_exec" and "code" in args:
|
|
129
127
|
code = args["code"]
|
|
128
|
+
code_stripped = code.strip()
|
|
130
129
|
if "def " in code:
|
|
131
|
-
func_match = code.split("def ")[1].split("(")[0]
|
|
130
|
+
func_match = code.split("def ")[1].split("(")[0]
|
|
132
131
|
print(f" {tool_name}: defining function {func_match}()")
|
|
133
132
|
elif "class " in code:
|
|
134
|
-
class_match = (
|
|
135
|
-
code.split("class ")[1].split("(")[0].split(":")[0]
|
|
136
|
-
if "class " in code
|
|
137
|
-
else ""
|
|
138
|
-
)
|
|
133
|
+
class_match = code.split("class ")[1].split("(")[0].split(":")[0]
|
|
139
134
|
print(f" {tool_name}: defining class {class_match}")
|
|
140
|
-
elif "import " in code and len(
|
|
141
|
-
print(f" {tool_name}: {
|
|
142
|
-
elif "=" in code and len(
|
|
135
|
+
elif "import " in code and len(code_stripped.split("\n")) == 1:
|
|
136
|
+
print(f" {tool_name}: {code_stripped}")
|
|
137
|
+
elif "=" in code and len(code_stripped.split("\n")) == 1:
|
|
143
138
|
var_name = code.split("=")[0].strip()
|
|
144
139
|
print(f" {tool_name}: assigning variable {var_name}")
|
|
145
|
-
elif
|
|
140
|
+
elif code_stripped.startswith("print("):
|
|
146
141
|
print(
|
|
147
|
-
f" {tool_name}: {
|
|
142
|
+
f" {tool_name}: {code_stripped[:50]}{'...' if len(code_stripped) > 50 else ''}"
|
|
148
143
|
)
|
|
149
144
|
elif "read_csv" in code or "read_excel" in code or "read_json" in code:
|
|
150
145
|
print(f" {tool_name}: loading data file")
|
|
@@ -171,32 +166,23 @@ def _print_tool_progress(tool_name: str, args: dict):
|
|
|
171
166
|
print(f"\n {tool_name}:")
|
|
172
167
|
todos = args["todos"]
|
|
173
168
|
for todo in todos:
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
if todo["status"] == "pending"
|
|
179
|
-
else "▶"
|
|
180
|
-
)
|
|
181
|
-
print(f" {status_symbol} {todo['content']}")
|
|
169
|
+
status = todo.get("status", "")
|
|
170
|
+
content = todo.get("content", "")
|
|
171
|
+
status_symbol = "☒" if status == "completed" else "☐" if status == "pending" else "▶"
|
|
172
|
+
print(f" {status_symbol} {content}")
|
|
182
173
|
else:
|
|
183
|
-
|
|
184
|
-
if len(
|
|
185
|
-
|
|
186
|
-
print(f" {tool_name}: {arg_str}")
|
|
174
|
+
args_str = str(args)
|
|
175
|
+
arg_display = args_str[:30] + "..." if len(args_str) > 30 else args_str
|
|
176
|
+
print(f" {tool_name}: {arg_display}")
|
|
187
177
|
|
|
188
178
|
|
|
189
|
-
def _process_tool_calls(msg,
|
|
179
|
+
def _process_tool_calls(msg, stats: dict, quiet: bool):
|
|
190
180
|
"""Process tool calls from a message, updating stats and optionally printing."""
|
|
191
181
|
if hasattr(msg, "tool_calls") and msg.tool_calls:
|
|
192
182
|
for tool_call in msg.tool_calls:
|
|
193
183
|
tool_name = tool_call.get("name") or tool_call.get("function", {}).get(
|
|
194
184
|
"name"
|
|
195
185
|
)
|
|
196
|
-
tool_id = tool_call.get("id")
|
|
197
|
-
if tool_id:
|
|
198
|
-
current_tools[tool_id] = tool_name
|
|
199
|
-
|
|
200
186
|
if tool_name:
|
|
201
187
|
stats["tool_usage"][tool_name] = (
|
|
202
188
|
stats["tool_usage"].get(tool_name, 0) + 1
|
|
@@ -214,9 +200,6 @@ def _process_tool_calls(msg, current_tools: dict, stats: dict, quiet: bool):
|
|
|
214
200
|
for tool_call in tool_calls:
|
|
215
201
|
function = tool_call.get("function", {})
|
|
216
202
|
tool_name = function.get("name")
|
|
217
|
-
tool_id = tool_call.get("id")
|
|
218
|
-
if tool_id and tool_name:
|
|
219
|
-
current_tools[tool_id] = tool_name
|
|
220
203
|
|
|
221
204
|
if tool_name:
|
|
222
205
|
stats["tool_usage"][tool_name] = (
|
|
@@ -226,11 +209,9 @@ def _process_tool_calls(msg, current_tools: dict, stats: dict, quiet: bool):
|
|
|
226
209
|
if not quiet and tool_name:
|
|
227
210
|
args_str = function.get("arguments", "{}")
|
|
228
211
|
try:
|
|
229
|
-
import json
|
|
230
|
-
|
|
231
212
|
args = json.loads(args_str)
|
|
232
213
|
_print_tool_progress(tool_name, args)
|
|
233
|
-
except
|
|
214
|
+
except json.JSONDecodeError:
|
|
234
215
|
print(f" {tool_name}")
|
|
235
216
|
|
|
236
217
|
|
|
@@ -244,6 +225,7 @@ def _update_token_stats(msg, stats: dict):
|
|
|
244
225
|
"completion_tokens", 0
|
|
245
226
|
)
|
|
246
227
|
stats["token_consumption"]["total_tokens"] += usage.get("total_tokens", 0)
|
|
228
|
+
return # Avoid double-counting if both metadata sources exist
|
|
247
229
|
|
|
248
230
|
if hasattr(msg, "usage_metadata") and msg.usage_metadata:
|
|
249
231
|
stats["token_consumption"]["input_tokens"] += msg.usage_metadata.get(
|
|
@@ -286,7 +268,6 @@ def run_agent(
|
|
|
286
268
|
config = {"configurable": {"thread_id": thread_id}, "recursion_limit": limit}
|
|
287
269
|
|
|
288
270
|
messages = []
|
|
289
|
-
current_tools = {}
|
|
290
271
|
|
|
291
272
|
# Initialize statistics
|
|
292
273
|
stats = {
|
|
@@ -295,8 +276,6 @@ def run_agent(
|
|
|
295
276
|
"execution_time_seconds": 0,
|
|
296
277
|
}
|
|
297
278
|
|
|
298
|
-
import time
|
|
299
|
-
|
|
300
279
|
start_time = time.time()
|
|
301
280
|
|
|
302
281
|
# Stream the agent's work
|
|
@@ -314,7 +293,7 @@ def run_agent(
|
|
|
314
293
|
messages.append(msg)
|
|
315
294
|
|
|
316
295
|
# Process tool calls (always update stats, optionally print)
|
|
317
|
-
_process_tool_calls(msg,
|
|
296
|
+
_process_tool_calls(msg, stats, quiet)
|
|
318
297
|
|
|
319
298
|
# Update token statistics
|
|
320
299
|
_update_token_stats(msg, stats)
|
{agentic_python_coder-2.2.0 → agentic_python_coder-2.3.0}/coder/src/agentic_python_coder/cli.py
RENAMED
|
@@ -23,7 +23,11 @@ from agentic_python_coder.project_md import (
|
|
|
23
23
|
check_packages_available,
|
|
24
24
|
create_project_prompt,
|
|
25
25
|
)
|
|
26
|
-
from agentic_python_coder.llm import
|
|
26
|
+
from agentic_python_coder.llm import (
|
|
27
|
+
DEFAULT_MODEL,
|
|
28
|
+
list_available_models,
|
|
29
|
+
load_model_config,
|
|
30
|
+
)
|
|
27
31
|
from agentic_python_coder import __version__
|
|
28
32
|
|
|
29
33
|
|
|
@@ -88,7 +92,8 @@ def parse_args():
|
|
|
88
92
|
)
|
|
89
93
|
|
|
90
94
|
parser.add_argument(
|
|
91
|
-
"--version",
|
|
95
|
+
"--version",
|
|
96
|
+
"-V",
|
|
92
97
|
action="version",
|
|
93
98
|
version=f"%(prog)s {__version__}",
|
|
94
99
|
)
|
|
@@ -106,7 +111,9 @@ def parse_args():
|
|
|
106
111
|
help="Path to task file (creates {basename}_code.py and {basename}.jsonl)",
|
|
107
112
|
)
|
|
108
113
|
|
|
109
|
-
parser.add_argument(
|
|
114
|
+
parser.add_argument(
|
|
115
|
+
"--model", help=f"Model name or JSON file (default: {DEFAULT_MODEL})"
|
|
116
|
+
)
|
|
110
117
|
|
|
111
118
|
parser.add_argument(
|
|
112
119
|
"--interactive", "-i", action="store_true", help="Interactive mode"
|
|
@@ -145,7 +152,8 @@ def parse_args():
|
|
|
145
152
|
)
|
|
146
153
|
|
|
147
154
|
parser.add_argument(
|
|
148
|
-
"--quiet",
|
|
155
|
+
"--quiet",
|
|
156
|
+
"-q",
|
|
149
157
|
action="store_true",
|
|
150
158
|
help="Suppress console output during execution",
|
|
151
159
|
)
|
|
@@ -176,13 +184,13 @@ def copy_resource_dir(source_path, dest_path: Path):
|
|
|
176
184
|
dest_item = dest_path / item.name
|
|
177
185
|
if item.is_file():
|
|
178
186
|
# Skip __pycache__ and .pyc files
|
|
179
|
-
if item.name.endswith(
|
|
187
|
+
if item.name.endswith(".pyc") or item.name == "__pycache__":
|
|
180
188
|
continue
|
|
181
189
|
# Read and write file content
|
|
182
190
|
content = item.read_bytes()
|
|
183
191
|
dest_item.write_bytes(content)
|
|
184
192
|
elif item.is_dir():
|
|
185
|
-
if item.name ==
|
|
193
|
+
if item.name == "__pycache__":
|
|
186
194
|
continue
|
|
187
195
|
copy_resource_dir(item, dest_item)
|
|
188
196
|
|
|
@@ -216,7 +224,9 @@ def init_examples(template: str = "all"):
|
|
|
216
224
|
|
|
217
225
|
print(f"\nExamples initialized in: {output_dir.absolute()}")
|
|
218
226
|
print("\nUsage:")
|
|
219
|
-
print(
|
|
227
|
+
print(
|
|
228
|
+
f" coder --with cpmpy --project {output_dir}/cpmpy/cpmpy.md --task {output_dir}/cpmpy/sample_tasks/n_queens.md"
|
|
229
|
+
)
|
|
220
230
|
|
|
221
231
|
|
|
222
232
|
def validate_packages(packages):
|