raysurfer 1.4.1 → 1.4.3
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 +62 -23
- package/dist/client.d.ts.map +1 -1
- package/dist/index.d.ts +5 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +988 -761
- package/dist/runner.d.ts +80 -0
- package/dist/runner.d.ts.map +1 -0
- package/dist/sdk-client.d.ts +2 -2
- package/dist/sdk-client.d.ts.map +1 -1
- 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,12 @@ 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
|
+
}
|
|
529
454
|
const result = await this.request("POST", "/api/retrieve/search", data, this.workspaceHeaders(params.workspaceId));
|
|
530
455
|
return {
|
|
531
456
|
matches: result.matches.map((m) => {
|
|
@@ -563,7 +488,13 @@ class RaySurfer {
|
|
|
563
488
|
dependencies: normalizeDependencies(m.dependencies),
|
|
564
489
|
agentId: m.agent_id ?? null,
|
|
565
490
|
comments: m.comments ?? [],
|
|
566
|
-
functions
|
|
491
|
+
functions,
|
|
492
|
+
type: m.type ?? "file",
|
|
493
|
+
downloadUrl: m.download_url ?? null,
|
|
494
|
+
fileTree: m.file_tree ?? null,
|
|
495
|
+
fileCount: m.file_count ?? null,
|
|
496
|
+
framework: m.framework ?? null,
|
|
497
|
+
readmePreview: m.readme_preview ?? null
|
|
567
498
|
};
|
|
568
499
|
}),
|
|
569
500
|
totalFound: result.total_found,
|
|
@@ -716,7 +647,7 @@ class RaySurfer {
|
|
|
716
647
|
|
|
717
648
|
## IMPORTANT: Pre-validated Code Files Available
|
|
718
649
|
`,
|
|
719
|
-
|
|
650
|
+
`The following validated code has been retrieved from the cache. Use these files directly instead of regenerating code.
|
|
720
651
|
`
|
|
721
652
|
];
|
|
722
653
|
for (const f of files) {
|
|
@@ -851,6 +782,35 @@ class RaySurfer {
|
|
|
851
782
|
hasMore: response.has_more
|
|
852
783
|
};
|
|
853
784
|
}
|
|
785
|
+
async log(params) {
|
|
786
|
+
const response = await this.request("POST", "/api/logs/ingest", {
|
|
787
|
+
log_hash: params.logHash,
|
|
788
|
+
value: params.value,
|
|
789
|
+
source: params.source ?? "",
|
|
790
|
+
scope: params.scope ?? "",
|
|
791
|
+
run_id: params.runId ?? "",
|
|
792
|
+
metadata: params.metadata ?? {}
|
|
793
|
+
});
|
|
794
|
+
return response.log_hash;
|
|
795
|
+
}
|
|
796
|
+
async getLog(logHash, limit = 50) {
|
|
797
|
+
const response = await this.request("GET", `/api/logs/hash/${logHash}`, { limit });
|
|
798
|
+
return {
|
|
799
|
+
logHash: response.log_hash,
|
|
800
|
+
source: response.source,
|
|
801
|
+
totalEvents: response.total_events,
|
|
802
|
+
recentEvents: response.recent_events.map((e) => ({
|
|
803
|
+
id: e.id,
|
|
804
|
+
logHash: e.log_hash,
|
|
805
|
+
source: e.source,
|
|
806
|
+
value: e.value,
|
|
807
|
+
preview: e.preview,
|
|
808
|
+
runId: e.run_id,
|
|
809
|
+
metadata: e.metadata,
|
|
810
|
+
loggedAt: e.logged_at
|
|
811
|
+
}))
|
|
812
|
+
};
|
|
813
|
+
}
|
|
854
814
|
async voteCodeSnip(params) {
|
|
855
815
|
const data = {
|
|
856
816
|
task: params.task,
|
|
@@ -1067,6 +1027,35 @@ class RaySurfer {
|
|
|
1067
1027
|
codegen
|
|
1068
1028
|
});
|
|
1069
1029
|
}
|
|
1030
|
+
async chat(query, options) {
|
|
1031
|
+
const response = await this.request("POST", "/api/agent-chat", {
|
|
1032
|
+
user_query: query,
|
|
1033
|
+
user_id: options.user,
|
|
1034
|
+
org_id: options.org,
|
|
1035
|
+
model: options.model ?? "sonnet",
|
|
1036
|
+
max_turns: options.maxTurns ?? 8
|
|
1037
|
+
});
|
|
1038
|
+
return {
|
|
1039
|
+
success: response.success,
|
|
1040
|
+
output: response.output,
|
|
1041
|
+
error: response.error,
|
|
1042
|
+
sessionId: response.session_id,
|
|
1043
|
+
durationMs: response.duration_ms,
|
|
1044
|
+
changedFiles: response.changed_files ?? [],
|
|
1045
|
+
workspaceFiles: response.org_workspace_files ?? []
|
|
1046
|
+
};
|
|
1047
|
+
}
|
|
1048
|
+
async heartbeat(options) {
|
|
1049
|
+
return this.request("POST", "/api/agents/heartbeat", {
|
|
1050
|
+
agent_id: options.agentId,
|
|
1051
|
+
agent_name: options.agentName,
|
|
1052
|
+
status: options.status ?? "running",
|
|
1053
|
+
current_task: options.currentTask,
|
|
1054
|
+
cpu_percent: options.cpuPercent,
|
|
1055
|
+
memory_percent: options.memoryPercent,
|
|
1056
|
+
metadata: options.metadata
|
|
1057
|
+
});
|
|
1058
|
+
}
|
|
1070
1059
|
async publishFunctionRegistry(functions) {
|
|
1071
1060
|
const snippetNames = [];
|
|
1072
1061
|
for (const fn of functions) {
|
|
@@ -1115,53 +1104,733 @@ class RaySurfer {
|
|
|
1115
1104
|
};
|
|
1116
1105
|
}
|
|
1117
1106
|
}
|
|
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
|
-
}
|
|
1107
|
+
var VERSION = "1.4.3", DEFAULT_BASE_URL = "https://api.raysurfer.com", MAX_RETRIES = 3, RETRY_BASE_DELAY = 500, RETRYABLE_STATUS_CODES, client_default;
|
|
1108
|
+
var init_client = __esm(() => {
|
|
1109
|
+
init_errors();
|
|
1110
|
+
RETRYABLE_STATUS_CODES = new Set([429, 500, 502, 503, 504]);
|
|
1111
|
+
client_default = RaySurfer;
|
|
1112
|
+
});
|
|
1130
1113
|
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1114
|
+
// src/sdk-client.ts
|
|
1115
|
+
var exports_sdk_client = {};
|
|
1116
|
+
__export(exports_sdk_client, {
|
|
1117
|
+
query: () => query,
|
|
1118
|
+
default: () => sdk_client_default,
|
|
1119
|
+
RaysurferOpencodeClient: () => ClaudeSDKClient,
|
|
1120
|
+
RaysurferClient: () => ClaudeSDKClient,
|
|
1121
|
+
ClaudeSDKClient: () => ClaudeSDKClient
|
|
1122
|
+
});
|
|
1123
|
+
import { existsSync, mkdirSync, readFileSync as readFileSync2, writeFileSync } from "node:fs";
|
|
1124
|
+
import { join } from "node:path";
|
|
1125
|
+
function resolveRunParseSampleRate(configured) {
|
|
1126
|
+
if (configured !== undefined) {
|
|
1127
|
+
if (!Number.isFinite(configured) || configured < 0 || configured > 1) {
|
|
1128
|
+
throw new Error(`runParseSampleRate must be between 0.0 and 1.0 inclusive; got ${configured}.`);
|
|
1129
|
+
}
|
|
1130
|
+
return configured;
|
|
1148
1131
|
}
|
|
1149
|
-
|
|
1150
|
-
|
|
1132
|
+
const envValue = process.env[RUN_PARSE_SAMPLE_RATE_ENV_VAR];
|
|
1133
|
+
if (!envValue || envValue.trim() === "") {
|
|
1134
|
+
return DEFAULT_RUN_PARSE_SAMPLE_RATE;
|
|
1151
1135
|
}
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1136
|
+
const parsed = Number(envValue);
|
|
1137
|
+
if (!Number.isFinite(parsed) || parsed < 0 || parsed > 1) {
|
|
1138
|
+
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}.`);
|
|
1139
|
+
return DEFAULT_RUN_PARSE_SAMPLE_RATE;
|
|
1155
1140
|
}
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1141
|
+
return parsed;
|
|
1142
|
+
}
|
|
1143
|
+
function shouldParseRunForAiVoting(sampleRate) {
|
|
1144
|
+
if (sampleRate >= 1)
|
|
1145
|
+
return true;
|
|
1146
|
+
if (sampleRate <= 0)
|
|
1147
|
+
return false;
|
|
1148
|
+
return Math.random() < sampleRate;
|
|
1149
|
+
}
|
|
1150
|
+
function augmentSystemPrompt(systemPrompt, addition) {
|
|
1151
|
+
if (!addition)
|
|
1152
|
+
return systemPrompt;
|
|
1153
|
+
if (typeof systemPrompt === "string")
|
|
1154
|
+
return systemPrompt + addition;
|
|
1155
|
+
if (systemPrompt?.type === "preset") {
|
|
1156
|
+
return { ...systemPrompt, append: (systemPrompt.append ?? "") + addition };
|
|
1157
|
+
}
|
|
1158
|
+
return addition;
|
|
1159
|
+
}
|
|
1160
|
+
function splitOptions(options) {
|
|
1161
|
+
const {
|
|
1162
|
+
workspaceId,
|
|
1163
|
+
publicSnips,
|
|
1164
|
+
debug,
|
|
1165
|
+
runParseSampleRate,
|
|
1166
|
+
workingDirectory,
|
|
1167
|
+
agentId,
|
|
1168
|
+
...sdkOptions
|
|
1169
|
+
} = options;
|
|
1170
|
+
return {
|
|
1171
|
+
sdkOptions,
|
|
1172
|
+
extras: {
|
|
1173
|
+
workspaceId,
|
|
1174
|
+
publicSnips,
|
|
1175
|
+
debug,
|
|
1176
|
+
runParseSampleRate,
|
|
1177
|
+
workingDirectory,
|
|
1178
|
+
agentId
|
|
1179
|
+
}
|
|
1180
|
+
};
|
|
1181
|
+
}
|
|
1182
|
+
function applyDefaultAgentCompatibilityOptions(options) {
|
|
1183
|
+
const merged = { ...options };
|
|
1184
|
+
const hasToolsPreset = merged.tools !== undefined && merged.tools !== null;
|
|
1185
|
+
const hasAllowedTools = Array.isArray(merged.allowedTools) && merged.allowedTools.length > 0;
|
|
1186
|
+
if (!hasToolsPreset && !hasAllowedTools) {
|
|
1187
|
+
merged.tools = DEFAULT_AGENT_COMPAT_TOOLS_PRESET;
|
|
1188
|
+
}
|
|
1189
|
+
if (merged.sandbox && typeof merged.sandbox === "object") {
|
|
1190
|
+
merged.sandbox = {
|
|
1191
|
+
...DEFAULT_SANDBOX_SETTINGS,
|
|
1192
|
+
...merged.sandbox
|
|
1193
|
+
};
|
|
1194
|
+
} else {
|
|
1195
|
+
merged.sandbox = { ...DEFAULT_SANDBOX_SETTINGS };
|
|
1196
|
+
}
|
|
1197
|
+
return merged;
|
|
1198
|
+
}
|
|
1199
|
+
function query(params) {
|
|
1200
|
+
return new RaysurferQuery(params);
|
|
1201
|
+
}
|
|
1202
|
+
|
|
1203
|
+
class ClaudeSDKClient {
|
|
1204
|
+
options;
|
|
1205
|
+
constructor(options = {}) {
|
|
1206
|
+
this.options = options;
|
|
1207
|
+
}
|
|
1208
|
+
query(prompt) {
|
|
1209
|
+
return query({ prompt, options: this.options });
|
|
1210
|
+
}
|
|
1211
|
+
}
|
|
1212
|
+
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) => ({
|
|
1213
|
+
log: (...args) => enabled && console.log("[raysurfer]", ...args),
|
|
1214
|
+
time: (label) => enabled && console.time(`[raysurfer] ${label}`),
|
|
1215
|
+
timeEnd: (label) => enabled && console.timeEnd(`[raysurfer] ${label}`),
|
|
1216
|
+
table: (data) => enabled && console.table(data),
|
|
1217
|
+
group: (label) => enabled && console.group(`[raysurfer] ${label}`),
|
|
1218
|
+
groupEnd: () => enabled && console.groupEnd()
|
|
1219
|
+
}), RaysurferQuery, sdk_client_default;
|
|
1220
|
+
var init_sdk_client = __esm(() => {
|
|
1221
|
+
init_client();
|
|
1222
|
+
DEFAULT_AGENT_COMPAT_TOOLS_PRESET = {
|
|
1223
|
+
type: "preset",
|
|
1224
|
+
preset: "claude_code"
|
|
1225
|
+
};
|
|
1226
|
+
DEFAULT_SANDBOX_SETTINGS = {
|
|
1227
|
+
enabled: true,
|
|
1228
|
+
autoAllowBashIfSandboxed: true
|
|
1229
|
+
};
|
|
1230
|
+
FILE_MODIFY_TOOLS = ["Write", "Edit", "MultiEdit", "NotebookEdit"];
|
|
1231
|
+
TRACKABLE_EXTENSIONS = new Set([
|
|
1232
|
+
".py",
|
|
1233
|
+
".js",
|
|
1234
|
+
".ts",
|
|
1235
|
+
".rb",
|
|
1236
|
+
".go",
|
|
1237
|
+
".rs",
|
|
1238
|
+
".java",
|
|
1239
|
+
".cpp",
|
|
1240
|
+
".c",
|
|
1241
|
+
".h",
|
|
1242
|
+
".pdf",
|
|
1243
|
+
".docx",
|
|
1244
|
+
".xlsx",
|
|
1245
|
+
".csv",
|
|
1246
|
+
".json",
|
|
1247
|
+
".yaml",
|
|
1248
|
+
".yml",
|
|
1249
|
+
".xml",
|
|
1250
|
+
".html",
|
|
1251
|
+
".css",
|
|
1252
|
+
".md",
|
|
1253
|
+
".txt",
|
|
1254
|
+
".sh",
|
|
1255
|
+
".sql"
|
|
1256
|
+
]);
|
|
1257
|
+
BASH_OUTPUT_PATTERNS = [
|
|
1258
|
+
/>>\s*([^\s;&|]+)/g,
|
|
1259
|
+
/>\s*([^\s;&|]+)/g,
|
|
1260
|
+
/-o\s+([^\s;&|]+)/g,
|
|
1261
|
+
/--output[=\s]+([^\s;&|]+)/g,
|
|
1262
|
+
/savefig\(['"]([^'"]+)['"]\)/g,
|
|
1263
|
+
/to_csv\(['"]([^'"]+)['"]\)/g,
|
|
1264
|
+
/to_excel\(['"]([^'"]+)['"]\)/g,
|
|
1265
|
+
/write\(['"]([^'"]+)['"]\)/g
|
|
1266
|
+
];
|
|
1267
|
+
RaysurferQuery = class RaysurferQuery {
|
|
1268
|
+
_inner = null;
|
|
1269
|
+
_initPromise = null;
|
|
1270
|
+
_raysurfer = null;
|
|
1271
|
+
_cachedFiles = [];
|
|
1272
|
+
_modifiedFilePaths = new Set;
|
|
1273
|
+
_bashGeneratedFiles = new Set;
|
|
1274
|
+
_executionLogs = [];
|
|
1275
|
+
_taskSucceeded = false;
|
|
1276
|
+
_generatedCodeBlocks = [];
|
|
1277
|
+
_cacheUploadDone = false;
|
|
1278
|
+
_messageCount = 0;
|
|
1279
|
+
_startTime = 0;
|
|
1280
|
+
_promptText;
|
|
1281
|
+
_params;
|
|
1282
|
+
_debug;
|
|
1283
|
+
_cacheEnabled;
|
|
1284
|
+
_workDir;
|
|
1285
|
+
_apiKey;
|
|
1286
|
+
_baseUrl;
|
|
1287
|
+
_extras;
|
|
1288
|
+
_sdkOptions;
|
|
1289
|
+
_runParseSampleRate;
|
|
1290
|
+
_parseRunForAiVoting;
|
|
1291
|
+
constructor(params) {
|
|
1292
|
+
this._params = params;
|
|
1293
|
+
const options = params.options ?? {};
|
|
1294
|
+
const { sdkOptions, extras } = splitOptions(options);
|
|
1295
|
+
this._sdkOptions = applyDefaultAgentCompatibilityOptions(sdkOptions);
|
|
1296
|
+
this._extras = extras;
|
|
1297
|
+
this._promptText = typeof params.prompt === "string" ? params.prompt : null;
|
|
1298
|
+
const debugEnabled = extras.debug || process.env.RAYSURFER_DEBUG === "true";
|
|
1299
|
+
this._debug = createDebugLogger(debugEnabled);
|
|
1300
|
+
this._apiKey = process.env.RAYSURFER_API_KEY;
|
|
1301
|
+
this._baseUrl = process.env.RAYSURFER_BASE_URL || DEFAULT_RAYSURFER_URL;
|
|
1302
|
+
this._cacheEnabled = !!this._apiKey;
|
|
1303
|
+
this._runParseSampleRate = resolveRunParseSampleRate(extras.runParseSampleRate);
|
|
1304
|
+
this._parseRunForAiVoting = shouldParseRunForAiVoting(this._runParseSampleRate);
|
|
1305
|
+
if (extras.workingDirectory && !sdkOptions.cwd) {
|
|
1306
|
+
console.warn("[raysurfer] workingDirectory is deprecated, use cwd instead");
|
|
1307
|
+
this._sdkOptions.cwd = extras.workingDirectory;
|
|
1308
|
+
}
|
|
1309
|
+
this._workDir = this._sdkOptions.cwd || process.cwd();
|
|
1310
|
+
}
|
|
1311
|
+
async _initialize() {
|
|
1312
|
+
this._debug.group("Raysurfer Query Started");
|
|
1313
|
+
this._debug.log("Prompt:", this._promptText ?? "<stream>");
|
|
1314
|
+
this._debug.log("Cache enabled:", this._cacheEnabled);
|
|
1315
|
+
this._debug.log("Base URL:", this._baseUrl);
|
|
1316
|
+
this._debug.log("Run parse sample rate:", this._runParseSampleRate);
|
|
1317
|
+
this._debug.log("Parse this run for AI voting:", this._parseRunForAiVoting);
|
|
1318
|
+
if (!this._cacheEnabled) {
|
|
1319
|
+
console.warn("[raysurfer] RAYSURFER_API_KEY not set - caching disabled");
|
|
1320
|
+
}
|
|
1321
|
+
let addToLlmPrompt = "";
|
|
1322
|
+
if (this._cacheEnabled && this._promptText) {
|
|
1323
|
+
this._raysurfer = new RaySurfer({
|
|
1324
|
+
apiKey: this._apiKey,
|
|
1325
|
+
baseUrl: this._baseUrl,
|
|
1326
|
+
workspaceId: this._extras.workspaceId,
|
|
1327
|
+
snipsDesired: this._extras.workspaceId ? "client" : undefined,
|
|
1328
|
+
publicSnips: this._extras.publicSnips,
|
|
1329
|
+
agentId: this._extras.agentId
|
|
1330
|
+
});
|
|
1331
|
+
try {
|
|
1332
|
+
this._debug.time("Cache lookup");
|
|
1333
|
+
const cacheDir = join(this._workDir, CACHE_DIR);
|
|
1334
|
+
const response = await this._raysurfer.getCodeFiles({
|
|
1335
|
+
task: this._promptText,
|
|
1336
|
+
topK: 5,
|
|
1337
|
+
minVerdictScore: 0.3,
|
|
1338
|
+
preferComplete: true,
|
|
1339
|
+
perFunctionReputation: true,
|
|
1340
|
+
cacheDir
|
|
1341
|
+
});
|
|
1342
|
+
this._debug.timeEnd("Cache lookup");
|
|
1343
|
+
this._cachedFiles = response.files;
|
|
1344
|
+
addToLlmPrompt = response.addToLlmPrompt;
|
|
1345
|
+
this._debug.log(`Found ${this._cachedFiles.length} cached files:`);
|
|
1346
|
+
console.log("[raysurfer] Cache hit:", this._cachedFiles.length, "snippets retrieved");
|
|
1347
|
+
if (this._cachedFiles.length > 0) {
|
|
1348
|
+
this._debug.table(this._cachedFiles.map((f) => ({
|
|
1349
|
+
filename: f.filename,
|
|
1350
|
+
score: `${Math.round(f.score * 100)}%`,
|
|
1351
|
+
thumbs: `${f.thumbsUp}/${f.thumbsDown}`,
|
|
1352
|
+
sourceLength: `${f.source.length} chars`
|
|
1353
|
+
})));
|
|
1354
|
+
try {
|
|
1355
|
+
mkdirSync(cacheDir, { recursive: true });
|
|
1356
|
+
for (const file of this._cachedFiles) {
|
|
1357
|
+
const filePath = join(cacheDir, file.filename);
|
|
1358
|
+
writeFileSync(filePath, file.source, "utf-8");
|
|
1359
|
+
this._debug.log(` → Wrote cached file: ${filePath}`);
|
|
1360
|
+
this._modifiedFilePaths.add(filePath);
|
|
1361
|
+
}
|
|
1362
|
+
} catch (writeErr) {
|
|
1363
|
+
this._debug.log("Failed to write cached files:", writeErr instanceof Error ? writeErr : String(writeErr));
|
|
1364
|
+
}
|
|
1365
|
+
}
|
|
1366
|
+
} catch (error) {
|
|
1367
|
+
const errMsg = error instanceof Error ? error.message : String(error);
|
|
1368
|
+
this._debug.log("Cache lookup failed:", errMsg);
|
|
1369
|
+
console.warn("[raysurfer] Cache unavailable:", errMsg);
|
|
1370
|
+
}
|
|
1371
|
+
}
|
|
1372
|
+
const augmented = augmentSystemPrompt(this._sdkOptions.systemPrompt, addToLlmPrompt);
|
|
1373
|
+
const augmentedOptions = {
|
|
1374
|
+
...this._sdkOptions,
|
|
1375
|
+
systemPrompt: augmented
|
|
1376
|
+
};
|
|
1377
|
+
this._debug.log("Augmented prompt addition:", addToLlmPrompt.length, "chars");
|
|
1378
|
+
let sdkQueryFn;
|
|
1379
|
+
try {
|
|
1380
|
+
const sdk = await import("@anthropic-ai/claude-agent-sdk");
|
|
1381
|
+
sdkQueryFn = sdk.query;
|
|
1382
|
+
} catch {
|
|
1383
|
+
throw new Error("Could not import @anthropic-ai/claude-agent-sdk. Install it with: npm install @anthropic-ai/claude-agent-sdk");
|
|
1384
|
+
}
|
|
1385
|
+
this._debug.time("Claude API call");
|
|
1386
|
+
this._debug.log("Calling Claude Agent SDK...");
|
|
1387
|
+
this._startTime = Date.now();
|
|
1388
|
+
this._inner = sdkQueryFn({
|
|
1389
|
+
prompt: this._params.prompt,
|
|
1390
|
+
options: augmentedOptions
|
|
1391
|
+
});
|
|
1392
|
+
}
|
|
1393
|
+
async _ensureInit() {
|
|
1394
|
+
if (!this._inner) {
|
|
1395
|
+
if (!this._initPromise) {
|
|
1396
|
+
this._initPromise = this._initialize();
|
|
1397
|
+
}
|
|
1398
|
+
await this._initPromise;
|
|
1399
|
+
}
|
|
1400
|
+
return this._inner;
|
|
1401
|
+
}
|
|
1402
|
+
_extractBashOutputFiles(command) {
|
|
1403
|
+
for (const pattern of BASH_OUTPUT_PATTERNS) {
|
|
1404
|
+
pattern.lastIndex = 0;
|
|
1405
|
+
let match = pattern.exec(command);
|
|
1406
|
+
while (match !== null) {
|
|
1407
|
+
const filePath = match[1];
|
|
1408
|
+
if (filePath && filePath.length > 0) {
|
|
1409
|
+
const ext = filePath.substring(filePath.lastIndexOf(".")).toLowerCase();
|
|
1410
|
+
if (TRACKABLE_EXTENSIONS.has(ext)) {
|
|
1411
|
+
this._bashGeneratedFiles.add(filePath);
|
|
1412
|
+
this._debug.log(` → Bash output file detected: ${filePath}`);
|
|
1413
|
+
}
|
|
1414
|
+
}
|
|
1415
|
+
match = pattern.exec(command);
|
|
1416
|
+
}
|
|
1417
|
+
}
|
|
1418
|
+
}
|
|
1419
|
+
_trackMessage(message) {
|
|
1420
|
+
this._messageCount++;
|
|
1421
|
+
const msg = message;
|
|
1422
|
+
const elapsed = Date.now() - this._startTime;
|
|
1423
|
+
this._debug.log(`
|
|
1424
|
+
═══════════════════════════════════════════════════`);
|
|
1425
|
+
this._debug.log(`Message #${this._messageCount} [${elapsed}ms] type=${msg.type} subtype=${msg.subtype ?? "none"}`);
|
|
1426
|
+
this._debug.log(`═══════════════════════════════════════════════════`);
|
|
1427
|
+
this._debug.log(JSON.stringify(msg, null, 2));
|
|
1428
|
+
if (msg.type === "assistant" && msg.message?.content) {
|
|
1429
|
+
const blocks = msg.message.content;
|
|
1430
|
+
for (const block of blocks) {
|
|
1431
|
+
if (block.type === "tool_use" && block.name && FILE_MODIFY_TOOLS.includes(block.name)) {
|
|
1432
|
+
const filePath = block.input?.file_path ?? block.input?.notebook_path;
|
|
1433
|
+
if (filePath) {
|
|
1434
|
+
this._debug.log(` → ${block.name} tool detected:`, filePath);
|
|
1435
|
+
this._modifiedFilePaths.add(filePath);
|
|
1436
|
+
}
|
|
1437
|
+
}
|
|
1438
|
+
if (block.type === "tool_use" && block.name === "Bash") {
|
|
1439
|
+
const command = block.input?.command;
|
|
1440
|
+
if (command) {
|
|
1441
|
+
this._extractBashOutputFiles(command);
|
|
1442
|
+
}
|
|
1443
|
+
}
|
|
1444
|
+
if (block.type === "tool_result" && block.content) {
|
|
1445
|
+
if (this._parseRunForAiVoting) {
|
|
1446
|
+
this._executionLogs.push(block.content.slice(0, 5000));
|
|
1447
|
+
}
|
|
1448
|
+
}
|
|
1449
|
+
if (block.type === "text" && block.text) {
|
|
1450
|
+
const codeMatches = block.text.match(/```(?:typescript|javascript|ts|js)?\n?([\s\S]*?)\n?```/g);
|
|
1451
|
+
if (codeMatches) {
|
|
1452
|
+
for (const match of codeMatches) {
|
|
1453
|
+
const code = match.replace(/```(?:typescript|javascript|ts|js)?\n?/, "").replace(/\n?```$/, "");
|
|
1454
|
+
if (code.trim().length > 50) {
|
|
1455
|
+
this._generatedCodeBlocks.push(code.trim());
|
|
1456
|
+
this._debug.log(` → Extracted code block (${code.length} chars)`);
|
|
1457
|
+
}
|
|
1458
|
+
}
|
|
1459
|
+
}
|
|
1460
|
+
}
|
|
1461
|
+
}
|
|
1462
|
+
}
|
|
1463
|
+
if (msg.type === "result" && msg.subtype === "success") {
|
|
1464
|
+
this._taskSucceeded = true;
|
|
1465
|
+
this._debug.timeEnd("Claude API call");
|
|
1466
|
+
this._debug.log("Task succeeded!");
|
|
1467
|
+
this._debug.log(" Duration:", msg.duration_ms, "ms");
|
|
1468
|
+
this._debug.log(" Total cost:", msg.total_cost_usd, "USD");
|
|
1469
|
+
this._debug.log(" Turns:", msg.num_turns);
|
|
1470
|
+
}
|
|
1471
|
+
if (msg.type === "result" && msg.subtype !== "success") {
|
|
1472
|
+
this._debug.timeEnd("Claude API call");
|
|
1473
|
+
this._debug.log("Task failed:", msg.subtype);
|
|
1474
|
+
}
|
|
1475
|
+
}
|
|
1476
|
+
async _uploadCache() {
|
|
1477
|
+
if (this._cacheUploadDone)
|
|
1478
|
+
return;
|
|
1479
|
+
this._cacheUploadDone = true;
|
|
1480
|
+
this._debug.log("Total messages streamed:", this._messageCount);
|
|
1481
|
+
this._debug.log("Modified files tracked:", this._modifiedFilePaths.size);
|
|
1482
|
+
this._debug.log("Code blocks extracted:", this._generatedCodeBlocks.length);
|
|
1483
|
+
const filesToCache = [];
|
|
1484
|
+
for (const filePath of this._modifiedFilePaths) {
|
|
1485
|
+
if (filePath.includes(CACHE_DIR)) {
|
|
1486
|
+
this._debug.log(" → Skipping cached file:", filePath);
|
|
1487
|
+
continue;
|
|
1488
|
+
}
|
|
1489
|
+
try {
|
|
1490
|
+
if (existsSync(filePath)) {
|
|
1491
|
+
const content = readFileSync2(filePath, "utf-8");
|
|
1492
|
+
if (content.includes("\x00")) {
|
|
1493
|
+
this._debug.log(" → Skipping binary file:", filePath);
|
|
1494
|
+
continue;
|
|
1495
|
+
}
|
|
1496
|
+
filesToCache.push({ path: filePath, content });
|
|
1497
|
+
this._debug.log(" → Will cache file:", filePath, `(${content.length} chars)`);
|
|
1498
|
+
} else {
|
|
1499
|
+
this._debug.log(" → File not found:", filePath);
|
|
1500
|
+
}
|
|
1501
|
+
} catch (err) {
|
|
1502
|
+
this._debug.log(" → Failed to read file:", filePath, err instanceof Error ? err : String(err));
|
|
1503
|
+
}
|
|
1504
|
+
}
|
|
1505
|
+
for (const filePath of this._bashGeneratedFiles) {
|
|
1506
|
+
if (this._modifiedFilePaths.has(filePath))
|
|
1507
|
+
continue;
|
|
1508
|
+
try {
|
|
1509
|
+
if (existsSync(filePath)) {
|
|
1510
|
+
const content = readFileSync2(filePath, "utf-8");
|
|
1511
|
+
if (!content.includes("\x00")) {
|
|
1512
|
+
filesToCache.push({ path: filePath, content });
|
|
1513
|
+
this._debug.log(" → Will cache Bash-generated file:", filePath, `(${content.length} chars)`);
|
|
1514
|
+
}
|
|
1515
|
+
}
|
|
1516
|
+
} catch {
|
|
1517
|
+
this._debug.log(" → Failed to read Bash-generated file:", filePath);
|
|
1518
|
+
}
|
|
1519
|
+
}
|
|
1520
|
+
if (this._generatedCodeBlocks.length > 0) {
|
|
1521
|
+
const largestBlock = this._generatedCodeBlocks.reduce((a, b) => a.length > b.length ? a : b);
|
|
1522
|
+
filesToCache.push({
|
|
1523
|
+
path: "generated-code.ts",
|
|
1524
|
+
content: largestBlock
|
|
1525
|
+
});
|
|
1526
|
+
this._debug.log(" → Will cache generated code block:", `(${largestBlock.length} chars)`);
|
|
1527
|
+
}
|
|
1528
|
+
this._debug.log("Total items to cache:", filesToCache.length);
|
|
1529
|
+
if (this._cacheEnabled && this._raysurfer && this._taskSucceeded && this._promptText) {
|
|
1530
|
+
const cachedBlocksForVoting = this._parseRunForAiVoting ? this._cachedFiles.map((f) => ({
|
|
1531
|
+
codeBlockId: f.codeBlockId,
|
|
1532
|
+
filename: f.filename,
|
|
1533
|
+
description: f.description
|
|
1534
|
+
})) : [];
|
|
1535
|
+
if (filesToCache.length > 0 || cachedBlocksForVoting.length > 0) {
|
|
1536
|
+
try {
|
|
1537
|
+
this._debug.time("Cache upload + voting");
|
|
1538
|
+
if (!this._parseRunForAiVoting) {
|
|
1539
|
+
this._debug.log("Skipping AI voting parse for this run due sampling");
|
|
1540
|
+
}
|
|
1541
|
+
const joinedLogs = this._parseRunForAiVoting && this._executionLogs.length > 0 ? this._executionLogs.join(`
|
|
1542
|
+
---
|
|
1543
|
+
`) : undefined;
|
|
1544
|
+
this._debug.log("Uploading", filesToCache.length, "files, voting for", cachedBlocksForVoting.length, "cached blocks,", this._executionLogs.length, "log entries...");
|
|
1545
|
+
for (const [i, file] of filesToCache.entries()) {
|
|
1546
|
+
await this._raysurfer.uploadNewCodeSnip({
|
|
1547
|
+
task: this._promptText,
|
|
1548
|
+
fileWritten: file,
|
|
1549
|
+
succeeded: true,
|
|
1550
|
+
cachedCodeBlocks: i === 0 && cachedBlocksForVoting.length > 0 ? cachedBlocksForVoting : undefined,
|
|
1551
|
+
useRaysurferAiVoting: this._parseRunForAiVoting,
|
|
1552
|
+
executionLogs: joinedLogs,
|
|
1553
|
+
perFunctionReputation: true
|
|
1554
|
+
});
|
|
1555
|
+
}
|
|
1556
|
+
if (filesToCache.length === 0 && cachedBlocksForVoting.length > 0) {
|
|
1557
|
+
for (const cb of cachedBlocksForVoting) {
|
|
1558
|
+
await this._raysurfer.voteCodeSnip({
|
|
1559
|
+
task: this._promptText,
|
|
1560
|
+
codeBlockId: cb.codeBlockId,
|
|
1561
|
+
codeBlockName: cb.filename,
|
|
1562
|
+
codeBlockDescription: cb.description,
|
|
1563
|
+
succeeded: true
|
|
1564
|
+
});
|
|
1565
|
+
}
|
|
1566
|
+
}
|
|
1567
|
+
this._debug.timeEnd("Cache upload + voting");
|
|
1568
|
+
this._debug.log("Cache upload successful, voting queued on backend");
|
|
1569
|
+
console.log("[raysurfer] Cache upload successful:", filesToCache.length, "files stored");
|
|
1570
|
+
} catch (error) {
|
|
1571
|
+
const errMsg = error instanceof Error ? error.message : String(error);
|
|
1572
|
+
this._debug.log("Cache upload failed:", errMsg);
|
|
1573
|
+
console.warn("[raysurfer] Cache upload failed:", errMsg);
|
|
1574
|
+
}
|
|
1575
|
+
}
|
|
1576
|
+
}
|
|
1577
|
+
this._debug.groupEnd();
|
|
1578
|
+
}
|
|
1579
|
+
async next(...args) {
|
|
1580
|
+
const inner = await this._ensureInit();
|
|
1581
|
+
const result = await inner.next(...args);
|
|
1582
|
+
if (!result.done) {
|
|
1583
|
+
this._trackMessage(result.value);
|
|
1584
|
+
} else {
|
|
1585
|
+
await this._uploadCache();
|
|
1586
|
+
}
|
|
1587
|
+
return result;
|
|
1588
|
+
}
|
|
1589
|
+
async return(value) {
|
|
1590
|
+
if (this._inner) {
|
|
1591
|
+
await this._uploadCache();
|
|
1592
|
+
return this._inner.return(value);
|
|
1593
|
+
}
|
|
1594
|
+
return { done: true, value: undefined };
|
|
1595
|
+
}
|
|
1596
|
+
async throw(e) {
|
|
1597
|
+
if (this._inner)
|
|
1598
|
+
return this._inner.throw(e);
|
|
1599
|
+
throw e;
|
|
1600
|
+
}
|
|
1601
|
+
[Symbol.asyncIterator]() {
|
|
1602
|
+
return this;
|
|
1603
|
+
}
|
|
1604
|
+
async[Symbol.asyncDispose]() {
|
|
1605
|
+
this.close();
|
|
1606
|
+
}
|
|
1607
|
+
async interrupt() {
|
|
1608
|
+
return (await this._ensureInit()).interrupt();
|
|
1609
|
+
}
|
|
1610
|
+
async setPermissionMode(mode) {
|
|
1611
|
+
return (await this._ensureInit()).setPermissionMode(mode);
|
|
1612
|
+
}
|
|
1613
|
+
async setModel(model) {
|
|
1614
|
+
return (await this._ensureInit()).setModel(model);
|
|
1615
|
+
}
|
|
1616
|
+
async setMaxThinkingTokens(maxThinkingTokens) {
|
|
1617
|
+
return (await this._ensureInit()).setMaxThinkingTokens(maxThinkingTokens);
|
|
1618
|
+
}
|
|
1619
|
+
async supportedCommands() {
|
|
1620
|
+
return (await this._ensureInit()).supportedCommands();
|
|
1621
|
+
}
|
|
1622
|
+
async supportedModels() {
|
|
1623
|
+
return (await this._ensureInit()).supportedModels();
|
|
1624
|
+
}
|
|
1625
|
+
async mcpServerStatus() {
|
|
1626
|
+
return (await this._ensureInit()).mcpServerStatus();
|
|
1627
|
+
}
|
|
1628
|
+
async accountInfo() {
|
|
1629
|
+
return (await this._ensureInit()).accountInfo();
|
|
1630
|
+
}
|
|
1631
|
+
async rewindFiles(userMessageId, options) {
|
|
1632
|
+
return (await this._ensureInit()).rewindFiles(userMessageId, options);
|
|
1633
|
+
}
|
|
1634
|
+
async setMcpServers(servers) {
|
|
1635
|
+
return (await this._ensureInit()).setMcpServers(servers);
|
|
1636
|
+
}
|
|
1637
|
+
async streamInput(stream) {
|
|
1638
|
+
return (await this._ensureInit()).streamInput(stream);
|
|
1639
|
+
}
|
|
1640
|
+
close() {
|
|
1641
|
+
if (this._inner)
|
|
1642
|
+
this._inner.close();
|
|
1643
|
+
}
|
|
1644
|
+
};
|
|
1645
|
+
sdk_client_default = query;
|
|
1646
|
+
});
|
|
1647
|
+
|
|
1648
|
+
// src/types.ts
|
|
1649
|
+
var ExecutionState;
|
|
1650
|
+
((ExecutionState2) => {
|
|
1651
|
+
ExecutionState2["COMPLETED"] = "completed";
|
|
1652
|
+
ExecutionState2["ERRORED"] = "errored";
|
|
1653
|
+
ExecutionState2["TIMED_OUT"] = "timed_out";
|
|
1654
|
+
ExecutionState2["CANCELLED"] = "cancelled";
|
|
1655
|
+
})(ExecutionState ||= {});
|
|
1656
|
+
var AgentVerdict;
|
|
1657
|
+
((AgentVerdict2) => {
|
|
1658
|
+
AgentVerdict2["THUMBS_UP"] = "thumbs_up";
|
|
1659
|
+
AgentVerdict2["THUMBS_DOWN"] = "thumbs_down";
|
|
1660
|
+
AgentVerdict2["PENDING"] = "pending";
|
|
1661
|
+
})(AgentVerdict ||= {});
|
|
1662
|
+
|
|
1663
|
+
// src/accessible.ts
|
|
1664
|
+
function toJsonLike(value) {
|
|
1665
|
+
if (value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
1666
|
+
return value;
|
|
1667
|
+
}
|
|
1668
|
+
if (value === undefined) {
|
|
1669
|
+
return null;
|
|
1670
|
+
}
|
|
1671
|
+
if (Array.isArray(value)) {
|
|
1672
|
+
return value.map((item) => toJsonLike(item));
|
|
1673
|
+
}
|
|
1674
|
+
if (typeof value === "object") {
|
|
1675
|
+
const result = {};
|
|
1676
|
+
for (const [key, nested] of Object.entries(value)) {
|
|
1677
|
+
result[key] = toJsonLike(nested);
|
|
1678
|
+
}
|
|
1679
|
+
return result;
|
|
1680
|
+
}
|
|
1681
|
+
return String(value);
|
|
1682
|
+
}
|
|
1683
|
+
function queueUsageTracking(fn, args, result, durationMs, errorMessage) {
|
|
1684
|
+
const client = fn._raysurferClient;
|
|
1685
|
+
if (!client)
|
|
1686
|
+
return;
|
|
1687
|
+
const codeBlockId = fn._raysurferSchema.codeBlockId ?? `function_registry:${fn._raysurferSchema.name}`;
|
|
1688
|
+
const outputData = errorMessage === undefined ? result : { error: errorMessage };
|
|
1689
|
+
client.storeExecution({
|
|
1690
|
+
codeBlockId,
|
|
1691
|
+
triggeringTask: `agent_accessible:${fn._raysurferSchema.name}`,
|
|
1692
|
+
inputData: {
|
|
1693
|
+
args: toJsonLike(args)
|
|
1694
|
+
},
|
|
1695
|
+
outputData: toJsonLike(outputData),
|
|
1696
|
+
executionState: errorMessage ? "errored" /* ERRORED */ : "completed" /* COMPLETED */,
|
|
1697
|
+
durationMs,
|
|
1698
|
+
errorMessage
|
|
1699
|
+
}).catch(() => {});
|
|
1700
|
+
}
|
|
1701
|
+
function inferParameters(fn) {
|
|
1702
|
+
const src = fn.toString();
|
|
1703
|
+
const match = /^[^(]*\(([^)]*)\)/.exec(src);
|
|
1704
|
+
const paramStr = match?.[1];
|
|
1705
|
+
if (!paramStr?.trim())
|
|
1706
|
+
return {};
|
|
1707
|
+
const params = {};
|
|
1708
|
+
const parts = paramStr.split(",");
|
|
1709
|
+
for (const part of parts) {
|
|
1710
|
+
const cleaned = part.trim().replace(/\/\*.*?\*\//g, "").replace(/=.*$/, "").replace(/:.*$/, "").trim();
|
|
1711
|
+
if (cleaned && cleaned !== "..." && !cleaned.startsWith("...")) {
|
|
1712
|
+
params[cleaned] = "string";
|
|
1713
|
+
}
|
|
1714
|
+
}
|
|
1715
|
+
return params;
|
|
1716
|
+
}
|
|
1717
|
+
function agentAccessible(fn, options) {
|
|
1718
|
+
const resolvedName = options?.name ?? fn.name ?? "anonymous";
|
|
1719
|
+
const resolvedDescription = options?.description ?? "";
|
|
1720
|
+
const resolvedSchema = options?.inputSchema ?? options?.parameters ?? inferParameters(fn);
|
|
1721
|
+
let marked;
|
|
1722
|
+
const wrapped = (...args) => {
|
|
1723
|
+
const started = Date.now();
|
|
1724
|
+
try {
|
|
1725
|
+
const result = fn(...args);
|
|
1726
|
+
if (result instanceof Promise) {
|
|
1727
|
+
const trackedPromise = result.then((resolved) => {
|
|
1728
|
+
queueUsageTracking(marked, args, resolved, Date.now() - started);
|
|
1729
|
+
return resolved;
|
|
1730
|
+
}).catch((error) => {
|
|
1731
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1732
|
+
queueUsageTracking(marked, args, null, Date.now() - started, message);
|
|
1733
|
+
throw error;
|
|
1734
|
+
});
|
|
1735
|
+
return trackedPromise;
|
|
1736
|
+
}
|
|
1737
|
+
queueUsageTracking(marked, args, result, Date.now() - started);
|
|
1738
|
+
return result;
|
|
1739
|
+
} catch (error) {
|
|
1740
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1741
|
+
queueUsageTracking(marked, args, null, Date.now() - started, message);
|
|
1742
|
+
throw error;
|
|
1743
|
+
}
|
|
1744
|
+
};
|
|
1745
|
+
marked = wrapped;
|
|
1746
|
+
marked._raysurferAccessible = true;
|
|
1747
|
+
marked._raysurferSchema = {
|
|
1748
|
+
name: resolvedName,
|
|
1749
|
+
description: resolvedDescription,
|
|
1750
|
+
inputSchema: resolvedSchema,
|
|
1751
|
+
parameters: resolvedSchema,
|
|
1752
|
+
source: fn.toString()
|
|
1753
|
+
};
|
|
1754
|
+
return marked;
|
|
1755
|
+
}
|
|
1756
|
+
function toAnthropicTool(fn) {
|
|
1757
|
+
const schema = fn._raysurferSchema;
|
|
1758
|
+
return {
|
|
1759
|
+
name: schema.name,
|
|
1760
|
+
description: schema.description,
|
|
1761
|
+
input_schema: schema.inputSchema
|
|
1762
|
+
};
|
|
1763
|
+
}
|
|
1764
|
+
async function publishFunctionRegistry(client, functions) {
|
|
1765
|
+
const snippetNames = [];
|
|
1766
|
+
for (const fn of functions) {
|
|
1767
|
+
if (!fn._raysurferAccessible)
|
|
1768
|
+
continue;
|
|
1769
|
+
const schema = fn._raysurferSchema;
|
|
1770
|
+
const resp = await client.uploadNewCodeSnip({
|
|
1771
|
+
task: `Call ${schema.name}: ${schema.description}`,
|
|
1772
|
+
fileWritten: { path: `${schema.name}.ts`, content: schema.source },
|
|
1773
|
+
succeeded: true,
|
|
1774
|
+
useRaysurferAiVoting: false,
|
|
1775
|
+
tags: ["function_registry", "agent_accessible"]
|
|
1776
|
+
});
|
|
1777
|
+
if (resp.snippetName) {
|
|
1778
|
+
snippetNames.push(resp.snippetName);
|
|
1779
|
+
schema.codeBlockId = resp.snippetName;
|
|
1780
|
+
}
|
|
1781
|
+
setTrackingClient(fn, client);
|
|
1782
|
+
}
|
|
1783
|
+
return snippetNames;
|
|
1784
|
+
}
|
|
1785
|
+
function setTrackingClient(fn, client) {
|
|
1786
|
+
fn._raysurferClient = client;
|
|
1787
|
+
}
|
|
1788
|
+
// src/agent.ts
|
|
1789
|
+
init_client();
|
|
1790
|
+
var DEFAULT_CODEGEN_MODEL = "claude-opus-4-6";
|
|
1791
|
+
var DEFAULT_EXECUTION_TIMEOUT_MS = 300000;
|
|
1792
|
+
var CODEGEN_DOCS_URL = "https://docs.raysurfer.com/sdk/typescript#programmatic-tool-calling";
|
|
1793
|
+
function missingCodegenKeyError(value) {
|
|
1794
|
+
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}`);
|
|
1795
|
+
}
|
|
1796
|
+
function invalidCodegenPromptError(value) {
|
|
1797
|
+
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}`);
|
|
1798
|
+
}
|
|
1799
|
+
|
|
1800
|
+
class CodegenApp {
|
|
1801
|
+
_raysurfer;
|
|
1802
|
+
_defaultCodegenApiKey;
|
|
1803
|
+
_defaultCodegenModel;
|
|
1804
|
+
_defaultExecutionTimeoutMs;
|
|
1805
|
+
constructor(options = {}) {
|
|
1806
|
+
const {
|
|
1807
|
+
raysurfer,
|
|
1808
|
+
codegenApiKey,
|
|
1809
|
+
codegenModel,
|
|
1810
|
+
executionTimeoutMs,
|
|
1811
|
+
...clientOptions
|
|
1812
|
+
} = options;
|
|
1813
|
+
this._raysurfer = raysurfer ?? new client_default(clientOptions);
|
|
1814
|
+
this._defaultCodegenApiKey = codegenApiKey;
|
|
1815
|
+
this._defaultCodegenModel = codegenModel ?? DEFAULT_CODEGEN_MODEL;
|
|
1816
|
+
this._defaultExecutionTimeoutMs = executionTimeoutMs ?? DEFAULT_EXECUTION_TIMEOUT_MS;
|
|
1817
|
+
}
|
|
1818
|
+
get raysurfer() {
|
|
1819
|
+
return this._raysurfer;
|
|
1820
|
+
}
|
|
1821
|
+
tool(name, description, parameters, callback) {
|
|
1822
|
+
this._raysurfer.tool(name, description, parameters, callback);
|
|
1823
|
+
return this;
|
|
1824
|
+
}
|
|
1825
|
+
async run(task, options = {}) {
|
|
1826
|
+
const codegenApiKey = this.resolveCodegenApiKey(options.codegenApiKey);
|
|
1827
|
+
const codegenPrompt = this.resolveCodegenPrompt(task, options.codegenPrompt);
|
|
1828
|
+
const codegenModel = options.codegenModel ?? this._defaultCodegenModel;
|
|
1829
|
+
const timeout = options.executionTimeoutMs ?? this._defaultExecutionTimeoutMs;
|
|
1830
|
+
return this._raysurfer.executeWithSandboxCodegen(task, {
|
|
1831
|
+
provider: "anthropic",
|
|
1832
|
+
apiKey: codegenApiKey,
|
|
1833
|
+
prompt: codegenPrompt,
|
|
1165
1834
|
model: codegenModel
|
|
1166
1835
|
}, { timeout });
|
|
1167
1836
|
}
|
|
@@ -1190,6 +1859,10 @@ class CodegenApp {
|
|
|
1190
1859
|
throw invalidCodegenPromptError(value);
|
|
1191
1860
|
}
|
|
1192
1861
|
}
|
|
1862
|
+
|
|
1863
|
+
// src/index.ts
|
|
1864
|
+
init_client();
|
|
1865
|
+
|
|
1193
1866
|
// src/config.ts
|
|
1194
1867
|
import { readFileSync } from "node:fs";
|
|
1195
1868
|
function coerceStringList(value) {
|
|
@@ -1339,6 +2012,10 @@ function loadConfig(path, modules) {
|
|
|
1339
2012
|
}
|
|
1340
2013
|
return functions;
|
|
1341
2014
|
}
|
|
2015
|
+
|
|
2016
|
+
// src/index.ts
|
|
2017
|
+
init_errors();
|
|
2018
|
+
|
|
1342
2019
|
// src/logging.ts
|
|
1343
2020
|
var CAP = 1000;
|
|
1344
2021
|
var telemetry = new Map;
|
|
@@ -1685,535 +2362,83 @@ class ProgrammaticToolCallingSession {
|
|
|
1685
2362
|
}
|
|
1686
2363
|
}
|
|
1687
2364
|
}
|
|
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
|
-
}
|
|
2365
|
+
// src/runner.ts
|
|
2366
|
+
init_client();
|
|
1822
2367
|
|
|
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;
|
|
2368
|
+
class Agent {
|
|
1841
2369
|
_apiKey;
|
|
1842
2370
|
_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({
|
|
2371
|
+
_agentId;
|
|
2372
|
+
_allowedTools;
|
|
2373
|
+
_systemPrompt;
|
|
2374
|
+
_model;
|
|
2375
|
+
_raysurfer;
|
|
2376
|
+
constructor(options = {}) {
|
|
2377
|
+
this._apiKey = options.apiKey;
|
|
2378
|
+
this._baseUrl = options.baseUrl;
|
|
2379
|
+
this._agentId = options.agentId;
|
|
2380
|
+
this._allowedTools = options.allowedTools ?? ["Read", "Write", "Bash"];
|
|
2381
|
+
this._systemPrompt = options.systemPrompt ?? "You are a helpful assistant.";
|
|
2382
|
+
this._model = options.model;
|
|
2383
|
+
}
|
|
2384
|
+
ensureClient(orgId) {
|
|
2385
|
+
if (!this._raysurfer || orgId) {
|
|
2386
|
+
this._raysurfer = new client_default({
|
|
1880
2387
|
apiKey: this._apiKey,
|
|
1881
2388
|
baseUrl: this._baseUrl,
|
|
1882
|
-
|
|
1883
|
-
snipsDesired:
|
|
1884
|
-
|
|
1885
|
-
agentId: this._extras.agentId
|
|
2389
|
+
organizationId: orgId,
|
|
2390
|
+
snipsDesired: orgId ? "company" : undefined,
|
|
2391
|
+
agentId: this._agentId
|
|
1886
2392
|
});
|
|
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
2393
|
}
|
|
2394
|
+
return this._raysurfer;
|
|
2031
2395
|
}
|
|
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
|
-
}
|
|
2396
|
+
async run(messages, options = {}) {
|
|
2397
|
+
const rs = this.ensureClient(options.orgId);
|
|
2398
|
+
const lastUserMsg = [...messages].reverse().find((m) => m.role === "user");
|
|
2399
|
+
if (!lastUserMsg) {
|
|
2400
|
+
throw new Error("Messages must contain at least one user message.");
|
|
2060
2401
|
}
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2402
|
+
const query2 = lastUserMsg.content;
|
|
2403
|
+
const runId = crypto.randomUUID();
|
|
2404
|
+
const searchResult = await rs.search({ task: query2 });
|
|
2405
|
+
const codeUsed = searchResult.matches?.map((m) => ({
|
|
2406
|
+
code_block_id: m.codeBlock.id,
|
|
2407
|
+
filename: m.codeBlock.name,
|
|
2408
|
+
description: m.codeBlock.description
|
|
2409
|
+
})) ?? [];
|
|
2410
|
+
let succeeded = false;
|
|
2411
|
+
const responseMessages = [];
|
|
2412
|
+
try {
|
|
2413
|
+
const { query: sdkQuery } = await Promise.resolve().then(() => (init_sdk_client(), exports_sdk_client));
|
|
2414
|
+
for await (const msg of sdkQuery({
|
|
2415
|
+
prompt: query2,
|
|
2416
|
+
options: {
|
|
2417
|
+
allowedTools: this._allowedTools,
|
|
2418
|
+
systemPrompt: this._systemPrompt,
|
|
2419
|
+
model: this._model
|
|
2071
2420
|
}
|
|
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);
|
|
2421
|
+
})) {
|
|
2422
|
+
responseMessages.push(msg);
|
|
2423
|
+
if (typeof msg === "object" && msg !== null && "type" in msg && msg.type === "result" && "subtype" in msg && msg.subtype === "success") {
|
|
2424
|
+
succeeded = true;
|
|
2130
2425
|
}
|
|
2131
2426
|
}
|
|
2427
|
+
} catch {
|
|
2428
|
+
succeeded = false;
|
|
2132
2429
|
}
|
|
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 });
|
|
2430
|
+
return {
|
|
2431
|
+
runId,
|
|
2432
|
+
query: query2,
|
|
2433
|
+
succeeded,
|
|
2434
|
+
messages: responseMessages,
|
|
2435
|
+
codeUsed
|
|
2436
|
+
};
|
|
2212
2437
|
}
|
|
2213
2438
|
}
|
|
2214
|
-
var sdk_client_default = query;
|
|
2215
2439
|
|
|
2216
2440
|
// src/index.ts
|
|
2441
|
+
init_sdk_client();
|
|
2217
2442
|
import {
|
|
2218
2443
|
AbortError,
|
|
2219
2444
|
createSdkMcpServer,
|
|
@@ -2237,6 +2462,7 @@ export {
|
|
|
2237
2462
|
agentAccessible,
|
|
2238
2463
|
ValidationError,
|
|
2239
2464
|
VERSION,
|
|
2465
|
+
ClaudeSDKClient as RaysurferOpencodeClient,
|
|
2240
2466
|
ClaudeSDKClient as RaysurferClient,
|
|
2241
2467
|
RaySurferError,
|
|
2242
2468
|
client_default as RaySurferDefault,
|
|
@@ -2251,6 +2477,7 @@ export {
|
|
|
2251
2477
|
CacheUnavailableError,
|
|
2252
2478
|
AuthenticationError,
|
|
2253
2479
|
AgentVerdict,
|
|
2480
|
+
Agent,
|
|
2254
2481
|
AbortError,
|
|
2255
2482
|
APIError
|
|
2256
2483
|
};
|