agentshim 0.1.0__tar.gz → 0.2.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.
- agentshim-0.2.0/PKG-INFO +206 -0
- agentshim-0.2.0/README.md +195 -0
- {agentshim-0.1.0 → agentshim-0.2.0}/agentshim/__init__.py +6 -6
- agentshim-0.2.0/agentshim/base.py +330 -0
- {agentshim-0.1.0 → agentshim-0.2.0}/agentshim/cli_agent.py +3 -3
- {agentshim-0.1.0 → agentshim-0.2.0}/agentshim/codex/agent.py +1 -1
- {agentshim-0.1.0 → agentshim-0.2.0}/pyproject.toml +1 -1
- agentshim-0.2.0/tests/unit/test_coding_agent_facade.py +215 -0
- {agentshim-0.1.0 → agentshim-0.2.0}/tests/unit/test_coding_agent_recorder_default.py +2 -2
- {agentshim-0.1.0 → agentshim-0.2.0}/uv.lock +1 -1
- agentshim-0.1.0/PKG-INFO +0 -61
- agentshim-0.1.0/README.md +0 -50
- agentshim-0.1.0/agentshim/base.py +0 -52
- {agentshim-0.1.0 → agentshim-0.2.0}/.github/workflows/ci.yml +0 -0
- {agentshim-0.1.0 → agentshim-0.2.0}/.github/workflows/publish.yml +0 -0
- {agentshim-0.1.0 → agentshim-0.2.0}/.gitignore +0 -0
- {agentshim-0.1.0 → agentshim-0.2.0}/agentshim/claude/__init__.py +0 -0
- {agentshim-0.1.0 → agentshim-0.2.0}/agentshim/claude/agent.py +0 -0
- {agentshim-0.1.0 → agentshim-0.2.0}/agentshim/claude/events.py +0 -0
- {agentshim-0.1.0 → agentshim-0.2.0}/agentshim/claude/hooks/__init__.py +0 -0
- {agentshim-0.1.0 → agentshim-0.2.0}/agentshim/claude/hooks/confine_reads.py +0 -0
- {agentshim-0.1.0 → agentshim-0.2.0}/agentshim/claude_events.py +0 -0
- {agentshim-0.1.0 → agentshim-0.2.0}/agentshim/codex/__init__.py +0 -0
- {agentshim-0.1.0 → agentshim-0.2.0}/agentshim/codex/events.py +0 -0
- {agentshim-0.1.0 → agentshim-0.2.0}/agentshim/codex_events.py +0 -0
- {agentshim-0.1.0 → agentshim-0.2.0}/agentshim/events.py +0 -0
- {agentshim-0.1.0 → agentshim-0.2.0}/agentshim/gemini/__init__.py +0 -0
- {agentshim-0.1.0 → agentshim-0.2.0}/agentshim/gemini/agent.py +0 -0
- {agentshim-0.1.0 → agentshim-0.2.0}/agentshim/gemini/events.py +0 -0
- {agentshim-0.1.0 → agentshim-0.2.0}/agentshim/gemini_events.py +0 -0
- {agentshim-0.1.0 → agentshim-0.2.0}/agentshim/llm_client.py +0 -0
- {agentshim-0.1.0 → agentshim-0.2.0}/agentshim/mcp_config.py +0 -0
- {agentshim-0.1.0 → agentshim-0.2.0}/agentshim/opencode/__init__.py +0 -0
- {agentshim-0.1.0 → agentshim-0.2.0}/agentshim/opencode/agent.py +0 -0
- {agentshim-0.1.0 → agentshim-0.2.0}/agentshim/opencode/events.py +0 -0
- {agentshim-0.1.0 → agentshim-0.2.0}/agentshim/opencode_events.py +0 -0
- {agentshim-0.1.0 → agentshim-0.2.0}/agentshim/py.typed +0 -0
- {agentshim-0.1.0 → agentshim-0.2.0}/agentshim/sandbox.py +0 -0
- {agentshim-0.1.0 → agentshim-0.2.0}/agentshim/subagent.py +0 -0
- {agentshim-0.1.0 → agentshim-0.2.0}/agentshim/trajectory.py +0 -0
- {agentshim-0.1.0 → agentshim-0.2.0}/agentshim/usage.py +0 -0
- {agentshim-0.1.0 → agentshim-0.2.0}/agentshim/utils.py +0 -0
- {agentshim-0.1.0 → agentshim-0.2.0}/tests/unit/cli_agent/test_agent_cli_cleanup.py +0 -0
- {agentshim-0.1.0 → agentshim-0.2.0}/tests/unit/cli_agent/test_check_cli.py +0 -0
- {agentshim-0.1.0 → agentshim-0.2.0}/tests/unit/cli_agent/test_cli_prompt_passing.py +0 -0
- {agentshim-0.1.0 → agentshim-0.2.0}/tests/unit/llm/conftest.py +0 -0
- {agentshim-0.1.0 → agentshim-0.2.0}/tests/unit/llm/test_claude_stream.py +0 -0
- {agentshim-0.1.0 → agentshim-0.2.0}/tests/unit/llm/test_gemini_fixture.py +0 -0
- {agentshim-0.1.0 → agentshim-0.2.0}/tests/unit/llm/test_gemini_stream.py +0 -0
- {agentshim-0.1.0 → agentshim-0.2.0}/tests/unit/test_agent_cli_claude.py +0 -0
- {agentshim-0.1.0 → agentshim-0.2.0}/tests/unit/test_agent_cli_codex.py +0 -0
- {agentshim-0.1.0 → agentshim-0.2.0}/tests/unit/test_agent_cli_event_parsing.py +0 -0
- {agentshim-0.1.0 → agentshim-0.2.0}/tests/unit/test_agent_cli_mcp_unsupported.py +0 -0
- {agentshim-0.1.0 → agentshim-0.2.0}/tests/unit/test_agent_cli_resume.py +0 -0
- {agentshim-0.1.0 → agentshim-0.2.0}/tests/unit/test_agent_cli_sandbox.py +0 -0
- {agentshim-0.1.0 → agentshim-0.2.0}/tests/unit/test_cli_agent_usage.py +0 -0
- {agentshim-0.1.0 → agentshim-0.2.0}/tests/unit/test_mcp_config.py +0 -0
agentshim-0.2.0/PKG-INFO
ADDED
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: agentshim
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Provider-agnostic coding-agent CLI shims
|
|
5
|
+
Requires-Python: >=3.10
|
|
6
|
+
Requires-Dist: litellm>=1.0.0
|
|
7
|
+
Requires-Dist: loguru>=0.7.2
|
|
8
|
+
Provides-Extra: test
|
|
9
|
+
Requires-Dist: pytest>=8.0.0; extra == 'test'
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
|
|
12
|
+
# agentshim
|
|
13
|
+
|
|
14
|
+
`agentshim` wraps coding-agent CLIs behind one small Python interface.
|
|
15
|
+
|
|
16
|
+
It is useful when you want to drive tools like Claude Code, Codex, Gemini, or
|
|
17
|
+
Opencode from Python without writing provider-specific subprocess plumbing for
|
|
18
|
+
prompting, session resumption, event parsing, or MCP configuration.
|
|
19
|
+
|
|
20
|
+
## What It Includes
|
|
21
|
+
|
|
22
|
+
- a shared CLI agent abstraction with a provider registry
|
|
23
|
+
- adapters for Claude Code, Codex, Gemini, and Opencode
|
|
24
|
+
- stateful chat sessions that automatically resume provider-native threads
|
|
25
|
+
- MCP server config models for providers that support MCP
|
|
26
|
+
- sandbox settings helpers for Claude Code
|
|
27
|
+
- a lightweight LiteLLM client and subagent helper
|
|
28
|
+
- trajectory/usage helpers used by higher-level runtimes
|
|
29
|
+
|
|
30
|
+
## Install
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
uv add agentshim
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
`agentshim` does not bundle the underlying agent CLIs. You still need the
|
|
37
|
+
provider tool you want to use installed and authenticated on your machine, for
|
|
38
|
+
example `claude`, `codex`, `gemini`, or `opencode`.
|
|
39
|
+
|
|
40
|
+
## Getting Started
|
|
41
|
+
|
|
42
|
+
### 1. Use the Generic Agent Interface for Chat and Resume
|
|
43
|
+
|
|
44
|
+
If you want to choose a provider at runtime, instantiate `CodingAgent`
|
|
45
|
+
directly with a provider name.
|
|
46
|
+
|
|
47
|
+
```python
|
|
48
|
+
from agentshim import CodingAgent
|
|
49
|
+
|
|
50
|
+
agent = CodingAgent(provider="claude", model="sonnet")
|
|
51
|
+
chat = agent.start_session(cwd=".")
|
|
52
|
+
|
|
53
|
+
first_reply = chat.generate("Summarize this repository.")
|
|
54
|
+
follow_up = chat.generate("Now list the three highest-risk modules.")
|
|
55
|
+
|
|
56
|
+
print(first_reply)
|
|
57
|
+
print(follow_up)
|
|
58
|
+
print(chat.session_id)
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
`start_session()` returns a stateful chat object. On the first `generate(...)`
|
|
62
|
+
call, `agentshim` starts a fresh provider conversation. On later calls, it
|
|
63
|
+
automatically resumes the same underlying provider session using the session id
|
|
64
|
+
captured from the first run.
|
|
65
|
+
|
|
66
|
+
That corresponds roughly to these native CLI flows:
|
|
67
|
+
|
|
68
|
+
- Claude Code: first call is like `claude -p ...`, later calls add `claude --resume <session_id> ...`
|
|
69
|
+
- Codex: first call is like `codex exec ...`, later calls add `codex exec resume <thread_id> ...`
|
|
70
|
+
- Gemini: first call is like `gemini ...`, later calls add `gemini --resume <session_id> ...`
|
|
71
|
+
- Opencode: first call is like `opencode run ...`, later calls add `opencode run --session <session_id> ...`
|
|
72
|
+
|
|
73
|
+
If you only want a one-shot request, use `generate(...)` directly instead of
|
|
74
|
+
opening a session:
|
|
75
|
+
|
|
76
|
+
```python
|
|
77
|
+
from agentshim import CodexCodingAgent
|
|
78
|
+
|
|
79
|
+
agent = CodexCodingAgent(model="gpt-5")
|
|
80
|
+
reply = agent.generate("Write a short summary of this codebase.", cwd=".")
|
|
81
|
+
print(reply)
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### 2. Instantiate a Specific Provider Directly
|
|
85
|
+
|
|
86
|
+
If you already know which backend you want, construct the provider class
|
|
87
|
+
yourself.
|
|
88
|
+
|
|
89
|
+
```python
|
|
90
|
+
from agentshim import ClaudeCodeCodingAgent
|
|
91
|
+
|
|
92
|
+
agent = ClaudeCodeCodingAgent(model="sonnet")
|
|
93
|
+
chat = agent.start_session(cwd=".")
|
|
94
|
+
|
|
95
|
+
print(chat.generate("What does this project do?"))
|
|
96
|
+
print(chat.generate("Which files should I read first?"))
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
The bundled provider classes are:
|
|
100
|
+
|
|
101
|
+
- `ClaudeCodeCodingAgent`
|
|
102
|
+
- `CodexCodingAgent`
|
|
103
|
+
- `GeminiCodingAgent`
|
|
104
|
+
- `OpencodeCodingAgent`
|
|
105
|
+
|
|
106
|
+
### 3. Configure MCP Servers
|
|
107
|
+
|
|
108
|
+
Claude Code and Codex can be configured with MCP servers by passing
|
|
109
|
+
`HttpMcpServer` and `StdioMcpServer` objects at construction time.
|
|
110
|
+
|
|
111
|
+
```python
|
|
112
|
+
from agentshim import ClaudeCodeCodingAgent, HttpMcpServer, StdioMcpServer
|
|
113
|
+
|
|
114
|
+
agent = ClaudeCodeCodingAgent(
|
|
115
|
+
model="sonnet",
|
|
116
|
+
mcp_servers=[
|
|
117
|
+
HttpMcpServer(
|
|
118
|
+
name="docs",
|
|
119
|
+
url="http://localhost:9000/sse",
|
|
120
|
+
headers={"Authorization": "Bearer dev-token"},
|
|
121
|
+
),
|
|
122
|
+
StdioMcpServer(
|
|
123
|
+
name="github",
|
|
124
|
+
command="npx",
|
|
125
|
+
args=["-y", "@modelcontextprotocol/server-github"],
|
|
126
|
+
env={"GITHUB_TOKEN": "ghp_example"},
|
|
127
|
+
),
|
|
128
|
+
],
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
chat = agent.start_session(cwd=".")
|
|
132
|
+
print(chat.generate("Use the MCP tools to inspect the repo."))
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Notes:
|
|
136
|
+
|
|
137
|
+
- `HttpMcpServer` is for HTTP/SSE-backed MCP servers.
|
|
138
|
+
- `StdioMcpServer` is for subprocess-backed MCP servers.
|
|
139
|
+
- Gemini and Opencode currently reject `mcp_servers`; use Claude Code or Codex if you need MCP.
|
|
140
|
+
|
|
141
|
+
## Extending agentshim
|
|
142
|
+
|
|
143
|
+
Advanced users can register their own providers. `CodingAgent(...)` keeps its
|
|
144
|
+
main constructor portable; provider-specific constructor extras should go
|
|
145
|
+
through `backend_kwargs`.
|
|
146
|
+
|
|
147
|
+
```python
|
|
148
|
+
from agentshim import BaseCodingAgent, CodingAgent, register_provider
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
@register_provider("my-agent", aliases=("my-agent-dev",))
|
|
152
|
+
class MyAgent(BaseCodingAgent):
|
|
153
|
+
def __init__(
|
|
154
|
+
self,
|
|
155
|
+
model: str | None = None,
|
|
156
|
+
region: str | None = None,
|
|
157
|
+
recorder=None,
|
|
158
|
+
event_handler=None,
|
|
159
|
+
mcp_servers=None,
|
|
160
|
+
sandbox=False,
|
|
161
|
+
):
|
|
162
|
+
self.model = model
|
|
163
|
+
self.region = region
|
|
164
|
+
self.recorder = recorder
|
|
165
|
+
self.event_handler = event_handler
|
|
166
|
+
|
|
167
|
+
def generate(self, prompt: str, cwd=None, timeout=300, silent=False) -> str:
|
|
168
|
+
return f"handled: {prompt}"
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
agent = CodingAgent(
|
|
172
|
+
provider="my-agent-dev",
|
|
173
|
+
model="demo",
|
|
174
|
+
backend_kwargs={"region": "us-west1"},
|
|
175
|
+
)
|
|
176
|
+
print(agent.generate("hello"))
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
Notes:
|
|
180
|
+
|
|
181
|
+
- Registration is import-driven. Your provider is available only after the module defining it has been imported in the current Python process.
|
|
182
|
+
- `list_providers()` returns canonical provider names only. Aliases resolve via `get_provider_class(...)` and `CodingAgent(provider=...)`.
|
|
183
|
+
- `register_provider(...)` rejects invalid names, abstract classes, and accidental name collisions unless you pass `overwrite=True`.
|
|
184
|
+
- If you want `CodingAgent(...)` to instantiate your provider, its constructor should accept the shared kwargs `model`, `recorder`, `event_handler`, `mcp_servers`, and `sandbox` as needed.
|
|
185
|
+
- If your provider needs extra constructor arguments beyond the shared portable set, pass them via `backend_kwargs={...}` when constructing `CodingAgent(...)`.
|
|
186
|
+
|
|
187
|
+
## Development
|
|
188
|
+
|
|
189
|
+
```bash
|
|
190
|
+
uv sync --dev
|
|
191
|
+
uv run pytest
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
## Publishing
|
|
195
|
+
|
|
196
|
+
Build locally with:
|
|
197
|
+
|
|
198
|
+
```bash
|
|
199
|
+
uv build
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
Publish with:
|
|
203
|
+
|
|
204
|
+
```bash
|
|
205
|
+
uv publish
|
|
206
|
+
```
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
# agentshim
|
|
2
|
+
|
|
3
|
+
`agentshim` wraps coding-agent CLIs behind one small Python interface.
|
|
4
|
+
|
|
5
|
+
It is useful when you want to drive tools like Claude Code, Codex, Gemini, or
|
|
6
|
+
Opencode from Python without writing provider-specific subprocess plumbing for
|
|
7
|
+
prompting, session resumption, event parsing, or MCP configuration.
|
|
8
|
+
|
|
9
|
+
## What It Includes
|
|
10
|
+
|
|
11
|
+
- a shared CLI agent abstraction with a provider registry
|
|
12
|
+
- adapters for Claude Code, Codex, Gemini, and Opencode
|
|
13
|
+
- stateful chat sessions that automatically resume provider-native threads
|
|
14
|
+
- MCP server config models for providers that support MCP
|
|
15
|
+
- sandbox settings helpers for Claude Code
|
|
16
|
+
- a lightweight LiteLLM client and subagent helper
|
|
17
|
+
- trajectory/usage helpers used by higher-level runtimes
|
|
18
|
+
|
|
19
|
+
## Install
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
uv add agentshim
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
`agentshim` does not bundle the underlying agent CLIs. You still need the
|
|
26
|
+
provider tool you want to use installed and authenticated on your machine, for
|
|
27
|
+
example `claude`, `codex`, `gemini`, or `opencode`.
|
|
28
|
+
|
|
29
|
+
## Getting Started
|
|
30
|
+
|
|
31
|
+
### 1. Use the Generic Agent Interface for Chat and Resume
|
|
32
|
+
|
|
33
|
+
If you want to choose a provider at runtime, instantiate `CodingAgent`
|
|
34
|
+
directly with a provider name.
|
|
35
|
+
|
|
36
|
+
```python
|
|
37
|
+
from agentshim import CodingAgent
|
|
38
|
+
|
|
39
|
+
agent = CodingAgent(provider="claude", model="sonnet")
|
|
40
|
+
chat = agent.start_session(cwd=".")
|
|
41
|
+
|
|
42
|
+
first_reply = chat.generate("Summarize this repository.")
|
|
43
|
+
follow_up = chat.generate("Now list the three highest-risk modules.")
|
|
44
|
+
|
|
45
|
+
print(first_reply)
|
|
46
|
+
print(follow_up)
|
|
47
|
+
print(chat.session_id)
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
`start_session()` returns a stateful chat object. On the first `generate(...)`
|
|
51
|
+
call, `agentshim` starts a fresh provider conversation. On later calls, it
|
|
52
|
+
automatically resumes the same underlying provider session using the session id
|
|
53
|
+
captured from the first run.
|
|
54
|
+
|
|
55
|
+
That corresponds roughly to these native CLI flows:
|
|
56
|
+
|
|
57
|
+
- Claude Code: first call is like `claude -p ...`, later calls add `claude --resume <session_id> ...`
|
|
58
|
+
- Codex: first call is like `codex exec ...`, later calls add `codex exec resume <thread_id> ...`
|
|
59
|
+
- Gemini: first call is like `gemini ...`, later calls add `gemini --resume <session_id> ...`
|
|
60
|
+
- Opencode: first call is like `opencode run ...`, later calls add `opencode run --session <session_id> ...`
|
|
61
|
+
|
|
62
|
+
If you only want a one-shot request, use `generate(...)` directly instead of
|
|
63
|
+
opening a session:
|
|
64
|
+
|
|
65
|
+
```python
|
|
66
|
+
from agentshim import CodexCodingAgent
|
|
67
|
+
|
|
68
|
+
agent = CodexCodingAgent(model="gpt-5")
|
|
69
|
+
reply = agent.generate("Write a short summary of this codebase.", cwd=".")
|
|
70
|
+
print(reply)
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### 2. Instantiate a Specific Provider Directly
|
|
74
|
+
|
|
75
|
+
If you already know which backend you want, construct the provider class
|
|
76
|
+
yourself.
|
|
77
|
+
|
|
78
|
+
```python
|
|
79
|
+
from agentshim import ClaudeCodeCodingAgent
|
|
80
|
+
|
|
81
|
+
agent = ClaudeCodeCodingAgent(model="sonnet")
|
|
82
|
+
chat = agent.start_session(cwd=".")
|
|
83
|
+
|
|
84
|
+
print(chat.generate("What does this project do?"))
|
|
85
|
+
print(chat.generate("Which files should I read first?"))
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
The bundled provider classes are:
|
|
89
|
+
|
|
90
|
+
- `ClaudeCodeCodingAgent`
|
|
91
|
+
- `CodexCodingAgent`
|
|
92
|
+
- `GeminiCodingAgent`
|
|
93
|
+
- `OpencodeCodingAgent`
|
|
94
|
+
|
|
95
|
+
### 3. Configure MCP Servers
|
|
96
|
+
|
|
97
|
+
Claude Code and Codex can be configured with MCP servers by passing
|
|
98
|
+
`HttpMcpServer` and `StdioMcpServer` objects at construction time.
|
|
99
|
+
|
|
100
|
+
```python
|
|
101
|
+
from agentshim import ClaudeCodeCodingAgent, HttpMcpServer, StdioMcpServer
|
|
102
|
+
|
|
103
|
+
agent = ClaudeCodeCodingAgent(
|
|
104
|
+
model="sonnet",
|
|
105
|
+
mcp_servers=[
|
|
106
|
+
HttpMcpServer(
|
|
107
|
+
name="docs",
|
|
108
|
+
url="http://localhost:9000/sse",
|
|
109
|
+
headers={"Authorization": "Bearer dev-token"},
|
|
110
|
+
),
|
|
111
|
+
StdioMcpServer(
|
|
112
|
+
name="github",
|
|
113
|
+
command="npx",
|
|
114
|
+
args=["-y", "@modelcontextprotocol/server-github"],
|
|
115
|
+
env={"GITHUB_TOKEN": "ghp_example"},
|
|
116
|
+
),
|
|
117
|
+
],
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
chat = agent.start_session(cwd=".")
|
|
121
|
+
print(chat.generate("Use the MCP tools to inspect the repo."))
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Notes:
|
|
125
|
+
|
|
126
|
+
- `HttpMcpServer` is for HTTP/SSE-backed MCP servers.
|
|
127
|
+
- `StdioMcpServer` is for subprocess-backed MCP servers.
|
|
128
|
+
- Gemini and Opencode currently reject `mcp_servers`; use Claude Code or Codex if you need MCP.
|
|
129
|
+
|
|
130
|
+
## Extending agentshim
|
|
131
|
+
|
|
132
|
+
Advanced users can register their own providers. `CodingAgent(...)` keeps its
|
|
133
|
+
main constructor portable; provider-specific constructor extras should go
|
|
134
|
+
through `backend_kwargs`.
|
|
135
|
+
|
|
136
|
+
```python
|
|
137
|
+
from agentshim import BaseCodingAgent, CodingAgent, register_provider
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
@register_provider("my-agent", aliases=("my-agent-dev",))
|
|
141
|
+
class MyAgent(BaseCodingAgent):
|
|
142
|
+
def __init__(
|
|
143
|
+
self,
|
|
144
|
+
model: str | None = None,
|
|
145
|
+
region: str | None = None,
|
|
146
|
+
recorder=None,
|
|
147
|
+
event_handler=None,
|
|
148
|
+
mcp_servers=None,
|
|
149
|
+
sandbox=False,
|
|
150
|
+
):
|
|
151
|
+
self.model = model
|
|
152
|
+
self.region = region
|
|
153
|
+
self.recorder = recorder
|
|
154
|
+
self.event_handler = event_handler
|
|
155
|
+
|
|
156
|
+
def generate(self, prompt: str, cwd=None, timeout=300, silent=False) -> str:
|
|
157
|
+
return f"handled: {prompt}"
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
agent = CodingAgent(
|
|
161
|
+
provider="my-agent-dev",
|
|
162
|
+
model="demo",
|
|
163
|
+
backend_kwargs={"region": "us-west1"},
|
|
164
|
+
)
|
|
165
|
+
print(agent.generate("hello"))
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
Notes:
|
|
169
|
+
|
|
170
|
+
- Registration is import-driven. Your provider is available only after the module defining it has been imported in the current Python process.
|
|
171
|
+
- `list_providers()` returns canonical provider names only. Aliases resolve via `get_provider_class(...)` and `CodingAgent(provider=...)`.
|
|
172
|
+
- `register_provider(...)` rejects invalid names, abstract classes, and accidental name collisions unless you pass `overwrite=True`.
|
|
173
|
+
- If you want `CodingAgent(...)` to instantiate your provider, its constructor should accept the shared kwargs `model`, `recorder`, `event_handler`, `mcp_servers`, and `sandbox` as needed.
|
|
174
|
+
- If your provider needs extra constructor arguments beyond the shared portable set, pass them via `backend_kwargs={...}` when constructing `CodingAgent(...)`.
|
|
175
|
+
|
|
176
|
+
## Development
|
|
177
|
+
|
|
178
|
+
```bash
|
|
179
|
+
uv sync --dev
|
|
180
|
+
uv run pytest
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
## Publishing
|
|
184
|
+
|
|
185
|
+
Build locally with:
|
|
186
|
+
|
|
187
|
+
```bash
|
|
188
|
+
uv build
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
Publish with:
|
|
192
|
+
|
|
193
|
+
```bash
|
|
194
|
+
uv publish
|
|
195
|
+
```
|
|
@@ -1,15 +1,18 @@
|
|
|
1
|
-
from .base import CodingAgent
|
|
1
|
+
from .base import BaseAgentSession, BaseCodingAgent, CodingAgent, get_provider_class, list_providers, register_provider
|
|
2
2
|
from .claude import ClaudeCodeCodingAgent
|
|
3
3
|
from .codex import CodexCodingAgent
|
|
4
4
|
from .gemini import GeminiCodingAgent
|
|
5
|
-
from .llm_client import LiteLLMClient
|
|
6
5
|
from .mcp_config import HttpMcpServer, McpServerConfig, StdioMcpServer
|
|
7
6
|
from .opencode import OpencodeCodingAgent
|
|
8
7
|
from .sandbox import SandboxConfig
|
|
9
|
-
from .subagent import call_subagent, litellm_call_with_retry
|
|
10
8
|
|
|
11
9
|
__all__ = [
|
|
10
|
+
"BaseCodingAgent",
|
|
11
|
+
"BaseAgentSession",
|
|
12
12
|
"CodingAgent",
|
|
13
|
+
"get_provider_class",
|
|
14
|
+
"list_providers",
|
|
15
|
+
"register_provider",
|
|
13
16
|
"CodexCodingAgent",
|
|
14
17
|
"GeminiCodingAgent",
|
|
15
18
|
"OpencodeCodingAgent",
|
|
@@ -18,7 +21,4 @@ __all__ = [
|
|
|
18
21
|
"McpServerConfig",
|
|
19
22
|
"StdioMcpServer",
|
|
20
23
|
"SandboxConfig",
|
|
21
|
-
"call_subagent",
|
|
22
|
-
"litellm_call_with_retry",
|
|
23
|
-
"LiteLLMClient",
|
|
24
24
|
]
|