agentic-python-coder 2.2.1__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.1 → agentic_python_coder-2.3.0}/PKG-INFO +31 -15
- {agentic_python_coder-2.2.1 → agentic_python_coder-2.3.0}/README.md +18 -3
- agentic_python_coder-2.3.0/coder/src/agentic_python_coder/__init__.py +74 -0
- {agentic_python_coder-2.2.1 → agentic_python_coder-2.3.0}/coder/src/agentic_python_coder/agent.py +26 -46
- {agentic_python_coder-2.2.1 → 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.1 → 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.1 → agentic_python_coder-2.3.0}/coder/tests/test_library_api.py +7 -7
- {agentic_python_coder-2.2.1 → agentic_python_coder-2.3.0}/coder/tests/test_mcp_server.py +109 -20
- {agentic_python_coder-2.2.1 → agentic_python_coder-2.3.0}/pyproject.toml +13 -12
- agentic_python_coder-2.2.1/coder/src/agentic_python_coder/__init__.py +0 -39
- agentic_python_coder-2.2.1/coder/src/agentic_python_coder/kernel.py +0 -343
- agentic_python_coder-2.2.1/coder/src/agentic_python_coder/mcp_server.py +0 -485
- {agentic_python_coder-2.2.1 → agentic_python_coder-2.3.0}/.gitignore +0 -0
- {agentic_python_coder-2.2.1 → agentic_python_coder-2.3.0}/LICENSE +0 -0
- {agentic_python_coder-2.2.1 → agentic_python_coder-2.3.0}/coder/.gitignore +0 -0
- {agentic_python_coder-2.2.1 → agentic_python_coder-2.3.0}/coder/prompts/system.md +0 -0
- {agentic_python_coder-2.2.1 → agentic_python_coder-2.3.0}/coder/prompts/system_todo.md +0 -0
- {agentic_python_coder-2.2.1 → agentic_python_coder-2.3.0}/coder/src/agentic_python_coder/examples/__init__.py +0 -0
- {agentic_python_coder-2.2.1 → agentic_python_coder-2.3.0}/coder/src/agentic_python_coder/examples/clingo/README.md +0 -0
- {agentic_python_coder-2.2.1 → agentic_python_coder-2.3.0}/coder/src/agentic_python_coder/examples/clingo/clingo.md +0 -0
- {agentic_python_coder-2.2.1 → 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.1 → agentic_python_coder-2.3.0}/coder/src/agentic_python_coder/examples/clingo/sample_tasks/diagnosis.md +0 -0
- {agentic_python_coder-2.2.1 → 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.1 → 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.1 → 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.1 → agentic_python_coder-2.3.0}/coder/src/agentic_python_coder/examples/cpmpy/README.md +0 -0
- {agentic_python_coder-2.2.1 → agentic_python_coder-2.3.0}/coder/src/agentic_python_coder/examples/cpmpy/cpmpy.md +0 -0
- {agentic_python_coder-2.2.1 → 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.1 → 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.1 → agentic_python_coder-2.3.0}/coder/src/agentic_python_coder/examples/regex/README.md +0 -0
- {agentic_python_coder-2.2.1 → agentic_python_coder-2.3.0}/coder/src/agentic_python_coder/examples/regex/regex.md +0 -0
- {agentic_python_coder-2.2.1 → 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.1 → 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.1 → 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.1 → agentic_python_coder-2.3.0}/coder/src/agentic_python_coder/models/deepseek31.json +0 -0
- {agentic_python_coder-2.2.1 → agentic_python_coder-2.3.0}/coder/src/agentic_python_coder/models/gemini25.json +0 -0
- {agentic_python_coder-2.2.1 → agentic_python_coder-2.3.0}/coder/src/agentic_python_coder/models/gpt5.json +0 -0
- {agentic_python_coder-2.2.1 → agentic_python_coder-2.3.0}/coder/src/agentic_python_coder/models/grok41.json +0 -0
- {agentic_python_coder-2.2.1 → agentic_python_coder-2.3.0}/coder/src/agentic_python_coder/models/opus45.json +0 -0
- {agentic_python_coder-2.2.1 → agentic_python_coder-2.3.0}/coder/src/agentic_python_coder/models/qwen3.json +0 -0
- {agentic_python_coder-2.2.1 → agentic_python_coder-2.3.0}/coder/src/agentic_python_coder/models/sonnet45.json +0 -0
- {agentic_python_coder-2.2.1 → agentic_python_coder-2.3.0}/coder/src/agentic_python_coder/project_md.py +0 -0
- {agentic_python_coder-2.2.1 → agentic_python_coder-2.3.0}/coder/src/agentic_python_coder/runner.py +0 -0
- {agentic_python_coder-2.2.1 → agentic_python_coder-2.3.0}/coder/src/agentic_python_coder/tools.py +0 -0
- {agentic_python_coder-2.2.1 → agentic_python_coder-2.3.0}/coder/tests/test_kernel.py +0 -0
- {agentic_python_coder-2.2.1 → agentic_python_coder-2.3.0}/coder/tests/test_todo_flag_integration.py +0 -0
- {agentic_python_coder-2.2.1 → agentic_python_coder-2.3.0}/coder/tests/test_todo_tool_availability.py +0 -0
- {agentic_python_coder-2.2.1 → agentic_python_coder-2.3.0}/examples/clingo/README.md +0 -0
- {agentic_python_coder-2.2.1 → agentic_python_coder-2.3.0}/examples/clingo/clingo.md +0 -0
- {agentic_python_coder-2.2.1 → agentic_python_coder-2.3.0}/examples/clingo/sample_tasks/bird_reasoning.md +0 -0
- {agentic_python_coder-2.2.1 → agentic_python_coder-2.3.0}/examples/clingo/sample_tasks/diagnosis.md +0 -0
- {agentic_python_coder-2.2.1 → agentic_python_coder-2.3.0}/examples/clingo/sample_tasks/simple_coloring.md +0 -0
- {agentic_python_coder-2.2.1 → agentic_python_coder-2.3.0}/examples/clingo/sample_tasks/stable_marriage.md +0 -0
- {agentic_python_coder-2.2.1 → agentic_python_coder-2.3.0}/examples/clingo/sample_tasks/sudoku_mini.md +0 -0
- {agentic_python_coder-2.2.1 → agentic_python_coder-2.3.0}/examples/cpmpy/README.md +0 -0
- {agentic_python_coder-2.2.1 → agentic_python_coder-2.3.0}/examples/cpmpy/cpmpy.md +0 -0
- {agentic_python_coder-2.2.1 → agentic_python_coder-2.3.0}/examples/cpmpy/sample_problems/magic_square.md +0 -0
- {agentic_python_coder-2.2.1 → agentic_python_coder-2.3.0}/examples/cpmpy/sample_problems/n_queens.md +0 -0
- {agentic_python_coder-2.2.1 → agentic_python_coder-2.3.0}/examples/regex/README.md +0 -0
- {agentic_python_coder-2.2.1 → agentic_python_coder-2.3.0}/examples/regex/regex.md +0 -0
- {agentic_python_coder-2.2.1 → agentic_python_coder-2.3.0}/examples/regex/sample_tasks/email_extraction.md +0 -0
- {agentic_python_coder-2.2.1 → agentic_python_coder-2.3.0}/examples/regex/sample_tasks/phone_validation.md +0 -0
- {agentic_python_coder-2.2.1 → agentic_python_coder-2.3.0}/examples/regex/sample_tasks/test_email/email_extractor.py +0 -0
- {agentic_python_coder-2.2.1 → agentic_python_coder-2.3.0}/examples/regex/sample_tasks/test_email/extracted_emails.txt +0 -0
- {agentic_python_coder-2.2.1 → agentic_python_coder-2.3.0}/examples/regex/sample_tasks/test_email/text.txt +0 -0
- {agentic_python_coder-2.2.1 → 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
|
|
|
@@ -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.1 → 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
|
|
@@ -45,7 +48,7 @@ def create_coding_agent(
|
|
|
45
48
|
working_directory: Directory for file operations
|
|
46
49
|
system_prompt: System prompt as string (takes precedence over path)
|
|
47
50
|
system_prompt_path: Path to system prompt file (used if system_prompt not provided)
|
|
48
|
-
model: Optional model name (
|
|
51
|
+
model: Optional model name (uses configured default if not specified)
|
|
49
52
|
project_prompt: Optional project-specific prompt
|
|
50
53
|
with_packages: Optional list of packages for dynamic mode
|
|
51
54
|
task_content: Task description/content
|
|
@@ -66,8 +69,6 @@ def create_coding_agent(
|
|
|
66
69
|
|
|
67
70
|
# Store packages for kernel initialization
|
|
68
71
|
if with_packages is not None:
|
|
69
|
-
import os
|
|
70
|
-
|
|
71
72
|
os.environ["CODER_WITH_PACKAGES"] = ",".join(with_packages)
|
|
72
73
|
|
|
73
74
|
# Get LLM instance
|
|
@@ -108,15 +109,13 @@ def create_coding_agent(
|
|
|
108
109
|
|
|
109
110
|
# Create the agent with memory
|
|
110
111
|
checkpointer = InMemorySaver()
|
|
111
|
-
agent =
|
|
112
|
-
llm, tools,
|
|
112
|
+
agent = create_agent(
|
|
113
|
+
llm, tools, system_prompt=combined_prompt, checkpointer=checkpointer
|
|
113
114
|
)
|
|
114
115
|
|
|
115
116
|
# Store metadata for run_agent to use
|
|
116
117
|
agent._coder_metadata = {
|
|
117
118
|
"working_directory": working_directory,
|
|
118
|
-
"with_packages": with_packages,
|
|
119
|
-
"task_basename": task_basename,
|
|
120
119
|
}
|
|
121
120
|
|
|
122
121
|
return agent
|
|
@@ -126,24 +125,21 @@ def _print_tool_progress(tool_name: str, args: dict):
|
|
|
126
125
|
"""Print progress info for a tool call."""
|
|
127
126
|
if tool_name == "python_exec" and "code" in args:
|
|
128
127
|
code = args["code"]
|
|
128
|
+
code_stripped = code.strip()
|
|
129
129
|
if "def " in code:
|
|
130
|
-
func_match = code.split("def ")[1].split("(")[0]
|
|
130
|
+
func_match = code.split("def ")[1].split("(")[0]
|
|
131
131
|
print(f" {tool_name}: defining function {func_match}()")
|
|
132
132
|
elif "class " in code:
|
|
133
|
-
class_match = (
|
|
134
|
-
code.split("class ")[1].split("(")[0].split(":")[0]
|
|
135
|
-
if "class " in code
|
|
136
|
-
else ""
|
|
137
|
-
)
|
|
133
|
+
class_match = code.split("class ")[1].split("(")[0].split(":")[0]
|
|
138
134
|
print(f" {tool_name}: defining class {class_match}")
|
|
139
|
-
elif "import " in code and len(
|
|
140
|
-
print(f" {tool_name}: {
|
|
141
|
-
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:
|
|
142
138
|
var_name = code.split("=")[0].strip()
|
|
143
139
|
print(f" {tool_name}: assigning variable {var_name}")
|
|
144
|
-
elif
|
|
140
|
+
elif code_stripped.startswith("print("):
|
|
145
141
|
print(
|
|
146
|
-
f" {tool_name}: {
|
|
142
|
+
f" {tool_name}: {code_stripped[:50]}{'...' if len(code_stripped) > 50 else ''}"
|
|
147
143
|
)
|
|
148
144
|
elif "read_csv" in code or "read_excel" in code or "read_json" in code:
|
|
149
145
|
print(f" {tool_name}: loading data file")
|
|
@@ -170,32 +166,23 @@ def _print_tool_progress(tool_name: str, args: dict):
|
|
|
170
166
|
print(f"\n {tool_name}:")
|
|
171
167
|
todos = args["todos"]
|
|
172
168
|
for todo in todos:
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
if todo["status"] == "pending"
|
|
178
|
-
else "▶"
|
|
179
|
-
)
|
|
180
|
-
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}")
|
|
181
173
|
else:
|
|
182
|
-
|
|
183
|
-
if len(
|
|
184
|
-
|
|
185
|
-
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}")
|
|
186
177
|
|
|
187
178
|
|
|
188
|
-
def _process_tool_calls(msg,
|
|
179
|
+
def _process_tool_calls(msg, stats: dict, quiet: bool):
|
|
189
180
|
"""Process tool calls from a message, updating stats and optionally printing."""
|
|
190
181
|
if hasattr(msg, "tool_calls") and msg.tool_calls:
|
|
191
182
|
for tool_call in msg.tool_calls:
|
|
192
183
|
tool_name = tool_call.get("name") or tool_call.get("function", {}).get(
|
|
193
184
|
"name"
|
|
194
185
|
)
|
|
195
|
-
tool_id = tool_call.get("id")
|
|
196
|
-
if tool_id:
|
|
197
|
-
current_tools[tool_id] = tool_name
|
|
198
|
-
|
|
199
186
|
if tool_name:
|
|
200
187
|
stats["tool_usage"][tool_name] = (
|
|
201
188
|
stats["tool_usage"].get(tool_name, 0) + 1
|
|
@@ -213,9 +200,6 @@ def _process_tool_calls(msg, current_tools: dict, stats: dict, quiet: bool):
|
|
|
213
200
|
for tool_call in tool_calls:
|
|
214
201
|
function = tool_call.get("function", {})
|
|
215
202
|
tool_name = function.get("name")
|
|
216
|
-
tool_id = tool_call.get("id")
|
|
217
|
-
if tool_id and tool_name:
|
|
218
|
-
current_tools[tool_id] = tool_name
|
|
219
203
|
|
|
220
204
|
if tool_name:
|
|
221
205
|
stats["tool_usage"][tool_name] = (
|
|
@@ -225,11 +209,9 @@ def _process_tool_calls(msg, current_tools: dict, stats: dict, quiet: bool):
|
|
|
225
209
|
if not quiet and tool_name:
|
|
226
210
|
args_str = function.get("arguments", "{}")
|
|
227
211
|
try:
|
|
228
|
-
import json
|
|
229
|
-
|
|
230
212
|
args = json.loads(args_str)
|
|
231
213
|
_print_tool_progress(tool_name, args)
|
|
232
|
-
except
|
|
214
|
+
except json.JSONDecodeError:
|
|
233
215
|
print(f" {tool_name}")
|
|
234
216
|
|
|
235
217
|
|
|
@@ -243,6 +225,7 @@ def _update_token_stats(msg, stats: dict):
|
|
|
243
225
|
"completion_tokens", 0
|
|
244
226
|
)
|
|
245
227
|
stats["token_consumption"]["total_tokens"] += usage.get("total_tokens", 0)
|
|
228
|
+
return # Avoid double-counting if both metadata sources exist
|
|
246
229
|
|
|
247
230
|
if hasattr(msg, "usage_metadata") and msg.usage_metadata:
|
|
248
231
|
stats["token_consumption"]["input_tokens"] += msg.usage_metadata.get(
|
|
@@ -285,7 +268,6 @@ def run_agent(
|
|
|
285
268
|
config = {"configurable": {"thread_id": thread_id}, "recursion_limit": limit}
|
|
286
269
|
|
|
287
270
|
messages = []
|
|
288
|
-
current_tools = {}
|
|
289
271
|
|
|
290
272
|
# Initialize statistics
|
|
291
273
|
stats = {
|
|
@@ -294,8 +276,6 @@ def run_agent(
|
|
|
294
276
|
"execution_time_seconds": 0,
|
|
295
277
|
}
|
|
296
278
|
|
|
297
|
-
import time
|
|
298
|
-
|
|
299
279
|
start_time = time.time()
|
|
300
280
|
|
|
301
281
|
# Stream the agent's work
|
|
@@ -313,7 +293,7 @@ def run_agent(
|
|
|
313
293
|
messages.append(msg)
|
|
314
294
|
|
|
315
295
|
# Process tool calls (always update stats, optionally print)
|
|
316
|
-
_process_tool_calls(msg,
|
|
296
|
+
_process_tool_calls(msg, stats, quiet)
|
|
317
297
|
|
|
318
298
|
# Update token statistics
|
|
319
299
|
_update_token_stats(msg, stats)
|
{agentic_python_coder-2.2.1 → 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):
|