agentic-python-coder 3.1.0__tar.gz → 3.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.
Files changed (54) hide show
  1. agentic_python_coder-3.3.0/MEM/MEM_000.md +131 -0
  2. agentic_python_coder-3.3.0/MEM/MEM_001_frameworkless_react_agent.md +110 -0
  3. agentic_python_coder-3.3.0/MEM/MEM_002_tool_description_quality.md +107 -0
  4. {agentic_python_coder-3.1.0 → agentic_python_coder-3.3.0}/PKG-INFO +54 -12
  5. {agentic_python_coder-3.1.0 → agentic_python_coder-3.3.0}/README.md +42 -0
  6. {agentic_python_coder-3.1.0 → agentic_python_coder-3.3.0}/coder/src/agentic_python_coder/__init__.py +6 -1
  7. {agentic_python_coder-3.1.0 → agentic_python_coder-3.3.0}/coder/src/agentic_python_coder/agent.py +52 -14
  8. {agentic_python_coder-3.1.0 → agentic_python_coder-3.3.0}/coder/src/agentic_python_coder/cli.py +19 -4
  9. {agentic_python_coder-3.1.0 → agentic_python_coder-3.3.0}/coder/src/agentic_python_coder/examples/clingo/clingo.md +64 -1
  10. agentic_python_coder-3.3.0/coder/src/agentic_python_coder/examples/cpmpy/cpmpy.md +100 -0
  11. {agentic_python_coder-3.1.0 → agentic_python_coder-3.3.0}/coder/src/agentic_python_coder/kernel.py +17 -0
  12. {agentic_python_coder-3.1.0 → agentic_python_coder-3.3.0}/coder/src/agentic_python_coder/llm.py +23 -5
  13. {agentic_python_coder-3.1.0 → agentic_python_coder-3.3.0}/coder/src/agentic_python_coder/mcp_server.py +5 -6
  14. {agentic_python_coder-3.1.0 → agentic_python_coder-3.3.0}/coder/src/agentic_python_coder/models/deepseek31.json +0 -1
  15. {agentic_python_coder-3.1.0 → agentic_python_coder-3.3.0}/coder/src/agentic_python_coder/models/gemini25.json +0 -1
  16. agentic_python_coder-3.3.0/coder/src/agentic_python_coder/models/gemini31.json +6 -0
  17. {agentic_python_coder-3.1.0 → agentic_python_coder-3.3.0}/coder/src/agentic_python_coder/models/gemini3pro.json +0 -1
  18. {agentic_python_coder-3.1.0 → agentic_python_coder-3.3.0}/coder/src/agentic_python_coder/models/gpt52.json +0 -1
  19. agentic_python_coder-3.3.0/coder/src/agentic_python_coder/models/gpt56sol.json +5 -0
  20. agentic_python_coder-3.3.0/coder/src/agentic_python_coder/models/gpt56terra.json +5 -0
  21. {agentic_python_coder-3.1.0 → agentic_python_coder-3.3.0}/coder/src/agentic_python_coder/models/grok41.json +0 -1
  22. {agentic_python_coder-3.1.0 → agentic_python_coder-3.3.0}/coder/src/agentic_python_coder/models/opus45.json +1 -2
  23. agentic_python_coder-3.3.0/coder/src/agentic_python_coder/models/opus48.json +5 -0
  24. {agentic_python_coder-3.1.0 → agentic_python_coder-3.3.0}/coder/src/agentic_python_coder/models/qwen3.json +0 -1
  25. {agentic_python_coder-3.1.0 → agentic_python_coder-3.3.0}/coder/src/agentic_python_coder/models/sonnet45.json +1 -2
  26. agentic_python_coder-3.3.0/coder/src/agentic_python_coder/models/sonnet46.json +5 -0
  27. agentic_python_coder-3.3.0/coder/src/agentic_python_coder/models/sonnet5.json +5 -0
  28. {agentic_python_coder-3.1.0 → agentic_python_coder-3.3.0}/coder/src/agentic_python_coder/project_md.py +6 -2
  29. {agentic_python_coder-3.1.0 → agentic_python_coder-3.3.0}/coder/src/agentic_python_coder/runner.py +8 -1
  30. {agentic_python_coder-3.1.0 → agentic_python_coder-3.3.0}/coder/src/agentic_python_coder/tools.py +28 -7
  31. agentic_python_coder-3.3.0/examples/clingo/clingo.md +5 -0
  32. {agentic_python_coder-3.1.0 → agentic_python_coder-3.3.0}/pyproject.toml +12 -12
  33. agentic_python_coder-3.1.0/coder/src/agentic_python_coder/examples/cpmpy/cpmpy.md +0 -57
  34. {agentic_python_coder-3.1.0 → agentic_python_coder-3.3.0}/.gitignore +0 -0
  35. {agentic_python_coder-3.1.0 → agentic_python_coder-3.3.0}/LICENSE +0 -0
  36. {agentic_python_coder-3.1.0 → agentic_python_coder-3.3.0}/coder/.gitignore +0 -0
  37. {agentic_python_coder-3.1.0 → agentic_python_coder-3.3.0}/coder/prompts/system.md +0 -0
  38. {agentic_python_coder-3.1.0 → agentic_python_coder-3.3.0}/coder/prompts/system_todo.md +0 -0
  39. {agentic_python_coder-3.1.0 → agentic_python_coder-3.3.0}/coder/src/agentic_python_coder/examples/__init__.py +0 -0
  40. {agentic_python_coder-3.1.0 → agentic_python_coder-3.3.0}/coder/src/agentic_python_coder/examples/clingo/README.md +0 -0
  41. {agentic_python_coder-3.1.0 → agentic_python_coder-3.3.0}/coder/src/agentic_python_coder/examples/clingo/sample_tasks/bird_reasoning.md +0 -0
  42. {agentic_python_coder-3.1.0 → agentic_python_coder-3.3.0}/coder/src/agentic_python_coder/examples/clingo/sample_tasks/diagnosis.md +0 -0
  43. {agentic_python_coder-3.1.0 → agentic_python_coder-3.3.0}/coder/src/agentic_python_coder/examples/clingo/sample_tasks/simple_coloring.md +0 -0
  44. {agentic_python_coder-3.1.0 → agentic_python_coder-3.3.0}/coder/src/agentic_python_coder/examples/clingo/sample_tasks/stable_marriage.md +0 -0
  45. {agentic_python_coder-3.1.0 → agentic_python_coder-3.3.0}/coder/src/agentic_python_coder/examples/clingo/sample_tasks/sudoku_mini.md +0 -0
  46. {agentic_python_coder-3.1.0 → agentic_python_coder-3.3.0}/coder/src/agentic_python_coder/examples/cpmpy/README.md +0 -0
  47. {agentic_python_coder-3.1.0 → agentic_python_coder-3.3.0}/coder/src/agentic_python_coder/examples/cpmpy/sample_tasks/magic_square.md +0 -0
  48. {agentic_python_coder-3.1.0 → agentic_python_coder-3.3.0}/coder/src/agentic_python_coder/examples/cpmpy/sample_tasks/n_queens.md +0 -0
  49. {agentic_python_coder-3.1.0 → agentic_python_coder-3.3.0}/coder/src/agentic_python_coder/examples/regex/README.md +0 -0
  50. {agentic_python_coder-3.1.0 → agentic_python_coder-3.3.0}/coder/src/agentic_python_coder/examples/regex/regex.md +0 -0
  51. {agentic_python_coder-3.1.0 → agentic_python_coder-3.3.0}/coder/src/agentic_python_coder/examples/regex/sample_tasks/email_extraction.md +0 -0
  52. {agentic_python_coder-3.1.0 → agentic_python_coder-3.3.0}/coder/src/agentic_python_coder/examples/regex/sample_tasks/phone_validation.md +0 -0
  53. {agentic_python_coder-3.1.0 → agentic_python_coder-3.3.0}/coder/src/agentic_python_coder/examples/regex/sample_tasks/url_parsing.md +0 -0
  54. {agentic_python_coder-3.1.0 → agentic_python_coder-3.3.0}/coder/src/agentic_python_coder/models/gemini3flash.json +0 -0
