raysurfer 0.3.7 → 0.3.8
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.
- package/README.md +110 -89
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,113 +1,84 @@
|
|
|
1
1
|
# RaySurfer TypeScript SDK
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Drop-in replacement for Claude Agent SDK with automatic code caching.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
8
|
npm install raysurfer
|
|
9
|
-
# or
|
|
10
|
-
bun add raysurfer
|
|
11
9
|
```
|
|
12
10
|
|
|
13
|
-
##
|
|
11
|
+
## Setup
|
|
14
12
|
|
|
15
|
-
|
|
13
|
+
Set your API key:
|
|
16
14
|
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
const client = new RaySurfer({ apiKey: "rs_..." });
|
|
15
|
+
```bash
|
|
16
|
+
export RAYSURFER_API_KEY=your_api_key_here
|
|
17
|
+
```
|
|
21
18
|
|
|
22
|
-
|
|
23
|
-
const result = await client.storeCodeBlock({
|
|
24
|
-
name: "GitHub User Fetcher",
|
|
25
|
-
source: "async function fetchUser(username) { ... }",
|
|
26
|
-
entrypoint: "fetchUser",
|
|
27
|
-
language: "typescript",
|
|
28
|
-
});
|
|
19
|
+
Get your key from the [dashboard](https://raysurfer.com/dashboard/api-keys).
|
|
29
20
|
|
|
30
|
-
|
|
31
|
-
const response = await client.retrieve({ task: "Fetch GitHub user data" });
|
|
32
|
-
for (const match of response.codeBlocks) {
|
|
33
|
-
console.log(match.codeBlock.name, match.verdictScore);
|
|
34
|
-
}
|
|
35
|
-
```
|
|
21
|
+
## Usage
|
|
36
22
|
|
|
37
|
-
|
|
23
|
+
Swap your client class and method names. Options come directly from `@anthropic-ai/claude-agent-sdk`:
|
|
38
24
|
|
|
39
25
|
```typescript
|
|
26
|
+
// Before
|
|
27
|
+
import { ClaudeSDKClient, ClaudeAgentOptions } from "@anthropic-ai/claude-agent-sdk";
|
|
28
|
+
|
|
29
|
+
// After
|
|
40
30
|
import { RaysurferClient } from "raysurfer";
|
|
31
|
+
import { ClaudeAgentOptions } from "@anthropic-ai/claude-agent-sdk";
|
|
41
32
|
|
|
42
|
-
const
|
|
43
|
-
raysurferApiKey: "rs_...",
|
|
44
|
-
model: "claude-sonnet-4-5",
|
|
45
|
-
systemPrompt: "You are a helpful assistant.",
|
|
33
|
+
const options: ClaudeAgentOptions = {
|
|
46
34
|
allowedTools: ["Read", "Write", "Bash"],
|
|
47
|
-
|
|
35
|
+
systemPrompt: "You are a helpful assistant.",
|
|
36
|
+
};
|
|
48
37
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
}
|
|
38
|
+
const client = new RaysurferClient(options);
|
|
39
|
+
|
|
40
|
+
for await (const msg of client.raysurferQuery("Generate quarterly report")) {
|
|
41
|
+
console.log(msg);
|
|
54
42
|
}
|
|
55
43
|
```
|
|
56
44
|
|
|
57
|
-
##
|
|
45
|
+
## Method Mapping
|
|
58
46
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
5. **Caches results**: On success, generated code is stored back to the cache
|
|
47
|
+
| Claude SDK | Raysurfer |
|
|
48
|
+
|------------|-----------|
|
|
49
|
+
| `new ClaudeSDKClient(options)` | `new RaysurferClient(options)` |
|
|
50
|
+
| `client.query(prompt)` | `client.raysurferQuery(prompt)` |
|
|
64
51
|
|
|
65
|
-
##
|
|
52
|
+
## How It Works
|
|
66
53
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
minVerdictScore?: number; // default: 0.3
|
|
74
|
-
preferComplete?: boolean; // default: true
|
|
75
|
-
sandboxDir?: string; // default: ~/.raysurfer/sandbox
|
|
76
|
-
cleanupSandbox?: boolean; // default: true
|
|
77
|
-
cleanupOnError?: boolean; // default: false
|
|
78
|
-
|
|
79
|
-
// Standard Claude Agent SDK options
|
|
80
|
-
model?: string; // default: "claude-sonnet-4-5"
|
|
81
|
-
workingDirectory?: string;
|
|
82
|
-
systemPrompt?: string;
|
|
83
|
-
permissionMode?: "default" | "acceptEdits" | "plan" | "bypassPermissions";
|
|
84
|
-
maxBudgetUsd?: number;
|
|
85
|
-
allowedTools?: string[];
|
|
86
|
-
disallowedTools?: string[];
|
|
87
|
-
maxTurns?: number;
|
|
88
|
-
env?: Record<string, string>;
|
|
89
|
-
mcpServers?: Record<string, unknown>;
|
|
90
|
-
}
|
|
91
|
-
```
|
|
54
|
+
1. **On `raysurferQuery()`**: Retrieves cached code blocks matching your task
|
|
55
|
+
2. **Downloads to sandbox**: Files ready for the agent to execute
|
|
56
|
+
3. **Injects into prompt**: Agent sees proven code snippets
|
|
57
|
+
4. **After success**: New code is cached for next time
|
|
58
|
+
|
|
59
|
+
Caching is enabled automatically when `RAYSURFER_API_KEY` is set.
|
|
92
60
|
|
|
93
61
|
## Snippet Retrieval Scope
|
|
94
62
|
|
|
95
|
-
Control which snippets are retrieved using `publicSnips` and `snipsDesired`:
|
|
63
|
+
Control which cached snippets are retrieved using `publicSnips` and `snipsDesired`:
|
|
96
64
|
|
|
97
65
|
```typescript
|
|
98
|
-
import {
|
|
66
|
+
import { RaysurferClient } from "raysurfer";
|
|
67
|
+
import { ClaudeAgentOptions } from "@anthropic-ai/claude-agent-sdk";
|
|
68
|
+
|
|
69
|
+
const options: ClaudeAgentOptions = {
|
|
70
|
+
allowedTools: ["Read", "Write", "Bash"],
|
|
71
|
+
};
|
|
99
72
|
|
|
100
73
|
// Include both public and company snippets
|
|
101
|
-
const client = new
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
snipsDesired: "company", // Also include company-level snippets (Team/Enterprise)
|
|
74
|
+
const client = new RaysurferClient(options, {
|
|
75
|
+
publicSnips: true, // Include public/shared snippets
|
|
76
|
+
snipsDesired: "company", // Also include company-level snippets
|
|
105
77
|
});
|
|
106
78
|
|
|
107
79
|
// Enterprise: Retrieve client-specific snippets only
|
|
108
|
-
const enterpriseClient = new
|
|
109
|
-
|
|
110
|
-
snipsDesired: "client", // Client workspace snippets (Enterprise only)
|
|
80
|
+
const enterpriseClient = new RaysurferClient(options, {
|
|
81
|
+
snipsDesired: "client", // Client workspace snippets (Enterprise only)
|
|
111
82
|
});
|
|
112
83
|
```
|
|
113
84
|
|
|
@@ -117,26 +88,76 @@ const enterpriseClient = new RaySurfer({
|
|
|
117
88
|
| `snipsDesired: "company"` | TEAM or ENTERPRISE |
|
|
118
89
|
| `snipsDesired: "client"` | ENTERPRISE only |
|
|
119
90
|
|
|
120
|
-
##
|
|
91
|
+
## Full Example
|
|
121
92
|
|
|
122
|
-
|
|
93
|
+
```typescript
|
|
94
|
+
import { RaysurferClient } from "raysurfer";
|
|
95
|
+
import { ClaudeAgentOptions } from "@anthropic-ai/claude-agent-sdk";
|
|
96
|
+
|
|
97
|
+
process.env.RAYSURFER_API_KEY = "your_api_key";
|
|
98
|
+
|
|
99
|
+
const options: ClaudeAgentOptions = {
|
|
100
|
+
allowedTools: ["Read", "Write", "Bash"],
|
|
101
|
+
systemPrompt: "You are a helpful assistant.",
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
const client = new RaysurferClient(options);
|
|
105
|
+
|
|
106
|
+
// First run: generates and caches code
|
|
107
|
+
for await (const msg of client.raysurferQuery("Fetch GitHub trending repos")) {
|
|
108
|
+
console.log(msg);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Second run: retrieves from cache (instant)
|
|
112
|
+
for await (const msg of client.raysurferQuery("Fetch GitHub trending repos")) {
|
|
113
|
+
console.log(msg);
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Without Caching
|
|
118
|
+
|
|
119
|
+
If `RAYSURFER_API_KEY` is not set, `RaysurferClient` behaves exactly like `ClaudeSDKClient` — no caching, just a pass-through wrapper.
|
|
120
|
+
|
|
121
|
+
## Low-Level API
|
|
122
|
+
|
|
123
|
+
For custom integrations, use the `RaySurfer` client directly with three core methods:
|
|
123
124
|
|
|
124
125
|
```typescript
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
await client.
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
await client.
|
|
137
|
-
|
|
126
|
+
import { RaySurfer } from "raysurfer";
|
|
127
|
+
|
|
128
|
+
const client = new RaySurfer({ apiKey: "your_api_key" });
|
|
129
|
+
|
|
130
|
+
// 1. Get cached code snippets for a task
|
|
131
|
+
const snips = await client.getCodeSnips({ task: "Fetch GitHub trending repos" });
|
|
132
|
+
for (const match of snips.codeBlocks) {
|
|
133
|
+
console.log(`${match.codeBlock.name}: ${match.score}`);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// 2. Upload new code snippets after execution
|
|
137
|
+
await client.uploadNewCodeSnips(
|
|
138
|
+
"Fetch GitHub trending repos",
|
|
139
|
+
[{ filename: "fetch_repos.ts", content: "function fetch() { ... }" }],
|
|
140
|
+
true // succeeded
|
|
141
|
+
);
|
|
142
|
+
|
|
143
|
+
// 3. Vote on whether a cached snippet was useful
|
|
144
|
+
await client.voteCodeSnip({
|
|
145
|
+
task: "Fetch GitHub trending repos",
|
|
146
|
+
codeBlockId: "abc123",
|
|
147
|
+
codeBlockName: "github_fetcher",
|
|
148
|
+
codeBlockDescription: "Fetches trending repos from GitHub",
|
|
149
|
+
succeeded: true,
|
|
150
|
+
});
|
|
138
151
|
```
|
|
139
152
|
|
|
153
|
+
### Method Reference
|
|
154
|
+
|
|
155
|
+
| Method | Description |
|
|
156
|
+
|--------|-------------|
|
|
157
|
+
| `getCodeSnips({ task, topK?, minVerdictScore? })` | Retrieve cached code snippets by semantic search |
|
|
158
|
+
| `uploadNewCodeSnips(task, filesWritten, succeeded)` | Store new code files for future reuse |
|
|
159
|
+
| `voteCodeSnip({ task, codeBlockId, codeBlockName, codeBlockDescription, succeeded })` | Vote on snippet usefulness |
|
|
160
|
+
|
|
140
161
|
## License
|
|
141
162
|
|
|
142
163
|
MIT
|