raysurfer 0.6.1 → 0.6.2

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/dist/index.js DELETED
@@ -1,1191 +0,0 @@
1
- import { createRequire } from "node:module";
2
- var __create = Object.create;
3
- var __getProtoOf = Object.getPrototypeOf;
4
- var __defProp = Object.defineProperty;
5
- var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __hasOwnProp = Object.prototype.hasOwnProperty;
7
- var __toESM = (mod, isNodeMode, target) => {
8
- target = mod != null ? __create(__getProtoOf(mod)) : {};
9
- const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
10
- for (let key of __getOwnPropNames(mod))
11
- if (!__hasOwnProp.call(to, key))
12
- __defProp(to, key, {
13
- get: () => mod[key],
14
- enumerable: true
15
- });
16
- return to;
17
- };
18
- var __require = /* @__PURE__ */ createRequire(import.meta.url);
19
-
20
- // src/errors.ts
21
- class RaySurferError extends Error {
22
- constructor(message) {
23
- super(message);
24
- this.name = "RaySurferError";
25
- }
26
- }
27
-
28
- class APIError extends RaySurferError {
29
- statusCode;
30
- constructor(message, statusCode) {
31
- super(message);
32
- this.name = "APIError";
33
- this.statusCode = statusCode;
34
- }
35
- }
36
-
37
- class AuthenticationError extends RaySurferError {
38
- constructor(message = "Invalid API key") {
39
- super(message);
40
- this.name = "AuthenticationError";
41
- }
42
- }
43
-
44
- class CacheUnavailableError extends RaySurferError {
45
- statusCode;
46
- constructor(message = "Cache backend is unreachable", statusCode = 503) {
47
- super(message);
48
- this.name = "CacheUnavailableError";
49
- this.statusCode = statusCode;
50
- }
51
- }
52
-
53
- class RateLimitError extends RaySurferError {
54
- retryAfter;
55
- constructor(message = "Rate limit exceeded", retryAfter) {
56
- super(message);
57
- this.name = "RateLimitError";
58
- this.retryAfter = retryAfter;
59
- }
60
- }
61
-
62
- class ValidationError extends RaySurferError {
63
- field;
64
- constructor(message = "Validation failed", field) {
65
- super(message);
66
- this.name = "ValidationError";
67
- this.field = field;
68
- }
69
- }
70
-
71
- // src/client.ts
72
- var VERSION = "0.5.10";
73
- var DEFAULT_BASE_URL = "https://api.raysurfer.com";
74
- var MAX_RETRIES = 3;
75
- var RETRY_BASE_DELAY = 500;
76
- var RETRYABLE_STATUS_CODES = new Set([429, 500, 502, 503, 504]);
77
- function normalizeDependencies(rawDeps) {
78
- if (!rawDeps)
79
- return {};
80
- if (Array.isArray(rawDeps)) {
81
- const result = {};
82
- for (const pkg of rawDeps) {
83
- result[pkg] = "";
84
- }
85
- return result;
86
- }
87
- return rawDeps;
88
- }
89
-
90
- class RaySurfer {
91
- apiKey;
92
- baseUrl;
93
- timeout;
94
- organizationId;
95
- workspaceId;
96
- snipsDesired;
97
- publicSnips;
98
- constructor(options = {}) {
99
- this.apiKey = options.apiKey;
100
- this.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\/$/, "");
101
- this.timeout = options.timeout ?? 60000;
102
- this.organizationId = options.organizationId;
103
- this.workspaceId = options.workspaceId;
104
- this.snipsDesired = options.snipsDesired;
105
- this.publicSnips = options.publicSnips;
106
- }
107
- async request(method, path, body, headersOverride) {
108
- const headers = {
109
- "Content-Type": "application/json"
110
- };
111
- if (this.apiKey) {
112
- headers.Authorization = `Bearer ${this.apiKey}`;
113
- }
114
- if (this.organizationId) {
115
- headers["X-Raysurfer-Org-Id"] = this.organizationId;
116
- }
117
- if (this.workspaceId) {
118
- headers["X-Raysurfer-Workspace-Id"] = this.workspaceId;
119
- }
120
- if (this.snipsDesired) {
121
- headers["X-Raysurfer-Snips-Desired"] = this.snipsDesired;
122
- }
123
- if (this.publicSnips) {
124
- headers["X-Raysurfer-Public-Snips"] = "true";
125
- }
126
- headers["X-Raysurfer-SDK-Version"] = `typescript/${VERSION}`;
127
- if (headersOverride) {
128
- Object.assign(headers, headersOverride);
129
- }
130
- let lastError;
131
- for (let attempt = 0;attempt <= MAX_RETRIES; attempt++) {
132
- const controller = new AbortController;
133
- const timeoutId = setTimeout(() => controller.abort(), this.timeout);
134
- try {
135
- const response = await fetch(`${this.baseUrl}${path}`, {
136
- method,
137
- headers,
138
- body: body ? JSON.stringify(body) : undefined,
139
- signal: controller.signal
140
- });
141
- if (response.status === 401) {
142
- throw new AuthenticationError;
143
- }
144
- if (RETRYABLE_STATUS_CODES.has(response.status)) {
145
- const text = await response.text();
146
- if (response.status === 429) {
147
- const retryAfterHeader = response.headers.get("Retry-After");
148
- const retryAfterMs = retryAfterHeader ? parseFloat(retryAfterHeader) * 1000 : RETRY_BASE_DELAY * 2 ** attempt;
149
- if (attempt < MAX_RETRIES) {
150
- await new Promise((resolve) => setTimeout(resolve, retryAfterMs));
151
- continue;
152
- }
153
- throw new RateLimitError(text, retryAfterHeader ? parseFloat(retryAfterHeader) : undefined);
154
- }
155
- if (attempt < MAX_RETRIES) {
156
- const delay = RETRY_BASE_DELAY * 2 ** attempt;
157
- await new Promise((resolve) => setTimeout(resolve, delay));
158
- continue;
159
- }
160
- throw new CacheUnavailableError(text, response.status);
161
- }
162
- if (!response.ok) {
163
- const text = await response.text();
164
- throw new APIError(text, response.status);
165
- }
166
- return await response.json();
167
- } catch (error) {
168
- if (error instanceof TypeError && attempt < MAX_RETRIES) {
169
- lastError = error;
170
- const delay = RETRY_BASE_DELAY * 2 ** attempt;
171
- await new Promise((resolve) => setTimeout(resolve, delay));
172
- continue;
173
- }
174
- throw error;
175
- } finally {
176
- clearTimeout(timeoutId);
177
- }
178
- }
179
- throw lastError ?? new APIError("Request failed after retries");
180
- }
181
- workspaceHeaders(workspaceId) {
182
- if (!workspaceId)
183
- return;
184
- return { "X-Raysurfer-Workspace-Id": workspaceId };
185
- }
186
- async storeCodeBlock(params) {
187
- const data = {
188
- name: params.name,
189
- description: params.description ?? "",
190
- source: params.source,
191
- entrypoint: params.entrypoint,
192
- language: params.language,
193
- input_schema: params.inputSchema ?? {},
194
- output_schema: params.outputSchema ?? {},
195
- language_version: params.languageVersion ?? null,
196
- dependencies: params.dependencies ?? {},
197
- tags: params.tags ?? [],
198
- capabilities: params.capabilities ?? [],
199
- example_queries: params.exampleQueries ?? null
200
- };
201
- const result = await this.request("POST", "/api/store/code-block", data);
202
- return {
203
- success: result.success,
204
- codeBlockId: result.code_block_id,
205
- embeddingId: result.embedding_id,
206
- message: result.message
207
- };
208
- }
209
- async storeExecution(params) {
210
- const io = {
211
- input_data: params.inputData,
212
- input_hash: "",
213
- output_data: params.outputData,
214
- output_hash: "",
215
- output_type: typeof params.outputData
216
- };
217
- const data = {
218
- code_block_id: params.codeBlockId,
219
- triggering_task: params.triggeringTask,
220
- io,
221
- execution_state: params.executionState ?? "completed",
222
- duration_ms: params.durationMs ?? 0,
223
- error_message: params.errorMessage ?? null,
224
- error_type: params.errorType ?? null,
225
- verdict: params.verdict ?? null,
226
- review: params.review ?? null
227
- };
228
- const result = await this.request("POST", "/api/store/execution", data);
229
- return {
230
- success: result.success,
231
- executionId: result.execution_id,
232
- patternUpdated: result.pattern_updated,
233
- message: result.message
234
- };
235
- }
236
- async uploadNewCodeSnip(taskOrOptions, fileWritten, succeeded, cachedCodeBlocks, useRaysurferAiVoting = true, userVote, executionLogs, runUrl, workspaceId, dependencies, voteSource, voteCount) {
237
- let opts;
238
- if (typeof taskOrOptions === "object") {
239
- opts = taskOrOptions;
240
- } else {
241
- opts = {
242
- task: taskOrOptions,
243
- fileWritten,
244
- succeeded,
245
- cachedCodeBlocks,
246
- useRaysurferAiVoting,
247
- userVote,
248
- executionLogs,
249
- runUrl,
250
- workspaceId,
251
- dependencies,
252
- voteSource,
253
- voteCount
254
- };
255
- }
256
- const data = {
257
- task: opts.task,
258
- file_written: opts.fileWritten,
259
- succeeded: opts.succeeded,
260
- use_raysurfer_ai_voting: opts.useRaysurferAiVoting ?? true
261
- };
262
- if (opts.userVote !== undefined) {
263
- data.user_vote = opts.userVote;
264
- }
265
- if (opts.executionLogs) {
266
- data.execution_logs = opts.executionLogs;
267
- }
268
- if (opts.cachedCodeBlocks && opts.cachedCodeBlocks.length > 0) {
269
- data.cached_code_blocks = opts.cachedCodeBlocks.map((cb) => ({
270
- code_block_id: cb.codeBlockId,
271
- filename: cb.filename,
272
- description: cb.description
273
- }));
274
- }
275
- if (opts.runUrl) {
276
- data.run_url = opts.runUrl;
277
- }
278
- if (opts.dependencies) {
279
- data.dependencies = opts.dependencies;
280
- }
281
- if (opts.public) {
282
- data.public = true;
283
- }
284
- if (opts.voteSource !== undefined) {
285
- data.vote_source = opts.voteSource;
286
- }
287
- if (opts.voteCount !== undefined) {
288
- data.vote_count = opts.voteCount;
289
- }
290
- const result = await this.request("POST", "/api/store/execution-result", data, this.workspaceHeaders(opts.workspaceId));
291
- return {
292
- success: result.success,
293
- codeBlocksStored: result.code_blocks_stored,
294
- message: result.message
295
- };
296
- }
297
- uploadNewCodeSnips = this.uploadNewCodeSnip.bind(this);
298
- async uploadBulkCodeSnips(promptsOrOptions, filesWritten, logFiles, useRaysurferAiVoting = true, userVotes, workspaceId, voteSource, voteCount) {
299
- let opts;
300
- if (!Array.isArray(promptsOrOptions)) {
301
- opts = promptsOrOptions;
302
- } else {
303
- opts = {
304
- prompts: promptsOrOptions,
305
- filesWritten,
306
- logFiles,
307
- useRaysurferAiVoting,
308
- userVotes,
309
- workspaceId,
310
- voteSource,
311
- voteCount
312
- };
313
- }
314
- const normalizedLogs = opts.logFiles?.map((log) => {
315
- const content = typeof log.content === "string" ? log.content : Buffer.from(log.content).toString("base64");
316
- const encoding = typeof log.content === "string" ? log.encoding ?? "utf-8" : "base64";
317
- return {
318
- path: log.path,
319
- content,
320
- encoding,
321
- content_type: log.contentType
322
- };
323
- }) ?? [];
324
- const data = {
325
- prompts: opts.prompts,
326
- files_written: opts.filesWritten,
327
- log_files: normalizedLogs.length > 0 ? normalizedLogs : undefined,
328
- use_raysurfer_ai_voting: opts.useRaysurferAiVoting ?? true
329
- };
330
- if (opts.userVotes) {
331
- data.user_votes = opts.userVotes;
332
- }
333
- if (opts.voteSource !== undefined) {
334
- data.vote_source = opts.voteSource;
335
- }
336
- if (opts.voteCount !== undefined) {
337
- data.vote_count = opts.voteCount;
338
- }
339
- const result = await this.request("POST", "/api/store/bulk-execution-result", data, this.workspaceHeaders(opts.workspaceId));
340
- return {
341
- success: result.success,
342
- codeBlocksStored: result.code_blocks_stored,
343
- votesQueued: result.votes_queued,
344
- message: result.message,
345
- statusUrl: result.status_url ?? null
346
- };
347
- }
348
- async search(params) {
349
- const data = {
350
- task: params.task,
351
- top_k: params.topK ?? 5,
352
- min_verdict_score: params.minVerdictScore ?? 0.3,
353
- prefer_complete: params.preferComplete ?? false,
354
- input_schema: params.inputSchema ?? null
355
- };
356
- const result = await this.request("POST", "/api/retrieve/search", data, this.workspaceHeaders(params.workspaceId));
357
- return {
358
- matches: result.matches.map((m) => ({
359
- codeBlock: this.parseCodeBlock(m.code_block),
360
- score: m.score,
361
- thumbsUp: m.thumbs_up,
362
- thumbsDown: m.thumbs_down,
363
- filename: m.filename,
364
- language: m.language,
365
- entrypoint: m.entrypoint,
366
- dependencies: normalizeDependencies(m.dependencies)
367
- })),
368
- totalFound: result.total_found,
369
- cacheHit: result.cache_hit
370
- };
371
- }
372
- async getCodeSnips(params) {
373
- const response = await this.search({
374
- task: params.task,
375
- topK: params.topK ?? 10,
376
- minVerdictScore: params.minVerdictScore ?? 0
377
- });
378
- return {
379
- codeBlocks: response.matches.map((m) => ({
380
- codeBlock: m.codeBlock,
381
- score: m.score,
382
- thumbsUp: m.thumbsUp,
383
- thumbsDown: m.thumbsDown,
384
- recentExecutions: []
385
- })),
386
- totalFound: response.totalFound
387
- };
388
- }
389
- async retrieveBest(params) {
390
- const response = await this.search({
391
- task: params.task,
392
- topK: params.topK ?? 10,
393
- minVerdictScore: params.minVerdictScore ?? 0
394
- });
395
- let bestMatch = null;
396
- let bestScore = 0;
397
- const first = response.matches[0];
398
- if (first) {
399
- bestMatch = {
400
- codeBlock: first.codeBlock,
401
- score: first.score,
402
- thumbsUp: first.thumbsUp,
403
- thumbsDown: first.thumbsDown
404
- };
405
- bestScore = first.score;
406
- }
407
- const alternativeCandidates = response.matches.slice(1, 4).map((m) => ({
408
- codeBlockId: m.codeBlock.id,
409
- name: m.codeBlock.name,
410
- score: m.score,
411
- reason: m.thumbsUp > 0 ? `${m.thumbsUp} thumbs up, ${m.thumbsDown} thumbs down` : "No execution history"
412
- }));
413
- return {
414
- bestMatch,
415
- alternativeCandidates,
416
- retrievalConfidence: bestMatch ? String(bestScore.toFixed(4)) : "0"
417
- };
418
- }
419
- async getFewShotExamples(task, k = 3) {
420
- const data = { task, k };
421
- const result = await this.request("POST", "/api/retrieve/few-shot-examples", data);
422
- return result.examples.map((ex) => ({
423
- task: ex.task,
424
- inputSample: ex.input_sample,
425
- outputSample: ex.output_sample,
426
- codeSnippet: ex.code_snippet
427
- }));
428
- }
429
- async getTaskPatterns(params) {
430
- const data = {
431
- task: params.task ?? null,
432
- code_block_id: params.codeBlockId ?? null,
433
- min_thumbs_up: params.minThumbsUp ?? 0,
434
- top_k: params.topK ?? 20
435
- };
436
- const result = await this.request("POST", "/api/retrieve/task-patterns", data);
437
- return result.patterns.map((p) => ({
438
- taskPattern: p.task_pattern,
439
- codeBlockId: p.code_block_id,
440
- codeBlockName: p.code_block_name,
441
- thumbsUp: p.thumbs_up,
442
- thumbsDown: p.thumbs_down,
443
- lastThumbsUp: p.last_thumbs_up,
444
- lastThumbsDown: p.last_thumbs_down
445
- }));
446
- }
447
- async getCodeFiles(params) {
448
- const response = await this.search({
449
- task: params.task,
450
- topK: params.topK ?? 5,
451
- minVerdictScore: params.minVerdictScore ?? 0.3,
452
- preferComplete: params.preferComplete ?? true
453
- });
454
- const files = response.matches.map((m) => ({
455
- codeBlockId: m.codeBlock.id,
456
- filename: m.filename,
457
- source: m.codeBlock.source,
458
- entrypoint: m.entrypoint,
459
- description: m.codeBlock.description,
460
- inputSchema: m.codeBlock.inputSchema,
461
- outputSchema: m.codeBlock.outputSchema,
462
- language: m.language,
463
- dependencies: m.dependencies,
464
- score: m.score,
465
- thumbsUp: m.thumbsUp,
466
- thumbsDown: m.thumbsDown
467
- }));
468
- const addToLlmPrompt = this.formatLlmPrompt(files, params.cacheDir ?? ".raysurfer_code");
469
- return {
470
- files,
471
- task: params.task,
472
- totalFound: response.totalFound,
473
- addToLlmPrompt
474
- };
475
- }
476
- formatLlmPrompt(files, cacheDir) {
477
- if (files.length === 0)
478
- return "";
479
- const lines = [
480
- `
481
-
482
- ## IMPORTANT: Pre-validated Code Files Available
483
- `,
484
- "The following validated code has been retrieved from the cache. " + `Use these files directly instead of regenerating code.
485
- `
486
- ];
487
- for (const f of files) {
488
- if (cacheDir) {
489
- const fullPath = `${cacheDir}/${f.filename}`;
490
- lines.push(`
491
- ### \`${f.filename}\` → \`${fullPath}\``);
492
- } else {
493
- lines.push(`
494
- ### \`${f.filename}\``);
495
- }
496
- lines.push(`- **Description**: ${f.description}`);
497
- lines.push(`- **Language**: ${f.language}`);
498
- lines.push(`- **Entrypoint**: \`${f.entrypoint}\``);
499
- lines.push(`- **Confidence**: ${Math.round(f.score * 100)}%`);
500
- const deps = Object.entries(f.dependencies);
501
- if (deps.length > 0) {
502
- lines.push(`- **Dependencies**: ${deps.map(([k, v]) => `${k}@${v}`).join(", ")}`);
503
- }
504
- }
505
- lines.push(`
506
-
507
- **Instructions**:`);
508
- lines.push("1. Read the cached file(s) before writing new code");
509
- lines.push("2. Use the cached code as your starting point");
510
- lines.push("3. Only modify if the task requires specific changes");
511
- lines.push(`4. Do not regenerate code that already exists
512
- `);
513
- return lines.join(`
514
- `);
515
- }
516
- async autoReview(params) {
517
- const response = await this.request("POST", "/api/store/auto-review", {
518
- execution_id: params.executionId,
519
- triggering_task: params.triggeringTask,
520
- execution_state: params.executionState,
521
- input_data: params.inputData,
522
- output_data: params.outputData,
523
- code_block_name: params.codeBlockName,
524
- code_block_description: params.codeBlockDescription,
525
- error_message: params.errorMessage
526
- });
527
- return {
528
- success: response.success,
529
- executionId: response.execution_id,
530
- review: {
531
- timestamp: response.review.timestamp,
532
- verdict: response.review.verdict,
533
- reasoning: response.review.reasoning,
534
- whatWorked: response.review.what_worked,
535
- whatDidntWork: response.review.what_didnt_work,
536
- outputWasUseful: response.review.output_was_useful,
537
- outputWasCorrect: response.review.output_was_correct,
538
- outputWasComplete: response.review.output_was_complete,
539
- errorWasAppropriate: response.review.error_was_appropriate,
540
- wouldUseAgain: response.review.would_use_again,
541
- suggestedImprovements: response.review.suggested_improvements,
542
- requiredWorkaround: response.review.required_workaround,
543
- workaroundDescription: response.review.workaround_description
544
- },
545
- message: response.message
546
- };
547
- }
548
- async getExecutions(params = {}) {
549
- const response = await this.request("POST", "/api/retrieve/executions", {
550
- code_block_id: params.codeBlockId,
551
- task: params.task,
552
- verdict: params.verdict,
553
- limit: params.limit ?? 20
554
- });
555
- return {
556
- executions: response.executions.map((exec) => ({
557
- id: exec.id,
558
- codeBlockId: exec.code_block_id,
559
- timestamp: exec.timestamp,
560
- executionState: exec.execution_state,
561
- durationMs: exec.duration_ms,
562
- errorMessage: exec.error_message,
563
- errorType: exec.error_type,
564
- io: {
565
- inputData: exec.io.input_data,
566
- inputHash: exec.io.input_hash,
567
- outputData: exec.io.output_data,
568
- outputHash: exec.io.output_hash,
569
- outputType: exec.io.output_type
570
- },
571
- triggeringTask: exec.triggering_task,
572
- retrievalScore: exec.retrieval_score,
573
- verdict: exec.verdict,
574
- review: exec.review ? {
575
- timestamp: exec.review.timestamp,
576
- verdict: exec.review.verdict,
577
- reasoning: exec.review.reasoning,
578
- whatWorked: exec.review.what_worked,
579
- whatDidntWork: exec.review.what_didnt_work,
580
- outputWasUseful: exec.review.output_was_useful,
581
- outputWasCorrect: exec.review.output_was_correct,
582
- outputWasComplete: exec.review.output_was_complete,
583
- errorWasAppropriate: exec.review.error_was_appropriate,
584
- wouldUseAgain: exec.review.would_use_again,
585
- suggestedImprovements: exec.review.suggested_improvements,
586
- requiredWorkaround: exec.review.required_workaround,
587
- workaroundDescription: exec.review.workaround_description
588
- } : null
589
- })),
590
- totalFound: response.total_found
591
- };
592
- }
593
- async voteCodeSnip(params) {
594
- const data = {
595
- task: params.task,
596
- code_block_id: params.codeBlockId,
597
- code_block_name: params.codeBlockName,
598
- code_block_description: params.codeBlockDescription,
599
- succeeded: params.succeeded
600
- };
601
- const result = await this.request("POST", "/api/store/cache-usage", data);
602
- return {
603
- success: result.success,
604
- votePending: result.vote_pending,
605
- message: result.message
606
- };
607
- }
608
- async browsePublic(params = {}) {
609
- const data = {
610
- limit: params.limit ?? 20,
611
- offset: params.offset ?? 0,
612
- sort_by: params.sortBy ?? "upvoted"
613
- };
614
- if (params.language) {
615
- data.language = params.language;
616
- }
617
- const result = await this.request("POST", "/api/snippets/public/list", data);
618
- return {
619
- snippets: result.snippets.map((s) => ({
620
- id: s.id,
621
- name: s.name,
622
- description: s.description,
623
- source: s.source,
624
- language: s.language,
625
- entrypoint: s.entrypoint,
626
- thumbsUp: s.thumbs_up,
627
- thumbsDown: s.thumbs_down,
628
- createdAt: s.created_at,
629
- namespace: s.namespace
630
- })),
631
- total: result.total,
632
- hasMore: result.has_more
633
- };
634
- }
635
- async searchPublic(params) {
636
- const data = {
637
- query: params.query,
638
- limit: params.limit ?? 20
639
- };
640
- if (params.language) {
641
- data.language = params.language;
642
- }
643
- const result = await this.request("POST", "/api/snippets/public/search", data);
644
- return {
645
- snippets: result.snippets.map((s) => ({
646
- id: s.id,
647
- name: s.name,
648
- description: s.description,
649
- source: s.source,
650
- language: s.language,
651
- entrypoint: s.entrypoint,
652
- thumbsUp: s.thumbs_up,
653
- thumbsDown: s.thumbs_down,
654
- createdAt: s.created_at,
655
- namespace: s.namespace
656
- })),
657
- total: result.total,
658
- query: result.query
659
- };
660
- }
661
- async submitExecutionResult(task, fileWritten, succeeded) {
662
- return this.uploadNewCodeSnip(task, fileWritten, succeeded);
663
- }
664
- async retrieve(params) {
665
- return this.getCodeSnips(params);
666
- }
667
- parseCodeBlock(data) {
668
- return {
669
- id: data.id,
670
- name: data.name,
671
- description: data.description,
672
- source: data.source,
673
- entrypoint: data.entrypoint,
674
- inputSchema: data.input_schema ?? {},
675
- outputSchema: data.output_schema ?? {},
676
- language: data.language,
677
- languageVersion: data.language_version,
678
- dependencies: normalizeDependencies(data.dependencies),
679
- tags: data.tags ?? [],
680
- capabilities: data.capabilities ?? [],
681
- exampleQueries: data.example_queries,
682
- createdAt: data.created_at,
683
- updatedAt: data.updated_at
684
- };
685
- }
686
- }
687
- var client_default = RaySurfer;
688
- // src/sdk-client.ts
689
- import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
690
- import { join } from "node:path";
691
- var DEFAULT_RAYSURFER_URL = "https://api.raysurfer.com";
692
- var CACHE_DIR = ".raysurfer_code";
693
- var FILE_MODIFY_TOOLS = ["Write", "Edit", "MultiEdit", "NotebookEdit"];
694
- var TRACKABLE_EXTENSIONS = new Set([
695
- ".py",
696
- ".js",
697
- ".ts",
698
- ".rb",
699
- ".go",
700
- ".rs",
701
- ".java",
702
- ".cpp",
703
- ".c",
704
- ".h",
705
- ".pdf",
706
- ".docx",
707
- ".xlsx",
708
- ".csv",
709
- ".json",
710
- ".yaml",
711
- ".yml",
712
- ".xml",
713
- ".html",
714
- ".css",
715
- ".md",
716
- ".txt",
717
- ".sh",
718
- ".sql"
719
- ]);
720
- var BASH_OUTPUT_PATTERNS = [
721
- />>\s*([^\s;&|]+)/g,
722
- />\s*([^\s;&|]+)/g,
723
- /-o\s+([^\s;&|]+)/g,
724
- /--output[=\s]+([^\s;&|]+)/g,
725
- /savefig\(['"]([^'"]+)['"]\)/g,
726
- /to_csv\(['"]([^'"]+)['"]\)/g,
727
- /to_excel\(['"]([^'"]+)['"]\)/g,
728
- /write\(['"]([^'"]+)['"]\)/g
729
- ];
730
- var createDebugLogger = (enabled) => ({
731
- log: (...args) => enabled && console.log("[raysurfer]", ...args),
732
- time: (label) => enabled && console.time(`[raysurfer] ${label}`),
733
- timeEnd: (label) => enabled && console.timeEnd(`[raysurfer] ${label}`),
734
- table: (data) => enabled && console.table(data),
735
- group: (label) => enabled && console.group(`[raysurfer] ${label}`),
736
- groupEnd: () => enabled && console.groupEnd()
737
- });
738
- function augmentSystemPrompt(systemPrompt, addition) {
739
- if (!addition)
740
- return systemPrompt;
741
- if (typeof systemPrompt === "string")
742
- return systemPrompt + addition;
743
- if (systemPrompt?.type === "preset") {
744
- return { ...systemPrompt, append: (systemPrompt.append ?? "") + addition };
745
- }
746
- return addition;
747
- }
748
- function splitOptions(options) {
749
- const {
750
- workspaceId,
751
- publicSnips,
752
- debug,
753
- workingDirectory,
754
- ...sdkOptions
755
- } = options;
756
- return {
757
- sdkOptions,
758
- extras: {
759
- workspaceId,
760
- publicSnips,
761
- debug,
762
- workingDirectory
763
- }
764
- };
765
- }
766
-
767
- class RaysurferQuery {
768
- _inner = null;
769
- _initPromise = null;
770
- _raysurfer = null;
771
- _cachedFiles = [];
772
- _modifiedFilePaths = new Set;
773
- _bashGeneratedFiles = new Set;
774
- _executionLogs = [];
775
- _taskSucceeded = false;
776
- _generatedCodeBlocks = [];
777
- _cacheUploadDone = false;
778
- _messageCount = 0;
779
- _startTime = 0;
780
- _promptText;
781
- _params;
782
- _debug;
783
- _cacheEnabled;
784
- _workDir;
785
- _apiKey;
786
- _baseUrl;
787
- _extras;
788
- _sdkOptions;
789
- constructor(params) {
790
- this._params = params;
791
- const options = params.options ?? {};
792
- const { sdkOptions, extras } = splitOptions(options);
793
- this._sdkOptions = sdkOptions;
794
- this._extras = extras;
795
- this._promptText = typeof params.prompt === "string" ? params.prompt : null;
796
- const debugEnabled = extras.debug || process.env.RAYSURFER_DEBUG === "true";
797
- this._debug = createDebugLogger(debugEnabled);
798
- this._apiKey = process.env.RAYSURFER_API_KEY;
799
- this._baseUrl = process.env.RAYSURFER_BASE_URL || DEFAULT_RAYSURFER_URL;
800
- this._cacheEnabled = !!this._apiKey;
801
- if (extras.workingDirectory && !sdkOptions.cwd) {
802
- console.warn("[raysurfer] workingDirectory is deprecated, use cwd instead");
803
- this._sdkOptions.cwd = extras.workingDirectory;
804
- }
805
- this._workDir = this._sdkOptions.cwd || process.cwd();
806
- }
807
- async _initialize() {
808
- this._debug.group("Raysurfer Query Started");
809
- this._debug.log("Prompt:", this._promptText ?? "<stream>");
810
- this._debug.log("Cache enabled:", this._cacheEnabled);
811
- this._debug.log("Base URL:", this._baseUrl);
812
- if (!this._cacheEnabled) {
813
- console.warn("[raysurfer] RAYSURFER_API_KEY not set - caching disabled");
814
- }
815
- let addToLlmPrompt = "";
816
- if (this._cacheEnabled && this._promptText) {
817
- this._raysurfer = new RaySurfer({
818
- apiKey: this._apiKey,
819
- baseUrl: this._baseUrl,
820
- workspaceId: this._extras.workspaceId,
821
- snipsDesired: this._extras.workspaceId ? "client" : undefined,
822
- publicSnips: this._extras.publicSnips
823
- });
824
- try {
825
- this._debug.time("Cache lookup");
826
- const cacheDir = join(this._workDir, CACHE_DIR);
827
- const response = await this._raysurfer.getCodeFiles({
828
- task: this._promptText,
829
- topK: 5,
830
- minVerdictScore: 0.3,
831
- preferComplete: true,
832
- cacheDir
833
- });
834
- this._debug.timeEnd("Cache lookup");
835
- this._cachedFiles = response.files;
836
- addToLlmPrompt = response.addToLlmPrompt;
837
- this._debug.log(`Found ${this._cachedFiles.length} cached files:`);
838
- console.log("[raysurfer] Cache hit:", this._cachedFiles.length, "snippets retrieved");
839
- if (this._cachedFiles.length > 0) {
840
- this._debug.table(this._cachedFiles.map((f) => ({
841
- filename: f.filename,
842
- score: `${Math.round(f.score * 100)}%`,
843
- thumbs: `${f.thumbsUp}/${f.thumbsDown}`,
844
- sourceLength: `${f.source.length} chars`
845
- })));
846
- try {
847
- mkdirSync(cacheDir, { recursive: true });
848
- for (const file of this._cachedFiles) {
849
- const filePath = join(cacheDir, file.filename);
850
- writeFileSync(filePath, file.source, "utf-8");
851
- this._debug.log(` → Wrote cached file: ${filePath}`);
852
- this._modifiedFilePaths.add(filePath);
853
- }
854
- } catch (writeErr) {
855
- this._debug.log("Failed to write cached files:", writeErr);
856
- }
857
- }
858
- } catch (error) {
859
- this._debug.log("Cache lookup failed:", error);
860
- console.warn("[raysurfer] Cache unavailable:", error instanceof Error ? error.message : error);
861
- }
862
- }
863
- const augmented = augmentSystemPrompt(this._sdkOptions.systemPrompt, addToLlmPrompt);
864
- const augmentedOptions = {
865
- ...this._sdkOptions,
866
- systemPrompt: augmented
867
- };
868
- this._debug.log("Augmented prompt addition:", addToLlmPrompt.length, "chars");
869
- let sdkQueryFn;
870
- try {
871
- const sdk = await import("@anthropic-ai/claude-agent-sdk");
872
- sdkQueryFn = sdk.query;
873
- } catch {
874
- throw new Error("Could not import @anthropic-ai/claude-agent-sdk. Install it with: npm install @anthropic-ai/claude-agent-sdk");
875
- }
876
- this._debug.time("Claude API call");
877
- this._debug.log("Calling Claude Agent SDK...");
878
- this._startTime = Date.now();
879
- this._inner = sdkQueryFn({
880
- prompt: this._params.prompt,
881
- options: augmentedOptions
882
- });
883
- }
884
- async _ensureInit() {
885
- if (!this._inner) {
886
- if (!this._initPromise) {
887
- this._initPromise = this._initialize();
888
- }
889
- await this._initPromise;
890
- }
891
- return this._inner;
892
- }
893
- _extractBashOutputFiles(command) {
894
- for (const pattern of BASH_OUTPUT_PATTERNS) {
895
- pattern.lastIndex = 0;
896
- let match = pattern.exec(command);
897
- while (match !== null) {
898
- const filePath = match[1];
899
- if (filePath && filePath.length > 0) {
900
- const ext = filePath.substring(filePath.lastIndexOf(".")).toLowerCase();
901
- if (TRACKABLE_EXTENSIONS.has(ext)) {
902
- this._bashGeneratedFiles.add(filePath);
903
- this._debug.log(` → Bash output file detected: ${filePath}`);
904
- }
905
- }
906
- match = pattern.exec(command);
907
- }
908
- }
909
- }
910
- _trackMessage(message) {
911
- this._messageCount++;
912
- const msg = message;
913
- const elapsed = Date.now() - this._startTime;
914
- this._debug.log(`
915
- ═══════════════════════════════════════════════════`);
916
- this._debug.log(`Message #${this._messageCount} [${elapsed}ms] type=${msg.type} subtype=${msg.subtype || "none"}`);
917
- this._debug.log(`═══════════════════════════════════════════════════`);
918
- this._debug.log(JSON.stringify(msg, null, 2));
919
- if (msg.type === "assistant") {
920
- const content = msg.message;
921
- const contentBlocks = content?.content;
922
- if (contentBlocks) {
923
- for (const block of contentBlocks) {
924
- if (block.type === "tool_use" && FILE_MODIFY_TOOLS.includes(block.name)) {
925
- const input = block.input;
926
- const filePath = input?.file_path ?? input?.notebook_path;
927
- if (filePath) {
928
- this._debug.log(` → ${block.name} tool detected:`, filePath);
929
- this._modifiedFilePaths.add(filePath);
930
- }
931
- }
932
- if (block.type === "tool_use" && block.name === "Bash") {
933
- const input = block.input;
934
- const command = input?.command;
935
- if (command) {
936
- this._extractBashOutputFiles(command);
937
- }
938
- }
939
- if (block.type === "tool_result") {
940
- const resultContent = block.content;
941
- if (resultContent) {
942
- this._executionLogs.push(resultContent.slice(0, 5000));
943
- }
944
- }
945
- if (block.type === "text") {
946
- const text = block.text;
947
- const codeMatches = text.match(/```(?:typescript|javascript|ts|js)?\n?([\s\S]*?)\n?```/g);
948
- if (codeMatches) {
949
- for (const match of codeMatches) {
950
- const code = match.replace(/```(?:typescript|javascript|ts|js)?\n?/, "").replace(/\n?```$/, "");
951
- if (code.trim().length > 50) {
952
- this._generatedCodeBlocks.push(code.trim());
953
- this._debug.log(` → Extracted code block (${code.length} chars)`);
954
- }
955
- }
956
- }
957
- }
958
- }
959
- }
960
- }
961
- if (msg.type === "result" && msg.subtype === "success") {
962
- this._taskSucceeded = true;
963
- this._debug.timeEnd("Claude API call");
964
- this._debug.log("Task succeeded!");
965
- const result = msg;
966
- this._debug.log(" Duration:", result.duration_ms, "ms");
967
- this._debug.log(" Total cost:", result.total_cost_usd, "USD");
968
- this._debug.log(" Turns:", result.num_turns);
969
- }
970
- if (msg.type === "result" && msg.subtype !== "success") {
971
- this._debug.timeEnd("Claude API call");
972
- this._debug.log("Task failed:", msg.subtype);
973
- }
974
- }
975
- async _uploadCache() {
976
- if (this._cacheUploadDone)
977
- return;
978
- this._cacheUploadDone = true;
979
- this._debug.log("Total messages streamed:", this._messageCount);
980
- this._debug.log("Modified files tracked:", this._modifiedFilePaths.size);
981
- this._debug.log("Code blocks extracted:", this._generatedCodeBlocks.length);
982
- const filesToCache = [];
983
- for (const filePath of this._modifiedFilePaths) {
984
- if (filePath.includes(CACHE_DIR)) {
985
- this._debug.log(" → Skipping cached file:", filePath);
986
- continue;
987
- }
988
- try {
989
- if (existsSync(filePath)) {
990
- const content = readFileSync(filePath, "utf-8");
991
- if (content.includes("\x00")) {
992
- this._debug.log(" → Skipping binary file:", filePath);
993
- continue;
994
- }
995
- filesToCache.push({ path: filePath, content });
996
- this._debug.log(" → Will cache file:", filePath, `(${content.length} chars)`);
997
- } else {
998
- this._debug.log(" → File not found:", filePath);
999
- }
1000
- } catch (err) {
1001
- this._debug.log(" → Failed to read file:", filePath, err);
1002
- }
1003
- }
1004
- for (const filePath of this._bashGeneratedFiles) {
1005
- if (this._modifiedFilePaths.has(filePath))
1006
- continue;
1007
- try {
1008
- if (existsSync(filePath)) {
1009
- const content = readFileSync(filePath, "utf-8");
1010
- if (!content.includes("\x00")) {
1011
- filesToCache.push({ path: filePath, content });
1012
- this._debug.log(" → Will cache Bash-generated file:", filePath, `(${content.length} chars)`);
1013
- }
1014
- }
1015
- } catch {
1016
- this._debug.log(" → Failed to read Bash-generated file:", filePath);
1017
- }
1018
- }
1019
- if (this._generatedCodeBlocks.length > 0) {
1020
- const largestBlock = this._generatedCodeBlocks.reduce((a, b) => a.length > b.length ? a : b);
1021
- filesToCache.push({
1022
- path: "generated-code.ts",
1023
- content: largestBlock
1024
- });
1025
- this._debug.log(" → Will cache generated code block:", `(${largestBlock.length} chars)`);
1026
- }
1027
- this._debug.log("Total items to cache:", filesToCache.length);
1028
- if (this._cacheEnabled && this._raysurfer && this._taskSucceeded && this._promptText) {
1029
- const cachedBlocksForVoting = this._cachedFiles.map((f) => ({
1030
- codeBlockId: f.codeBlockId,
1031
- filename: f.filename,
1032
- description: f.description
1033
- }));
1034
- if (filesToCache.length > 0 || cachedBlocksForVoting.length > 0) {
1035
- try {
1036
- this._debug.time("Cache upload + voting");
1037
- const joinedLogs = this._executionLogs.length > 0 ? this._executionLogs.join(`
1038
- ---
1039
- `) : undefined;
1040
- this._debug.log("Uploading", filesToCache.length, "files, voting for", cachedBlocksForVoting.length, "cached blocks,", this._executionLogs.length, "log entries...");
1041
- for (let i = 0;i < filesToCache.length; i++) {
1042
- const file = filesToCache[i];
1043
- await this._raysurfer.uploadNewCodeSnip(this._promptText, file, true, i === 0 && cachedBlocksForVoting.length > 0 ? cachedBlocksForVoting : undefined, true, undefined, joinedLogs);
1044
- }
1045
- if (filesToCache.length === 0 && cachedBlocksForVoting.length > 0) {
1046
- for (const cb of cachedBlocksForVoting) {
1047
- await this._raysurfer.voteCodeSnip({
1048
- task: this._promptText,
1049
- codeBlockId: cb.codeBlockId,
1050
- codeBlockName: cb.filename,
1051
- codeBlockDescription: cb.description,
1052
- succeeded: true
1053
- });
1054
- }
1055
- }
1056
- this._debug.timeEnd("Cache upload + voting");
1057
- this._debug.log("Cache upload successful, voting queued on backend");
1058
- console.log("[raysurfer] Cache upload successful:", filesToCache.length, "files stored");
1059
- } catch (error) {
1060
- this._debug.log("Cache upload failed:", error);
1061
- console.warn("[raysurfer] Cache upload failed:", error instanceof Error ? error.message : error);
1062
- }
1063
- }
1064
- }
1065
- this._debug.groupEnd();
1066
- }
1067
- async next(...args) {
1068
- const inner = await this._ensureInit();
1069
- const result = await inner.next(...args);
1070
- if (!result.done) {
1071
- this._trackMessage(result.value);
1072
- } else {
1073
- await this._uploadCache();
1074
- }
1075
- return result;
1076
- }
1077
- async return(value) {
1078
- if (this._inner) {
1079
- await this._uploadCache();
1080
- return this._inner.return(value);
1081
- }
1082
- return { done: true, value: undefined };
1083
- }
1084
- async throw(e) {
1085
- if (this._inner)
1086
- return this._inner.throw(e);
1087
- throw e;
1088
- }
1089
- [Symbol.asyncIterator]() {
1090
- return this;
1091
- }
1092
- async[Symbol.asyncDispose]() {
1093
- this.close();
1094
- }
1095
- async interrupt() {
1096
- return (await this._ensureInit()).interrupt();
1097
- }
1098
- async setPermissionMode(mode) {
1099
- return (await this._ensureInit()).setPermissionMode(mode);
1100
- }
1101
- async setModel(model) {
1102
- return (await this._ensureInit()).setModel(model);
1103
- }
1104
- async setMaxThinkingTokens(maxThinkingTokens) {
1105
- return (await this._ensureInit()).setMaxThinkingTokens(maxThinkingTokens);
1106
- }
1107
- async supportedCommands() {
1108
- return (await this._ensureInit()).supportedCommands();
1109
- }
1110
- async supportedModels() {
1111
- return (await this._ensureInit()).supportedModels();
1112
- }
1113
- async mcpServerStatus() {
1114
- return (await this._ensureInit()).mcpServerStatus();
1115
- }
1116
- async accountInfo() {
1117
- return (await this._ensureInit()).accountInfo();
1118
- }
1119
- async rewindFiles(userMessageId, options) {
1120
- return (await this._ensureInit()).rewindFiles(userMessageId, options);
1121
- }
1122
- async setMcpServers(servers) {
1123
- return (await this._ensureInit()).setMcpServers(servers);
1124
- }
1125
- async streamInput(stream) {
1126
- return (await this._ensureInit()).streamInput(stream);
1127
- }
1128
- close() {
1129
- if (this._inner)
1130
- this._inner.close();
1131
- }
1132
- }
1133
- function query(params) {
1134
- return new RaysurferQuery(params);
1135
- }
1136
-
1137
- class ClaudeSDKClient {
1138
- options;
1139
- constructor(options = {}) {
1140
- this.options = options;
1141
- }
1142
- query(prompt) {
1143
- return query({ prompt, options: this.options });
1144
- }
1145
- }
1146
- var sdk_client_default = query;
1147
- // src/types.ts
1148
- var ExecutionState;
1149
- ((ExecutionState2) => {
1150
- ExecutionState2["COMPLETED"] = "completed";
1151
- ExecutionState2["ERRORED"] = "errored";
1152
- ExecutionState2["TIMED_OUT"] = "timed_out";
1153
- ExecutionState2["CANCELLED"] = "cancelled";
1154
- })(ExecutionState ||= {});
1155
- var AgentVerdict;
1156
- ((AgentVerdict2) => {
1157
- AgentVerdict2["THUMBS_UP"] = "thumbs_up";
1158
- AgentVerdict2["THUMBS_DOWN"] = "thumbs_down";
1159
- AgentVerdict2["PENDING"] = "pending";
1160
- })(AgentVerdict ||= {});
1161
-
1162
- // src/index.ts
1163
- import {
1164
- AbortError,
1165
- createSdkMcpServer,
1166
- EXIT_REASONS,
1167
- HOOK_EVENTS,
1168
- tool
1169
- } from "@anthropic-ai/claude-agent-sdk";
1170
- export {
1171
- tool,
1172
- sdk_client_default as queryDefault,
1173
- query,
1174
- createSdkMcpServer,
1175
- ValidationError,
1176
- VERSION,
1177
- ClaudeSDKClient as RaysurferClient,
1178
- RaySurferError,
1179
- client_default as RaySurferDefault,
1180
- RaySurfer,
1181
- RateLimitError,
1182
- HOOK_EVENTS,
1183
- ExecutionState,
1184
- EXIT_REASONS,
1185
- ClaudeSDKClient,
1186
- CacheUnavailableError,
1187
- AuthenticationError,
1188
- AgentVerdict,
1189
- AbortError,
1190
- APIError
1191
- };