evolv-agent-sdk 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.
- evolv_agent_sdk-0.2.0/.gitignore +36 -0
- evolv_agent_sdk-0.2.0/LICENSE +21 -0
- evolv_agent_sdk-0.2.0/PKG-INFO +250 -0
- evolv_agent_sdk-0.2.0/README.md +217 -0
- evolv_agent_sdk-0.2.0/pyproject.toml +109 -0
- evolv_agent_sdk-0.2.0/src/evolv_agent_sdk/__init__.py +285 -0
- evolv_agent_sdk-0.2.0/src/evolv_agent_sdk/_bundled/.gitkeep +1 -0
- evolv_agent_sdk-0.2.0/src/evolv_agent_sdk/_cli_version.py +3 -0
- evolv_agent_sdk-0.2.0/src/evolv_agent_sdk/_errors.py +61 -0
- evolv_agent_sdk-0.2.0/src/evolv_agent_sdk/_internal/__init__.py +1 -0
- evolv_agent_sdk-0.2.0/src/evolv_agent_sdk/_internal/client.py +108 -0
- evolv_agent_sdk-0.2.0/src/evolv_agent_sdk/_internal/message_parser.py +181 -0
- evolv_agent_sdk-0.2.0/src/evolv_agent_sdk/_internal/query.py +547 -0
- evolv_agent_sdk-0.2.0/src/evolv_agent_sdk/_internal/transport/__init__.py +68 -0
- evolv_agent_sdk-0.2.0/src/evolv_agent_sdk/_internal/transport/subprocess_cli.py +712 -0
- evolv_agent_sdk-0.2.0/src/evolv_agent_sdk/_version.py +3 -0
- evolv_agent_sdk-0.2.0/src/evolv_agent_sdk/client.py +365 -0
- evolv_agent_sdk-0.2.0/src/evolv_agent_sdk/py.typed +0 -0
- evolv_agent_sdk-0.2.0/src/evolv_agent_sdk/query.py +99 -0
- evolv_agent_sdk-0.2.0/src/evolv_agent_sdk/types.py +689 -0
- evolv_agent_sdk-0.2.0/tests/conftest.py +86 -0
- evolv_agent_sdk-0.2.0/tests/test_client.py +108 -0
- evolv_agent_sdk-0.2.0/tests/test_message_parser.py +187 -0
- evolv_agent_sdk-0.2.0/tests/test_query.py +76 -0
- evolv_agent_sdk-0.2.0/tests/test_types.py +139 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Dependencies
|
|
2
|
+
node_modules/
|
|
3
|
+
.venv/
|
|
4
|
+
__pycache__/
|
|
5
|
+
*.pyc
|
|
6
|
+
|
|
7
|
+
# Build outputs
|
|
8
|
+
packages/cli/dist/
|
|
9
|
+
packages/sdk/dist/
|
|
10
|
+
*.egg-info/
|
|
11
|
+
|
|
12
|
+
# IDE
|
|
13
|
+
.idea/
|
|
14
|
+
.vscode/
|
|
15
|
+
*.swp
|
|
16
|
+
|
|
17
|
+
# OS
|
|
18
|
+
.DS_Store
|
|
19
|
+
Thumbs.db
|
|
20
|
+
|
|
21
|
+
# Lock files (keep for reproducibility, but comment if preferred)
|
|
22
|
+
# bun.lock
|
|
23
|
+
# uv.lock
|
|
24
|
+
|
|
25
|
+
# Environment
|
|
26
|
+
.env
|
|
27
|
+
.env.local
|
|
28
|
+
|
|
29
|
+
# Testing/cache
|
|
30
|
+
.mypy_cache/
|
|
31
|
+
.pytest_cache/
|
|
32
|
+
.ruff_cache/
|
|
33
|
+
coverage/
|
|
34
|
+
|
|
35
|
+
# Release artifacts
|
|
36
|
+
packages/cli/release/
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Snowflake Inc.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: evolv-agent-sdk
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Python SDK for evolv Code
|
|
5
|
+
Project-URL: Homepage, https://github.com/jeremy-newhouse/evolv-code
|
|
6
|
+
Project-URL: Documentation, https://github.com/jeremy-newhouse/evolv-code/tree/main/packages/sdk
|
|
7
|
+
Project-URL: Issues, https://github.com/jeremy-newhouse/evolv-code/issues
|
|
8
|
+
Author-email: evolv <support@evolv.ai>
|
|
9
|
+
License: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: agent,ai,claude,evolv,sdk
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Classifier: Typing :: Typed
|
|
21
|
+
Requires-Python: >=3.10
|
|
22
|
+
Requires-Dist: anyio>=4.0.0
|
|
23
|
+
Requires-Dist: mcp>=0.1.0
|
|
24
|
+
Requires-Dist: typing-extensions>=4.0.0; python_version < '3.11'
|
|
25
|
+
Provides-Extra: dev
|
|
26
|
+
Requires-Dist: anyio[trio]>=4.0.0; extra == 'dev'
|
|
27
|
+
Requires-Dist: mypy>=1.0.0; extra == 'dev'
|
|
28
|
+
Requires-Dist: pytest-asyncio>=0.20.0; extra == 'dev'
|
|
29
|
+
Requires-Dist: pytest-cov>=4.0.0; extra == 'dev'
|
|
30
|
+
Requires-Dist: pytest>=7.0.0; extra == 'dev'
|
|
31
|
+
Requires-Dist: ruff>=0.1.0; extra == 'dev'
|
|
32
|
+
Description-Content-Type: text/markdown
|
|
33
|
+
|
|
34
|
+
# evolv Agent SDK for Python
|
|
35
|
+
|
|
36
|
+
Python SDK for [evolv Code](https://github.com/evolv-ai/evolv-code), an AI coding assistant with full bidirectional streaming support.
|
|
37
|
+
|
|
38
|
+
## Installation
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
pip install evolv-agent-sdk
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
**Note:** The evolv Code CLI must be installed separately. Build from source at `/Users/jdnewhouse/repos/evolv-code` or set `EVOLV_CODE_CLI_PATH` environment variable.
|
|
45
|
+
|
|
46
|
+
## Quick Start
|
|
47
|
+
|
|
48
|
+
### Simple Query
|
|
49
|
+
|
|
50
|
+
```python
|
|
51
|
+
import asyncio
|
|
52
|
+
from evolv_agent_sdk import query, EvolvAgentOptions, AssistantMessage, TextBlock
|
|
53
|
+
|
|
54
|
+
async def main():
|
|
55
|
+
async for message in query(prompt="What is 2 + 2?"):
|
|
56
|
+
if isinstance(message, AssistantMessage):
|
|
57
|
+
for block in message.content:
|
|
58
|
+
if isinstance(block, TextBlock):
|
|
59
|
+
print(f"evolv: {block.text}")
|
|
60
|
+
|
|
61
|
+
asyncio.run(main())
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Multi-Query Client
|
|
65
|
+
|
|
66
|
+
```python
|
|
67
|
+
import asyncio
|
|
68
|
+
from evolv_agent_sdk import EvolvSDKClient, EvolvAgentOptions, AssistantMessage, TextBlock
|
|
69
|
+
|
|
70
|
+
async def main():
|
|
71
|
+
async with EvolvSDKClient() as client:
|
|
72
|
+
# First query
|
|
73
|
+
await client.query("What files are in this directory?")
|
|
74
|
+
async for msg in client.receive_response():
|
|
75
|
+
if isinstance(msg, AssistantMessage):
|
|
76
|
+
for block in msg.content:
|
|
77
|
+
if isinstance(block, TextBlock):
|
|
78
|
+
print(block.text)
|
|
79
|
+
|
|
80
|
+
# Second query (note: each query is independent)
|
|
81
|
+
await client.query("How many are Python files?")
|
|
82
|
+
async for msg in client.receive_response():
|
|
83
|
+
if isinstance(msg, AssistantMessage):
|
|
84
|
+
for block in msg.content:
|
|
85
|
+
if isinstance(block, TextBlock):
|
|
86
|
+
print(block.text)
|
|
87
|
+
|
|
88
|
+
asyncio.run(main())
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Bidirectional Streaming Mode
|
|
92
|
+
|
|
93
|
+
evolv Code CLI supports full bidirectional streaming with `--input-format stream-json`:
|
|
94
|
+
|
|
95
|
+
```python
|
|
96
|
+
import asyncio
|
|
97
|
+
from evolv_agent_sdk import query, EvolvAgentOptions
|
|
98
|
+
from evolv_agent_sdk.types import PermissionResultAllow, PermissionResultDeny
|
|
99
|
+
|
|
100
|
+
async def my_can_use_tool(tool_name, tool_input, context):
|
|
101
|
+
"""Custom tool permission callback."""
|
|
102
|
+
if tool_name == "Bash" and "rm" in tool_input.get("command", ""):
|
|
103
|
+
return PermissionResultDeny(message="Destructive command blocked")
|
|
104
|
+
return PermissionResultAllow()
|
|
105
|
+
|
|
106
|
+
async def main():
|
|
107
|
+
options = EvolvAgentOptions(
|
|
108
|
+
can_use_tool=my_can_use_tool,
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
async for message in query(
|
|
112
|
+
prompt=my_async_input_generator(), # AsyncIterable for streaming
|
|
113
|
+
options=options,
|
|
114
|
+
):
|
|
115
|
+
print(message)
|
|
116
|
+
|
|
117
|
+
asyncio.run(main())
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## API Reference
|
|
121
|
+
|
|
122
|
+
### `query()`
|
|
123
|
+
|
|
124
|
+
One-shot query function for simple, stateless interactions.
|
|
125
|
+
|
|
126
|
+
```python
|
|
127
|
+
async for message in query(
|
|
128
|
+
prompt="Your question here",
|
|
129
|
+
options=EvolvAgentOptions(
|
|
130
|
+
cwd="/path/to/working/directory",
|
|
131
|
+
model="your-model",
|
|
132
|
+
)
|
|
133
|
+
):
|
|
134
|
+
print(message)
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### `EvolvSDKClient`
|
|
138
|
+
|
|
139
|
+
Client for running multiple queries. Each query spawns a new process.
|
|
140
|
+
|
|
141
|
+
```python
|
|
142
|
+
async with EvolvSDKClient(options) as client:
|
|
143
|
+
await client.query("First question")
|
|
144
|
+
async for msg in client.receive_response():
|
|
145
|
+
print(msg)
|
|
146
|
+
|
|
147
|
+
await client.query("Second question")
|
|
148
|
+
async for msg in client.receive_response():
|
|
149
|
+
print(msg)
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### `EvolvAgentOptions`
|
|
153
|
+
|
|
154
|
+
Configuration options for the SDK:
|
|
155
|
+
|
|
156
|
+
| Option | Type | Description |
|
|
157
|
+
|--------|------|-------------|
|
|
158
|
+
| `cli_path` | `str \| Path` | Path to evolv CLI binary |
|
|
159
|
+
| `cwd` | `str \| Path` | Working directory for commands |
|
|
160
|
+
| `model` | `str` | Model to use |
|
|
161
|
+
| `connection` | `str` | Snowflake connection name |
|
|
162
|
+
| `resume` | `str` | Session ID to resume |
|
|
163
|
+
| `continue_conversation` | `bool` | Continue most recent session |
|
|
164
|
+
| `env` | `dict[str, str]` | Environment variables |
|
|
165
|
+
| `can_use_tool` | `Callable` | Tool permission callback (bidirectional mode) |
|
|
166
|
+
| `hooks` | `dict` | SDK hooks for PreToolUse, PostToolUse, etc. |
|
|
167
|
+
| `mcp_servers` | `dict` | SDK MCP servers (in-process) |
|
|
168
|
+
|
|
169
|
+
## Environment Variables
|
|
170
|
+
|
|
171
|
+
| Variable | Description |
|
|
172
|
+
|----------|-------------|
|
|
173
|
+
| `EVOLV_CODE_CLI_PATH` | Path to evolv CLI binary |
|
|
174
|
+
| `EVOLV_CODE_ENTRYPOINT` | SDK entrypoint identifier |
|
|
175
|
+
| `EVOLV_AGENT_SDK_SKIP_VERSION_CHECK` | Skip CLI version check |
|
|
176
|
+
| `EVOLV_CODE_STREAM_CLOSE_TIMEOUT` | Timeout for stream close (ms) |
|
|
177
|
+
|
|
178
|
+
## Message Types
|
|
179
|
+
|
|
180
|
+
The SDK yields several message types:
|
|
181
|
+
|
|
182
|
+
- `AssistantMessage` - Response from evolv with content blocks
|
|
183
|
+
- `UserMessage` - User input messages
|
|
184
|
+
- `SystemMessage` - System notifications
|
|
185
|
+
- `ResultMessage` - Final result with metadata
|
|
186
|
+
|
|
187
|
+
### Content Blocks
|
|
188
|
+
|
|
189
|
+
`AssistantMessage.content` contains a list of content blocks:
|
|
190
|
+
|
|
191
|
+
- `TextBlock` - Text response
|
|
192
|
+
- `ThinkingBlock` - Internal reasoning (if enabled)
|
|
193
|
+
- `ToolUseBlock` - Tool invocation
|
|
194
|
+
- `ToolResultBlock` - Tool execution result
|
|
195
|
+
|
|
196
|
+
## Features
|
|
197
|
+
|
|
198
|
+
### Bidirectional Streaming
|
|
199
|
+
|
|
200
|
+
evolv Code CLI supports `--input-format stream-json` for full bidirectional communication:
|
|
201
|
+
|
|
202
|
+
| Feature | evolv Code | Cortex Code |
|
|
203
|
+
|---------|------------|-------------|
|
|
204
|
+
| `--input-format stream-json` | ✅ Supported | ❌ Not available |
|
|
205
|
+
| `can_use_tool` callback | ✅ Supported | ❌ Not available |
|
|
206
|
+
| `interrupt()` | ✅ Supported | ❌ Not available |
|
|
207
|
+
| `set_permission_mode()` | ✅ Supported | ❌ Not available |
|
|
208
|
+
| `set_model()` | ✅ Supported | ❌ Not available |
|
|
209
|
+
| SDK Hooks | ✅ Supported | ❌ Not available |
|
|
210
|
+
| SDK MCP Servers | ✅ Supported | ❌ Not available |
|
|
211
|
+
|
|
212
|
+
### Fallback Mode
|
|
213
|
+
|
|
214
|
+
When using Cortex CLI (without bidirectional support), the SDK falls back to print mode:
|
|
215
|
+
|
|
216
|
+
```python
|
|
217
|
+
# Use --continue to resume the most recent session
|
|
218
|
+
options = EvolvAgentOptions(continue_conversation=True)
|
|
219
|
+
|
|
220
|
+
# Or resume a specific session
|
|
221
|
+
options = EvolvAgentOptions(resume="session-id-here")
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
## Backward Compatibility
|
|
225
|
+
|
|
226
|
+
For migration from Claude Agent SDK or Cortex Agent SDK:
|
|
227
|
+
|
|
228
|
+
```python
|
|
229
|
+
from evolv_agent_sdk import (
|
|
230
|
+
# Claude aliases
|
|
231
|
+
ClaudeSDKClient, # Alias for EvolvSDKClient
|
|
232
|
+
ClaudeAgentOptions, # Alias for EvolvAgentOptions
|
|
233
|
+
ClaudeSDKError, # Alias for EvolvSDKError
|
|
234
|
+
|
|
235
|
+
# Cortex aliases
|
|
236
|
+
CortexSDKClient, # Alias for EvolvSDKClient
|
|
237
|
+
CortexAgentOptions, # Alias for EvolvAgentOptions
|
|
238
|
+
CortexSDKError, # Alias for EvolvSDKError
|
|
239
|
+
)
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
## License
|
|
243
|
+
|
|
244
|
+
MIT License - see [LICENSE](LICENSE) for details.
|
|
245
|
+
|
|
246
|
+
## Links
|
|
247
|
+
|
|
248
|
+
- [evolv Code CLI](https://github.com/evolv-ai/evolv-code)
|
|
249
|
+
- [GitHub Repository](https://github.com/evolv-ai/evolv-agent-sdk-python)
|
|
250
|
+
- [Issue Tracker](https://github.com/evolv-ai/evolv-agent-sdk-python/issues)
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
# evolv Agent SDK for Python
|
|
2
|
+
|
|
3
|
+
Python SDK for [evolv Code](https://github.com/evolv-ai/evolv-code), an AI coding assistant with full bidirectional streaming support.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install evolv-agent-sdk
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
**Note:** The evolv Code CLI must be installed separately. Build from source at `/Users/jdnewhouse/repos/evolv-code` or set `EVOLV_CODE_CLI_PATH` environment variable.
|
|
12
|
+
|
|
13
|
+
## Quick Start
|
|
14
|
+
|
|
15
|
+
### Simple Query
|
|
16
|
+
|
|
17
|
+
```python
|
|
18
|
+
import asyncio
|
|
19
|
+
from evolv_agent_sdk import query, EvolvAgentOptions, AssistantMessage, TextBlock
|
|
20
|
+
|
|
21
|
+
async def main():
|
|
22
|
+
async for message in query(prompt="What is 2 + 2?"):
|
|
23
|
+
if isinstance(message, AssistantMessage):
|
|
24
|
+
for block in message.content:
|
|
25
|
+
if isinstance(block, TextBlock):
|
|
26
|
+
print(f"evolv: {block.text}")
|
|
27
|
+
|
|
28
|
+
asyncio.run(main())
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### Multi-Query Client
|
|
32
|
+
|
|
33
|
+
```python
|
|
34
|
+
import asyncio
|
|
35
|
+
from evolv_agent_sdk import EvolvSDKClient, EvolvAgentOptions, AssistantMessage, TextBlock
|
|
36
|
+
|
|
37
|
+
async def main():
|
|
38
|
+
async with EvolvSDKClient() as client:
|
|
39
|
+
# First query
|
|
40
|
+
await client.query("What files are in this directory?")
|
|
41
|
+
async for msg in client.receive_response():
|
|
42
|
+
if isinstance(msg, AssistantMessage):
|
|
43
|
+
for block in msg.content:
|
|
44
|
+
if isinstance(block, TextBlock):
|
|
45
|
+
print(block.text)
|
|
46
|
+
|
|
47
|
+
# Second query (note: each query is independent)
|
|
48
|
+
await client.query("How many are Python files?")
|
|
49
|
+
async for msg in client.receive_response():
|
|
50
|
+
if isinstance(msg, AssistantMessage):
|
|
51
|
+
for block in msg.content:
|
|
52
|
+
if isinstance(block, TextBlock):
|
|
53
|
+
print(block.text)
|
|
54
|
+
|
|
55
|
+
asyncio.run(main())
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Bidirectional Streaming Mode
|
|
59
|
+
|
|
60
|
+
evolv Code CLI supports full bidirectional streaming with `--input-format stream-json`:
|
|
61
|
+
|
|
62
|
+
```python
|
|
63
|
+
import asyncio
|
|
64
|
+
from evolv_agent_sdk import query, EvolvAgentOptions
|
|
65
|
+
from evolv_agent_sdk.types import PermissionResultAllow, PermissionResultDeny
|
|
66
|
+
|
|
67
|
+
async def my_can_use_tool(tool_name, tool_input, context):
|
|
68
|
+
"""Custom tool permission callback."""
|
|
69
|
+
if tool_name == "Bash" and "rm" in tool_input.get("command", ""):
|
|
70
|
+
return PermissionResultDeny(message="Destructive command blocked")
|
|
71
|
+
return PermissionResultAllow()
|
|
72
|
+
|
|
73
|
+
async def main():
|
|
74
|
+
options = EvolvAgentOptions(
|
|
75
|
+
can_use_tool=my_can_use_tool,
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
async for message in query(
|
|
79
|
+
prompt=my_async_input_generator(), # AsyncIterable for streaming
|
|
80
|
+
options=options,
|
|
81
|
+
):
|
|
82
|
+
print(message)
|
|
83
|
+
|
|
84
|
+
asyncio.run(main())
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## API Reference
|
|
88
|
+
|
|
89
|
+
### `query()`
|
|
90
|
+
|
|
91
|
+
One-shot query function for simple, stateless interactions.
|
|
92
|
+
|
|
93
|
+
```python
|
|
94
|
+
async for message in query(
|
|
95
|
+
prompt="Your question here",
|
|
96
|
+
options=EvolvAgentOptions(
|
|
97
|
+
cwd="/path/to/working/directory",
|
|
98
|
+
model="your-model",
|
|
99
|
+
)
|
|
100
|
+
):
|
|
101
|
+
print(message)
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### `EvolvSDKClient`
|
|
105
|
+
|
|
106
|
+
Client for running multiple queries. Each query spawns a new process.
|
|
107
|
+
|
|
108
|
+
```python
|
|
109
|
+
async with EvolvSDKClient(options) as client:
|
|
110
|
+
await client.query("First question")
|
|
111
|
+
async for msg in client.receive_response():
|
|
112
|
+
print(msg)
|
|
113
|
+
|
|
114
|
+
await client.query("Second question")
|
|
115
|
+
async for msg in client.receive_response():
|
|
116
|
+
print(msg)
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### `EvolvAgentOptions`
|
|
120
|
+
|
|
121
|
+
Configuration options for the SDK:
|
|
122
|
+
|
|
123
|
+
| Option | Type | Description |
|
|
124
|
+
|--------|------|-------------|
|
|
125
|
+
| `cli_path` | `str \| Path` | Path to evolv CLI binary |
|
|
126
|
+
| `cwd` | `str \| Path` | Working directory for commands |
|
|
127
|
+
| `model` | `str` | Model to use |
|
|
128
|
+
| `connection` | `str` | Snowflake connection name |
|
|
129
|
+
| `resume` | `str` | Session ID to resume |
|
|
130
|
+
| `continue_conversation` | `bool` | Continue most recent session |
|
|
131
|
+
| `env` | `dict[str, str]` | Environment variables |
|
|
132
|
+
| `can_use_tool` | `Callable` | Tool permission callback (bidirectional mode) |
|
|
133
|
+
| `hooks` | `dict` | SDK hooks for PreToolUse, PostToolUse, etc. |
|
|
134
|
+
| `mcp_servers` | `dict` | SDK MCP servers (in-process) |
|
|
135
|
+
|
|
136
|
+
## Environment Variables
|
|
137
|
+
|
|
138
|
+
| Variable | Description |
|
|
139
|
+
|----------|-------------|
|
|
140
|
+
| `EVOLV_CODE_CLI_PATH` | Path to evolv CLI binary |
|
|
141
|
+
| `EVOLV_CODE_ENTRYPOINT` | SDK entrypoint identifier |
|
|
142
|
+
| `EVOLV_AGENT_SDK_SKIP_VERSION_CHECK` | Skip CLI version check |
|
|
143
|
+
| `EVOLV_CODE_STREAM_CLOSE_TIMEOUT` | Timeout for stream close (ms) |
|
|
144
|
+
|
|
145
|
+
## Message Types
|
|
146
|
+
|
|
147
|
+
The SDK yields several message types:
|
|
148
|
+
|
|
149
|
+
- `AssistantMessage` - Response from evolv with content blocks
|
|
150
|
+
- `UserMessage` - User input messages
|
|
151
|
+
- `SystemMessage` - System notifications
|
|
152
|
+
- `ResultMessage` - Final result with metadata
|
|
153
|
+
|
|
154
|
+
### Content Blocks
|
|
155
|
+
|
|
156
|
+
`AssistantMessage.content` contains a list of content blocks:
|
|
157
|
+
|
|
158
|
+
- `TextBlock` - Text response
|
|
159
|
+
- `ThinkingBlock` - Internal reasoning (if enabled)
|
|
160
|
+
- `ToolUseBlock` - Tool invocation
|
|
161
|
+
- `ToolResultBlock` - Tool execution result
|
|
162
|
+
|
|
163
|
+
## Features
|
|
164
|
+
|
|
165
|
+
### Bidirectional Streaming
|
|
166
|
+
|
|
167
|
+
evolv Code CLI supports `--input-format stream-json` for full bidirectional communication:
|
|
168
|
+
|
|
169
|
+
| Feature | evolv Code | Cortex Code |
|
|
170
|
+
|---------|------------|-------------|
|
|
171
|
+
| `--input-format stream-json` | ✅ Supported | ❌ Not available |
|
|
172
|
+
| `can_use_tool` callback | ✅ Supported | ❌ Not available |
|
|
173
|
+
| `interrupt()` | ✅ Supported | ❌ Not available |
|
|
174
|
+
| `set_permission_mode()` | ✅ Supported | ❌ Not available |
|
|
175
|
+
| `set_model()` | ✅ Supported | ❌ Not available |
|
|
176
|
+
| SDK Hooks | ✅ Supported | ❌ Not available |
|
|
177
|
+
| SDK MCP Servers | ✅ Supported | ❌ Not available |
|
|
178
|
+
|
|
179
|
+
### Fallback Mode
|
|
180
|
+
|
|
181
|
+
When using Cortex CLI (without bidirectional support), the SDK falls back to print mode:
|
|
182
|
+
|
|
183
|
+
```python
|
|
184
|
+
# Use --continue to resume the most recent session
|
|
185
|
+
options = EvolvAgentOptions(continue_conversation=True)
|
|
186
|
+
|
|
187
|
+
# Or resume a specific session
|
|
188
|
+
options = EvolvAgentOptions(resume="session-id-here")
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
## Backward Compatibility
|
|
192
|
+
|
|
193
|
+
For migration from Claude Agent SDK or Cortex Agent SDK:
|
|
194
|
+
|
|
195
|
+
```python
|
|
196
|
+
from evolv_agent_sdk import (
|
|
197
|
+
# Claude aliases
|
|
198
|
+
ClaudeSDKClient, # Alias for EvolvSDKClient
|
|
199
|
+
ClaudeAgentOptions, # Alias for EvolvAgentOptions
|
|
200
|
+
ClaudeSDKError, # Alias for EvolvSDKError
|
|
201
|
+
|
|
202
|
+
# Cortex aliases
|
|
203
|
+
CortexSDKClient, # Alias for EvolvSDKClient
|
|
204
|
+
CortexAgentOptions, # Alias for EvolvAgentOptions
|
|
205
|
+
CortexSDKError, # Alias for EvolvSDKError
|
|
206
|
+
)
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
## License
|
|
210
|
+
|
|
211
|
+
MIT License - see [LICENSE](LICENSE) for details.
|
|
212
|
+
|
|
213
|
+
## Links
|
|
214
|
+
|
|
215
|
+
- [evolv Code CLI](https://github.com/evolv-ai/evolv-code)
|
|
216
|
+
- [GitHub Repository](https://github.com/evolv-ai/evolv-agent-sdk-python)
|
|
217
|
+
- [Issue Tracker](https://github.com/evolv-ai/evolv-agent-sdk-python/issues)
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "evolv-agent-sdk"
|
|
7
|
+
version = "0.2.0"
|
|
8
|
+
description = "Python SDK for evolv Code"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
license = {text = "MIT"}
|
|
12
|
+
authors = [
|
|
13
|
+
{name = "evolv", email = "support@evolv.ai"},
|
|
14
|
+
]
|
|
15
|
+
classifiers = [
|
|
16
|
+
"Development Status :: 3 - Alpha",
|
|
17
|
+
"Intended Audience :: Developers",
|
|
18
|
+
"License :: OSI Approved :: MIT License",
|
|
19
|
+
"Programming Language :: Python :: 3",
|
|
20
|
+
"Programming Language :: Python :: 3.10",
|
|
21
|
+
"Programming Language :: Python :: 3.11",
|
|
22
|
+
"Programming Language :: Python :: 3.12",
|
|
23
|
+
"Programming Language :: Python :: 3.13",
|
|
24
|
+
"Typing :: Typed",
|
|
25
|
+
]
|
|
26
|
+
keywords = ["evolv", "ai", "sdk", "agent", "claude"]
|
|
27
|
+
dependencies = [
|
|
28
|
+
"anyio>=4.0.0",
|
|
29
|
+
"typing_extensions>=4.0.0; python_version<'3.11'",
|
|
30
|
+
"mcp>=0.1.0",
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
[project.optional-dependencies]
|
|
34
|
+
dev = [
|
|
35
|
+
"pytest>=7.0.0",
|
|
36
|
+
"pytest-asyncio>=0.20.0",
|
|
37
|
+
"anyio[trio]>=4.0.0",
|
|
38
|
+
"pytest-cov>=4.0.0",
|
|
39
|
+
"mypy>=1.0.0",
|
|
40
|
+
"ruff>=0.1.0",
|
|
41
|
+
]
|
|
42
|
+
|
|
43
|
+
[project.urls]
|
|
44
|
+
Homepage = "https://github.com/jeremy-newhouse/evolv-code"
|
|
45
|
+
Documentation = "https://github.com/jeremy-newhouse/evolv-code/tree/main/packages/sdk"
|
|
46
|
+
Issues = "https://github.com/jeremy-newhouse/evolv-code/issues"
|
|
47
|
+
|
|
48
|
+
[tool.hatch.build.targets.wheel]
|
|
49
|
+
packages = ["src/evolv_agent_sdk"]
|
|
50
|
+
only-include = ["src/evolv_agent_sdk"]
|
|
51
|
+
|
|
52
|
+
[tool.hatch.build.targets.sdist]
|
|
53
|
+
include = [
|
|
54
|
+
"/src",
|
|
55
|
+
"/tests",
|
|
56
|
+
"/README.md",
|
|
57
|
+
"/LICENSE",
|
|
58
|
+
]
|
|
59
|
+
|
|
60
|
+
[tool.pytest.ini_options]
|
|
61
|
+
testpaths = ["tests"]
|
|
62
|
+
pythonpath = ["src"]
|
|
63
|
+
addopts = [
|
|
64
|
+
"--import-mode=importlib",
|
|
65
|
+
"-p", "asyncio",
|
|
66
|
+
]
|
|
67
|
+
|
|
68
|
+
[tool.pytest-asyncio]
|
|
69
|
+
asyncio_mode = "auto"
|
|
70
|
+
|
|
71
|
+
[tool.mypy]
|
|
72
|
+
python_version = "3.10"
|
|
73
|
+
strict = true
|
|
74
|
+
warn_return_any = true
|
|
75
|
+
warn_unused_configs = true
|
|
76
|
+
disallow_untyped_defs = true
|
|
77
|
+
disallow_incomplete_defs = true
|
|
78
|
+
check_untyped_defs = true
|
|
79
|
+
disallow_untyped_decorators = true
|
|
80
|
+
no_implicit_optional = true
|
|
81
|
+
warn_redundant_casts = true
|
|
82
|
+
warn_unused_ignores = true
|
|
83
|
+
warn_no_return = true
|
|
84
|
+
warn_unreachable = true
|
|
85
|
+
strict_equality = true
|
|
86
|
+
|
|
87
|
+
[tool.ruff]
|
|
88
|
+
target-version = "py310"
|
|
89
|
+
line-length = 88
|
|
90
|
+
|
|
91
|
+
[tool.ruff.lint]
|
|
92
|
+
select = [
|
|
93
|
+
"E", # pycodestyle errors
|
|
94
|
+
"W", # pycodestyle warnings
|
|
95
|
+
"F", # pyflakes
|
|
96
|
+
"I", # isort
|
|
97
|
+
"N", # pep8-naming
|
|
98
|
+
"UP", # pyupgrade
|
|
99
|
+
"B", # flake8-bugbear
|
|
100
|
+
"C4", # flake8-comprehensions
|
|
101
|
+
"PTH", # flake8-use-pathlib
|
|
102
|
+
"SIM", # flake8-simplify
|
|
103
|
+
]
|
|
104
|
+
ignore = [
|
|
105
|
+
"E501", # line too long (handled by formatter)
|
|
106
|
+
]
|
|
107
|
+
|
|
108
|
+
[tool.ruff.lint.isort]
|
|
109
|
+
known-first-party = ["evolv_agent_sdk"]
|