raysurfer 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.
- raysurfer-0.2.0/.gitignore +27 -0
- raysurfer-0.2.0/CLAUDE.md +189 -0
- raysurfer-0.2.0/PKG-INFO +125 -0
- raysurfer-0.2.0/README.md +98 -0
- raysurfer-0.2.0/pyproject.toml +54 -0
- raysurfer-0.2.0/src/raysurfer/__init__.py +51 -0
- raysurfer-0.2.0/src/raysurfer/client.py +518 -0
- raysurfer-0.2.0/src/raysurfer/exceptions.py +21 -0
- raysurfer-0.2.0/src/raysurfer/sdk_client.py +295 -0
- raysurfer-0.2.0/src/raysurfer/sdk_types.py +30 -0
- raysurfer-0.2.0/src/raysurfer/types.py +168 -0
- raysurfer-0.2.0/tests/__init__.py +1 -0
- raysurfer-0.2.0/tests/test_client.py +28 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
__pycache__/
|
|
2
|
+
*.py[cod]
|
|
3
|
+
*$py.class
|
|
4
|
+
*.so
|
|
5
|
+
.Python
|
|
6
|
+
build/
|
|
7
|
+
develop-eggs/
|
|
8
|
+
dist/
|
|
9
|
+
downloads/
|
|
10
|
+
eggs/
|
|
11
|
+
.eggs/
|
|
12
|
+
lib/
|
|
13
|
+
lib64/
|
|
14
|
+
parts/
|
|
15
|
+
sdist/
|
|
16
|
+
var/
|
|
17
|
+
wheels/
|
|
18
|
+
*.egg-info/
|
|
19
|
+
.installed.cfg
|
|
20
|
+
*.egg
|
|
21
|
+
.env
|
|
22
|
+
.venv
|
|
23
|
+
env/
|
|
24
|
+
venv/
|
|
25
|
+
.pytest_cache/
|
|
26
|
+
.ruff_cache/
|
|
27
|
+
.mypy_cache/
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
# Raysurfer Python SDK
|
|
2
|
+
|
|
3
|
+
Python SDK for Raysurfer - code block caching and retrieval for AI agents with Claude Agent SDK integration.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install raysurfer
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
### Basic Client (Store/Retrieve Code Blocks)
|
|
14
|
+
|
|
15
|
+
```python
|
|
16
|
+
from raysurfer import AsyncRaySurfer
|
|
17
|
+
|
|
18
|
+
async with AsyncRaySurfer(api_key="rs_...") as client:
|
|
19
|
+
# Store a code block
|
|
20
|
+
result = await client.store_code_block(
|
|
21
|
+
name="GitHub User Fetcher",
|
|
22
|
+
source="def fetch_user(username): ...",
|
|
23
|
+
entrypoint="fetch_user",
|
|
24
|
+
language="python",
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
# Retrieve code blocks for a task
|
|
28
|
+
response = await client.retrieve(task="Fetch GitHub user data")
|
|
29
|
+
for match in response.code_blocks:
|
|
30
|
+
print(match.code_block.name, match.verdict_score)
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### Claude Agent SDK Integration
|
|
34
|
+
|
|
35
|
+
```python
|
|
36
|
+
from raysurfer import RaysurferClient, RaysurferAgentOptions
|
|
37
|
+
|
|
38
|
+
options = RaysurferAgentOptions(
|
|
39
|
+
raysurfer_api_key="rs_...",
|
|
40
|
+
allowed_tools=["Read", "Write", "Bash"],
|
|
41
|
+
system_prompt="You are a helpful assistant.",
|
|
42
|
+
model="claude-opus-4-5", # Default
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
async with RaysurferClient(options=options) as client:
|
|
46
|
+
# Pre-fetches code files, downloads to sandbox, injects into prompt
|
|
47
|
+
await client.query("Fetch user data from GitHub API")
|
|
48
|
+
|
|
49
|
+
# Agent sees code files in system prompt and can execute with Bash
|
|
50
|
+
async for msg in client.receive_response():
|
|
51
|
+
print(msg)
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## RaysurferAgentOptions
|
|
55
|
+
|
|
56
|
+
Drop-in replacement options for `ClaudeAgentOptions` with Raysurfer-specific settings:
|
|
57
|
+
|
|
58
|
+
```python
|
|
59
|
+
@dataclass
|
|
60
|
+
class RaysurferAgentOptions:
|
|
61
|
+
# Raysurfer-specific
|
|
62
|
+
raysurfer_api_key: str | None = None
|
|
63
|
+
raysurfer_base_url: str = "https://api.raysurfer.com"
|
|
64
|
+
prefetch_count: int = 5
|
|
65
|
+
min_verdict_score: float = 0.3
|
|
66
|
+
prefer_complete: bool = True
|
|
67
|
+
sandbox_dir: Path = ~/.raysurfer/sandbox
|
|
68
|
+
|
|
69
|
+
# Standard ClaudeAgentOptions (all passed through)
|
|
70
|
+
allowed_tools: list[str] | None = None
|
|
71
|
+
model: str = "claude-opus-4-5"
|
|
72
|
+
system_prompt: str | dict | None = None
|
|
73
|
+
sandbox: dict | None = None
|
|
74
|
+
# ... all other ClaudeAgentOptions fields
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## How It Works
|
|
78
|
+
|
|
79
|
+
1. **On `query()`**: RaysurferClient calls the backend to get relevant code files
|
|
80
|
+
2. **Downloads to sandbox**: Files are written to `~/.raysurfer/sandbox/`
|
|
81
|
+
3. **Injects into prompt**: Code snippets are added to the system prompt
|
|
82
|
+
4. **Agent executes**: Agent can run the code using the Bash tool within the sandbox
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
# Claude Agent SDK Python Reference
|
|
87
|
+
|
|
88
|
+
## Core Classes
|
|
89
|
+
|
|
90
|
+
### `ClaudeSDKClient`
|
|
91
|
+
|
|
92
|
+
```python
|
|
93
|
+
async with ClaudeSDKClient(options=options) as client:
|
|
94
|
+
await client.query("Hello Claude")
|
|
95
|
+
async for message in client.receive_response():
|
|
96
|
+
print(message)
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### `ClaudeAgentOptions`
|
|
100
|
+
|
|
101
|
+
```python
|
|
102
|
+
ClaudeAgentOptions(
|
|
103
|
+
allowed_tools=["Read", "Write", "Bash"],
|
|
104
|
+
disallowed_tools=[],
|
|
105
|
+
permission_mode="acceptEdits", # or "default", "plan", "bypassPermissions"
|
|
106
|
+
system_prompt="You are helpful.",
|
|
107
|
+
model="claude-opus-4-5",
|
|
108
|
+
cwd="/path/to/project",
|
|
109
|
+
sandbox={"enabled": True},
|
|
110
|
+
max_turns=10,
|
|
111
|
+
# ... more options
|
|
112
|
+
)
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Key parameters:
|
|
116
|
+
- `allowed_tools`: Tools the agent can use
|
|
117
|
+
- `permission_mode`: How permissions are handled
|
|
118
|
+
- `model`: Claude model to use
|
|
119
|
+
- `sandbox`: Enable sandboxed execution
|
|
120
|
+
- `setting_sources`: `["user", "project", "local"]` to load CLAUDE.md files
|
|
121
|
+
|
|
122
|
+
### `SandboxSettings`
|
|
123
|
+
|
|
124
|
+
```python
|
|
125
|
+
sandbox={
|
|
126
|
+
"enabled": True,
|
|
127
|
+
"autoAllowBashIfSandboxed": True,
|
|
128
|
+
"excludedCommands": ["docker"],
|
|
129
|
+
"network": {
|
|
130
|
+
"allowLocalBinding": True,
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## Message Types
|
|
136
|
+
|
|
137
|
+
```python
|
|
138
|
+
from claude_agent_sdk import (
|
|
139
|
+
AssistantMessage,
|
|
140
|
+
TextBlock,
|
|
141
|
+
ToolUseBlock,
|
|
142
|
+
ResultMessage,
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
async for message in client.receive_response():
|
|
146
|
+
if isinstance(message, AssistantMessage):
|
|
147
|
+
for block in message.content:
|
|
148
|
+
if isinstance(block, TextBlock):
|
|
149
|
+
print(block.text)
|
|
150
|
+
elif isinstance(block, ToolUseBlock):
|
|
151
|
+
print(f"Using tool: {block.name}")
|
|
152
|
+
elif isinstance(message, ResultMessage):
|
|
153
|
+
print(f"Done! Cost: ${message.total_cost_usd}")
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
## Custom Tools
|
|
157
|
+
|
|
158
|
+
```python
|
|
159
|
+
from claude_agent_sdk import tool, create_sdk_mcp_server
|
|
160
|
+
|
|
161
|
+
@tool("greet", "Greet a user", {"name": str})
|
|
162
|
+
async def greet(args):
|
|
163
|
+
return {"content": [{"type": "text", "text": f"Hello, {args['name']}!"}]}
|
|
164
|
+
|
|
165
|
+
server = create_sdk_mcp_server("my-tools", tools=[greet])
|
|
166
|
+
|
|
167
|
+
options = ClaudeAgentOptions(
|
|
168
|
+
mcp_servers={"tools": server},
|
|
169
|
+
allowed_tools=["mcp__tools__greet"],
|
|
170
|
+
)
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
## Error Handling
|
|
174
|
+
|
|
175
|
+
```python
|
|
176
|
+
from claude_agent_sdk import (
|
|
177
|
+
CLINotFoundError,
|
|
178
|
+
ProcessError,
|
|
179
|
+
CLIConnectionError,
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
try:
|
|
183
|
+
async for message in query(prompt="Hello"):
|
|
184
|
+
print(message)
|
|
185
|
+
except CLINotFoundError:
|
|
186
|
+
print("Install Claude Code: npm install -g @anthropic-ai/claude-code")
|
|
187
|
+
except ProcessError as e:
|
|
188
|
+
print(f"Process failed: {e.exit_code}")
|
|
189
|
+
```
|
raysurfer-0.2.0/PKG-INFO
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: raysurfer
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Python SDK for RaySurfer - code block caching and retrieval for AI agents with Claude Agent SDK integration
|
|
5
|
+
Project-URL: Homepage, https://raysurfer.com
|
|
6
|
+
Project-URL: Repository, https://github.com/raymondxu/raysurfer-python
|
|
7
|
+
Author: Raymond Xu
|
|
8
|
+
License-Expression: MIT
|
|
9
|
+
Keywords: agents,ai,anthropic,claude,code-blocks,embeddings,retrieval
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
18
|
+
Requires-Python: >=3.10
|
|
19
|
+
Requires-Dist: claude-agent-sdk>=0.1.0
|
|
20
|
+
Requires-Dist: httpx>=0.25.0
|
|
21
|
+
Requires-Dist: pydantic>=2.0.0
|
|
22
|
+
Provides-Extra: dev
|
|
23
|
+
Requires-Dist: pytest-asyncio>=0.21.0; extra == 'dev'
|
|
24
|
+
Requires-Dist: pytest>=7.0.0; extra == 'dev'
|
|
25
|
+
Requires-Dist: ruff>=0.1.0; extra == 'dev'
|
|
26
|
+
Description-Content-Type: text/markdown
|
|
27
|
+
|
|
28
|
+
# RaySurfer Python SDK
|
|
29
|
+
|
|
30
|
+
Store and retrieve code blocks for AI agents with semantic search and verdict-aware scoring.
|
|
31
|
+
|
|
32
|
+
## Install
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
pip install raysurfer
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Quick Start
|
|
39
|
+
|
|
40
|
+
```python
|
|
41
|
+
from raysurfer import RaySurfer
|
|
42
|
+
|
|
43
|
+
rs = RaySurfer(api_key="your-api-key")
|
|
44
|
+
|
|
45
|
+
# Store a code block
|
|
46
|
+
result = rs.store_code_block(
|
|
47
|
+
name="fetch_weather",
|
|
48
|
+
source="""
|
|
49
|
+
def fetch_weather(city: str) -> dict:
|
|
50
|
+
import requests
|
|
51
|
+
resp = requests.get(f"https://api.weather.com/{city}")
|
|
52
|
+
return resp.json()
|
|
53
|
+
""",
|
|
54
|
+
entrypoint="fetch_weather",
|
|
55
|
+
language="python",
|
|
56
|
+
description="Fetches weather data for a city",
|
|
57
|
+
tags=["api", "weather"],
|
|
58
|
+
)
|
|
59
|
+
print(f"Stored: {result.code_block_id}")
|
|
60
|
+
|
|
61
|
+
# Retrieve code blocks by task
|
|
62
|
+
results = rs.retrieve("get weather data for a location")
|
|
63
|
+
for match in results.code_blocks:
|
|
64
|
+
print(f"{match.code_block.name}: {match.score}")
|
|
65
|
+
|
|
66
|
+
# Get the single best match with verdict-aware scoring
|
|
67
|
+
best = rs.retrieve_best("fetch current temperature")
|
|
68
|
+
if best.best_match:
|
|
69
|
+
print(f"Best: {best.best_match.code_block.name}")
|
|
70
|
+
print(f"Confidence: {best.retrieval_confidence}")
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Async Usage
|
|
74
|
+
|
|
75
|
+
```python
|
|
76
|
+
from raysurfer import AsyncRaySurfer
|
|
77
|
+
|
|
78
|
+
async def main():
|
|
79
|
+
async with AsyncRaySurfer(api_key="your-api-key") as rs:
|
|
80
|
+
results = await rs.retrieve("parse JSON data")
|
|
81
|
+
print(results.code_blocks)
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Store Execution Records
|
|
85
|
+
|
|
86
|
+
Track how code blocks perform to improve future retrieval:
|
|
87
|
+
|
|
88
|
+
```python
|
|
89
|
+
from raysurfer import RaySurfer, ExecutionState, AgentVerdict
|
|
90
|
+
|
|
91
|
+
rs = RaySurfer(api_key="your-api-key")
|
|
92
|
+
|
|
93
|
+
# After running a code block
|
|
94
|
+
rs.store_execution(
|
|
95
|
+
code_block_id="cb_xxx",
|
|
96
|
+
triggering_task="get weather for NYC",
|
|
97
|
+
input_data={"city": "NYC"},
|
|
98
|
+
output_data={"temp": 72, "conditions": "sunny"},
|
|
99
|
+
execution_state=ExecutionState.COMPLETED,
|
|
100
|
+
duration_ms=150,
|
|
101
|
+
verdict=AgentVerdict.THUMBS_UP,
|
|
102
|
+
)
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## API Reference
|
|
106
|
+
|
|
107
|
+
### `RaySurfer` / `AsyncRaySurfer`
|
|
108
|
+
|
|
109
|
+
**Store methods:**
|
|
110
|
+
- `store_code_block(...)` - Store a new code block
|
|
111
|
+
- `store_execution(...)` - Store an execution record with optional verdict
|
|
112
|
+
|
|
113
|
+
**Retrieve methods:**
|
|
114
|
+
- `retrieve(task)` - Semantic search for code blocks
|
|
115
|
+
- `retrieve_best(task)` - Get the single best match with scoring
|
|
116
|
+
- `get_few_shot_examples(task)` - Get examples for code generation
|
|
117
|
+
- `get_task_patterns(...)` - Get proven task→code mappings
|
|
118
|
+
|
|
119
|
+
## Verdict System
|
|
120
|
+
|
|
121
|
+
RaySurfer uses thumbs up/down verdicts that are **independent** of execution state:
|
|
122
|
+
- A technical error can be thumbs up (correct validation behavior)
|
|
123
|
+
- A successful execution can be thumbs down (useless output)
|
|
124
|
+
|
|
125
|
+
This allows the system to learn which code blocks are actually *useful*, not just which ones run without errors.
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# RaySurfer Python SDK
|
|
2
|
+
|
|
3
|
+
Store and retrieve code blocks for AI agents with semantic search and verdict-aware scoring.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install raysurfer
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```python
|
|
14
|
+
from raysurfer import RaySurfer
|
|
15
|
+
|
|
16
|
+
rs = RaySurfer(api_key="your-api-key")
|
|
17
|
+
|
|
18
|
+
# Store a code block
|
|
19
|
+
result = rs.store_code_block(
|
|
20
|
+
name="fetch_weather",
|
|
21
|
+
source="""
|
|
22
|
+
def fetch_weather(city: str) -> dict:
|
|
23
|
+
import requests
|
|
24
|
+
resp = requests.get(f"https://api.weather.com/{city}")
|
|
25
|
+
return resp.json()
|
|
26
|
+
""",
|
|
27
|
+
entrypoint="fetch_weather",
|
|
28
|
+
language="python",
|
|
29
|
+
description="Fetches weather data for a city",
|
|
30
|
+
tags=["api", "weather"],
|
|
31
|
+
)
|
|
32
|
+
print(f"Stored: {result.code_block_id}")
|
|
33
|
+
|
|
34
|
+
# Retrieve code blocks by task
|
|
35
|
+
results = rs.retrieve("get weather data for a location")
|
|
36
|
+
for match in results.code_blocks:
|
|
37
|
+
print(f"{match.code_block.name}: {match.score}")
|
|
38
|
+
|
|
39
|
+
# Get the single best match with verdict-aware scoring
|
|
40
|
+
best = rs.retrieve_best("fetch current temperature")
|
|
41
|
+
if best.best_match:
|
|
42
|
+
print(f"Best: {best.best_match.code_block.name}")
|
|
43
|
+
print(f"Confidence: {best.retrieval_confidence}")
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Async Usage
|
|
47
|
+
|
|
48
|
+
```python
|
|
49
|
+
from raysurfer import AsyncRaySurfer
|
|
50
|
+
|
|
51
|
+
async def main():
|
|
52
|
+
async with AsyncRaySurfer(api_key="your-api-key") as rs:
|
|
53
|
+
results = await rs.retrieve("parse JSON data")
|
|
54
|
+
print(results.code_blocks)
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Store Execution Records
|
|
58
|
+
|
|
59
|
+
Track how code blocks perform to improve future retrieval:
|
|
60
|
+
|
|
61
|
+
```python
|
|
62
|
+
from raysurfer import RaySurfer, ExecutionState, AgentVerdict
|
|
63
|
+
|
|
64
|
+
rs = RaySurfer(api_key="your-api-key")
|
|
65
|
+
|
|
66
|
+
# After running a code block
|
|
67
|
+
rs.store_execution(
|
|
68
|
+
code_block_id="cb_xxx",
|
|
69
|
+
triggering_task="get weather for NYC",
|
|
70
|
+
input_data={"city": "NYC"},
|
|
71
|
+
output_data={"temp": 72, "conditions": "sunny"},
|
|
72
|
+
execution_state=ExecutionState.COMPLETED,
|
|
73
|
+
duration_ms=150,
|
|
74
|
+
verdict=AgentVerdict.THUMBS_UP,
|
|
75
|
+
)
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## API Reference
|
|
79
|
+
|
|
80
|
+
### `RaySurfer` / `AsyncRaySurfer`
|
|
81
|
+
|
|
82
|
+
**Store methods:**
|
|
83
|
+
- `store_code_block(...)` - Store a new code block
|
|
84
|
+
- `store_execution(...)` - Store an execution record with optional verdict
|
|
85
|
+
|
|
86
|
+
**Retrieve methods:**
|
|
87
|
+
- `retrieve(task)` - Semantic search for code blocks
|
|
88
|
+
- `retrieve_best(task)` - Get the single best match with scoring
|
|
89
|
+
- `get_few_shot_examples(task)` - Get examples for code generation
|
|
90
|
+
- `get_task_patterns(...)` - Get proven task→code mappings
|
|
91
|
+
|
|
92
|
+
## Verdict System
|
|
93
|
+
|
|
94
|
+
RaySurfer uses thumbs up/down verdicts that are **independent** of execution state:
|
|
95
|
+
- A technical error can be thumbs up (correct validation behavior)
|
|
96
|
+
- A successful execution can be thumbs down (useless output)
|
|
97
|
+
|
|
98
|
+
This allows the system to learn which code blocks are actually *useful*, not just which ones run without errors.
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "raysurfer"
|
|
7
|
+
version = "0.2.0"
|
|
8
|
+
description = "Python SDK for RaySurfer - code block caching and retrieval for AI agents with Claude Agent SDK integration"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = "MIT"
|
|
11
|
+
requires-python = ">=3.10"
|
|
12
|
+
authors = [
|
|
13
|
+
{ name = "Raymond Xu" }
|
|
14
|
+
]
|
|
15
|
+
keywords = ["ai", "agents", "code-blocks", "retrieval", "embeddings", "claude", "anthropic"]
|
|
16
|
+
classifiers = [
|
|
17
|
+
"Development Status :: 3 - Alpha",
|
|
18
|
+
"Intended Audience :: Developers",
|
|
19
|
+
"License :: OSI Approved :: MIT License",
|
|
20
|
+
"Programming Language :: Python :: 3",
|
|
21
|
+
"Programming Language :: Python :: 3.10",
|
|
22
|
+
"Programming Language :: Python :: 3.11",
|
|
23
|
+
"Programming Language :: Python :: 3.12",
|
|
24
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
25
|
+
]
|
|
26
|
+
dependencies = [
|
|
27
|
+
"httpx>=0.25.0",
|
|
28
|
+
"pydantic>=2.0.0",
|
|
29
|
+
"claude-agent-sdk>=0.1.0",
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
[project.optional-dependencies]
|
|
33
|
+
dev = [
|
|
34
|
+
"pytest>=7.0.0",
|
|
35
|
+
"pytest-asyncio>=0.21.0",
|
|
36
|
+
"ruff>=0.1.0",
|
|
37
|
+
]
|
|
38
|
+
|
|
39
|
+
[project.urls]
|
|
40
|
+
Homepage = "https://raysurfer.com"
|
|
41
|
+
Repository = "https://github.com/raymondxu/raysurfer-python"
|
|
42
|
+
|
|
43
|
+
[tool.hatch.build.targets.wheel]
|
|
44
|
+
packages = ["src/raysurfer"]
|
|
45
|
+
|
|
46
|
+
[tool.ruff]
|
|
47
|
+
line-length = 100
|
|
48
|
+
target-version = "py310"
|
|
49
|
+
|
|
50
|
+
[tool.ruff.lint]
|
|
51
|
+
select = ["E", "F", "I", "W"]
|
|
52
|
+
|
|
53
|
+
[tool.pytest.ini_options]
|
|
54
|
+
asyncio_mode = "auto"
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"""
|
|
2
|
+
RaySurfer Python SDK
|
|
3
|
+
|
|
4
|
+
Store and retrieve code blocks for AI agents with semantic search
|
|
5
|
+
and verdict-aware scoring.
|
|
6
|
+
|
|
7
|
+
Includes Claude Agent SDK integration via RaysurferClient.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from raysurfer.client import RaySurfer, AsyncRaySurfer
|
|
11
|
+
from raysurfer.sdk_client import RaysurferClient, RaysurferAgentOptions
|
|
12
|
+
from raysurfer.types import (
|
|
13
|
+
AgentReview,
|
|
14
|
+
AgentVerdict,
|
|
15
|
+
BestMatch,
|
|
16
|
+
CodeBlock,
|
|
17
|
+
ExecutionIO,
|
|
18
|
+
ExecutionRecord,
|
|
19
|
+
ExecutionState,
|
|
20
|
+
FewShotExample,
|
|
21
|
+
TaskPattern,
|
|
22
|
+
)
|
|
23
|
+
from raysurfer.sdk_types import CodeFile, GetCodeFilesResponse
|
|
24
|
+
from raysurfer.exceptions import RaySurferError, APIError, AuthenticationError
|
|
25
|
+
|
|
26
|
+
__version__ = "0.2.0"
|
|
27
|
+
|
|
28
|
+
__all__ = [
|
|
29
|
+
# Clients
|
|
30
|
+
"RaySurfer",
|
|
31
|
+
"AsyncRaySurfer",
|
|
32
|
+
# Claude Agent SDK integration
|
|
33
|
+
"RaysurferClient",
|
|
34
|
+
"RaysurferAgentOptions",
|
|
35
|
+
# Types
|
|
36
|
+
"AgentReview",
|
|
37
|
+
"AgentVerdict",
|
|
38
|
+
"BestMatch",
|
|
39
|
+
"CodeBlock",
|
|
40
|
+
"CodeFile",
|
|
41
|
+
"ExecutionIO",
|
|
42
|
+
"ExecutionRecord",
|
|
43
|
+
"ExecutionState",
|
|
44
|
+
"FewShotExample",
|
|
45
|
+
"GetCodeFilesResponse",
|
|
46
|
+
"TaskPattern",
|
|
47
|
+
# Exceptions
|
|
48
|
+
"RaySurferError",
|
|
49
|
+
"APIError",
|
|
50
|
+
"AuthenticationError",
|
|
51
|
+
]
|