raysurfer 0.4.1__py3-none-any.whl

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/types.py ADDED
@@ -0,0 +1,198 @@
1
+ """RaySurfer SDK types - mirrors the backend API types"""
2
+
3
+ from datetime import datetime
4
+ from enum import Enum
5
+ from typing import Any
6
+
7
+ from pydantic import BaseModel, Field
8
+
9
+
10
+ class ExecutionState(str, Enum):
11
+ """Technical execution outcome - NOT a quality judgment"""
12
+
13
+ COMPLETED = "completed"
14
+ ERRORED = "errored"
15
+ TIMED_OUT = "timed_out"
16
+ CANCELLED = "cancelled"
17
+
18
+
19
+ class AgentVerdict(str, Enum):
20
+ """Agent's judgment on whether an execution was useful"""
21
+
22
+ THUMBS_UP = "thumbs_up"
23
+ THUMBS_DOWN = "thumbs_down"
24
+ PENDING = "pending"
25
+
26
+
27
+ class SnipsDesired(str, Enum):
28
+ """Scope of private snippets for retrieval"""
29
+
30
+ COMPANY = "company" # Organization-level snippets (Team or Enterprise tier)
31
+ CLIENT = "client" # Client workspace snippets (Enterprise tier only)
32
+
33
+
34
+ class CodeBlock(BaseModel):
35
+ """A stored code block with metadata for semantic retrieval"""
36
+
37
+ id: str
38
+ name: str
39
+ description: str
40
+ source: str
41
+ entrypoint: str
42
+ input_schema: dict[str, Any] = Field(default_factory=dict)
43
+ output_schema: dict[str, Any] = Field(default_factory=dict)
44
+ language: str
45
+ language_version: str | None = None
46
+ dependencies: list[str] = Field(default_factory=list)
47
+ tags: list[str] = Field(default_factory=list)
48
+ capabilities: list[str] = Field(default_factory=list)
49
+ example_queries: list[str] | None = None
50
+ created_at: datetime | None = None
51
+ updated_at: datetime | None = None
52
+
53
+
54
+ class ExecutionIO(BaseModel):
55
+ """Stores the actual input/output data"""
56
+
57
+ input_data: dict[str, Any]
58
+ input_hash: str = ""
59
+ output_data: Any = None
60
+ output_hash: str = ""
61
+ output_type: str = "unknown"
62
+
63
+
64
+ class AgentReview(BaseModel):
65
+ """Agent's assessment of whether an execution was useful"""
66
+
67
+ timestamp: datetime = Field(default_factory=datetime.utcnow)
68
+ verdict: AgentVerdict
69
+ reasoning: str
70
+ what_worked: list[str] = Field(default_factory=list)
71
+ what_didnt_work: list[str] = Field(default_factory=list)
72
+ output_was_useful: bool
73
+ output_was_correct: bool
74
+ output_was_complete: bool
75
+ error_was_appropriate: bool | None = None
76
+ would_use_again: bool
77
+ suggested_improvements: list[str] = Field(default_factory=list)
78
+ required_workaround: bool = False
79
+ workaround_description: str | None = None
80
+
81
+
82
+ class ExecutionRecord(BaseModel):
83
+ """Full execution trace"""
84
+
85
+ id: str
86
+ code_block_id: str
87
+ timestamp: datetime = Field(default_factory=datetime.utcnow)
88
+ execution_state: ExecutionState
89
+ duration_ms: int
90
+ error_message: str | None = None
91
+ error_type: str | None = None
92
+ io: ExecutionIO
93
+ triggering_task: str
94
+ retrieval_score: float = 0.0
95
+ verdict: AgentVerdict = AgentVerdict.PENDING
96
+ review: AgentReview | None = None
97
+
98
+
99
+ class BestMatch(BaseModel):
100
+ """The best matching code block with full scoring"""
101
+
102
+ code_block: CodeBlock
103
+ combined_score: float
104
+ vector_score: float
105
+ verdict_score: float
106
+ error_resilience: float
107
+ thumbs_up: int
108
+ thumbs_down: int
109
+
110
+
111
+ class AlternativeCandidate(BaseModel):
112
+ """An alternative candidate code block"""
113
+
114
+ code_block_id: str
115
+ name: str
116
+ combined_score: float
117
+ reason: str
118
+
119
+
120
+ class FewShotExample(BaseModel):
121
+ """A few-shot example for code generation"""
122
+
123
+ task: str
124
+ input_sample: dict[str, Any]
125
+ output_sample: Any
126
+ code_snippet: str
127
+
128
+
129
+ class TaskPattern(BaseModel):
130
+ """A proven task→code mapping"""
131
+
132
+ task_pattern: str
133
+ code_block_id: str
134
+ code_block_name: str
135
+ thumbs_up: int
136
+ thumbs_down: int
137
+ verdict_score: float
138
+ error_resilience: float
139
+ last_thumbs_up: datetime | None = None
140
+ last_thumbs_down: datetime | None = None
141
+
142
+
143
+ # Response types
144
+ class StoreCodeBlockResponse(BaseModel):
145
+ success: bool
146
+ code_block_id: str
147
+ embedding_id: str
148
+ message: str
149
+
150
+
151
+ class StoreExecutionResponse(BaseModel):
152
+ success: bool
153
+ execution_id: str
154
+ pattern_updated: bool
155
+ message: str
156
+
157
+
158
+ class RetrieveCodeBlockResponse(BaseModel):
159
+ code_blocks: list["CodeBlockMatch"]
160
+ total_found: int
161
+
162
+
163
+ class CodeBlockMatch(BaseModel):
164
+ code_block: CodeBlock
165
+ score: float
166
+ verdict_score: float
167
+ thumbs_up: int
168
+ thumbs_down: int
169
+ recent_executions: list[ExecutionRecord] = Field(default_factory=list)
170
+
171
+
172
+ class RetrieveBestResponse(BaseModel):
173
+ best_match: BestMatch | None
174
+ alternative_candidates: list[AlternativeCandidate]
175
+ retrieval_confidence: str
176
+
177
+
178
+ class FileWritten(BaseModel):
179
+ """A file written during agent execution"""
180
+
181
+ path: str
182
+ content: str
183
+
184
+
185
+ class SubmitExecutionResultRequest(BaseModel):
186
+ """Raw execution result - backend handles all processing"""
187
+
188
+ task: str
189
+ files_written: list[FileWritten]
190
+ succeeded: bool
191
+
192
+
193
+ class SubmitExecutionResultResponse(BaseModel):
194
+ """Response from submitting execution result"""
195
+
196
+ success: bool
197
+ code_blocks_stored: int
198
+ message: str
@@ -0,0 +1,157 @@
1
+ Metadata-Version: 2.4
2
+ Name: raysurfer
3
+ Version: 0.4.1
4
+ Summary: Drop-in replacement for Claude Agent SDK with automatic code caching - just swap your import
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-httpx>=0.30.0; extra == 'dev'
25
+ Requires-Dist: pytest>=7.0.0; extra == 'dev'
26
+ Requires-Dist: ruff>=0.1.0; extra == 'dev'
27
+ Description-Content-Type: text/markdown
28
+
29
+ # RaySurfer Python SDK
30
+
31
+ Drop-in replacement for Claude Agent SDK with automatic code caching. Same API, 20-30x faster.
32
+
33
+ ## Install
34
+
35
+ ```bash
36
+ pip install raysurfer
37
+ ```
38
+
39
+ ## Quick Start
40
+
41
+ Swap `ClaudeSDKClient` for `RaysurferClient` - everything else stays the same:
42
+
43
+ ```python
44
+ # from claude_agent_sdk import ClaudeSDKClient, ClaudeAgentOptions
45
+ from raysurfer import RaysurferClient, RaysurferAgentOptions
46
+
47
+ options = RaysurferAgentOptions(
48
+ raysurfer_api_key="your-api-key",
49
+ allowed_tools=["Read", "Write", "Bash"],
50
+ model="claude-sonnet-4-20250514",
51
+ )
52
+
53
+ # async with ClaudeSDKClient(options) as client:
54
+ async with RaysurferClient(options) as client:
55
+ await client.query("Generate quarterly sales report")
56
+ async for msg in client.receive_response():
57
+ print(msg)
58
+ ```
59
+
60
+ That's it. Your agent now automatically:
61
+ - Pre-fetches relevant cached code before each task
62
+ - Injects proven code snippets into the system prompt
63
+ - Stores successful outputs for future reuse
64
+
65
+ ## How It Works
66
+
67
+ 1. **On `query()`**: Retrieves cached code blocks matching your task
68
+ 2. **Downloads to sandbox**: Files ready for the agent to execute
69
+ 3. **Injects into prompt**: Agent sees proven code snippets
70
+ 4. **After success**: New code is cached for next time
71
+
72
+ **Measured Results:**
73
+ - Without RaySurfer: 34.2s, 11 iterations, 2 tool calls
74
+ - With RaySurfer: 1.4s, 1 iteration, 0 tool calls
75
+ - **Speedup: 24x faster**
76
+
77
+ ## RaysurferAgentOptions
78
+
79
+ All `ClaudeAgentOptions` fields are supported, plus:
80
+
81
+ ```python
82
+ RaysurferAgentOptions(
83
+ # Raysurfer-specific
84
+ raysurfer_api_key="your-api-key",
85
+ prefetch_count=5, # Code files to pre-fetch
86
+ min_verdict_score=0.3, # Quality threshold
87
+
88
+ # Standard Claude Agent SDK options
89
+ allowed_tools=["Read", "Write", "Bash"],
90
+ model="claude-sonnet-4-20250514",
91
+ system_prompt="You are helpful.",
92
+ permission_mode="acceptEdits",
93
+ # ... all other ClaudeAgentOptions
94
+ )
95
+ ```
96
+
97
+ ## Snippet Retrieval Scope
98
+
99
+ Control which snippets are retrieved using `public_snips` and `snips_desired`:
100
+
101
+ ```python
102
+ from raysurfer import RaysurferClient
103
+
104
+ # Include both public and company snippets
105
+ client = RaysurferClient(
106
+ options=options,
107
+ public_snips=True, # Include public/shared snippets
108
+ snips_desired="company", # Also include company-level snippets (Team/Enterprise)
109
+ )
110
+
111
+ # Enterprise: Retrieve client-specific snippets only
112
+ client = RaysurferClient(
113
+ options=options,
114
+ snips_desired="client", # Client workspace snippets (Enterprise only)
115
+ )
116
+ ```
117
+
118
+ | Configuration | Required Tier |
119
+ |--------------|---------------|
120
+ | `public_snips=True` only | FREE (default) |
121
+ | `snips_desired="company"` | TEAM or ENTERPRISE |
122
+ | `snips_desired="client"` | ENTERPRISE only |
123
+
124
+ ## Low-Level API
125
+
126
+ For direct code block storage and retrieval:
127
+
128
+ ```python
129
+ from raysurfer import RaySurfer
130
+
131
+ rs = RaySurfer(api_key="your-api-key")
132
+
133
+ # Store a code block
134
+ rs.store_code_block(
135
+ name="fetch_weather",
136
+ source="def fetch_weather(city): ...",
137
+ entrypoint="fetch_weather",
138
+ language="python",
139
+ )
140
+
141
+ # Retrieve by task
142
+ results = rs.retrieve("get weather data")
143
+ for match in results.code_blocks:
144
+ print(f"{match.code_block.name}: {match.score}")
145
+ ```
146
+
147
+ ## Verdict System
148
+
149
+ RaySurfer learns which code actually works through thumbs up/down verdicts:
150
+ - A technical error can be thumbs up (correct validation)
151
+ - A successful run can be thumbs down (useless output)
152
+
153
+ The system learns usefulness, not just whether code runs.
154
+
155
+ ## Examples
156
+
157
+ See [examples/](./examples) for complete demos.
@@ -0,0 +1,9 @@
1
+ raysurfer/__init__.py,sha256=T3RhatqdJg_bSOjBaS_TCcNfGeo0iTvqZAHGs3NeHxg,2355
2
+ raysurfer/client.py,sha256=i4K5YcSPiBv1pU65EE4vopE2DsvNWNb7-ao7QcM8B5o,27338
3
+ raysurfer/exceptions.py,sha256=3HIkH4OPMRWyceHxegeiL0mVXAIRgE55DT2YrkWVEwU,425
4
+ raysurfer/sdk_client.py,sha256=JNbqsLTKgy-J4Z6iCo1jfo-gYdkTq5f20sgoIDjondA,22207
5
+ raysurfer/sdk_types.py,sha256=obp1oF4_MlFsylpIdOICHChNeK3OgqQvr2aPkjr8FoI,775
6
+ raysurfer/types.py,sha256=BnA5lZu9mW9XaOLPW4f4PmYazpUQX9-joIGOeMWcmAQ,4910
7
+ raysurfer-0.4.1.dist-info/METADATA,sha256=8-XDU9sLK0oJB-qWKExnOIMoTCDc-TAlr3Iu-tLPHj8,4694
8
+ raysurfer-0.4.1.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
9
+ raysurfer-0.4.1.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.28.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any