@@ -0,0 +1,131 @@
1
+ ---
2
+ keywords: [session log, process notes, history]
3
+ context: Searchable session log — grep when needed, not loaded routinely
4
+ added: 2026-01-31
5
+ ---
6
+ # Process Notes
7
+
8
+ Searchable session log. Not loaded routinely—search with grep when needed.
9
+
10
+ ---
11
+ ## 2026-02-23
12
+
13
+ **Goal**: Add new model configs (sonnet46, gemini31) and publish v3.2.0
14
+
15
+ **Done**:
16
+ - Created sonnet46.json (anthropic/claude-sonnet-4.6, temp 0.0)
17
+ - Created gemini31.json (google/gemini-3.1-pro-preview, temp 0.0, timeout 120)
18
+ - Added reasoning/thinking token support in llm.py
19
+ - Bumped version to 3.2.0, all 70 unit tests pass
20
+ - Published to PyPI
21
+
22
+ **Tried**:
23
+ - Initially copied gemini3pro params (temp 0.3, top_p 0.9) for gemini31 — Stefan corrected to temp 0.0, no top_p
24
+
25
+ **Notes**: Quick session. Stefan provided the gemini model path directly (google/gemini-3.1-pro-preview).
26
+
27
+ ---
28
+ ## 2026-02-15
29
+
30
+ **Goal**: Routine maintenance — dependency updates, new model config, code review fixes
31
+
32
+ **Done**:
33
+ - Bumped deps: openai 2.16→2.21, rich 14.3.1→14.3.2, ipykernel 7.1→7.2
34
+ - Added gemini3flash model config (Gemini 3 Flash Preview)
35
+ - Code review (ULTRA) found 6 issues in llm.py — all fixed: provider routing bug, OSError handling, model_path→model_id rename, empty "Available:" message, Warning→Error label, unnecessary ./ prefix
36
+ - Published v3.1.0 to PyPI
37
+ - Migrated EXPERTISE/ → MEM/ (2 entries + PROCESS_NOTES.md)
38
+
39
+ **Tried**:
40
+ - Initially copied gemini3pro.json params blindly for gemini3flash — Stefan caught this, verified actual supported params via WS7
41
+
42
+ **Notes**: PyPI token is at ~/git/.pipy.txt (updated CLAUDE.md to record this)
43
+
44
+ ---
45
+
46
+
47
+ ## 2026-01-31 (session 3)
48
+
49
+ **Goal**: Run e2e benchmark tests across models, fix failures, improve prompts, merge v3.0.0 to main, publish to PyPI
50
+
51
+ **Done**:
52
+ - Ran hard problem benchmarks (5 CPMpy + 5 Clingo) across opus45, gpt52, gemini3pro
53
+ - Created gemini3pro.json model config (google/gemini-3-pro-preview)
54
+ - Fixed gpt52 max_tokens: 3000→16384 (was truncating tool calls, caused 0/5 Clingo)
55
+ - Rewrote Clingo validate.py (old one was wrong ASP-Bench full-suite validator)
56
+ - Added mandatory verification prompts to system.md, system_todo.md, and save_code tool description
57
+ - Analyzed GPT-5.2 CPMpy failures with GPPT consult (circular verification, wrong problem interpretation)
58
+ - Fixed flaky test_todo_flag_integration (catch TimeoutExpired for partial output)
59
+ - Squash-merged dev→main, published v3.0.0 to PyPI
60
+ - Updated README: examples link, gemini3pro in model list
61
+
62
+ **Tried**:
63
+ - Verification prompts in system prompt + tool description — improved opus45 CPMpy 4/5→5/5 and gpt52 Clingo 0/5→5/5
64
+ - GPT-5.2 on CPMpy still only 2/5 despite verification prompts — model sometimes ignores them (2 tool calls before save) or writes circular verify()
65
+ - Gemini 3 Pro initially 0/10 with max_tokens=2048; bumped to 16384 → 5/10
66
+
67
+ **Notes**: Key insight — verification gates work but models can write verify() functions that re-implement solver bugs instead of checking problem text independently. Future prompt work should address this circular verification pitfall.
68
+
69
+ ---
70
+
71
+ ## 2026-01-31 (session 2)
72
+
73
+ **Goal**: Clean up dev branch for v3.0.0 release — model configs, tool descriptions, README, examples consolidation
74
+
75
+ **Done**:
76
+ - Replaced gpt5 model config with gpt52 (openai/gpt-5.2)
77
+ - Restored verbose LangGraph-era tool descriptions in tools.py (fixes performance regression on hard tasks)
78
+ - Restored parameter schemas to match tested reference (title fields, additionalProperties style)
79
+ - Created EXPERTISE/E002_tool_description_quality.md
80
+ - Removed LangGraph badge and references from README
81
+ - Bumped all dependency minimum versions to current
82
+ - Consolidated examples: deleted legacy examples/ dir, kept only bundled coder/src/.../examples/
83
+ - Confirmed _todo.md project prompts are unused (--todo only switches system prompt)
84
+ - Improved CPMpy project prompt with InDomain constraint and pitfalls section
85
+ - Copied e2e challenge tests (hard_cpmpy, hard_clingo) to tests/ (gitignored)
86
+ - All 70 unit tests pass
87
+
88
+ **Tried**:
89
+ - Initially kept minimal tool descriptions after LangGraph removal — caused performance regression on challenging tasks, discovered in separate test session
90
+ - Tried using "description" field in JSON schemas instead of "title" — reverted to match LangGraph-generated style that was proven to work
91
+
92
+ **Notes**: Tool descriptions are behavioral instructions for the model, not documentation. Verbose descriptions with examples, Args/Returns sections are essential for tool-calling quality. This is documented in E002.
93
+
94
+ ---
95
+
96
+ ## 2026-01-31
97
+
98
+ **Goal**: Update model configs and fix tool description regression
99
+
100
+ **Done**:
101
+ - Replaced gpt5 model config with gpt52 (openai/gpt-5.2) — JSON, README, tests
102
+ - Restored tool descriptions in tools.py to verbose LangGraph-era format (critical for performance)
103
+ - Restored parameter schemas to match tested reference (title fields, additionalProperties style)
104
+ - Created EXPERTISE/E002_tool_description_quality.md
105
+ - Removed unused _task_basename import in test_library_api.py
106
+
107
+ **Tried**:
108
+ - Initially kept minimal tool descriptions after LangGraph removal — caused performance regression on challenging tasks
109
+ - Discovered that verbose descriptions with examples, Args/Returns sections are essential for model tool-calling quality
110
+
111
+ **Notes**: Tool descriptions are behavioral instructions for the model, not documentation for humans. This is a key insight for any framework migration.
112
+
113
+ ---
114
+
115
+ ## 2026-01-30
116
+
117
+ **Goal**: Verify test suite, create expertise entry for frameworkless agent pattern, housekeeping
118
+
119
+ **Done**:
120
+ - Ran all 70 pytest tests — all pass after v3.0.0 migration
121
+ - Confirmed examples/ has sample tasks but no automated e2e tests
122
+ - Created EXPERTISE/E001_frameworkless_react_agent.md documenting the frameworkless ReAct pattern
123
+ - Added EXPERTISE/ to .gitignore, committed and pushed to dev
124
+ - Removed dead links from Key Documents (LOCAL/ directory no longer exists)
125
+
126
+ **Tried**:
127
+ - Looked for e2e tests in examples/ — only sample task files and one manual test run (regex/sample_tasks/test_email/)
128
+
129
+ **Notes**: E2E tests remain the top priority open goal. They need mocked OpenAI API responses (mock client.chat.completions.create()).
130
+
131
+ ---
@@ -0,0 +1,110 @@
1
+ ---
2
+ keywords: [react, agent, openai, frameworkless, langgraph, langchain, migration, tool-calling]
3
+ context: Building LLM-powered agents without heavy frameworks (LangGraph, LangChain, CrewAI, etc.)
4
+ added: 2026-01-30
5
+ ---
6
+ # Frameworkless ReAct Agent Pattern
7
+
8
+ ## Insight
9
+
10
+ A fully functional ReAct agent requires only ~4 components using the `openai` Python client directly, with no framework overhead:
11
+
12
+ 1. **LLM config** — A dataclass wrapping `openai.OpenAI` client, model path, and API params (temperature, max_tokens). Route through OpenRouter for multi-provider access.
13
+
14
+ 2. **Tool registry** — A `Tool` dataclass (name, description, JSON Schema parameters, callable function) with a `ToolRegistry` class that converts tools to OpenAI format via `to_openai_tool()`. Each tool's `execute()` returns a JSON string.
15
+
16
+ 3. **ReAct loop** — A simple `for step in range(limit)` loop that:
17
+ - Calls `client.chat.completions.create()` with messages + tools
18
+ - If response has `tool_calls`: execute each, append tool results to messages
19
+ - If no `tool_calls`: it's the final answer — break
20
+ - Messages list grows naturally (system → user → assistant+tool_calls → tool → assistant+tool_calls → ... → assistant)
21
+
22
+ 4. **Agent dataclass** — Holds config, tools, system prompt, working directory, and persistent `messages` list (enables multi-turn/interactive mode).
23
+
24
+ ### Key advantages over LangGraph/LangChain
25
+
26
+ - **Dependency reduction**: 112 → 69 installed packages (removed all LangChain/LangGraph deps)
27
+ - **Debuggability**: The entire agent loop is ~60 lines of straightforward Python. No graph compilation, no state machines, no hidden middleware.
28
+ - **Message format control**: Full control over the `messages` list. No framework-imposed message wrappers or serialization formats.
29
+ - **Token tracking**: Direct access to `response.usage.prompt_tokens` / `completion_tokens`.
30
+ - **Error handling**: Tool errors are just JSON strings fed back to the model — the model self-corrects. No need for framework error recovery machinery.
31
+
32
+ ### Pitfalls learned during migration
33
+
34
+ - **`model or "default"` bug**: If `model=""` (empty string), `or` evaluates to `"default"` — use explicit `None` checks instead.
35
+ - **Environment variable leaks**: Global env vars (e.g., `CODER_WITH_PACKAGES`) persist across runs — always clear them with `os.environ.pop()` when not set.
36
+ - **Global state accumulation**: Module-level globals (todo lists, file basenames) accumulate across runs. Add a `reset_global_state()` function called at agent creation time.
37
+ - **Tool call message format**: OpenAI API requires tool_calls in assistant messages to be dicts with `id`, `type`, `function.name`, `function.arguments`. Missing any field causes cryptic errors.
38
+ - **UTF-8 encoding**: Always use `encoding="utf-8"` when opening files — platform default encoding can vary.
39
+
40
+ ### When to use a framework instead
41
+
42
+ - If you need **graph-based workflows** with conditional branching between multiple agents
43
+ - If you need **built-in memory/persistence** across sessions (vector stores, checkpoints)
44
+ - If you need **streaming with backpressure** and complex output routing
45
+ - For simple single-agent ReAct loops, the framework adds complexity without benefit
46
+
47
+ ## Example
48
+
49
+ ```python
50
+ from dataclasses import dataclass, field
51
+ from openai import OpenAI
52
+ import json
53
+
54
+ @dataclass
55
+ class Tool:
56
+ name: str
57
+ description: str
58
+ parameters: dict
59
+ function: callable
60
+
61
+ def to_openai_tool(self):
62
+ return {
63
+ "type": "function",
64
+ "function": {
65
+ "name": self.name,
66
+ "description": self.description,
67
+ "parameters": self.parameters,
68
+ },
69
+ }
70
+
71
+ def execute(self, **kwargs):
72
+ return self.function(**kwargs)
73
+
74
+ # ReAct loop core (~30 lines)
75
+ def run(client, model, messages, tools, limit=200):
76
+ openai_tools = [t.to_openai_tool() for t in tools]
77
+ tool_map = {t.name: t for t in tools}
78
+
79
+ for _ in range(limit):
80
+ resp = client.chat.completions.create(
81
+ model=model, messages=messages, tools=openai_tools, tool_choice="auto"
82
+ )
83
+ msg = resp.choices[0].message
84
+
85
+ if msg.tool_calls:
86
+ messages.append({
87
+ "role": "assistant",
88
+ "content": msg.content or "",
89
+ "tool_calls": [
90
+ {"id": tc.id, "type": "function",
91
+ "function": {"name": tc.function.name,
92
+ "arguments": tc.function.arguments}}
93
+ for tc in msg.tool_calls
94
+ ],
95
+ })
96
+ for tc in msg.tool_calls:
97
+ args = json.loads(tc.function.arguments)
98
+ result = tool_map[tc.function.name].execute(**args)
99
+ messages.append({"role": "tool", "tool_call_id": tc.id, "content": result})
100
+ else:
101
+ messages.append({"role": "assistant", "content": msg.content or ""})
102
+ break
103
+ return messages
104
+ ```
105
+
106
+ ## Reference
107
+
108
+ - Blueprint implementation: `/Users/szeider/work/myreact` (the original pattern)
109
+ - Production implementation: `coder/src/agentic_python_coder/agent.py` (v3.0.0)
110
+ - Migration context: LangGraph v2.x → frameworkless in one session, all 70 tests passing
@@ -0,0 +1,107 @@
1
+ ---
2
+ keywords: [tool-descriptions, openai, tool-calling, performance, langgraph, schema, regression]
3
+ context: When writing or modifying OpenAI tool definitions for agents that use tool calling
4
+ added: 2026-01-31
5
+ ---
6
+ # Tool Description Quality Impacts Agent Performance
7
+
8
+ ## Insight
9
+
10
+ Verbose, LangGraph-style tool descriptions significantly outperform minimal descriptions on challenging tasks. When migrating from LangGraph to frameworkless tool definitions, preserving the full docstring content is critical.
11
+
12
+ ### What works (LangGraph-style verbose descriptions)
13
+
14
+ 1. **Multiple examples** showing multi-step usage patterns — not just what the tool does, but how to chain calls (e.g., define a function in one call, use it in the next)
15
+ 2. **Explicit Args section** describing each parameter in natural language
16
+ 3. **Explicit Returns section** listing every possible field in the response JSON (`success`, `stdout`, `result`, `stderr`, `error`)
17
+ 4. **Behavioral hints** embedded in the description (e.g., "The kernel maintains state between executions!", "use print() to see output")
18
+
19
+ ### What fails (minimal descriptions)
20
+
21
+ Stripping descriptions to just the core purpose (e.g., "Execute Python code in a persistent IPython kernel.") removes behavioral guidance the model relies on for:
22
+ - Understanding that state persists across calls
23
+ - Knowing what output format to expect
24
+ - Planning multi-step tool use sequences
25
+
26
+ ### Parameter schema style also matters
27
+
28
+ The LangGraph auto-generated schemas use `"title"` fields on properties and top-level schema, plus `"additionalProperties": True` for flexible object items. Switching to `"description"` fields and strict schemas (with explicit properties and enums) may change how models interpret and use the tools. When in doubt, match the schema style that was tested and proven to work.
29
+
30
+ ### Verification gates in tool descriptions
31
+
32
+ Adding verification requirements to `save_code` tool description ("Only call this AFTER you have executed the code and confirmed it produces correct output") measurably improved benchmark scores. Opus 4.5 went from 4/5→5/5 on hard CPMpy and GPT-5.2 from 0/5→5/5 on hard Clingo after adding these gates. However, GPT-5.2 still sometimes ignores verification (only 2 tool calls before saving on 016_sports). The verification prompt works better on some models than others.
33
+
34
+ ### Circular verification pitfall
35
+
36
+ Models that do write verify() functions sometimes verify against their own wrong model rather than the problem statement. The verify() re-implements the same bugs as the solver constraints. Prompt language should explicitly require deriving verification checks from the problem text, not from the model code.
37
+
38
+ ### Key takeaway
39
+
40
+ Tool descriptions are not documentation for humans — they are **behavioral instructions for the model**. Treat them as part of the prompt engineering, not as code comments to be minimized.
41
+
42
+ **Updated**: 2026-01-31
43
+
44
+ ## Example
45
+
46
+ ```python
47
+ # BAD: Minimal description (causes performance regression)
48
+ PYTHON_EXEC_TOOL = Tool(
49
+ name="python_exec",
50
+ description="Execute Python code in a persistent IPython kernel.",
51
+ parameters={
52
+ "type": "object",
53
+ "properties": {
54
+ "code": {"type": "string", "description": "Python code to execute."},
55
+ },
56
+ "required": ["code"],
57
+ },
58
+ function=python_exec,
59
+ )
60
+
61
+ # GOOD: Verbose LangGraph-style description (proven performance)
62
+ PYTHON_EXEC_TOOL = Tool(
63
+ name="python_exec",
64
+ description=(
65
+ "Execute Python code in a persistent IPython kernel.\n\n"
66
+ "IMPORTANT: The kernel maintains state between executions!\n"
67
+ "- Variables, functions, and imports persist across calls\n"
68
+ "- Use print() to see output, or the last expression will be returned\n"
69
+ "- The kernel runs in the working directory context\n\n"
70
+ "Example:\n"
71
+ " First call: x = 5\n"
72
+ ' Second call: print(x) # Returns: {"success": true, "stdout": "5"}\n\n'
73
+ " First call: def add(a, b): return a + b\n"
74
+ ' Second call: add(3, 4) # Returns: {"success": true, "result": "7"}\n\n'
75
+ "The code executes in the working directory context, so you can read/write files\n"
76
+ "using relative paths.\n\n"
77
+ "Args:\n"
78
+ " code: Python code to execute. Multi-line code is supported.\n\n"
79
+ "Returns:\n"
80
+ " JSON string with execution results:\n"
81
+ " - success: boolean indicating if execution succeeded\n"
82
+ " - stdout: captured print output (if any)\n"
83
+ " - result: the last expression's value (if any)\n"
84
+ " - stderr: warnings (if any)\n"
85
+ " - error: error message (if execution failed)"
86
+ ),
87
+ parameters={
88
+ "type": "object",
89
+ "properties": {
90
+ "code": {
91
+ "type": "string",
92
+ "title": "Code",
93
+ },
94
+ },
95
+ "required": ["code"],
96
+ "title": "python_exec",
97
+ },
98
+ function=python_exec,
99
+ )
100
+ ```
101
+
102
+ ## Reference
103
+
104
+ - Regression discovered: 2026-01-31 during benchmark testing of dev branch
105
+ - Fix verified in: `/Users/szeider/temp/codertest/agentic-python-coder-dev/`
106
+ - Production file: `coder/src/agentic_python_coder/tools.py`
107
+ - Related: E001_frameworkless_react_agent.md (migration context)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agentic-python-coder
3
- Version: 3.1.0
3
+ Version: 3.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,21 +14,21 @@ 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>=7.2.0
18
- Requires-Dist: jupyter-client>=8.8.0
19
- Requires-Dist: mcp>=1.26.0
20
- Requires-Dist: openai>=2.21.0
21
- Requires-Dist: python-dotenv>=1.2.1
17
+ Requires-Dist: ipykernel>=7.3.0
18
+ Requires-Dist: jupyter-client>=8.9.1
19
+ Requires-Dist: mcp>=1.28.1
20
+ Requires-Dist: openai>=2.45.0
21
+ Requires-Dist: python-dotenv>=1.2.2
22
22
  Requires-Dist: pyyaml>=6.0.3
