raysurfer 1.4.2 → 1.4.4
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/client.d.ts +64 -23
- package/dist/client.d.ts.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +989 -760
- package/dist/runner.d.ts +80 -0
- package/dist/runner.d.ts.map +1 -0
- package/dist/types.d.ts +46 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,219 +1,71 @@
|
|
|
1
1
|
import { createRequire } from "node:module";
|
|
2
|
-
var __create = Object.create;
|
|
3
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
4
2
|
var __defProp = Object.defineProperty;
|
|
5
|
-
var
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
for (
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
3
|
+
var __returnValue = (v) => v;
|
|
4
|
+
function __exportSetter(name, newValue) {
|
|
5
|
+
this[name] = __returnValue.bind(null, newValue);
|
|
6
|
+
}
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, {
|
|
10
|
+
get: all[name],
|
|
11
|
+
enumerable: true,
|
|
12
|
+
configurable: true,
|
|
13
|
+
set: __exportSetter.bind(all, name)
|
|
14
|
+
});
|
|
17
15
|
};
|
|
16
|
+
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
18
17
|
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
19
18
|
|
|
20
|
-
// src/
|
|
21
|
-
var
|
|
22
|
-
((
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
})(ExecutionState ||= {});
|
|
28
|
-
var AgentVerdict;
|
|
29
|
-
((AgentVerdict2) => {
|
|
30
|
-
AgentVerdict2["THUMBS_UP"] = "thumbs_up";
|
|
31
|
-
AgentVerdict2["THUMBS_DOWN"] = "thumbs_down";
|
|
32
|
-
AgentVerdict2["PENDING"] = "pending";
|
|
33
|
-
})(AgentVerdict ||= {});
|
|
34
|
-
|
|
35
|
-
// src/accessible.ts
|
|
36
|
-
function toJsonLike(value) {
|
|
37
|
-
if (value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
38
|
-
return value;
|
|
39
|
-
}
|
|
40
|
-
if (value === undefined) {
|
|
41
|
-
return null;
|
|
42
|
-
}
|
|
43
|
-
if (Array.isArray(value)) {
|
|
44
|
-
return value.map((item) => toJsonLike(item));
|
|
45
|
-
}
|
|
46
|
-
if (typeof value === "object") {
|
|
47
|
-
const result = {};
|
|
48
|
-
for (const [key, nested] of Object.entries(value)) {
|
|
49
|
-
result[key] = toJsonLike(nested);
|
|
19
|
+
// src/errors.ts
|
|
20
|
+
var RaySurferError, APIError, AuthenticationError, CacheUnavailableError, RateLimitError, ValidationError;
|
|
21
|
+
var init_errors = __esm(() => {
|
|
22
|
+
RaySurferError = class RaySurferError extends Error {
|
|
23
|
+
constructor(message) {
|
|
24
|
+
super(message);
|
|
25
|
+
this.name = "RaySurferError";
|
|
50
26
|
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
return;
|
|
59
|
-
const codeBlockId = fn._raysurferSchema.codeBlockId ?? `function_registry:${fn._raysurferSchema.name}`;
|
|
60
|
-
const outputData = errorMessage === undefined ? result : { error: errorMessage };
|
|
61
|
-
client.storeExecution({
|
|
62
|
-
codeBlockId,
|
|
63
|
-
triggeringTask: `agent_accessible:${fn._raysurferSchema.name}`,
|
|
64
|
-
inputData: {
|
|
65
|
-
args: toJsonLike(args)
|
|
66
|
-
},
|
|
67
|
-
outputData: toJsonLike(outputData),
|
|
68
|
-
executionState: errorMessage ? "errored" /* ERRORED */ : "completed" /* COMPLETED */,
|
|
69
|
-
durationMs,
|
|
70
|
-
errorMessage
|
|
71
|
-
}).catch(() => {});
|
|
72
|
-
}
|
|
73
|
-
function inferParameters(fn) {
|
|
74
|
-
const src = fn.toString();
|
|
75
|
-
const match = /^[^(]*\(([^)]*)\)/.exec(src);
|
|
76
|
-
const paramStr = match?.[1];
|
|
77
|
-
if (!paramStr?.trim())
|
|
78
|
-
return {};
|
|
79
|
-
const params = {};
|
|
80
|
-
const parts = paramStr.split(",");
|
|
81
|
-
for (const part of parts) {
|
|
82
|
-
const cleaned = part.trim().replace(/\/\*.*?\*\//g, "").replace(/=.*$/, "").replace(/:.*$/, "").trim();
|
|
83
|
-
if (cleaned && cleaned !== "..." && !cleaned.startsWith("...")) {
|
|
84
|
-
params[cleaned] = "string";
|
|
27
|
+
};
|
|
28
|
+
APIError = class APIError extends RaySurferError {
|
|
29
|
+
statusCode;
|
|
30
|
+
constructor(message, statusCode) {
|
|
31
|
+
super(message);
|
|
32
|
+
this.name = "APIError";
|
|
33
|
+
this.statusCode = statusCode;
|
|
85
34
|
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
const resolvedDescription = options?.description ?? "";
|
|
92
|
-
const resolvedSchema = options?.inputSchema ?? options?.parameters ?? inferParameters(fn);
|
|
93
|
-
let marked;
|
|
94
|
-
const wrapped = (...args) => {
|
|
95
|
-
const started = Date.now();
|
|
96
|
-
try {
|
|
97
|
-
const result = fn(...args);
|
|
98
|
-
if (result instanceof Promise) {
|
|
99
|
-
const trackedPromise = result.then((resolved) => {
|
|
100
|
-
queueUsageTracking(marked, args, resolved, Date.now() - started);
|
|
101
|
-
return resolved;
|
|
102
|
-
}).catch((error) => {
|
|
103
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
104
|
-
queueUsageTracking(marked, args, null, Date.now() - started, message);
|
|
105
|
-
throw error;
|
|
106
|
-
});
|
|
107
|
-
return trackedPromise;
|
|
108
|
-
}
|
|
109
|
-
queueUsageTracking(marked, args, result, Date.now() - started);
|
|
110
|
-
return result;
|
|
111
|
-
} catch (error) {
|
|
112
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
113
|
-
queueUsageTracking(marked, args, null, Date.now() - started, message);
|
|
114
|
-
throw error;
|
|
35
|
+
};
|
|
36
|
+
AuthenticationError = class AuthenticationError extends RaySurferError {
|
|
37
|
+
constructor(message = "Invalid API key") {
|
|
38
|
+
super(message);
|
|
39
|
+
this.name = "AuthenticationError";
|
|
115
40
|
}
|
|
116
41
|
};
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
source: fn.toString()
|
|
42
|
+
CacheUnavailableError = class CacheUnavailableError extends RaySurferError {
|
|
43
|
+
statusCode;
|
|
44
|
+
constructor(message = "Cache backend is unreachable", statusCode = 503) {
|
|
45
|
+
super(message);
|
|
46
|
+
this.name = "CacheUnavailableError";
|
|
47
|
+
this.statusCode = statusCode;
|
|
48
|
+
}
|
|
125
49
|
};
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
input_schema: schema.inputSchema
|
|
50
|
+
RateLimitError = class RateLimitError extends RaySurferError {
|
|
51
|
+
retryAfter;
|
|
52
|
+
constructor(message = "Rate limit exceeded", retryAfter) {
|
|
53
|
+
super(message);
|
|
54
|
+
this.name = "RateLimitError";
|
|
55
|
+
this.retryAfter = retryAfter;
|
|
56
|
+
}
|
|
134
57
|
};
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
const schema = fn._raysurferSchema;
|
|
142
|
-
const resp = await client.uploadNewCodeSnip({
|
|
143
|
-
task: `Call ${schema.name}: ${schema.description}`,
|
|
144
|
-
fileWritten: { path: `${schema.name}.ts`, content: schema.source },
|
|
145
|
-
succeeded: true,
|
|
146
|
-
useRaysurferAiVoting: false,
|
|
147
|
-
tags: ["function_registry", "agent_accessible"]
|
|
148
|
-
});
|
|
149
|
-
if (resp.snippetName) {
|
|
150
|
-
snippetNames.push(resp.snippetName);
|
|
151
|
-
schema.codeBlockId = resp.snippetName;
|
|
58
|
+
ValidationError = class ValidationError extends RaySurferError {
|
|
59
|
+
field;
|
|
60
|
+
constructor(message = "Validation failed", field) {
|
|
61
|
+
super(message);
|
|
62
|
+
this.name = "ValidationError";
|
|
63
|
+
this.field = field;
|
|
152
64
|
}
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
return snippetNames;
|
|
156
|
-
}
|
|
157
|
-
function setTrackingClient(fn, client) {
|
|
158
|
-
fn._raysurferClient = client;
|
|
159
|
-
}
|
|
160
|
-
// src/errors.ts
|
|
161
|
-
class RaySurferError extends Error {
|
|
162
|
-
constructor(message) {
|
|
163
|
-
super(message);
|
|
164
|
-
this.name = "RaySurferError";
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
class APIError extends RaySurferError {
|
|
169
|
-
statusCode;
|
|
170
|
-
constructor(message, statusCode) {
|
|
171
|
-
super(message);
|
|
172
|
-
this.name = "APIError";
|
|
173
|
-
this.statusCode = statusCode;
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
class AuthenticationError extends RaySurferError {
|
|
178
|
-
constructor(message = "Invalid API key") {
|
|
179
|
-
super(message);
|
|
180
|
-
this.name = "AuthenticationError";
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
class CacheUnavailableError extends RaySurferError {
|
|
185
|
-
statusCode;
|
|
186
|
-
constructor(message = "Cache backend is unreachable", statusCode = 503) {
|
|
187
|
-
super(message);
|
|
188
|
-
this.name = "CacheUnavailableError";
|
|
189
|
-
this.statusCode = statusCode;
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
class RateLimitError extends RaySurferError {
|
|
194
|
-
retryAfter;
|
|
195
|
-
constructor(message = "Rate limit exceeded", retryAfter) {
|
|
196
|
-
super(message);
|
|
197
|
-
this.name = "RateLimitError";
|
|
198
|
-
this.retryAfter = retryAfter;
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
class ValidationError extends RaySurferError {
|
|
203
|
-
field;
|
|
204
|
-
constructor(message = "Validation failed", field) {
|
|
205
|
-
super(message);
|
|
206
|
-
this.name = "ValidationError";
|
|
207
|
-
this.field = field;
|
|
208
|
-
}
|
|
209
|
-
}
|
|
65
|
+
};
|
|
66
|
+
});
|
|
210
67
|
|
|
211
68
|
// src/client.ts
|
|
212
|
-
var VERSION = "1.4.0";
|
|
213
|
-
var DEFAULT_BASE_URL = "https://api.raysurfer.com";
|
|
214
|
-
var MAX_RETRIES = 3;
|
|
215
|
-
var RETRY_BASE_DELAY = 500;
|
|
216
|
-
var RETRYABLE_STATUS_CODES = new Set([429, 500, 502, 503, 504]);
|
|
217
69
|
function normalizeDependencies(rawDeps) {
|
|
218
70
|
if (!rawDeps)
|
|
219
71
|
return {};
|
|
@@ -385,6 +237,9 @@ class RaySurfer {
|
|
|
385
237
|
if (typeof taskOrOptions === "object") {
|
|
386
238
|
opts = taskOrOptions;
|
|
387
239
|
} else {
|
|
240
|
+
if (!fileWritten || succeeded === undefined) {
|
|
241
|
+
throw new Error("fileWritten and succeeded are required when using positional arguments");
|
|
242
|
+
}
|
|
388
243
|
opts = {
|
|
389
244
|
task: taskOrOptions,
|
|
390
245
|
fileWritten,
|
|
@@ -400,6 +255,9 @@ class RaySurfer {
|
|
|
400
255
|
voteCount
|
|
401
256
|
};
|
|
402
257
|
}
|
|
258
|
+
if (opts.repoPath || opts.githubUrl) {
|
|
259
|
+
return this.uploadRepo(opts);
|
|
260
|
+
}
|
|
403
261
|
if (opts.fileWritten && opts.filesWritten) {
|
|
404
262
|
throw new Error("Provide either fileWritten or filesWritten, not both.");
|
|
405
263
|
}
|
|
@@ -411,7 +269,7 @@ class RaySurfer {
|
|
|
411
269
|
normalizedFiles.push(...opts.filesWritten);
|
|
412
270
|
}
|
|
413
271
|
if (normalizedFiles.length === 0) {
|
|
414
|
-
throw new Error("Missing required file input: provide fileWritten or
|
|
272
|
+
throw new Error("Missing required file input: provide fileWritten, filesWritten, repoPath, or githubUrl.");
|
|
415
273
|
}
|
|
416
274
|
if (normalizedFiles.length > 1) {
|
|
417
275
|
const responses = [];
|
|
@@ -449,7 +307,8 @@ class RaySurfer {
|
|
|
449
307
|
public: opts.public || undefined,
|
|
450
308
|
vote_source: opts.voteSource,
|
|
451
309
|
vote_count: opts.voteCount,
|
|
452
|
-
per_function_reputation: opts.perFunctionReputation || undefined
|
|
310
|
+
per_function_reputation: opts.perFunctionReputation || undefined,
|
|
311
|
+
content_type: opts.contentType
|
|
453
312
|
};
|
|
454
313
|
const result = await this.request("POST", "/api/store/execution-result", data, this.workspaceHeaders(opts.workspaceId));
|
|
455
314
|
return {
|
|
@@ -459,6 +318,63 @@ class RaySurfer {
|
|
|
459
318
|
snippetName: result.snippet_name ?? null
|
|
460
319
|
};
|
|
461
320
|
}
|
|
321
|
+
async uploadRepo(opts) {
|
|
322
|
+
const files = [];
|
|
323
|
+
if (opts.repoPath) {
|
|
324
|
+
const fs = await import("node:fs");
|
|
325
|
+
const path = await import("node:path");
|
|
326
|
+
const skipDirs = new Set([
|
|
327
|
+
".git",
|
|
328
|
+
"__pycache__",
|
|
329
|
+
"node_modules",
|
|
330
|
+
".venv",
|
|
331
|
+
"venv",
|
|
332
|
+
".tox",
|
|
333
|
+
"dist",
|
|
334
|
+
"build"
|
|
335
|
+
]);
|
|
336
|
+
const walkDir = (dir, base) => {
|
|
337
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
338
|
+
if (skipDirs.has(entry.name))
|
|
339
|
+
continue;
|
|
340
|
+
const fullPath = path.join(dir, entry.name);
|
|
341
|
+
const relPath = path.join(base, entry.name);
|
|
342
|
+
if (entry.isDirectory()) {
|
|
343
|
+
walkDir(fullPath, relPath);
|
|
344
|
+
} else if (entry.isFile()) {
|
|
345
|
+
try {
|
|
346
|
+
const content = fs.readFileSync(fullPath, "utf-8");
|
|
347
|
+
files.push({ path: relPath, content });
|
|
348
|
+
} catch {}
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
};
|
|
352
|
+
walkDir(opts.repoPath, "");
|
|
353
|
+
}
|
|
354
|
+
const requestData = {
|
|
355
|
+
task: opts.task,
|
|
356
|
+
files
|
|
357
|
+
};
|
|
358
|
+
if (opts.githubUrl) {
|
|
359
|
+
requestData.github_url = opts.githubUrl;
|
|
360
|
+
}
|
|
361
|
+
if (opts.dependencies) {
|
|
362
|
+
requestData.dependencies = opts.dependencies;
|
|
363
|
+
}
|
|
364
|
+
if (opts.tags) {
|
|
365
|
+
requestData.tags = opts.tags;
|
|
366
|
+
}
|
|
367
|
+
if (opts.contentType) {
|
|
368
|
+
requestData.content_type = opts.contentType;
|
|
369
|
+
}
|
|
370
|
+
const result = await this.request("POST", "/api/store/repo", requestData, this.workspaceHeaders(opts.workspaceId));
|
|
371
|
+
return {
|
|
372
|
+
success: result.success,
|
|
373
|
+
codeBlocksStored: result.success ? 1 : 0,
|
|
374
|
+
message: result.message,
|
|
375
|
+
snippetName: result.repo_id ?? null
|
|
376
|
+
};
|
|
377
|
+
}
|
|
462
378
|
uploadNewCodeSnip = this.upload.bind(this);
|
|
463
379
|
uploadNewCodeSnips = this.upload.bind(this);
|
|
464
380
|
async delete(snippetId, options) {
|
|
@@ -474,6 +390,9 @@ class RaySurfer {
|
|
|
474
390
|
if (!Array.isArray(promptsOrOptions)) {
|
|
475
391
|
opts = promptsOrOptions;
|
|
476
392
|
} else {
|
|
393
|
+
if (!filesWritten) {
|
|
394
|
+
throw new Error("filesWritten is required when using positional arguments");
|
|
395
|
+
}
|
|
477
396
|
opts = {
|
|
478
397
|
prompts: promptsOrOptions,
|
|
479
398
|
filesWritten,
|
|
@@ -526,6 +445,15 @@ class RaySurfer {
|
|
|
526
445
|
if (params.perFunctionReputation) {
|
|
527
446
|
data.per_function_reputation = true;
|
|
528
447
|
}
|
|
448
|
+
if (params.resultType && params.resultType !== "any") {
|
|
449
|
+
data.result_type = params.resultType;
|
|
450
|
+
}
|
|
451
|
+
if (params.contentType) {
|
|
452
|
+
data.content_type = params.contentType;
|
|
453
|
+
}
|
|
454
|
+
if (params.autoSummarize) {
|
|
455
|
+
data.auto_summarize = true;
|
|
456
|
+
}
|
|
529
457
|
const result = await this.request("POST", "/api/retrieve/search", data, this.workspaceHeaders(params.workspaceId));
|
|
530
458
|
return {
|
|
531
459
|
matches: result.matches.map((m) => {
|
|
@@ -563,7 +491,13 @@ class RaySurfer {
|
|
|
563
491
|
dependencies: normalizeDependencies(m.dependencies),
|
|
564
492
|
agentId: m.agent_id ?? null,
|
|
565
493
|
comments: m.comments ?? [],
|
|
566
|
-
functions
|
|
494
|
+
functions,
|
|
495
|
+
type: m.type ?? "file",
|
|
496
|
+
downloadUrl: m.download_url ?? null,
|
|
497
|
+
fileTree: m.file_tree ?? null,
|
|
498
|
+
fileCount: m.file_count ?? null,
|
|
499
|
+
framework: m.framework ?? null,
|
|
500
|
+
readmePreview: m.readme_preview ?? null
|
|
567
501
|
};
|
|
568
502
|
}),
|
|
569
503
|
totalFound: result.total_found,
|
|
@@ -716,7 +650,7 @@ class RaySurfer {
|
|
|
716
650
|
|
|
717
651
|
## IMPORTANT: Pre-validated Code Files Available
|
|
718
652
|
`,
|
|
719
|
-
|
|
653
|
+
`The following validated code has been retrieved from the cache. Use these files directly instead of regenerating code.
|
|
720
654
|
`
|
|
721
655
|
];
|
|
722
656
|
for (const f of files) {
|
|
@@ -851,6 +785,35 @@ class RaySurfer {
|
|
|
851
785
|
hasMore: response.has_more
|
|
852
786
|
};
|
|
853
787
|
}
|
|
788
|
+
async log(params) {
|
|
789
|
+
const response = await this.request("POST", "/api/logs/ingest", {
|
|
790
|
+
log_hash: params.logHash,
|
|
791
|
+
value: params.value,
|
|
792
|
+
source: params.source ?? "",
|
|
793
|
+
scope: params.scope ?? "",
|
|
794
|
+
run_id: params.runId ?? "",
|
|
795
|
+
metadata: params.metadata ?? {}
|
|
796
|
+
});
|
|
797
|
+
return response.log_hash;
|
|
798
|
+
}
|
|
799
|
+
async getLog(logHash, limit = 50) {
|
|
800
|
+
const response = await this.request("GET", `/api/logs/hash/${logHash}`, { limit });
|
|
801
|
+
return {
|
|
802
|
+
logHash: response.log_hash,
|
|
803
|
+
source: response.source,
|
|
804
|
+
totalEvents: response.total_events,
|
|
805
|
+
recentEvents: response.recent_events.map((e) => ({
|
|
806
|
+
id: e.id,
|
|
807
|
+
logHash: e.log_hash,
|
|
808
|
+
source: e.source,
|
|
809
|
+
value: e.value,
|
|
810
|
+
preview: e.preview,
|
|
811
|
+
runId: e.run_id,
|
|
812
|
+
metadata: e.metadata,
|
|
813
|
+
loggedAt: e.logged_at
|
|
814
|
+
}))
|
|
815
|
+
};
|
|
816
|
+
}
|
|
854
817
|
async voteCodeSnip(params) {
|
|
855
818
|
const data = {
|
|
856
819
|
task: params.task,
|
|
@@ -1067,6 +1030,35 @@ class RaySurfer {
|
|
|
1067
1030
|
codegen
|
|
1068
1031
|
});
|
|
1069
1032
|
}
|
|
1033
|
+
async chat(query, options) {
|
|
1034
|
+
const response = await this.request("POST", "/api/agent-chat", {
|
|
1035
|
+
user_query: query,
|
|
1036
|
+
user_id: options.user,
|
|
1037
|
+
org_id: options.org,
|
|
1038
|
+
model: options.model ?? "sonnet",
|
|
1039
|
+
max_turns: options.maxTurns ?? 8
|
|
1040
|
+
});
|
|
1041
|
+
return {
|
|
1042
|
+
success: response.success,
|
|
1043
|
+
output: response.output,
|
|
1044
|
+
error: response.error,
|
|
1045
|
+
sessionId: response.session_id,
|
|
1046
|
+
durationMs: response.duration_ms,
|
|
1047
|
+
changedFiles: response.changed_files ?? [],
|
|
1048
|
+
workspaceFiles: response.org_workspace_files ?? []
|
|
1049
|
+
};
|
|
1050
|
+
}
|
|
1051
|
+
async heartbeat(options) {
|
|
1052
|
+
return this.request("POST", "/api/agents/heartbeat", {
|
|
1053
|
+
agent_id: options.agentId,
|
|
1054
|
+
agent_name: options.agentName,
|
|
1055
|
+
status: options.status ?? "running",
|
|
1056
|
+
current_task: options.currentTask,
|
|
1057
|
+
cpu_percent: options.cpuPercent,
|
|
1058
|
+
memory_percent: options.memoryPercent,
|
|
1059
|
+
metadata: options.metadata
|
|
1060
|
+
});
|
|
1061
|
+
}
|
|
1070
1062
|
async publishFunctionRegistry(functions) {
|
|
1071
1063
|
const snippetNames = [];
|
|
1072
1064
|
for (const fn of functions) {
|
|
@@ -1115,52 +1107,732 @@ class RaySurfer {
|
|
|
1115
1107
|
};
|
|
1116
1108
|
}
|
|
1117
1109
|
}
|
|
1118
|
-
var
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
function missingCodegenKeyError(value) {
|
|
1125
|
-
return new Error(`Invalid codegenApiKey value: ${String(value)}. Expected format: non-empty provider API key string. ` + "Current tier/state: tier=unknown, codegen_api_key_missing=true (not configured on app and not provided at call-time). " + `Fix: pass codegenApiKey in app config or run(...). Docs: ${CODEGEN_DOCS_URL}`);
|
|
1126
|
-
}
|
|
1127
|
-
function invalidCodegenPromptError(value) {
|
|
1128
|
-
return new Error(`Invalid codegenPrompt value: ${String(value)}. Expected format: non-empty prompt string. ` + "Current tier/state: tier=unknown, codegen_prompt_invalid=true. " + `Fix: pass codegenPrompt or provide a non-empty task. Docs: ${CODEGEN_DOCS_URL}`);
|
|
1129
|
-
}
|
|
1110
|
+
var VERSION = "1.4.3", DEFAULT_BASE_URL = "https://api.raysurfer.com", MAX_RETRIES = 3, RETRY_BASE_DELAY = 500, RETRYABLE_STATUS_CODES, client_default;
|
|
1111
|
+
var init_client = __esm(() => {
|
|
1112
|
+
init_errors();
|
|
1113
|
+
RETRYABLE_STATUS_CODES = new Set([429, 500, 502, 503, 504]);
|
|
1114
|
+
client_default = RaySurfer;
|
|
1115
|
+
});
|
|
1130
1116
|
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1117
|
+
// src/sdk-client.ts
|
|
1118
|
+
var exports_sdk_client = {};
|
|
1119
|
+
__export(exports_sdk_client, {
|
|
1120
|
+
query: () => query,
|
|
1121
|
+
default: () => sdk_client_default,
|
|
1122
|
+
RaysurferOpencodeClient: () => ClaudeSDKClient,
|
|
1123
|
+
RaysurferClient: () => ClaudeSDKClient,
|
|
1124
|
+
ClaudeSDKClient: () => ClaudeSDKClient
|
|
1125
|
+
});
|
|
1126
|
+
import { existsSync, mkdirSync, readFileSync as readFileSync2, writeFileSync } from "node:fs";
|
|
1127
|
+
import { join } from "node:path";
|
|
1128
|
+
function resolveRunParseSampleRate(configured) {
|
|
1129
|
+
if (configured !== undefined) {
|
|
1130
|
+
if (!Number.isFinite(configured) || configured < 0 || configured > 1) {
|
|
1131
|
+
throw new Error(`runParseSampleRate must be between 0.0 and 1.0 inclusive; got ${configured}.`);
|
|
1132
|
+
}
|
|
1133
|
+
return configured;
|
|
1148
1134
|
}
|
|
1149
|
-
|
|
1150
|
-
|
|
1135
|
+
const envValue = process.env[RUN_PARSE_SAMPLE_RATE_ENV_VAR];
|
|
1136
|
+
if (!envValue || envValue.trim() === "") {
|
|
1137
|
+
return DEFAULT_RUN_PARSE_SAMPLE_RATE;
|
|
1151
1138
|
}
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1139
|
+
const parsed = Number(envValue);
|
|
1140
|
+
if (!Number.isFinite(parsed) || parsed < 0 || parsed > 1) {
|
|
1141
|
+
console.warn(`[raysurfer] ${RUN_PARSE_SAMPLE_RATE_ENV_VAR}=${JSON.stringify(envValue)} is invalid. ` + `Expected a number between 0.0 and 1.0 inclusive. Falling back to ${DEFAULT_RUN_PARSE_SAMPLE_RATE}.`);
|
|
1142
|
+
return DEFAULT_RUN_PARSE_SAMPLE_RATE;
|
|
1155
1143
|
}
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1144
|
+
return parsed;
|
|
1145
|
+
}
|
|
1146
|
+
function shouldParseRunForAiVoting(sampleRate) {
|
|
1147
|
+
if (sampleRate >= 1)
|
|
1148
|
+
return true;
|
|
1149
|
+
if (sampleRate <= 0)
|
|
1150
|
+
return false;
|
|
1151
|
+
return Math.random() < sampleRate;
|
|
1152
|
+
}
|
|
1153
|
+
function augmentSystemPrompt(systemPrompt, addition) {
|
|
1154
|
+
if (!addition)
|
|
1155
|
+
return systemPrompt;
|
|
1156
|
+
if (typeof systemPrompt === "string")
|
|
1157
|
+
return systemPrompt + addition;
|
|
1158
|
+
if (systemPrompt?.type === "preset") {
|
|
1159
|
+
return { ...systemPrompt, append: (systemPrompt.append ?? "") + addition };
|
|
1160
|
+
}
|
|
1161
|
+
return addition;
|
|
1162
|
+
}
|
|
1163
|
+
function splitOptions(options) {
|
|
1164
|
+
const {
|
|
1165
|
+
workspaceId,
|
|
1166
|
+
publicSnips,
|
|
1167
|
+
debug,
|
|
1168
|
+
runParseSampleRate,
|
|
1169
|
+
workingDirectory,
|
|
1170
|
+
agentId,
|
|
1171
|
+
...sdkOptions
|
|
1172
|
+
} = options;
|
|
1173
|
+
return {
|
|
1174
|
+
sdkOptions,
|
|
1175
|
+
extras: {
|
|
1176
|
+
workspaceId,
|
|
1177
|
+
publicSnips,
|
|
1178
|
+
debug,
|
|
1179
|
+
runParseSampleRate,
|
|
1180
|
+
workingDirectory,
|
|
1181
|
+
agentId
|
|
1182
|
+
}
|
|
1183
|
+
};
|
|
1184
|
+
}
|
|
1185
|
+
function applyDefaultAgentCompatibilityOptions(options) {
|
|
1186
|
+
const merged = { ...options };
|
|
1187
|
+
const hasToolsPreset = merged.tools !== undefined && merged.tools !== null;
|
|
1188
|
+
const hasAllowedTools = Array.isArray(merged.allowedTools) && merged.allowedTools.length > 0;
|
|
1189
|
+
if (!hasToolsPreset && !hasAllowedTools) {
|
|
1190
|
+
merged.tools = DEFAULT_AGENT_COMPAT_TOOLS_PRESET;
|
|
1191
|
+
}
|
|
1192
|
+
if (merged.sandbox && typeof merged.sandbox === "object") {
|
|
1193
|
+
merged.sandbox = {
|
|
1194
|
+
...DEFAULT_SANDBOX_SETTINGS,
|
|
1195
|
+
...merged.sandbox
|
|
1196
|
+
};
|
|
1197
|
+
} else {
|
|
1198
|
+
merged.sandbox = { ...DEFAULT_SANDBOX_SETTINGS };
|
|
1199
|
+
}
|
|
1200
|
+
return merged;
|
|
1201
|
+
}
|
|
1202
|
+
function query(params) {
|
|
1203
|
+
return new RaysurferQuery(params);
|
|
1204
|
+
}
|
|
1205
|
+
|
|
1206
|
+
class ClaudeSDKClient {
|
|
1207
|
+
options;
|
|
1208
|
+
constructor(options = {}) {
|
|
1209
|
+
this.options = options;
|
|
1210
|
+
}
|
|
1211
|
+
query(prompt) {
|
|
1212
|
+
return query({ prompt, options: this.options });
|
|
1213
|
+
}
|
|
1214
|
+
}
|
|
1215
|
+
var DEFAULT_RAYSURFER_URL = "https://api.raysurfer.com", CACHE_DIR = ".raysurfer_code", DEFAULT_RUN_PARSE_SAMPLE_RATE = 1, RUN_PARSE_SAMPLE_RATE_ENV_VAR = "RAYSURFER_RUN_PARSE_SAMPLE_RATE", DEFAULT_AGENT_COMPAT_TOOLS_PRESET, DEFAULT_SANDBOX_SETTINGS, FILE_MODIFY_TOOLS, TRACKABLE_EXTENSIONS, BASH_OUTPUT_PATTERNS, createDebugLogger = (enabled) => ({
|
|
1216
|
+
log: (...args) => enabled && console.log("[raysurfer]", ...args),
|
|
1217
|
+
time: (label) => enabled && console.time(`[raysurfer] ${label}`),
|
|
1218
|
+
timeEnd: (label) => enabled && console.timeEnd(`[raysurfer] ${label}`),
|
|
1219
|
+
table: (data) => enabled && console.table(data),
|
|
1220
|
+
group: (label) => enabled && console.group(`[raysurfer] ${label}`),
|
|
1221
|
+
groupEnd: () => enabled && console.groupEnd()
|
|
1222
|
+
}), RaysurferQuery, sdk_client_default;
|
|
1223
|
+
var init_sdk_client = __esm(() => {
|
|
1224
|
+
init_client();
|
|
1225
|
+
DEFAULT_AGENT_COMPAT_TOOLS_PRESET = {
|
|
1226
|
+
type: "preset",
|
|
1227
|
+
preset: "claude_code"
|
|
1228
|
+
};
|
|
1229
|
+
DEFAULT_SANDBOX_SETTINGS = {
|
|
1230
|
+
enabled: true,
|
|
1231
|
+
autoAllowBashIfSandboxed: true
|
|
1232
|
+
};
|
|
1233
|
+
FILE_MODIFY_TOOLS = ["Write", "Edit", "MultiEdit", "NotebookEdit"];
|
|
1234
|
+
TRACKABLE_EXTENSIONS = new Set([
|
|
1235
|
+
".py",
|
|
1236
|
+
".js",
|
|
1237
|
+
".ts",
|
|
1238
|
+
".rb",
|
|
1239
|
+
".go",
|
|
1240
|
+
".rs",
|
|
1241
|
+
".java",
|
|
1242
|
+
".cpp",
|
|
1243
|
+
".c",
|
|
1244
|
+
".h",
|
|
1245
|
+
".pdf",
|
|
1246
|
+
".docx",
|
|
1247
|
+
".xlsx",
|
|
1248
|
+
".csv",
|
|
1249
|
+
".json",
|
|
1250
|
+
".yaml",
|
|
1251
|
+
".yml",
|
|
1252
|
+
".xml",
|
|
1253
|
+
".html",
|
|
1254
|
+
".css",
|
|
1255
|
+
".md",
|
|
1256
|
+
".txt",
|
|
1257
|
+
".sh",
|
|
1258
|
+
".sql"
|
|
1259
|
+
]);
|
|
1260
|
+
BASH_OUTPUT_PATTERNS = [
|
|
1261
|
+
/>>\s*([^\s;&|]+)/g,
|
|
1262
|
+
/>\s*([^\s;&|]+)/g,
|
|
1263
|
+
/-o\s+([^\s;&|]+)/g,
|
|
1264
|
+
/--output[=\s]+([^\s;&|]+)/g,
|
|
1265
|
+
/savefig\(['"]([^'"]+)['"]\)/g,
|
|
1266
|
+
/to_csv\(['"]([^'"]+)['"]\)/g,
|
|
1267
|
+
/to_excel\(['"]([^'"]+)['"]\)/g,
|
|
1268
|
+
/write\(['"]([^'"]+)['"]\)/g
|
|
1269
|
+
];
|
|
1270
|
+
RaysurferQuery = class RaysurferQuery {
|
|
1271
|
+
_inner = null;
|
|
1272
|
+
_initPromise = null;
|
|
1273
|
+
_raysurfer = null;
|
|
1274
|
+
_cachedFiles = [];
|
|
1275
|
+
_modifiedFilePaths = new Set;
|
|
1276
|
+
_bashGeneratedFiles = new Set;
|
|
1277
|
+
_executionLogs = [];
|
|
1278
|
+
_taskSucceeded = false;
|
|
1279
|
+
_generatedCodeBlocks = [];
|
|
1280
|
+
_cacheUploadDone = false;
|
|
1281
|
+
_messageCount = 0;
|
|
1282
|
+
_startTime = 0;
|
|
1283
|
+
_promptText;
|
|
1284
|
+
_params;
|
|
1285
|
+
_debug;
|
|
1286
|
+
_cacheEnabled;
|
|
1287
|
+
_workDir;
|
|
1288
|
+
_apiKey;
|
|
1289
|
+
_baseUrl;
|
|
1290
|
+
_extras;
|
|
1291
|
+
_sdkOptions;
|
|
1292
|
+
_runParseSampleRate;
|
|
1293
|
+
_parseRunForAiVoting;
|
|
1294
|
+
constructor(params) {
|
|
1295
|
+
this._params = params;
|
|
1296
|
+
const options = params.options ?? {};
|
|
1297
|
+
const { sdkOptions, extras } = splitOptions(options);
|
|
1298
|
+
this._sdkOptions = applyDefaultAgentCompatibilityOptions(sdkOptions);
|
|
1299
|
+
this._extras = extras;
|
|
1300
|
+
this._promptText = typeof params.prompt === "string" ? params.prompt : null;
|
|
1301
|
+
const debugEnabled = extras.debug || process.env.RAYSURFER_DEBUG === "true";
|
|
1302
|
+
this._debug = createDebugLogger(debugEnabled);
|
|
1303
|
+
this._apiKey = process.env.RAYSURFER_API_KEY;
|
|
1304
|
+
this._baseUrl = process.env.RAYSURFER_BASE_URL || DEFAULT_RAYSURFER_URL;
|
|
1305
|
+
this._cacheEnabled = !!this._apiKey;
|
|
1306
|
+
this._runParseSampleRate = resolveRunParseSampleRate(extras.runParseSampleRate);
|
|
1307
|
+
this._parseRunForAiVoting = shouldParseRunForAiVoting(this._runParseSampleRate);
|
|
1308
|
+
if (extras.workingDirectory && !sdkOptions.cwd) {
|
|
1309
|
+
console.warn("[raysurfer] workingDirectory is deprecated, use cwd instead");
|
|
1310
|
+
this._sdkOptions.cwd = extras.workingDirectory;
|
|
1311
|
+
}
|
|
1312
|
+
this._workDir = this._sdkOptions.cwd || process.cwd();
|
|
1313
|
+
}
|
|
1314
|
+
async _initialize() {
|
|
1315
|
+
this._debug.group("Raysurfer Query Started");
|
|
1316
|
+
this._debug.log("Prompt:", this._promptText ?? "<stream>");
|
|
1317
|
+
this._debug.log("Cache enabled:", this._cacheEnabled);
|
|
1318
|
+
this._debug.log("Base URL:", this._baseUrl);
|
|
1319
|
+
this._debug.log("Run parse sample rate:", this._runParseSampleRate);
|
|
1320
|
+
this._debug.log("Parse this run for AI voting:", this._parseRunForAiVoting);
|
|
1321
|
+
if (!this._cacheEnabled) {
|
|
1322
|
+
console.warn("[raysurfer] RAYSURFER_API_KEY not set - caching disabled");
|
|
1323
|
+
}
|
|
1324
|
+
let addToLlmPrompt = "";
|
|
1325
|
+
if (this._cacheEnabled && this._promptText) {
|
|
1326
|
+
this._raysurfer = new RaySurfer({
|
|
1327
|
+
apiKey: this._apiKey,
|
|
1328
|
+
baseUrl: this._baseUrl,
|
|
1329
|
+
workspaceId: this._extras.workspaceId,
|
|
1330
|
+
snipsDesired: this._extras.workspaceId ? "client" : undefined,
|
|
1331
|
+
publicSnips: this._extras.publicSnips,
|
|
1332
|
+
agentId: this._extras.agentId
|
|
1333
|
+
});
|
|
1334
|
+
try {
|
|
1335
|
+
this._debug.time("Cache lookup");
|
|
1336
|
+
const cacheDir = join(this._workDir, CACHE_DIR);
|
|
1337
|
+
const response = await this._raysurfer.getCodeFiles({
|
|
1338
|
+
task: this._promptText,
|
|
1339
|
+
topK: 5,
|
|
1340
|
+
minVerdictScore: 0.3,
|
|
1341
|
+
preferComplete: true,
|
|
1342
|
+
perFunctionReputation: true,
|
|
1343
|
+
cacheDir
|
|
1344
|
+
});
|
|
1345
|
+
this._debug.timeEnd("Cache lookup");
|
|
1346
|
+
this._cachedFiles = response.files;
|
|
1347
|
+
addToLlmPrompt = response.addToLlmPrompt;
|
|
1348
|
+
this._debug.log(`Found ${this._cachedFiles.length} cached files:`);
|
|
1349
|
+
console.log("[raysurfer] Cache hit:", this._cachedFiles.length, "snippets retrieved");
|
|
1350
|
+
if (this._cachedFiles.length > 0) {
|
|
1351
|
+
this._debug.table(this._cachedFiles.map((f) => ({
|
|
1352
|
+
filename: f.filename,
|
|
1353
|
+
score: `${Math.round(f.score * 100)}%`,
|
|
1354
|
+
thumbs: `${f.thumbsUp}/${f.thumbsDown}`,
|
|
1355
|
+
sourceLength: `${f.source.length} chars`
|
|
1356
|
+
})));
|
|
1357
|
+
try {
|
|
1358
|
+
mkdirSync(cacheDir, { recursive: true });
|
|
1359
|
+
for (const file of this._cachedFiles) {
|
|
1360
|
+
const filePath = join(cacheDir, file.filename);
|
|
1361
|
+
writeFileSync(filePath, file.source, "utf-8");
|
|
1362
|
+
this._debug.log(` → Wrote cached file: ${filePath}`);
|
|
1363
|
+
this._modifiedFilePaths.add(filePath);
|
|
1364
|
+
}
|
|
1365
|
+
} catch (writeErr) {
|
|
1366
|
+
this._debug.log("Failed to write cached files:", writeErr instanceof Error ? writeErr : String(writeErr));
|
|
1367
|
+
}
|
|
1368
|
+
}
|
|
1369
|
+
} catch (error) {
|
|
1370
|
+
const errMsg = error instanceof Error ? error.message : String(error);
|
|
1371
|
+
this._debug.log("Cache lookup failed:", errMsg);
|
|
1372
|
+
console.warn("[raysurfer] Cache unavailable:", errMsg);
|
|
1373
|
+
}
|
|
1374
|
+
}
|
|
1375
|
+
const augmented = augmentSystemPrompt(this._sdkOptions.systemPrompt, addToLlmPrompt);
|
|
1376
|
+
const augmentedOptions = {
|
|
1377
|
+
...this._sdkOptions,
|
|
1378
|
+
systemPrompt: augmented
|
|
1379
|
+
};
|
|
1380
|
+
this._debug.log("Augmented prompt addition:", addToLlmPrompt.length, "chars");
|
|
1381
|
+
let sdkQueryFn;
|
|
1382
|
+
try {
|
|
1383
|
+
const sdk = await import("@anthropic-ai/claude-agent-sdk");
|
|
1384
|
+
sdkQueryFn = sdk.query;
|
|
1385
|
+
} catch {
|
|
1386
|
+
throw new Error("Could not import @anthropic-ai/claude-agent-sdk. Install it with: npm install @anthropic-ai/claude-agent-sdk");
|
|
1387
|
+
}
|
|
1388
|
+
this._debug.time("Claude API call");
|
|
1389
|
+
this._debug.log("Calling Claude Agent SDK...");
|
|
1390
|
+
this._startTime = Date.now();
|
|
1391
|
+
this._inner = sdkQueryFn({
|
|
1392
|
+
prompt: this._params.prompt,
|
|
1393
|
+
options: augmentedOptions
|
|
1394
|
+
});
|
|
1395
|
+
}
|
|
1396
|
+
async _ensureInit() {
|
|
1397
|
+
if (!this._inner) {
|
|
1398
|
+
if (!this._initPromise) {
|
|
1399
|
+
this._initPromise = this._initialize();
|
|
1400
|
+
}
|
|
1401
|
+
await this._initPromise;
|
|
1402
|
+
}
|
|
1403
|
+
return this._inner;
|
|
1404
|
+
}
|
|
1405
|
+
_extractBashOutputFiles(command) {
|
|
1406
|
+
for (const pattern of BASH_OUTPUT_PATTERNS) {
|
|
1407
|
+
pattern.lastIndex = 0;
|
|
1408
|
+
let match = pattern.exec(command);
|
|
1409
|
+
while (match !== null) {
|
|
1410
|
+
const filePath = match[1];
|
|
1411
|
+
if (filePath && filePath.length > 0) {
|
|
1412
|
+
const ext = filePath.substring(filePath.lastIndexOf(".")).toLowerCase();
|
|
1413
|
+
if (TRACKABLE_EXTENSIONS.has(ext)) {
|
|
1414
|
+
this._bashGeneratedFiles.add(filePath);
|
|
1415
|
+
this._debug.log(` → Bash output file detected: ${filePath}`);
|
|
1416
|
+
}
|
|
1417
|
+
}
|
|
1418
|
+
match = pattern.exec(command);
|
|
1419
|
+
}
|
|
1420
|
+
}
|
|
1421
|
+
}
|
|
1422
|
+
_trackMessage(message) {
|
|
1423
|
+
this._messageCount++;
|
|
1424
|
+
const msg = message;
|
|
1425
|
+
const elapsed = Date.now() - this._startTime;
|
|
1426
|
+
this._debug.log(`
|
|
1427
|
+
═══════════════════════════════════════════════════`);
|
|
1428
|
+
this._debug.log(`Message #${this._messageCount} [${elapsed}ms] type=${msg.type} subtype=${msg.subtype ?? "none"}`);
|
|
1429
|
+
this._debug.log(`═══════════════════════════════════════════════════`);
|
|
1430
|
+
this._debug.log(JSON.stringify(msg, null, 2));
|
|
1431
|
+
if (msg.type === "assistant" && msg.message?.content) {
|
|
1432
|
+
const blocks = msg.message.content;
|
|
1433
|
+
for (const block of blocks) {
|
|
1434
|
+
if (block.type === "tool_use" && block.name && FILE_MODIFY_TOOLS.includes(block.name)) {
|
|
1435
|
+
const filePath = block.input?.file_path ?? block.input?.notebook_path;
|
|
1436
|
+
if (filePath) {
|
|
1437
|
+
this._debug.log(` → ${block.name} tool detected:`, filePath);
|
|
1438
|
+
this._modifiedFilePaths.add(filePath);
|
|
1439
|
+
}
|
|
1440
|
+
}
|
|
1441
|
+
if (block.type === "tool_use" && block.name === "Bash") {
|
|
1442
|
+
const command = block.input?.command;
|
|
1443
|
+
if (command) {
|
|
1444
|
+
this._extractBashOutputFiles(command);
|
|
1445
|
+
}
|
|
1446
|
+
}
|
|
1447
|
+
if (block.type === "tool_result" && block.content) {
|
|
1448
|
+
if (this._parseRunForAiVoting) {
|
|
1449
|
+
this._executionLogs.push(block.content.slice(0, 5000));
|
|
1450
|
+
}
|
|
1451
|
+
}
|
|
1452
|
+
if (block.type === "text" && block.text) {
|
|
1453
|
+
const codeMatches = block.text.match(/```(?:typescript|javascript|ts|js)?\n?([\s\S]*?)\n?```/g);
|
|
1454
|
+
if (codeMatches) {
|
|
1455
|
+
for (const match of codeMatches) {
|
|
1456
|
+
const code = match.replace(/```(?:typescript|javascript|ts|js)?\n?/, "").replace(/\n?```$/, "");
|
|
1457
|
+
if (code.trim().length > 50) {
|
|
1458
|
+
this._generatedCodeBlocks.push(code.trim());
|
|
1459
|
+
this._debug.log(` → Extracted code block (${code.length} chars)`);
|
|
1460
|
+
}
|
|
1461
|
+
}
|
|
1462
|
+
}
|
|
1463
|
+
}
|
|
1464
|
+
}
|
|
1465
|
+
}
|
|
1466
|
+
if (msg.type === "result" && msg.subtype === "success") {
|
|
1467
|
+
this._taskSucceeded = true;
|
|
1468
|
+
this._debug.timeEnd("Claude API call");
|
|
1469
|
+
this._debug.log("Task succeeded!");
|
|
1470
|
+
this._debug.log(" Duration:", msg.duration_ms, "ms");
|
|
1471
|
+
this._debug.log(" Total cost:", msg.total_cost_usd, "USD");
|
|
1472
|
+
this._debug.log(" Turns:", msg.num_turns);
|
|
1473
|
+
}
|
|
1474
|
+
if (msg.type === "result" && msg.subtype !== "success") {
|
|
1475
|
+
this._debug.timeEnd("Claude API call");
|
|
1476
|
+
this._debug.log("Task failed:", msg.subtype);
|
|
1477
|
+
}
|
|
1478
|
+
}
|
|
1479
|
+
async _uploadCache() {
|
|
1480
|
+
if (this._cacheUploadDone)
|
|
1481
|
+
return;
|
|
1482
|
+
this._cacheUploadDone = true;
|
|
1483
|
+
this._debug.log("Total messages streamed:", this._messageCount);
|
|
1484
|
+
this._debug.log("Modified files tracked:", this._modifiedFilePaths.size);
|
|
1485
|
+
this._debug.log("Code blocks extracted:", this._generatedCodeBlocks.length);
|
|
1486
|
+
const filesToCache = [];
|
|
1487
|
+
for (const filePath of this._modifiedFilePaths) {
|
|
1488
|
+
if (filePath.includes(CACHE_DIR)) {
|
|
1489
|
+
this._debug.log(" → Skipping cached file:", filePath);
|
|
1490
|
+
continue;
|
|
1491
|
+
}
|
|
1492
|
+
try {
|
|
1493
|
+
if (existsSync(filePath)) {
|
|
1494
|
+
const content = readFileSync2(filePath, "utf-8");
|
|
1495
|
+
if (content.includes("\x00")) {
|
|
1496
|
+
this._debug.log(" → Skipping binary file:", filePath);
|
|
1497
|
+
continue;
|
|
1498
|
+
}
|
|
1499
|
+
filesToCache.push({ path: filePath, content });
|
|
1500
|
+
this._debug.log(" → Will cache file:", filePath, `(${content.length} chars)`);
|
|
1501
|
+
} else {
|
|
1502
|
+
this._debug.log(" → File not found:", filePath);
|
|
1503
|
+
}
|
|
1504
|
+
} catch (err) {
|
|
1505
|
+
this._debug.log(" → Failed to read file:", filePath, err instanceof Error ? err : String(err));
|
|
1506
|
+
}
|
|
1507
|
+
}
|
|
1508
|
+
for (const filePath of this._bashGeneratedFiles) {
|
|
1509
|
+
if (this._modifiedFilePaths.has(filePath))
|
|
1510
|
+
continue;
|
|
1511
|
+
try {
|
|
1512
|
+
if (existsSync(filePath)) {
|
|
1513
|
+
const content = readFileSync2(filePath, "utf-8");
|
|
1514
|
+
if (!content.includes("\x00")) {
|
|
1515
|
+
filesToCache.push({ path: filePath, content });
|
|
1516
|
+
this._debug.log(" → Will cache Bash-generated file:", filePath, `(${content.length} chars)`);
|
|
1517
|
+
}
|
|
1518
|
+
}
|
|
1519
|
+
} catch {
|
|
1520
|
+
this._debug.log(" → Failed to read Bash-generated file:", filePath);
|
|
1521
|
+
}
|
|
1522
|
+
}
|
|
1523
|
+
if (this._generatedCodeBlocks.length > 0) {
|
|
1524
|
+
const largestBlock = this._generatedCodeBlocks.reduce((a, b) => a.length > b.length ? a : b);
|
|
1525
|
+
filesToCache.push({
|
|
1526
|
+
path: "generated-code.ts",
|
|
1527
|
+
content: largestBlock
|
|
1528
|
+
});
|
|
1529
|
+
this._debug.log(" → Will cache generated code block:", `(${largestBlock.length} chars)`);
|
|
1530
|
+
}
|
|
1531
|
+
this._debug.log("Total items to cache:", filesToCache.length);
|
|
1532
|
+
if (this._cacheEnabled && this._raysurfer && this._taskSucceeded && this._promptText) {
|
|
1533
|
+
const cachedBlocksForVoting = this._parseRunForAiVoting ? this._cachedFiles.map((f) => ({
|
|
1534
|
+
codeBlockId: f.codeBlockId,
|
|
1535
|
+
filename: f.filename,
|
|
1536
|
+
description: f.description
|
|
1537
|
+
})) : [];
|
|
1538
|
+
if (filesToCache.length > 0 || cachedBlocksForVoting.length > 0) {
|
|
1539
|
+
try {
|
|
1540
|
+
this._debug.time("Cache upload + voting");
|
|
1541
|
+
if (!this._parseRunForAiVoting) {
|
|
1542
|
+
this._debug.log("Skipping AI voting parse for this run due sampling");
|
|
1543
|
+
}
|
|
1544
|
+
const joinedLogs = this._parseRunForAiVoting && this._executionLogs.length > 0 ? this._executionLogs.join(`
|
|
1545
|
+
---
|
|
1546
|
+
`) : undefined;
|
|
1547
|
+
this._debug.log("Uploading", filesToCache.length, "files, voting for", cachedBlocksForVoting.length, "cached blocks,", this._executionLogs.length, "log entries...");
|
|
1548
|
+
for (const [i, file] of filesToCache.entries()) {
|
|
1549
|
+
await this._raysurfer.uploadNewCodeSnip({
|
|
1550
|
+
task: this._promptText,
|
|
1551
|
+
fileWritten: file,
|
|
1552
|
+
succeeded: true,
|
|
1553
|
+
cachedCodeBlocks: i === 0 && cachedBlocksForVoting.length > 0 ? cachedBlocksForVoting : undefined,
|
|
1554
|
+
useRaysurferAiVoting: this._parseRunForAiVoting,
|
|
1555
|
+
executionLogs: joinedLogs,
|
|
1556
|
+
perFunctionReputation: true
|
|
1557
|
+
});
|
|
1558
|
+
}
|
|
1559
|
+
if (filesToCache.length === 0 && cachedBlocksForVoting.length > 0) {
|
|
1560
|
+
for (const cb of cachedBlocksForVoting) {
|
|
1561
|
+
await this._raysurfer.voteCodeSnip({
|
|
1562
|
+
task: this._promptText,
|
|
1563
|
+
codeBlockId: cb.codeBlockId,
|
|
1564
|
+
codeBlockName: cb.filename,
|
|
1565
|
+
codeBlockDescription: cb.description,
|
|
1566
|
+
succeeded: true
|
|
1567
|
+
});
|
|
1568
|
+
}
|
|
1569
|
+
}
|
|
1570
|
+
this._debug.timeEnd("Cache upload + voting");
|
|
1571
|
+
this._debug.log("Cache upload successful, voting queued on backend");
|
|
1572
|
+
console.log("[raysurfer] Cache upload successful:", filesToCache.length, "files stored");
|
|
1573
|
+
} catch (error) {
|
|
1574
|
+
const errMsg = error instanceof Error ? error.message : String(error);
|
|
1575
|
+
this._debug.log("Cache upload failed:", errMsg);
|
|
1576
|
+
console.warn("[raysurfer] Cache upload failed:", errMsg);
|
|
1577
|
+
}
|
|
1578
|
+
}
|
|
1579
|
+
}
|
|
1580
|
+
this._debug.groupEnd();
|
|
1581
|
+
}
|
|
1582
|
+
async next(...args) {
|
|
1583
|
+
const inner = await this._ensureInit();
|
|
1584
|
+
const result = await inner.next(...args);
|
|
1585
|
+
if (!result.done) {
|
|
1586
|
+
this._trackMessage(result.value);
|
|
1587
|
+
} else {
|
|
1588
|
+
await this._uploadCache();
|
|
1589
|
+
}
|
|
1590
|
+
return result;
|
|
1591
|
+
}
|
|
1592
|
+
async return(value) {
|
|
1593
|
+
if (this._inner) {
|
|
1594
|
+
await this._uploadCache();
|
|
1595
|
+
return this._inner.return(value);
|
|
1596
|
+
}
|
|
1597
|
+
return { done: true, value: undefined };
|
|
1598
|
+
}
|
|
1599
|
+
async throw(e) {
|
|
1600
|
+
if (this._inner)
|
|
1601
|
+
return this._inner.throw(e);
|
|
1602
|
+
throw e;
|
|
1603
|
+
}
|
|
1604
|
+
[Symbol.asyncIterator]() {
|
|
1605
|
+
return this;
|
|
1606
|
+
}
|
|
1607
|
+
async[Symbol.asyncDispose]() {
|
|
1608
|
+
this.close();
|
|
1609
|
+
}
|
|
1610
|
+
async interrupt() {
|
|
1611
|
+
return (await this._ensureInit()).interrupt();
|
|
1612
|
+
}
|
|
1613
|
+
async setPermissionMode(mode) {
|
|
1614
|
+
return (await this._ensureInit()).setPermissionMode(mode);
|
|
1615
|
+
}
|
|
1616
|
+
async setModel(model) {
|
|
1617
|
+
return (await this._ensureInit()).setModel(model);
|
|
1618
|
+
}
|
|
1619
|
+
async setMaxThinkingTokens(maxThinkingTokens) {
|
|
1620
|
+
return (await this._ensureInit()).setMaxThinkingTokens(maxThinkingTokens);
|
|
1621
|
+
}
|
|
1622
|
+
async supportedCommands() {
|
|
1623
|
+
return (await this._ensureInit()).supportedCommands();
|
|
1624
|
+
}
|
|
1625
|
+
async supportedModels() {
|
|
1626
|
+
return (await this._ensureInit()).supportedModels();
|
|
1627
|
+
}
|
|
1628
|
+
async mcpServerStatus() {
|
|
1629
|
+
return (await this._ensureInit()).mcpServerStatus();
|
|
1630
|
+
}
|
|
1631
|
+
async accountInfo() {
|
|
1632
|
+
return (await this._ensureInit()).accountInfo();
|
|
1633
|
+
}
|
|
1634
|
+
async rewindFiles(userMessageId, options) {
|
|
1635
|
+
return (await this._ensureInit()).rewindFiles(userMessageId, options);
|
|
1636
|
+
}
|
|
1637
|
+
async setMcpServers(servers) {
|
|
1638
|
+
return (await this._ensureInit()).setMcpServers(servers);
|
|
1639
|
+
}
|
|
1640
|
+
async streamInput(stream) {
|
|
1641
|
+
return (await this._ensureInit()).streamInput(stream);
|
|
1642
|
+
}
|
|
1643
|
+
close() {
|
|
1644
|
+
if (this._inner)
|
|
1645
|
+
this._inner.close();
|
|
1646
|
+
}
|
|
1647
|
+
};
|
|
1648
|
+
sdk_client_default = query;
|
|
1649
|
+
});
|
|
1650
|
+
|
|
1651
|
+
// src/types.ts
|
|
1652
|
+
var ExecutionState;
|
|
1653
|
+
((ExecutionState2) => {
|
|
1654
|
+
ExecutionState2["COMPLETED"] = "completed";
|
|
1655
|
+
ExecutionState2["ERRORED"] = "errored";
|
|
1656
|
+
ExecutionState2["TIMED_OUT"] = "timed_out";
|
|
1657
|
+
ExecutionState2["CANCELLED"] = "cancelled";
|
|
1658
|
+
})(ExecutionState ||= {});
|
|
1659
|
+
var AgentVerdict;
|
|
1660
|
+
((AgentVerdict2) => {
|
|
1661
|
+
AgentVerdict2["THUMBS_UP"] = "thumbs_up";
|
|
1662
|
+
AgentVerdict2["THUMBS_DOWN"] = "thumbs_down";
|
|
1663
|
+
AgentVerdict2["PENDING"] = "pending";
|
|
1664
|
+
})(AgentVerdict ||= {});
|
|
1665
|
+
|
|
1666
|
+
// src/accessible.ts
|
|
1667
|
+
function toJsonLike(value) {
|
|
1668
|
+
if (value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
1669
|
+
return value;
|
|
1670
|
+
}
|
|
1671
|
+
if (value === undefined) {
|
|
1672
|
+
return null;
|
|
1673
|
+
}
|
|
1674
|
+
if (Array.isArray(value)) {
|
|
1675
|
+
return value.map((item) => toJsonLike(item));
|
|
1676
|
+
}
|
|
1677
|
+
if (typeof value === "object") {
|
|
1678
|
+
const result = {};
|
|
1679
|
+
for (const [key, nested] of Object.entries(value)) {
|
|
1680
|
+
result[key] = toJsonLike(nested);
|
|
1681
|
+
}
|
|
1682
|
+
return result;
|
|
1683
|
+
}
|
|
1684
|
+
return String(value);
|
|
1685
|
+
}
|
|
1686
|
+
function queueUsageTracking(fn, args, result, durationMs, errorMessage) {
|
|
1687
|
+
const client = fn._raysurferClient;
|
|
1688
|
+
if (!client)
|
|
1689
|
+
return;
|
|
1690
|
+
const codeBlockId = fn._raysurferSchema.codeBlockId ?? `function_registry:${fn._raysurferSchema.name}`;
|
|
1691
|
+
const outputData = errorMessage === undefined ? result : { error: errorMessage };
|
|
1692
|
+
client.storeExecution({
|
|
1693
|
+
codeBlockId,
|
|
1694
|
+
triggeringTask: `agent_accessible:${fn._raysurferSchema.name}`,
|
|
1695
|
+
inputData: {
|
|
1696
|
+
args: toJsonLike(args)
|
|
1697
|
+
},
|
|
1698
|
+
outputData: toJsonLike(outputData),
|
|
1699
|
+
executionState: errorMessage ? "errored" /* ERRORED */ : "completed" /* COMPLETED */,
|
|
1700
|
+
durationMs,
|
|
1701
|
+
errorMessage
|
|
1702
|
+
}).catch(() => {});
|
|
1703
|
+
}
|
|
1704
|
+
function inferParameters(fn) {
|
|
1705
|
+
const src = fn.toString();
|
|
1706
|
+
const match = /^[^(]*\(([^)]*)\)/.exec(src);
|
|
1707
|
+
const paramStr = match?.[1];
|
|
1708
|
+
if (!paramStr?.trim())
|
|
1709
|
+
return {};
|
|
1710
|
+
const params = {};
|
|
1711
|
+
const parts = paramStr.split(",");
|
|
1712
|
+
for (const part of parts) {
|
|
1713
|
+
const cleaned = part.trim().replace(/\/\*.*?\*\//g, "").replace(/=.*$/, "").replace(/:.*$/, "").trim();
|
|
1714
|
+
if (cleaned && cleaned !== "..." && !cleaned.startsWith("...")) {
|
|
1715
|
+
params[cleaned] = "string";
|
|
1716
|
+
}
|
|
1717
|
+
}
|
|
1718
|
+
return params;
|
|
1719
|
+
}
|
|
1720
|
+
function agentAccessible(fn, options) {
|
|
1721
|
+
const resolvedName = options?.name ?? fn.name ?? "anonymous";
|
|
1722
|
+
const resolvedDescription = options?.description ?? "";
|
|
1723
|
+
const resolvedSchema = options?.inputSchema ?? options?.parameters ?? inferParameters(fn);
|
|
1724
|
+
let marked;
|
|
1725
|
+
const wrapped = (...args) => {
|
|
1726
|
+
const started = Date.now();
|
|
1727
|
+
try {
|
|
1728
|
+
const result = fn(...args);
|
|
1729
|
+
if (result instanceof Promise) {
|
|
1730
|
+
const trackedPromise = result.then((resolved) => {
|
|
1731
|
+
queueUsageTracking(marked, args, resolved, Date.now() - started);
|
|
1732
|
+
return resolved;
|
|
1733
|
+
}).catch((error) => {
|
|
1734
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1735
|
+
queueUsageTracking(marked, args, null, Date.now() - started, message);
|
|
1736
|
+
throw error;
|
|
1737
|
+
});
|
|
1738
|
+
return trackedPromise;
|
|
1739
|
+
}
|
|
1740
|
+
queueUsageTracking(marked, args, result, Date.now() - started);
|
|
1741
|
+
return result;
|
|
1742
|
+
} catch (error) {
|
|
1743
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1744
|
+
queueUsageTracking(marked, args, null, Date.now() - started, message);
|
|
1745
|
+
throw error;
|
|
1746
|
+
}
|
|
1747
|
+
};
|
|
1748
|
+
marked = wrapped;
|
|
1749
|
+
marked._raysurferAccessible = true;
|
|
1750
|
+
marked._raysurferSchema = {
|
|
1751
|
+
name: resolvedName,
|
|
1752
|
+
description: resolvedDescription,
|
|
1753
|
+
inputSchema: resolvedSchema,
|
|
1754
|
+
parameters: resolvedSchema,
|
|
1755
|
+
source: fn.toString()
|
|
1756
|
+
};
|
|
1757
|
+
return marked;
|
|
1758
|
+
}
|
|
1759
|
+
function toAnthropicTool(fn) {
|
|
1760
|
+
const schema = fn._raysurferSchema;
|
|
1761
|
+
return {
|
|
1762
|
+
name: schema.name,
|
|
1763
|
+
description: schema.description,
|
|
1764
|
+
input_schema: schema.inputSchema
|
|
1765
|
+
};
|
|
1766
|
+
}
|
|
1767
|
+
async function publishFunctionRegistry(client, functions) {
|
|
1768
|
+
const snippetNames = [];
|
|
1769
|
+
for (const fn of functions) {
|
|
1770
|
+
if (!fn._raysurferAccessible)
|
|
1771
|
+
continue;
|
|
1772
|
+
const schema = fn._raysurferSchema;
|
|
1773
|
+
const resp = await client.uploadNewCodeSnip({
|
|
1774
|
+
task: `Call ${schema.name}: ${schema.description}`,
|
|
1775
|
+
fileWritten: { path: `${schema.name}.ts`, content: schema.source },
|
|
1776
|
+
succeeded: true,
|
|
1777
|
+
useRaysurferAiVoting: false,
|
|
1778
|
+
tags: ["function_registry", "agent_accessible"]
|
|
1779
|
+
});
|
|
1780
|
+
if (resp.snippetName) {
|
|
1781
|
+
snippetNames.push(resp.snippetName);
|
|
1782
|
+
schema.codeBlockId = resp.snippetName;
|
|
1783
|
+
}
|
|
1784
|
+
setTrackingClient(fn, client);
|
|
1785
|
+
}
|
|
1786
|
+
return snippetNames;
|
|
1787
|
+
}
|
|
1788
|
+
function setTrackingClient(fn, client) {
|
|
1789
|
+
fn._raysurferClient = client;
|
|
1790
|
+
}
|
|
1791
|
+
// src/agent.ts
|
|
1792
|
+
init_client();
|
|
1793
|
+
var DEFAULT_CODEGEN_MODEL = "claude-opus-4-6";
|
|
1794
|
+
var DEFAULT_EXECUTION_TIMEOUT_MS = 300000;
|
|
1795
|
+
var CODEGEN_DOCS_URL = "https://docs.raysurfer.com/sdk/typescript#programmatic-tool-calling";
|
|
1796
|
+
function missingCodegenKeyError(value) {
|
|
1797
|
+
return new Error(`Invalid codegenApiKey value: ${String(value)}. Expected format: non-empty provider API key string. ` + "Current tier/state: tier=unknown, codegen_api_key_missing=true (not configured on app and not provided at call-time). " + `Fix: pass codegenApiKey in app config or run(...). Docs: ${CODEGEN_DOCS_URL}`);
|
|
1798
|
+
}
|
|
1799
|
+
function invalidCodegenPromptError(value) {
|
|
1800
|
+
return new Error(`Invalid codegenPrompt value: ${String(value)}. Expected format: non-empty prompt string. ` + "Current tier/state: tier=unknown, codegen_prompt_invalid=true. " + `Fix: pass codegenPrompt or provide a non-empty task. Docs: ${CODEGEN_DOCS_URL}`);
|
|
1801
|
+
}
|
|
1802
|
+
|
|
1803
|
+
class CodegenApp {
|
|
1804
|
+
_raysurfer;
|
|
1805
|
+
_defaultCodegenApiKey;
|
|
1806
|
+
_defaultCodegenModel;
|
|
1807
|
+
_defaultExecutionTimeoutMs;
|
|
1808
|
+
constructor(options = {}) {
|
|
1809
|
+
const {
|
|
1810
|
+
raysurfer,
|
|
1811
|
+
codegenApiKey,
|
|
1812
|
+
codegenModel,
|
|
1813
|
+
executionTimeoutMs,
|
|
1814
|
+
...clientOptions
|
|
1815
|
+
} = options;
|
|
1816
|
+
this._raysurfer = raysurfer ?? new client_default(clientOptions);
|
|
1817
|
+
this._defaultCodegenApiKey = codegenApiKey;
|
|
1818
|
+
this._defaultCodegenModel = codegenModel ?? DEFAULT_CODEGEN_MODEL;
|
|
1819
|
+
this._defaultExecutionTimeoutMs = executionTimeoutMs ?? DEFAULT_EXECUTION_TIMEOUT_MS;
|
|
1820
|
+
}
|
|
1821
|
+
get raysurfer() {
|
|
1822
|
+
return this._raysurfer;
|
|
1823
|
+
}
|
|
1824
|
+
tool(name, description, parameters, callback) {
|
|
1825
|
+
this._raysurfer.tool(name, description, parameters, callback);
|
|
1826
|
+
return this;
|
|
1827
|
+
}
|
|
1828
|
+
async run(task, options = {}) {
|
|
1829
|
+
const codegenApiKey = this.resolveCodegenApiKey(options.codegenApiKey);
|
|
1830
|
+
const codegenPrompt = this.resolveCodegenPrompt(task, options.codegenPrompt);
|
|
1831
|
+
const codegenModel = options.codegenModel ?? this._defaultCodegenModel;
|
|
1832
|
+
const timeout = options.executionTimeoutMs ?? this._defaultExecutionTimeoutMs;
|
|
1833
|
+
return this._raysurfer.executeWithSandboxCodegen(task, {
|
|
1834
|
+
provider: "anthropic",
|
|
1835
|
+
apiKey: codegenApiKey,
|
|
1164
1836
|
prompt: codegenPrompt,
|
|
1165
1837
|
model: codegenModel
|
|
1166
1838
|
}, { timeout });
|
|
@@ -1190,6 +1862,10 @@ class CodegenApp {
|
|
|
1190
1862
|
throw invalidCodegenPromptError(value);
|
|
1191
1863
|
}
|
|
1192
1864
|
}
|
|
1865
|
+
|
|
1866
|
+
// src/index.ts
|
|
1867
|
+
init_client();
|
|
1868
|
+
|
|
1193
1869
|
// src/config.ts
|
|
1194
1870
|
import { readFileSync } from "node:fs";
|
|
1195
1871
|
function coerceStringList(value) {
|
|
@@ -1339,6 +2015,10 @@ function loadConfig(path, modules) {
|
|
|
1339
2015
|
}
|
|
1340
2016
|
return functions;
|
|
1341
2017
|
}
|
|
2018
|
+
|
|
2019
|
+
// src/index.ts
|
|
2020
|
+
init_errors();
|
|
2021
|
+
|
|
1342
2022
|
// src/logging.ts
|
|
1343
2023
|
var CAP = 1000;
|
|
1344
2024
|
var telemetry = new Map;
|
|
@@ -1685,535 +2365,83 @@ class ProgrammaticToolCallingSession {
|
|
|
1685
2365
|
}
|
|
1686
2366
|
}
|
|
1687
2367
|
}
|
|
1688
|
-
// src/
|
|
1689
|
-
|
|
1690
|
-
import { join } from "node:path";
|
|
1691
|
-
var DEFAULT_RAYSURFER_URL = "https://api.raysurfer.com";
|
|
1692
|
-
var CACHE_DIR = ".raysurfer_code";
|
|
1693
|
-
var DEFAULT_RUN_PARSE_SAMPLE_RATE = 1;
|
|
1694
|
-
var RUN_PARSE_SAMPLE_RATE_ENV_VAR = "RAYSURFER_RUN_PARSE_SAMPLE_RATE";
|
|
1695
|
-
var DEFAULT_AGENT_COMPAT_TOOLS_PRESET = {
|
|
1696
|
-
type: "preset",
|
|
1697
|
-
preset: "claude_code"
|
|
1698
|
-
};
|
|
1699
|
-
var DEFAULT_SANDBOX_SETTINGS = {
|
|
1700
|
-
enabled: true,
|
|
1701
|
-
autoAllowBashIfSandboxed: true
|
|
1702
|
-
};
|
|
1703
|
-
function resolveRunParseSampleRate(configured) {
|
|
1704
|
-
if (configured !== undefined) {
|
|
1705
|
-
if (!Number.isFinite(configured) || configured < 0 || configured > 1) {
|
|
1706
|
-
throw new Error(`runParseSampleRate must be between 0.0 and 1.0 inclusive; got ${configured}.`);
|
|
1707
|
-
}
|
|
1708
|
-
return configured;
|
|
1709
|
-
}
|
|
1710
|
-
const envValue = process.env[RUN_PARSE_SAMPLE_RATE_ENV_VAR];
|
|
1711
|
-
if (!envValue || envValue.trim() === "") {
|
|
1712
|
-
return DEFAULT_RUN_PARSE_SAMPLE_RATE;
|
|
1713
|
-
}
|
|
1714
|
-
const parsed = Number(envValue);
|
|
1715
|
-
if (!Number.isFinite(parsed) || parsed < 0 || parsed > 1) {
|
|
1716
|
-
console.warn(`[raysurfer] ${RUN_PARSE_SAMPLE_RATE_ENV_VAR}=${JSON.stringify(envValue)} is invalid. ` + `Expected a number between 0.0 and 1.0 inclusive. Falling back to ${DEFAULT_RUN_PARSE_SAMPLE_RATE}.`);
|
|
1717
|
-
return DEFAULT_RUN_PARSE_SAMPLE_RATE;
|
|
1718
|
-
}
|
|
1719
|
-
return parsed;
|
|
1720
|
-
}
|
|
1721
|
-
function shouldParseRunForAiVoting(sampleRate) {
|
|
1722
|
-
if (sampleRate >= 1)
|
|
1723
|
-
return true;
|
|
1724
|
-
if (sampleRate <= 0)
|
|
1725
|
-
return false;
|
|
1726
|
-
return Math.random() < sampleRate;
|
|
1727
|
-
}
|
|
1728
|
-
var FILE_MODIFY_TOOLS = ["Write", "Edit", "MultiEdit", "NotebookEdit"];
|
|
1729
|
-
var TRACKABLE_EXTENSIONS = new Set([
|
|
1730
|
-
".py",
|
|
1731
|
-
".js",
|
|
1732
|
-
".ts",
|
|
1733
|
-
".rb",
|
|
1734
|
-
".go",
|
|
1735
|
-
".rs",
|
|
1736
|
-
".java",
|
|
1737
|
-
".cpp",
|
|
1738
|
-
".c",
|
|
1739
|
-
".h",
|
|
1740
|
-
".pdf",
|
|
1741
|
-
".docx",
|
|
1742
|
-
".xlsx",
|
|
1743
|
-
".csv",
|
|
1744
|
-
".json",
|
|
1745
|
-
".yaml",
|
|
1746
|
-
".yml",
|
|
1747
|
-
".xml",
|
|
1748
|
-
".html",
|
|
1749
|
-
".css",
|
|
1750
|
-
".md",
|
|
1751
|
-
".txt",
|
|
1752
|
-
".sh",
|
|
1753
|
-
".sql"
|
|
1754
|
-
]);
|
|
1755
|
-
var BASH_OUTPUT_PATTERNS = [
|
|
1756
|
-
/>>\s*([^\s;&|]+)/g,
|
|
1757
|
-
/>\s*([^\s;&|]+)/g,
|
|
1758
|
-
/-o\s+([^\s;&|]+)/g,
|
|
1759
|
-
/--output[=\s]+([^\s;&|]+)/g,
|
|
1760
|
-
/savefig\(['"]([^'"]+)['"]\)/g,
|
|
1761
|
-
/to_csv\(['"]([^'"]+)['"]\)/g,
|
|
1762
|
-
/to_excel\(['"]([^'"]+)['"]\)/g,
|
|
1763
|
-
/write\(['"]([^'"]+)['"]\)/g
|
|
1764
|
-
];
|
|
1765
|
-
var createDebugLogger = (enabled) => ({
|
|
1766
|
-
log: (...args) => enabled && console.log("[raysurfer]", ...args),
|
|
1767
|
-
time: (label) => enabled && console.time(`[raysurfer] ${label}`),
|
|
1768
|
-
timeEnd: (label) => enabled && console.timeEnd(`[raysurfer] ${label}`),
|
|
1769
|
-
table: (data) => enabled && console.table(data),
|
|
1770
|
-
group: (label) => enabled && console.group(`[raysurfer] ${label}`),
|
|
1771
|
-
groupEnd: () => enabled && console.groupEnd()
|
|
1772
|
-
});
|
|
1773
|
-
function augmentSystemPrompt(systemPrompt, addition) {
|
|
1774
|
-
if (!addition)
|
|
1775
|
-
return systemPrompt;
|
|
1776
|
-
if (typeof systemPrompt === "string")
|
|
1777
|
-
return systemPrompt + addition;
|
|
1778
|
-
if (systemPrompt?.type === "preset") {
|
|
1779
|
-
return { ...systemPrompt, append: (systemPrompt.append ?? "") + addition };
|
|
1780
|
-
}
|
|
1781
|
-
return addition;
|
|
1782
|
-
}
|
|
1783
|
-
function splitOptions(options) {
|
|
1784
|
-
const {
|
|
1785
|
-
workspaceId,
|
|
1786
|
-
publicSnips,
|
|
1787
|
-
debug,
|
|
1788
|
-
runParseSampleRate,
|
|
1789
|
-
workingDirectory,
|
|
1790
|
-
agentId,
|
|
1791
|
-
...sdkOptions
|
|
1792
|
-
} = options;
|
|
1793
|
-
return {
|
|
1794
|
-
sdkOptions,
|
|
1795
|
-
extras: {
|
|
1796
|
-
workspaceId,
|
|
1797
|
-
publicSnips,
|
|
1798
|
-
debug,
|
|
1799
|
-
runParseSampleRate,
|
|
1800
|
-
workingDirectory,
|
|
1801
|
-
agentId
|
|
1802
|
-
}
|
|
1803
|
-
};
|
|
1804
|
-
}
|
|
1805
|
-
function applyDefaultAgentCompatibilityOptions(options) {
|
|
1806
|
-
const merged = { ...options };
|
|
1807
|
-
const hasToolsPreset = merged.tools !== undefined && merged.tools !== null;
|
|
1808
|
-
const hasAllowedTools = Array.isArray(merged.allowedTools) && merged.allowedTools.length > 0;
|
|
1809
|
-
if (!hasToolsPreset && !hasAllowedTools) {
|
|
1810
|
-
merged.tools = DEFAULT_AGENT_COMPAT_TOOLS_PRESET;
|
|
1811
|
-
}
|
|
1812
|
-
if (merged.sandbox && typeof merged.sandbox === "object") {
|
|
1813
|
-
merged.sandbox = {
|
|
1814
|
-
...DEFAULT_SANDBOX_SETTINGS,
|
|
1815
|
-
...merged.sandbox
|
|
1816
|
-
};
|
|
1817
|
-
} else {
|
|
1818
|
-
merged.sandbox = { ...DEFAULT_SANDBOX_SETTINGS };
|
|
1819
|
-
}
|
|
1820
|
-
return merged;
|
|
1821
|
-
}
|
|
2368
|
+
// src/runner.ts
|
|
2369
|
+
init_client();
|
|
1822
2370
|
|
|
1823
|
-
class
|
|
1824
|
-
_inner = null;
|
|
1825
|
-
_initPromise = null;
|
|
1826
|
-
_raysurfer = null;
|
|
1827
|
-
_cachedFiles = [];
|
|
1828
|
-
_modifiedFilePaths = new Set;
|
|
1829
|
-
_bashGeneratedFiles = new Set;
|
|
1830
|
-
_executionLogs = [];
|
|
1831
|
-
_taskSucceeded = false;
|
|
1832
|
-
_generatedCodeBlocks = [];
|
|
1833
|
-
_cacheUploadDone = false;
|
|
1834
|
-
_messageCount = 0;
|
|
1835
|
-
_startTime = 0;
|
|
1836
|
-
_promptText;
|
|
1837
|
-
_params;
|
|
1838
|
-
_debug;
|
|
1839
|
-
_cacheEnabled;
|
|
1840
|
-
_workDir;
|
|
2371
|
+
class Agent {
|
|
1841
2372
|
_apiKey;
|
|
1842
2373
|
_baseUrl;
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
this.
|
|
1852
|
-
this.
|
|
1853
|
-
this.
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
this.
|
|
1858
|
-
|
|
1859
|
-
this._runParseSampleRate = resolveRunParseSampleRate(extras.runParseSampleRate);
|
|
1860
|
-
this._parseRunForAiVoting = shouldParseRunForAiVoting(this._runParseSampleRate);
|
|
1861
|
-
if (extras.workingDirectory && !sdkOptions.cwd) {
|
|
1862
|
-
console.warn("[raysurfer] workingDirectory is deprecated, use cwd instead");
|
|
1863
|
-
this._sdkOptions.cwd = extras.workingDirectory;
|
|
1864
|
-
}
|
|
1865
|
-
this._workDir = this._sdkOptions.cwd || process.cwd();
|
|
1866
|
-
}
|
|
1867
|
-
async _initialize() {
|
|
1868
|
-
this._debug.group("Raysurfer Query Started");
|
|
1869
|
-
this._debug.log("Prompt:", this._promptText ?? "<stream>");
|
|
1870
|
-
this._debug.log("Cache enabled:", this._cacheEnabled);
|
|
1871
|
-
this._debug.log("Base URL:", this._baseUrl);
|
|
1872
|
-
this._debug.log("Run parse sample rate:", this._runParseSampleRate);
|
|
1873
|
-
this._debug.log("Parse this run for AI voting:", this._parseRunForAiVoting);
|
|
1874
|
-
if (!this._cacheEnabled) {
|
|
1875
|
-
console.warn("[raysurfer] RAYSURFER_API_KEY not set - caching disabled");
|
|
1876
|
-
}
|
|
1877
|
-
let addToLlmPrompt = "";
|
|
1878
|
-
if (this._cacheEnabled && this._promptText) {
|
|
1879
|
-
this._raysurfer = new RaySurfer({
|
|
2374
|
+
_agentId;
|
|
2375
|
+
_allowedTools;
|
|
2376
|
+
_systemPrompt;
|
|
2377
|
+
_model;
|
|
2378
|
+
_raysurfer;
|
|
2379
|
+
constructor(options = {}) {
|
|
2380
|
+
this._apiKey = options.apiKey;
|
|
2381
|
+
this._baseUrl = options.baseUrl;
|
|
2382
|
+
this._agentId = options.agentId;
|
|
2383
|
+
this._allowedTools = options.allowedTools ?? ["Read", "Write", "Bash"];
|
|
2384
|
+
this._systemPrompt = options.systemPrompt ?? "You are a helpful assistant.";
|
|
2385
|
+
this._model = options.model;
|
|
2386
|
+
}
|
|
2387
|
+
ensureClient(orgId) {
|
|
2388
|
+
if (!this._raysurfer || orgId) {
|
|
2389
|
+
this._raysurfer = new client_default({
|
|
1880
2390
|
apiKey: this._apiKey,
|
|
1881
2391
|
baseUrl: this._baseUrl,
|
|
1882
|
-
|
|
1883
|
-
snipsDesired:
|
|
1884
|
-
|
|
1885
|
-
agentId: this._extras.agentId
|
|
2392
|
+
organizationId: orgId,
|
|
2393
|
+
snipsDesired: orgId ? "company" : undefined,
|
|
2394
|
+
agentId: this._agentId
|
|
1886
2395
|
});
|
|
1887
|
-
try {
|
|
1888
|
-
this._debug.time("Cache lookup");
|
|
1889
|
-
const cacheDir = join(this._workDir, CACHE_DIR);
|
|
1890
|
-
const response = await this._raysurfer.getCodeFiles({
|
|
1891
|
-
task: this._promptText,
|
|
1892
|
-
topK: 5,
|
|
1893
|
-
minVerdictScore: 0.3,
|
|
1894
|
-
preferComplete: true,
|
|
1895
|
-
perFunctionReputation: true,
|
|
1896
|
-
cacheDir
|
|
1897
|
-
});
|
|
1898
|
-
this._debug.timeEnd("Cache lookup");
|
|
1899
|
-
this._cachedFiles = response.files;
|
|
1900
|
-
addToLlmPrompt = response.addToLlmPrompt;
|
|
1901
|
-
this._debug.log(`Found ${this._cachedFiles.length} cached files:`);
|
|
1902
|
-
console.log("[raysurfer] Cache hit:", this._cachedFiles.length, "snippets retrieved");
|
|
1903
|
-
if (this._cachedFiles.length > 0) {
|
|
1904
|
-
this._debug.table(this._cachedFiles.map((f) => ({
|
|
1905
|
-
filename: f.filename,
|
|
1906
|
-
score: `${Math.round(f.score * 100)}%`,
|
|
1907
|
-
thumbs: `${f.thumbsUp}/${f.thumbsDown}`,
|
|
1908
|
-
sourceLength: `${f.source.length} chars`
|
|
1909
|
-
})));
|
|
1910
|
-
try {
|
|
1911
|
-
mkdirSync(cacheDir, { recursive: true });
|
|
1912
|
-
for (const file of this._cachedFiles) {
|
|
1913
|
-
const filePath = join(cacheDir, file.filename);
|
|
1914
|
-
writeFileSync(filePath, file.source, "utf-8");
|
|
1915
|
-
this._debug.log(` → Wrote cached file: ${filePath}`);
|
|
1916
|
-
this._modifiedFilePaths.add(filePath);
|
|
1917
|
-
}
|
|
1918
|
-
} catch (writeErr) {
|
|
1919
|
-
this._debug.log("Failed to write cached files:", writeErr instanceof Error ? writeErr : String(writeErr));
|
|
1920
|
-
}
|
|
1921
|
-
}
|
|
1922
|
-
} catch (error) {
|
|
1923
|
-
const errMsg = error instanceof Error ? error.message : String(error);
|
|
1924
|
-
this._debug.log("Cache lookup failed:", errMsg);
|
|
1925
|
-
console.warn("[raysurfer] Cache unavailable:", errMsg);
|
|
1926
|
-
}
|
|
1927
|
-
}
|
|
1928
|
-
const augmented = augmentSystemPrompt(this._sdkOptions.systemPrompt, addToLlmPrompt);
|
|
1929
|
-
const augmentedOptions = {
|
|
1930
|
-
...this._sdkOptions,
|
|
1931
|
-
systemPrompt: augmented
|
|
1932
|
-
};
|
|
1933
|
-
this._debug.log("Augmented prompt addition:", addToLlmPrompt.length, "chars");
|
|
1934
|
-
let sdkQueryFn;
|
|
1935
|
-
try {
|
|
1936
|
-
const sdk = await import("@anthropic-ai/claude-agent-sdk");
|
|
1937
|
-
sdkQueryFn = sdk.query;
|
|
1938
|
-
} catch {
|
|
1939
|
-
throw new Error("Could not import @anthropic-ai/claude-agent-sdk. Install it with: npm install @anthropic-ai/claude-agent-sdk");
|
|
1940
|
-
}
|
|
1941
|
-
this._debug.time("Claude API call");
|
|
1942
|
-
this._debug.log("Calling Claude Agent SDK...");
|
|
1943
|
-
this._startTime = Date.now();
|
|
1944
|
-
this._inner = sdkQueryFn({
|
|
1945
|
-
prompt: this._params.prompt,
|
|
1946
|
-
options: augmentedOptions
|
|
1947
|
-
});
|
|
1948
|
-
}
|
|
1949
|
-
async _ensureInit() {
|
|
1950
|
-
if (!this._inner) {
|
|
1951
|
-
if (!this._initPromise) {
|
|
1952
|
-
this._initPromise = this._initialize();
|
|
1953
|
-
}
|
|
1954
|
-
await this._initPromise;
|
|
1955
|
-
}
|
|
1956
|
-
return this._inner;
|
|
1957
|
-
}
|
|
1958
|
-
_extractBashOutputFiles(command) {
|
|
1959
|
-
for (const pattern of BASH_OUTPUT_PATTERNS) {
|
|
1960
|
-
pattern.lastIndex = 0;
|
|
1961
|
-
let match = pattern.exec(command);
|
|
1962
|
-
while (match !== null) {
|
|
1963
|
-
const filePath = match[1];
|
|
1964
|
-
if (filePath && filePath.length > 0) {
|
|
1965
|
-
const ext = filePath.substring(filePath.lastIndexOf(".")).toLowerCase();
|
|
1966
|
-
if (TRACKABLE_EXTENSIONS.has(ext)) {
|
|
1967
|
-
this._bashGeneratedFiles.add(filePath);
|
|
1968
|
-
this._debug.log(` → Bash output file detected: ${filePath}`);
|
|
1969
|
-
}
|
|
1970
|
-
}
|
|
1971
|
-
match = pattern.exec(command);
|
|
1972
|
-
}
|
|
1973
|
-
}
|
|
1974
|
-
}
|
|
1975
|
-
_trackMessage(message) {
|
|
1976
|
-
this._messageCount++;
|
|
1977
|
-
const msg = message;
|
|
1978
|
-
const elapsed = Date.now() - this._startTime;
|
|
1979
|
-
this._debug.log(`
|
|
1980
|
-
═══════════════════════════════════════════════════`);
|
|
1981
|
-
this._debug.log(`Message #${this._messageCount} [${elapsed}ms] type=${msg.type} subtype=${msg.subtype ?? "none"}`);
|
|
1982
|
-
this._debug.log(`═══════════════════════════════════════════════════`);
|
|
1983
|
-
this._debug.log(JSON.stringify(msg, null, 2));
|
|
1984
|
-
if (msg.type === "assistant" && msg.message?.content) {
|
|
1985
|
-
const blocks = msg.message.content;
|
|
1986
|
-
for (const block of blocks) {
|
|
1987
|
-
if (block.type === "tool_use" && block.name && FILE_MODIFY_TOOLS.includes(block.name)) {
|
|
1988
|
-
const filePath = block.input?.file_path ?? block.input?.notebook_path;
|
|
1989
|
-
if (filePath) {
|
|
1990
|
-
this._debug.log(` → ${block.name} tool detected:`, filePath);
|
|
1991
|
-
this._modifiedFilePaths.add(filePath);
|
|
1992
|
-
}
|
|
1993
|
-
}
|
|
1994
|
-
if (block.type === "tool_use" && block.name === "Bash") {
|
|
1995
|
-
const command = block.input?.command;
|
|
1996
|
-
if (command) {
|
|
1997
|
-
this._extractBashOutputFiles(command);
|
|
1998
|
-
}
|
|
1999
|
-
}
|
|
2000
|
-
if (block.type === "tool_result" && block.content) {
|
|
2001
|
-
if (this._parseRunForAiVoting) {
|
|
2002
|
-
this._executionLogs.push(block.content.slice(0, 5000));
|
|
2003
|
-
}
|
|
2004
|
-
}
|
|
2005
|
-
if (block.type === "text" && block.text) {
|
|
2006
|
-
const codeMatches = block.text.match(/```(?:typescript|javascript|ts|js)?\n?([\s\S]*?)\n?```/g);
|
|
2007
|
-
if (codeMatches) {
|
|
2008
|
-
for (const match of codeMatches) {
|
|
2009
|
-
const code = match.replace(/```(?:typescript|javascript|ts|js)?\n?/, "").replace(/\n?```$/, "");
|
|
2010
|
-
if (code.trim().length > 50) {
|
|
2011
|
-
this._generatedCodeBlocks.push(code.trim());
|
|
2012
|
-
this._debug.log(` → Extracted code block (${code.length} chars)`);
|
|
2013
|
-
}
|
|
2014
|
-
}
|
|
2015
|
-
}
|
|
2016
|
-
}
|
|
2017
|
-
}
|
|
2018
|
-
}
|
|
2019
|
-
if (msg.type === "result" && msg.subtype === "success") {
|
|
2020
|
-
this._taskSucceeded = true;
|
|
2021
|
-
this._debug.timeEnd("Claude API call");
|
|
2022
|
-
this._debug.log("Task succeeded!");
|
|
2023
|
-
this._debug.log(" Duration:", msg.duration_ms, "ms");
|
|
2024
|
-
this._debug.log(" Total cost:", msg.total_cost_usd, "USD");
|
|
2025
|
-
this._debug.log(" Turns:", msg.num_turns);
|
|
2026
|
-
}
|
|
2027
|
-
if (msg.type === "result" && msg.subtype !== "success") {
|
|
2028
|
-
this._debug.timeEnd("Claude API call");
|
|
2029
|
-
this._debug.log("Task failed:", msg.subtype);
|
|
2030
2396
|
}
|
|
2397
|
+
return this._raysurfer;
|
|
2031
2398
|
}
|
|
2032
|
-
async
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
this._debug.log("Modified files tracked:", this._modifiedFilePaths.size);
|
|
2038
|
-
this._debug.log("Code blocks extracted:", this._generatedCodeBlocks.length);
|
|
2039
|
-
const filesToCache = [];
|
|
2040
|
-
for (const filePath of this._modifiedFilePaths) {
|
|
2041
|
-
if (filePath.includes(CACHE_DIR)) {
|
|
2042
|
-
this._debug.log(" → Skipping cached file:", filePath);
|
|
2043
|
-
continue;
|
|
2044
|
-
}
|
|
2045
|
-
try {
|
|
2046
|
-
if (existsSync(filePath)) {
|
|
2047
|
-
const content = readFileSync2(filePath, "utf-8");
|
|
2048
|
-
if (content.includes("\x00")) {
|
|
2049
|
-
this._debug.log(" → Skipping binary file:", filePath);
|
|
2050
|
-
continue;
|
|
2051
|
-
}
|
|
2052
|
-
filesToCache.push({ path: filePath, content });
|
|
2053
|
-
this._debug.log(" → Will cache file:", filePath, `(${content.length} chars)`);
|
|
2054
|
-
} else {
|
|
2055
|
-
this._debug.log(" → File not found:", filePath);
|
|
2056
|
-
}
|
|
2057
|
-
} catch (err) {
|
|
2058
|
-
this._debug.log(" → Failed to read file:", filePath, err instanceof Error ? err : String(err));
|
|
2059
|
-
}
|
|
2399
|
+
async run(messages, options = {}) {
|
|
2400
|
+
const rs = this.ensureClient(options.orgId);
|
|
2401
|
+
const lastUserMsg = [...messages].reverse().find((m) => m.role === "user");
|
|
2402
|
+
if (!lastUserMsg) {
|
|
2403
|
+
throw new Error("Messages must contain at least one user message.");
|
|
2060
2404
|
}
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2405
|
+
const query2 = lastUserMsg.content;
|
|
2406
|
+
const runId = crypto.randomUUID();
|
|
2407
|
+
const searchResult = await rs.search({ task: query2 });
|
|
2408
|
+
const codeUsed = searchResult.matches?.map((m) => ({
|
|
2409
|
+
code_block_id: m.codeBlock.id,
|
|
2410
|
+
filename: m.codeBlock.name,
|
|
2411
|
+
description: m.codeBlock.description
|
|
2412
|
+
})) ?? [];
|
|
2413
|
+
let succeeded = false;
|
|
2414
|
+
const responseMessages = [];
|
|
2415
|
+
try {
|
|
2416
|
+
const { query: sdkQuery } = await Promise.resolve().then(() => (init_sdk_client(), exports_sdk_client));
|
|
2417
|
+
for await (const msg of sdkQuery({
|
|
2418
|
+
prompt: query2,
|
|
2419
|
+
options: {
|
|
2420
|
+
allowedTools: this._allowedTools,
|
|
2421
|
+
systemPrompt: this._systemPrompt,
|
|
2422
|
+
model: this._model
|
|
2071
2423
|
}
|
|
2072
|
-
}
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
if (this._generatedCodeBlocks.length > 0) {
|
|
2077
|
-
const largestBlock = this._generatedCodeBlocks.reduce((a, b) => a.length > b.length ? a : b);
|
|
2078
|
-
filesToCache.push({
|
|
2079
|
-
path: "generated-code.ts",
|
|
2080
|
-
content: largestBlock
|
|
2081
|
-
});
|
|
2082
|
-
this._debug.log(" → Will cache generated code block:", `(${largestBlock.length} chars)`);
|
|
2083
|
-
}
|
|
2084
|
-
this._debug.log("Total items to cache:", filesToCache.length);
|
|
2085
|
-
if (this._cacheEnabled && this._raysurfer && this._taskSucceeded && this._promptText) {
|
|
2086
|
-
const cachedBlocksForVoting = this._parseRunForAiVoting ? this._cachedFiles.map((f) => ({
|
|
2087
|
-
codeBlockId: f.codeBlockId,
|
|
2088
|
-
filename: f.filename,
|
|
2089
|
-
description: f.description
|
|
2090
|
-
})) : [];
|
|
2091
|
-
if (filesToCache.length > 0 || cachedBlocksForVoting.length > 0) {
|
|
2092
|
-
try {
|
|
2093
|
-
this._debug.time("Cache upload + voting");
|
|
2094
|
-
if (!this._parseRunForAiVoting) {
|
|
2095
|
-
this._debug.log("Skipping AI voting parse for this run due sampling");
|
|
2096
|
-
}
|
|
2097
|
-
const joinedLogs = this._parseRunForAiVoting && this._executionLogs.length > 0 ? this._executionLogs.join(`
|
|
2098
|
-
---
|
|
2099
|
-
`) : undefined;
|
|
2100
|
-
this._debug.log("Uploading", filesToCache.length, "files, voting for", cachedBlocksForVoting.length, "cached blocks,", this._executionLogs.length, "log entries...");
|
|
2101
|
-
for (const [i, file] of filesToCache.entries()) {
|
|
2102
|
-
await this._raysurfer.uploadNewCodeSnip({
|
|
2103
|
-
task: this._promptText,
|
|
2104
|
-
fileWritten: file,
|
|
2105
|
-
succeeded: true,
|
|
2106
|
-
cachedCodeBlocks: i === 0 && cachedBlocksForVoting.length > 0 ? cachedBlocksForVoting : undefined,
|
|
2107
|
-
useRaysurferAiVoting: this._parseRunForAiVoting,
|
|
2108
|
-
executionLogs: joinedLogs,
|
|
2109
|
-
perFunctionReputation: true
|
|
2110
|
-
});
|
|
2111
|
-
}
|
|
2112
|
-
if (filesToCache.length === 0 && cachedBlocksForVoting.length > 0) {
|
|
2113
|
-
for (const cb of cachedBlocksForVoting) {
|
|
2114
|
-
await this._raysurfer.voteCodeSnip({
|
|
2115
|
-
task: this._promptText,
|
|
2116
|
-
codeBlockId: cb.codeBlockId,
|
|
2117
|
-
codeBlockName: cb.filename,
|
|
2118
|
-
codeBlockDescription: cb.description,
|
|
2119
|
-
succeeded: true
|
|
2120
|
-
});
|
|
2121
|
-
}
|
|
2122
|
-
}
|
|
2123
|
-
this._debug.timeEnd("Cache upload + voting");
|
|
2124
|
-
this._debug.log("Cache upload successful, voting queued on backend");
|
|
2125
|
-
console.log("[raysurfer] Cache upload successful:", filesToCache.length, "files stored");
|
|
2126
|
-
} catch (error) {
|
|
2127
|
-
const errMsg = error instanceof Error ? error.message : String(error);
|
|
2128
|
-
this._debug.log("Cache upload failed:", errMsg);
|
|
2129
|
-
console.warn("[raysurfer] Cache upload failed:", errMsg);
|
|
2424
|
+
})) {
|
|
2425
|
+
responseMessages.push(msg);
|
|
2426
|
+
if (typeof msg === "object" && msg !== null && "type" in msg && msg.type === "result" && "subtype" in msg && msg.subtype === "success") {
|
|
2427
|
+
succeeded = true;
|
|
2130
2428
|
}
|
|
2131
2429
|
}
|
|
2430
|
+
} catch {
|
|
2431
|
+
succeeded = false;
|
|
2132
2432
|
}
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
} else {
|
|
2141
|
-
await this._uploadCache();
|
|
2142
|
-
}
|
|
2143
|
-
return result;
|
|
2144
|
-
}
|
|
2145
|
-
async return(value) {
|
|
2146
|
-
if (this._inner) {
|
|
2147
|
-
await this._uploadCache();
|
|
2148
|
-
return this._inner.return(value);
|
|
2149
|
-
}
|
|
2150
|
-
return { done: true, value: undefined };
|
|
2151
|
-
}
|
|
2152
|
-
async throw(e) {
|
|
2153
|
-
if (this._inner)
|
|
2154
|
-
return this._inner.throw(e);
|
|
2155
|
-
throw e;
|
|
2156
|
-
}
|
|
2157
|
-
[Symbol.asyncIterator]() {
|
|
2158
|
-
return this;
|
|
2159
|
-
}
|
|
2160
|
-
async[Symbol.asyncDispose]() {
|
|
2161
|
-
this.close();
|
|
2162
|
-
}
|
|
2163
|
-
async interrupt() {
|
|
2164
|
-
return (await this._ensureInit()).interrupt();
|
|
2165
|
-
}
|
|
2166
|
-
async setPermissionMode(mode) {
|
|
2167
|
-
return (await this._ensureInit()).setPermissionMode(mode);
|
|
2168
|
-
}
|
|
2169
|
-
async setModel(model) {
|
|
2170
|
-
return (await this._ensureInit()).setModel(model);
|
|
2171
|
-
}
|
|
2172
|
-
async setMaxThinkingTokens(maxThinkingTokens) {
|
|
2173
|
-
return (await this._ensureInit()).setMaxThinkingTokens(maxThinkingTokens);
|
|
2174
|
-
}
|
|
2175
|
-
async supportedCommands() {
|
|
2176
|
-
return (await this._ensureInit()).supportedCommands();
|
|
2177
|
-
}
|
|
2178
|
-
async supportedModels() {
|
|
2179
|
-
return (await this._ensureInit()).supportedModels();
|
|
2180
|
-
}
|
|
2181
|
-
async mcpServerStatus() {
|
|
2182
|
-
return (await this._ensureInit()).mcpServerStatus();
|
|
2183
|
-
}
|
|
2184
|
-
async accountInfo() {
|
|
2185
|
-
return (await this._ensureInit()).accountInfo();
|
|
2186
|
-
}
|
|
2187
|
-
async rewindFiles(userMessageId, options) {
|
|
2188
|
-
return (await this._ensureInit()).rewindFiles(userMessageId, options);
|
|
2189
|
-
}
|
|
2190
|
-
async setMcpServers(servers) {
|
|
2191
|
-
return (await this._ensureInit()).setMcpServers(servers);
|
|
2192
|
-
}
|
|
2193
|
-
async streamInput(stream) {
|
|
2194
|
-
return (await this._ensureInit()).streamInput(stream);
|
|
2195
|
-
}
|
|
2196
|
-
close() {
|
|
2197
|
-
if (this._inner)
|
|
2198
|
-
this._inner.close();
|
|
2199
|
-
}
|
|
2200
|
-
}
|
|
2201
|
-
function query(params) {
|
|
2202
|
-
return new RaysurferQuery(params);
|
|
2203
|
-
}
|
|
2204
|
-
|
|
2205
|
-
class ClaudeSDKClient {
|
|
2206
|
-
options;
|
|
2207
|
-
constructor(options = {}) {
|
|
2208
|
-
this.options = options;
|
|
2209
|
-
}
|
|
2210
|
-
query(prompt) {
|
|
2211
|
-
return query({ prompt, options: this.options });
|
|
2433
|
+
return {
|
|
2434
|
+
runId,
|
|
2435
|
+
query: query2,
|
|
2436
|
+
succeeded,
|
|
2437
|
+
messages: responseMessages,
|
|
2438
|
+
codeUsed
|
|
2439
|
+
};
|
|
2212
2440
|
}
|
|
2213
2441
|
}
|
|
2214
|
-
var sdk_client_default = query;
|
|
2215
2442
|
|
|
2216
2443
|
// src/index.ts
|
|
2444
|
+
init_sdk_client();
|
|
2217
2445
|
import {
|
|
2218
2446
|
AbortError,
|
|
2219
2447
|
createSdkMcpServer,
|
|
@@ -2252,6 +2480,7 @@ export {
|
|
|
2252
2480
|
CacheUnavailableError,
|
|
2253
2481
|
AuthenticationError,
|
|
2254
2482
|
AgentVerdict,
|
|
2483
|
+
Agent,
|
|
2255
2484
|
AbortError,
|
|
2256
2485
|
APIError
|
|
2257
2486
|
};
|