raysurfer 1.4.2 → 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/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 __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __hasOwnProp = Object.prototype.hasOwnProperty;
7
- var __toESM = (mod, isNodeMode, target) => {
8
- target = mod != null ? __create(__getProtoOf(mod)) : {};
9
- const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
10
- for (let key of __getOwnPropNames(mod))
11
- if (!__hasOwnProp.call(to, key))
12
- __defProp(to, key, {
13
- get: () => mod[key],
14
- enumerable: true
15
- });
16
- return to;
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/types.ts
21
- var ExecutionState;
22
- ((ExecutionState2) => {
23
- ExecutionState2["COMPLETED"] = "completed";
24
- ExecutionState2["ERRORED"] = "errored";
25
- ExecutionState2["TIMED_OUT"] = "timed_out";
26
- ExecutionState2["CANCELLED"] = "cancelled";
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
- return result;
52
- }
53
- return String(value);
54
- }
55
- function queueUsageTracking(fn, args, result, durationMs, errorMessage) {
56
- const client = fn._raysurferClient;
57
- if (!client)
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
- return params;
88
- }
89
- function agentAccessible(fn, options) {
90
- const resolvedName = options?.name ?? fn.name ?? "anonymous";
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
- marked = wrapped;
118
- marked._raysurferAccessible = true;
119
- marked._raysurferSchema = {
120
- name: resolvedName,
121
- description: resolvedDescription,
122
- inputSchema: resolvedSchema,
123
- parameters: resolvedSchema,
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
- return marked;
127
- }
128
- function toAnthropicTool(fn) {
129
- const schema = fn._raysurferSchema;
130
- return {
131
- name: schema.name,
132
- description: schema.description,
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
- async function publishFunctionRegistry(client, functions) {
137
- const snippetNames = [];
138
- for (const fn of functions) {
139
- if (!fn._raysurferAccessible)
140
- continue;
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
- setTrackingClient(fn, client);
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 filesWritten.");
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
- "The following validated code has been retrieved from the cache. " + `Use these files directly instead of regenerating code.
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 client_default = RaySurfer;
1119
-
1120
- // src/agent.ts
1121
- var DEFAULT_CODEGEN_MODEL = "claude-opus-4-6";
1122
- var DEFAULT_EXECUTION_TIMEOUT_MS = 300000;
1123
- var CODEGEN_DOCS_URL = "https://docs.raysurfer.com/sdk/typescript#programmatic-tool-calling";
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
- class CodegenApp {
1132
- _raysurfer;
1133
- _defaultCodegenApiKey;
1134
- _defaultCodegenModel;
1135
- _defaultExecutionTimeoutMs;
1136
- constructor(options = {}) {
1137
- const {
1138
- raysurfer,
1139
- codegenApiKey,
1140
- codegenModel,
1141
- executionTimeoutMs,
1142
- ...clientOptions
1143
- } = options;
1144
- this._raysurfer = raysurfer ?? new client_default(clientOptions);
1145
- this._defaultCodegenApiKey = codegenApiKey;
1146
- this._defaultCodegenModel = codegenModel ?? DEFAULT_CODEGEN_MODEL;
1147
- this._defaultExecutionTimeoutMs = executionTimeoutMs ?? DEFAULT_EXECUTION_TIMEOUT_MS;
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
- get raysurfer() {
1150
- return this._raysurfer;
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
- tool(name, description, parameters, callback) {
1153
- this._raysurfer.tool(name, description, parameters, callback);
1154
- return this;
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
- async run(task, options = {}) {
1157
- const codegenApiKey = this.resolveCodegenApiKey(options.codegenApiKey);
1158
- const codegenPrompt = this.resolveCodegenPrompt(task, options.codegenPrompt);
1159
- const codegenModel = options.codegenModel ?? this._defaultCodegenModel;
1160
- const timeout = options.executionTimeoutMs ?? this._defaultExecutionTimeoutMs;
1161
- return this._raysurfer.executeWithSandboxCodegen(task, {
1162
- provider: "anthropic",
1163
- apiKey: codegenApiKey,
1164
- prompt: codegenPrompt,
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/sdk-client.ts
1689
- import { existsSync, mkdirSync, readFileSync as readFileSync2, writeFileSync } from "node:fs";
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 RaysurferQuery {
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
- _extras;
1844
- _sdkOptions;
1845
- _runParseSampleRate;
1846
- _parseRunForAiVoting;
1847
- constructor(params) {
1848
- this._params = params;
1849
- const options = params.options ?? {};
1850
- const { sdkOptions, extras } = splitOptions(options);
1851
- this._sdkOptions = applyDefaultAgentCompatibilityOptions(sdkOptions);
1852
- this._extras = extras;
1853
- this._promptText = typeof params.prompt === "string" ? params.prompt : null;
1854
- const debugEnabled = extras.debug || process.env.RAYSURFER_DEBUG === "true";
1855
- this._debug = createDebugLogger(debugEnabled);
1856
- this._apiKey = process.env.RAYSURFER_API_KEY;
1857
- this._baseUrl = process.env.RAYSURFER_BASE_URL || DEFAULT_RAYSURFER_URL;
1858
- this._cacheEnabled = !!this._apiKey;
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
- workspaceId: this._extras.workspaceId,
1883
- snipsDesired: this._extras.workspaceId ? "client" : undefined,
1884
- publicSnips: this._extras.publicSnips,
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 _uploadCache() {
2033
- if (this._cacheUploadDone)
2034
- return;
2035
- this._cacheUploadDone = true;
2036
- this._debug.log("Total messages streamed:", this._messageCount);
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
- for (const filePath of this._bashGeneratedFiles) {
2062
- if (this._modifiedFilePaths.has(filePath))
2063
- continue;
2064
- try {
2065
- if (existsSync(filePath)) {
2066
- const content = readFileSync2(filePath, "utf-8");
2067
- if (!content.includes("\x00")) {
2068
- filesToCache.push({ path: filePath, content });
2069
- this._debug.log(" → Will cache Bash-generated file:", filePath, `(${content.length} chars)`);
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
- } catch {
2073
- this._debug.log(" → Failed to read Bash-generated file:", filePath);
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
- this._debug.groupEnd();
2134
- }
2135
- async next(...args) {
2136
- const inner = await this._ensureInit();
2137
- const result = await inner.next(...args);
2138
- if (!result.done) {
2139
- this._trackMessage(result.value);
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,
@@ -2252,6 +2477,7 @@ export {
2252
2477
  CacheUnavailableError,
2253
2478
  AuthenticationError,
2254
2479
  AgentVerdict,
2480
+ Agent,
2255
2481
  AbortError,
2256
2482
  APIError
2257
2483
  };