23
- Requires-Dist: rich>=14.3.2
23
+ Requires-Dist: rich>=15.0.0
24
24
  Provides-Extra: dev
25
- Requires-Dist: mypy>=1.19.1; extra == 'dev'
26
- Requires-Dist: ruff>=0.14.14; extra == 'dev'
25
+ Requires-Dist: mypy>=2.2.0; extra == 'dev'
26
+ Requires-Dist: ruff>=0.15.21; extra == 'dev'
27
27
  Provides-Extra: test
28
- Requires-Dist: pytest-asyncio>=1.3.0; extra == 'test'
29
- Requires-Dist: pytest-cov>=7.0.0; extra == 'test'
28
+ Requires-Dist: pytest-asyncio>=1.4.0; extra == 'test'
29
+ Requires-Dist: pytest-cov>=7.1.0; extra == 'test'
30
30
  Requires-Dist: pytest-watch>=4.2.0; extra == 'test'
31
- Requires-Dist: pytest>=9.0.2; extra == 'test'
31
+ Requires-Dist: pytest>=9.1.1; extra == 'test'
32
32
  Description-Content-Type: text/markdown
33
33
 
34
34
  # Agentic Python Coder
@@ -147,19 +147,41 @@ coder -i
147
147
  ```bash
148
148
  # Built-in models (versioned names)
149
149
  coder --model sonnet45 "task" # Claude Sonnet 4.5 (default)
150
+ coder --model sonnet46 "task" # Claude Sonnet 4.6
151
+ coder --model sonnet5 "task" # Claude Sonnet 5
150
152
  coder --model opus45 "task" # Claude Opus 4.5
153
+ coder --model opus48 "task" # Claude Opus 4.8
151
154
  coder --model deepseek31 "task" # DeepSeek v3.1
152
155
  coder --model grok41 "task" # X.AI Grok 4.1
153
156
  coder --model qwen3 "task" # Qwen3 Coder
154
157
  coder --model gemini25 "task" # Gemini Pro 2.5
155
158
  coder --model gemini3pro "task" # Gemini 3 Pro Preview
159
+ coder --model gemini31 "task" # Gemini 3.1 Pro Preview
156
160
  coder --model gemini3flash "task" # Gemini 3 Flash Preview (fast, low-cost)
157
161
  coder --model gpt52 "task" # GPT-5.2
162
+ coder --model gpt56sol "task" # GPT-5.6 Sol
163
+ coder --model gpt56terra "task" # GPT-5.6 Terra
158
164
 
159
165
  # Custom model (JSON file)
160
166
  coder --model ./mymodel.json "task"
161
167
  ```
