raysurfer 0.5.11 → 0.5.12

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 (2) hide show
  1. package/README.md +228 -68
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,6 +1,7 @@
1
1
  # RaySurfer TypeScript SDK
2
2
 
3
- Drop-in replacement for Claude Agent SDK with automatic code caching.
3
+ LLM output caching for AI agents. Retrieve proven code instead of
4
+ regenerating it.
4
5
 
5
6
  ## Installation
6
7
 
@@ -16,9 +17,221 @@ Set your API key:
16
17
  export RAYSURFER_API_KEY=your_api_key_here
17
18
  ```
18
19
 
19
- Get your key from the [dashboard](https://raysurfer.com/dashboard/api-keys).
20
+ Get your key from the
21
+ [dashboard](https://raysurfer.com/dashboard/api-keys).
20
22
 
21
- ## Usage
23
+ ## Low-Level API
24
+
25
+ For custom integrations, use the `RaySurfer` client directly with
26
+ any LLM provider.
27
+
28
+ ### Complete Example
29
+
30
+ ```typescript
31
+ import { RaySurfer } from "raysurfer";
32
+
33
+ const client = new RaySurfer({ apiKey: "your_api_key" });
34
+ const task = "Fetch GitHub trending repos";
35
+
36
+ // 1. Retrieve cached code files for a task
37
+ const result = await client.getCodeFiles({
38
+ task,
39
+ topK: 5,
40
+ minVerdictScore: 0.3,
41
+ });
42
+
43
+ // result.addToLlmPrompt contains a pre-formatted string like:
44
+ //
45
+ // You have access to pre-written code files:
46
+ // - .raysurfer_code/github_fetcher.ts: Fetches trending repos
47
+ // ...
48
+
49
+ // Augment your system prompt with cached code context
50
+ const basePrompt = "You are a helpful coding assistant.";
51
+ const augmentedPrompt = basePrompt + result.addToLlmPrompt;
52
+
53
+ // Use augmentedPrompt with any LLM provider (Anthropic, OpenAI, etc.)
54
+
55
+ // 2. Upload a new code file after execution
56
+ await client.uploadNewCodeSnip({
57
+ task,
58
+ fileWritten: {
59
+ path: "fetch_repos.ts",
60
+ content: "function fetch() { ... }",
61
+ },
62
+ succeeded: true,
63
+ executionLogs: "Fetched 10 trending repos successfully",
64
+ dependencies: { "node-fetch": "3.3.0", zod: "3.22.0" },
65
+ });
66
+
67
+ // 2b. Bulk upload prompts/logs/code for sandboxed grading
68
+ await client.uploadBulkCodeSnips(
69
+ ["Build a CLI tool", "Add CSV support"],
70
+ [{ path: "cli.ts", content: "function main() { ... }" }],
71
+ [
72
+ {
73
+ path: "logs/run.log",
74
+ content: "Task completed",
75
+ encoding: "utf-8",
76
+ },
77
+ ]
78
+ );
79
+
80
+ // 3. Vote on whether a cached snippet was useful
81
+ await client.voteCodeSnip({
82
+ task,
83
+ codeBlockId: result.files[0].codeBlockId,
84
+ codeBlockName: result.files[0].filename,
85
+ codeBlockDescription: result.files[0].description,
86
+ succeeded: true,
87
+ });
88
+ ```
89
+
90
+ ### Client Options
91
+
92
+ ```typescript
93
+ const client = new RaySurfer({
94
+ apiKey: "your_api_key",
95
+ baseUrl: "https://api.raysurfer.com", // optional
96
+ timeout: 30000, // optional, in ms
97
+ organizationId: "org_xxx", // optional, for team namespacing
98
+ workspaceId: "ws_xxx", // optional, for enterprise namespacing
99
+ snipsDesired: "company", // optional, snippet scope
100
+ publicSnips: true, // optional, include community snippets
101
+ });
102
+ ```
103
+
104
+ ### Response Fields
105
+
106
+ The `getCodeFiles()` response includes:
107
+
108
+ | Field | Type | Description |
109
+ | ---------------- | ------------ | --------------------------------- |
110
+ | `files` | `CodeFile[]` | Retrieved code files with metadata|
111
+ | `task` | `string` | The task that was searched |
112
+ | `totalFound` | `number` | Total matches found |
113
+ | `addToLlmPrompt` | `string` | Pre-formatted string to append to LLM system prompt |
114
+
115
+ Each `CodeFile` contains `codeBlockId`, `filename`, `source`,
116
+ `description`, `verdictScore`, `thumbsUp`, `thumbsDown`, and
117
+ `similarityScore`.
118
+
119
+ ### Store a Code Block with Full Metadata
120
+
121
+ ```typescript
122
+ const result = await client.storeCodeBlock({
123
+ name: "GitHub User Fetcher",
124
+ source: "function fetchUser(username) { ... }",
125
+ entrypoint: "fetchUser",
126
+ language: "typescript",
127
+ description: "Fetches user data from GitHub API",
128
+ tags: ["github", "api", "user"],
129
+ dependencies: { "node-fetch": "3.3.0" },
130
+ });
131
+ ```
132
+
133
+ ### Retrieve Few-Shot Examples
134
+
135
+ ```typescript
136
+ const examples = await client.getFewShotExamples(
137
+ "Parse CSV files",
138
+ 3
139
+ );
140
+
141
+ for (const ex of examples) {
142
+ console.log(`Task: ${ex.task}`);
143
+ console.log(`Code: ${ex.codeSnippet}`);
144
+ }
145
+ ```
146
+
147
+ ### Retrieve Task Patterns
148
+
149
+ ```typescript
150
+ const patterns = await client.getTaskPatterns({
151
+ task: "API integration",
152
+ minThumbsUp: 5,
153
+ topK: 20,
154
+ });
155
+
156
+ for (const p of patterns) {
157
+ console.log(`${p.taskPattern} -> ${p.codeBlockName}`);
158
+ }
159
+ ```
160
+
161
+ ### User-Provided Votes
162
+
163
+ Instead of relying on AI voting, provide your own votes:
164
+
165
+ ```typescript
166
+ // Single upload with your own vote (AI voting is skipped)
167
+ await client.uploadNewCodeSnip({
168
+ task: "Fetch GitHub trending repos",
169
+ fileWritten: file,
170
+ succeeded: true,
171
+ userVote: 1, // 1 = thumbs up, -1 = thumbs down
172
+ });
173
+
174
+ // Bulk upload with per-file votes (AI grading is skipped)
175
+ await client.uploadBulkCodeSnips(
176
+ ["Build a CLI tool", "Add CSV support"],
177
+ files,
178
+ logs,
179
+ true, // useRaysurferAiVoting (ignored when userVotes set)
180
+ { "app.ts": 1, "utils.ts": -1 } // userVotes
181
+ );
182
+ ```
183
+
184
+ ### Method Reference
185
+
186
+ | Method | Description |
187
+ |--------|-------------|
188
+ | `search({ task, topK?, minVerdictScore?, preferComplete?, inputSchema? })` | Unified search for cached code (recommended) |
189
+ | `getCodeFiles({ task, topK?, minVerdictScore?, preferComplete?, cacheDir? })` | Retrieve cached code files with `addToLlmPrompt` for LLM augmentation |
190
+ | `getCodeSnips({ task, topK?, minVerdictScore? })` | Retrieve cached code snippets by semantic search |
191
+ | `retrieveBest({ task, topK?, minVerdictScore? })` | Retrieve the single best match |
192
+ | `getFewShotExamples(task, k)` | Retrieve few-shot examples for code generation prompting |
193
+ | `getTaskPatterns({ task, minThumbsUp?, topK? })` | Retrieve proven task-to-code mappings |
194
+ | `storeCodeBlock({ name, source, entrypoint, language, description, tags?, dependencies?, ... })` | Store a code block with full metadata |
195
+ | `uploadNewCodeSnip({ task, fileWritten, succeeded, useRaysurferAiVoting?, userVote?, executionLogs?, dependencies? })` | Store a single code file with optional dependency versions |
196
+ | `uploadBulkCodeSnips(prompts, filesWritten, logFiles?, useRaysurferAiVoting?, userVotes?)` | Bulk upload for grading (AI votes by default, or provide per-file votes) |
197
+ | `voteCodeSnip({ task, codeBlockId, codeBlockName, codeBlockDescription, succeeded })` | Vote on snippet usefulness |
198
+
199
+ ### Exceptions
200
+
201
+ Both clients include built-in retry logic with exponential backoff
202
+ for transient failures (429, 5xx, network errors).
203
+
204
+ | Exception | Description |
205
+ | ----------------------- | ---------------------------------------------------- |
206
+ | `RaySurferError` | Base exception for all Raysurfer errors |
207
+ | `APIError` | API returned an error response (includes `statusCode`) |
208
+ | `AuthenticationError` | API key is invalid or missing |
209
+ | `CacheUnavailableError` | Cache backend is unreachable |
210
+ | `RateLimitError` | Rate limit exceeded after retries (includes `retryAfter`) |
211
+ | `ValidationError` | Request validation failed (includes `field`) |
212
+
213
+ ```typescript
214
+ import { RaySurfer, RateLimitError } from "raysurfer";
215
+
216
+ const client = new RaySurfer({ apiKey: "your_api_key" });
217
+
218
+ try {
219
+ const result = await client.getCodeSnips({
220
+ task: "Fetch GitHub repos",
221
+ });
222
+ } catch (e) {
223
+ if (e instanceof RateLimitError) {
224
+ console.log(`Rate limited after retries: ${e.message}`);
225
+ if (e.retryAfter) {
226
+ console.log(`Try again in ${e.retryAfter}ms`);
227
+ }
228
+ }
229
+ }
230
+ ```
231
+
232
+ ---
233
+
234
+ ## Claude Agent SDK Drop-in
22
235
 
23
236
  Swap your import — everything else stays the same:
24
237
 
@@ -40,8 +253,8 @@ for await (const message of query({
40
253
  }
41
254
  ```