162
168
 
169
+ A custom model JSON can also point at any OpenAI-compatible endpoint
170
+ (OpenAI directly, a local Ollama/vLLM server, etc.) instead of OpenRouter:
171
+
172
+ ```json
173
+ {
174
+ "path": "gpt-4o-mini",
175
+ "base_url": "https://api.openai.com/v1",
176
+ "api_key_env": "OPENAI_API_KEY",
177
+ "temperature": 0.0
178
+ }
179
+ ```
180
+
181
+ `base_url` overrides the OpenRouter endpoint; `api_key_env` names the
182
+ environment variable holding the key for that endpoint (default:
183
+ `OPENROUTER_API_KEY`).
184
+
163
185
  ### Project Templates
164
186
 
165
187
  Domain-specific templates improve results. Bundled examples are available on GitHub at [`coder/src/agentic_python_coder/examples/`](coder/src/agentic_python_coder/examples/). Use `--init` to copy them locally:
@@ -225,6 +247,7 @@ messages, stats, log_path = solve_task(
225
247
  save_log=True, # Save conversation log
226
248
  task_basename=None, # Base name for output files
227
249
  step_limit=None, # Max agent steps (default: 200)
250
+ llm_config=None, # Pre-built LLMConfig (overrides model/api_key)
228
251
  )
229
252
  ```
230
253
 
@@ -253,6 +276,25 @@ messages2, stats2 = run_agent(agent, "Now plot column A", quiet=True)
253
276
  print(get_final_response(messages2))
254
277
  ```
255
278
 
279
+ Instead of a model name, you can pass a pre-built `LLMConfig` wrapping any
280
+ OpenAI-compatible client:
281
+
282
+ ```python
283
+ from openai import OpenAI
284
+ from agentic_python_coder import LLMConfig, create_coding_agent
285
+
286
+ llm_config = LLMConfig(
287
+ client=OpenAI(api_key="...", base_url="https://api.openai.com/v1"),
288
+ model="gpt-4o-mini",
289
+ api_params={"temperature": 0.0},
290
+ )
291
+
292
+ agent = create_coding_agent(
293
+ working_directory="/tmp/workspace",
294
+ llm_config=llm_config,
295
+ )
296
+ ```
297
+
256
298
  #### `get_openrouter_llm()` — LLM Access
257
299
 
258
300
  ```python
@@ -114,19 +114,41 @@ coder -i
114
114
  ```bash
115
115
  # Built-in models (versioned names)
116
116
  coder --model sonnet45 "task" # Claude Sonnet 4.5 (default)
117
+ coder --model sonnet46 "task" # Claude Sonnet 4.6
118
+ coder --model sonnet5 "task" # Claude Sonnet 5
117
119
  coder --model opus45 "task" # Claude Opus 4.5