42
255
 
43
- All Claude SDK types are re-exported from `raysurfer`, so you don't need a
44
- separate import:
256
+ All Claude SDK types are re-exported from `raysurfer`, so you don't
257
+ need a separate import:
45
258
 
46
259
  ```typescript
47
260
  import {
@@ -52,16 +265,7 @@ import {
52
265
  } from "raysurfer";
53
266
  ```
54
267
 
55
- ## How It Works
56
-
57
- 1. **On query**: Retrieves cached code blocks matching your task
58
- 2. **Injects into prompt**: Agent sees proven code snippets
59
- 3. **After success**: New code is cached for next time
60
-
61
- Caching is enabled automatically when `RAYSURFER_API_KEY` is set. Without it,
62
- behaves exactly like the original SDK.
63
-
64
- ## Class-based API
268
+ ### Class-based API
65
269
 
66
270
  ```typescript
67
271
  import { ClaudeSDKClient } from "raysurfer";
@@ -76,7 +280,7 @@ for await (const msg of client.query("Fetch data from GitHub API")) {
76
280
  }
77
281
  ```
78
282
 
79
- ## System Prompt Preset
283
+ ### System Prompt Preset
80
284
 
81
285
  Use the Claude Code preset system prompt with appended instructions:
82
286
 
@@ -95,9 +299,10 @@ for await (const message of query({
95
299
  }
96
300
  ```
97
301
 
98
- ## Query Control Methods
302
+ ### Query Control Methods
99
303
 
100
- The `query()` function returns a `Query` object with full control methods:
304
+ The `query()` function returns a `Query` object with full control
305
+ methods:
101
306
 
102
307
  ```typescript
103
308
  const q = query({ prompt: "Build a REST API" });
@@ -111,6 +316,11 @@ const info = await q.accountInfo();
111
316
  q.close();
112
317
  ```
113
318
 
319
+ ### Without Caching
320
+
321
+ If `RAYSURFER_API_KEY` is not set, behaves exactly like the original
322
+ SDK — no caching, just a pass-through wrapper.
323
+
114
324
  ## Snippet Retrieval Scope
115
325
 
116
326
  Control which cached snippets are retrieved:
@@ -148,56 +358,6 @@ const client = new ClaudeSDKClient({ publicSnips: true });
148
358
  const rs = new RaySurfer({ apiKey: "...", publicSnips: true });
149
359
  ```
150
360
 
151
- ## Low-Level API
152
-
153
- For custom integrations, use the `RaySurfer` client directly:
154
-
155
- ```typescript
156
- import { RaySurfer } from "raysurfer";
157
-
158
- const client = new RaySurfer({ apiKey: "your_api_key" });
159
-
160
- // 1. Get cached code snippets for a task
161
- const snips = await client.getCodeSnips({
162
- task: "Fetch GitHub trending repos",
163
- });
164
- for (const match of snips.codeBlocks) {
165
- console.log(`${match.codeBlock.name}: ${match.score}`);
166
- }
167
-
168
- // Or use the unified search endpoint
169
- const searchResult = await client.search({
170
- task: "Fetch GitHub trending repos",
171
- });
172
- for (const match of searchResult.matches) {
173
- console.log(`${match.codeBlock.name}: ${match.combinedScore}`);
174
- }
175
-
176
- // 2. Upload a new code file after execution
177
- await client.uploadNewCodeSnip(
178
- "Fetch GitHub trending repos",
179
- { path: "fetch_repos.ts", content: "function fetch() { ... }" },
180
- true // succeeded
181
- );
182
-
183
- // 2b. Bulk upload prompts/logs/code for sandboxed grading
184
- await client.uploadBulkCodeSnips(
185
- ["Build a CLI tool", "Add CSV support"],
186
- [{ path: "cli.ts", content: "function main() { ... }" }],
187
- [{ path: "logs/run.log", content: "Task completed", encoding: "utf-8" }],
188
- true
189
- );
190
-
191
- // 3. Vote on whether a cached snippet was useful
192
- await client.voteCodeSnip({
193
- task: "Fetch GitHub trending repos",
194
- codeBlockId: "abc123",
195
- codeBlockName: "github_fetcher",
196
- codeBlockDescription: "Fetches trending repos from GitHub",
197
- succeeded: true,
198
- });
199
- ```
200
-
201
361
  ## License
202
362
 
203
363
  MIT
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "raysurfer",
3
- "version": "0.5.11",
3
+ "version": "0.5.12",
4
4
  "description": "Semantic code caching for LLM agents",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",