120
+ coder --model opus48 "task" # Claude Opus 4.8
118
121
  coder --model deepseek31 "task" # DeepSeek v3.1
119
122
  coder --model grok41 "task" # X.AI Grok 4.1
120
123
  coder --model qwen3 "task" # Qwen3 Coder
121
124
  coder --model gemini25 "task" # Gemini Pro 2.5
122
125
  coder --model gemini3pro "task" # Gemini 3 Pro Preview
126
+ coder --model gemini31 "task" # Gemini 3.1 Pro Preview
123
127
  coder --model gemini3flash "task" # Gemini 3 Flash Preview (fast, low-cost)
124
128
  coder --model gpt52 "task" # GPT-5.2
129
+ coder --model gpt56sol "task" # GPT-5.6 Sol
130
+ coder --model gpt56terra "task" # GPT-5.6 Terra
125
131
 
126
132
  # Custom model (JSON file)
127
133
  coder --model ./mymodel.json "task"
128
134
  ```
129
135
 
136
+ A custom model JSON can also point at any OpenAI-compatible endpoint
137
+ (OpenAI directly, a local Ollama/vLLM server, etc.) instead of OpenRouter:
138
+
139
+ ```json
140
+ {
141
+ "path": "gpt-4o-mini",
142
+ "base_url": "https://api.openai.com/v1",
143
+ "api_key_env": "OPENAI_API_KEY",
144
+ "temperature": 0.0
145
+ }
146
+ ```
147
+
148
+ `base_url` overrides the OpenRouter endpoint; `api_key_env` names the
149
+ environment variable holding the key for that endpoint (default:
150
+ `OPENROUTER_API_KEY`).
151
+
130
152
  ### Project Templates
131
153
 
132
154
  Domain-specific templates improve results. Bundled examples are available on GitHub at [`coder/src/agentic_python_coder/examples/`](coder/src/agentic_python_coder/examples/). Use `--init` to copy them locally:
@@ -192,6 +214,7 @@ messages, stats, log_path = solve_task(
192
214
  save_log=True, # Save conversation log
193
215
  task_basename=None, # Base name for output files
194
216
  step_limit=None, # Max agent steps (default: 200)
217
+ llm_config=None, # Pre-built LLMConfig (overrides model/api_key)
195
218
  )
196
219
  ```
197
220
 
@@ -220,6 +243,25 @@ messages2, stats2 = run_agent(agent, "Now plot column A", quiet=True)
220
243
  print(get_final_response(messages2))
221
244
  ```
222
245
 
246
+ Instead of a model name, you can pass a pre-built `LLMConfig` wrapping any
247
+ OpenAI-compatible client:
248
+
249
+ ```python
250
+ from openai import OpenAI
251
+ from agentic_python_coder import LLMConfig, create_coding_agent
252
+
253
+ llm_config = LLMConfig(
254
+ client=OpenAI(api_key="...", base_url="https://api.openai.com/v1"),
255
+ model="gpt-4o-mini",
256
+ api_params={"temperature": 0.0},
257
+ )
258
+
259
+ agent = create_coding_agent(
260
+ working_directory="/tmp/workspace",
261
+ llm_config=llm_config,
262
+ )
263
+ ```
264
+
223
265
  #### `get_openrouter_llm()` — LLM Access
224
266
 
225
267
  ```python
@@ -1,6 +1,11 @@
1
1
  """Python Coding Agent - A minimal coding assistant using direct OpenAI API and OpenRouter."""
2
2
 
3
- __version__ = "3.0.0"
3
+ from importlib.metadata import PackageNotFoundError, version as _package_version
4
+
5
+ try:
6
+ __version__ = _package_version("agentic-python-coder")
7
+ except PackageNotFoundError: # running from source without installation
8
+ __version__ = "0.0.0+unknown"
4
9
 
5
10
  # High-level API (recommended for most users)
6
11
  from agentic_python_coder.runner import solve_task