@blaxel/core 0.2.51-preview.125 → 0.2.52-dev.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/dist/cjs/.tsbuildinfo +1 -1
  2. package/dist/cjs/common/autoload.js +3 -0
  3. package/dist/cjs/common/sentry.js +219 -0
  4. package/dist/cjs/common/settings.js +13 -47
  5. package/dist/cjs/common/version.js +6 -0
  6. package/dist/cjs/sandbox/client/sdk.gen.js +124 -1
  7. package/dist/cjs/sandbox/filesystem/filesystem.js +81 -1
  8. package/dist/cjs/types/common/sentry.d.ts +17 -0
  9. package/dist/cjs/types/common/settings.d.ts +2 -1
  10. package/dist/cjs/types/common/version.d.ts +2 -0
  11. package/dist/cjs/types/sandbox/client/sdk.gen.d.ts +36 -1
  12. package/dist/cjs/types/sandbox/client/types.gen.d.ts +315 -0
  13. package/dist/cjs/types/sandbox/filesystem/filesystem.d.ts +5 -2
  14. package/dist/cjs/types/sandbox/filesystem/types.d.ts +20 -0
  15. package/dist/cjs-browser/.tsbuildinfo +1 -1
  16. package/dist/cjs-browser/common/autoload.js +3 -0
  17. package/dist/cjs-browser/common/sentry.js +219 -0
  18. package/dist/cjs-browser/common/settings.js +13 -47
  19. package/dist/cjs-browser/common/version.js +6 -0
  20. package/dist/cjs-browser/sandbox/client/sdk.gen.js +124 -1
  21. package/dist/cjs-browser/sandbox/filesystem/filesystem.js +81 -1
  22. package/dist/cjs-browser/types/common/sentry.d.ts +17 -0
  23. package/dist/cjs-browser/types/common/settings.d.ts +2 -1
  24. package/dist/cjs-browser/types/common/version.d.ts +2 -0
  25. package/dist/cjs-browser/types/sandbox/client/sdk.gen.d.ts +36 -1
  26. package/dist/cjs-browser/types/sandbox/client/types.gen.d.ts +315 -0
  27. package/dist/cjs-browser/types/sandbox/filesystem/filesystem.d.ts +5 -2
  28. package/dist/cjs-browser/types/sandbox/filesystem/types.d.ts +20 -0
  29. package/dist/esm/.tsbuildinfo +1 -1
  30. package/dist/esm/common/autoload.js +3 -0
  31. package/dist/esm/common/sentry.js +181 -0
  32. package/dist/esm/common/settings.js +13 -47
  33. package/dist/esm/common/version.js +3 -0
  34. package/dist/esm/sandbox/client/sdk.gen.js +116 -0
  35. package/dist/esm/sandbox/filesystem/filesystem.js +82 -2
  36. package/dist/esm-browser/.tsbuildinfo +1 -1
  37. package/dist/esm-browser/common/autoload.js +3 -0
  38. package/dist/esm-browser/common/sentry.js +181 -0
  39. package/dist/esm-browser/common/settings.js +13 -47
  40. package/dist/esm-browser/common/version.js +3 -0
  41. package/dist/esm-browser/sandbox/client/sdk.gen.js +116 -0
  42. package/dist/esm-browser/sandbox/filesystem/filesystem.js +82 -2
  43. package/package.json +4 -5
@@ -2,6 +2,7 @@ import { client } from "../client/client.gen.js";
2
2
  import { interceptors } from "../client/interceptors.js";
3
3
  import { responseInterceptors } from "../client/responseInterceptor.js";
4
4
  import { client as clientSandbox } from "../sandbox/client/client.gen.js";
5
+ import { initSentry } from "./sentry.js";
5
6
  import { settings } from "./settings.js";
6
7
  client.setConfig({
7
8
  baseUrl: settings.baseUrl,
@@ -18,6 +19,8 @@ for (const interceptor of responseInterceptors) {
18
19
  client.interceptors.response.use(interceptor);
19
20
  clientSandbox.interceptors.response.use(interceptor);
20
21
  }
22
+ // Initialize Sentry for SDK error tracking immediately when module loads
23
+ initSentry();
21
24
  // Allow to set custom configuration for browser environment
22
25
  export function initialize(config) {
23
26
  settings.setConfig(config);
@@ -0,0 +1,181 @@
1
+ import { settings } from "./settings.js";
2
+ import * as Sentry from "@sentry/node";
3
+ import { makeNodeTransport } from "@sentry/node";
4
+ // Isolated Sentry client for SDK-only error tracking (doesn't interfere with user's Sentry)
5
+ let sentryClient = null;
6
+ const capturedExceptions = new Set();
7
+ let handlersRegistered = false;
8
+ // SDK path patterns to identify errors originating from our SDK
9
+ const SDK_PATTERNS = [
10
+ "@blaxel/",
11
+ "blaxel-sdk",
12
+ "/node_modules/@blaxel/",
13
+ "/@blaxel/core/",
14
+ "/@blaxel/telemetry/",
15
+ ];
16
+ /**
17
+ * Check if an error originated from the SDK based on its stack trace.
18
+ * Returns true if the stack trace contains any SDK-related paths.
19
+ */
20
+ function isFromSDK(error) {
21
+ const stack = error.stack || "";
22
+ return SDK_PATTERNS.some((pattern) => stack.includes(pattern));
23
+ }
24
+ /**
25
+ * Initialize an isolated Sentry client for SDK error tracking.
26
+ * This creates a separate Sentry instance that won't interfere with any
27
+ * Sentry configuration the user might have in their application.
28
+ */
29
+ export function initSentry() {
30
+ try {
31
+ const dsn = settings.sentryDsn;
32
+ if (!dsn) {
33
+ return;
34
+ }
35
+ // Create an isolated Sentry client that doesn't touch the global scope
36
+ // This allows users to have their own Sentry.init() without conflicts
37
+ sentryClient = new Sentry.NodeClient({
38
+ dsn,
39
+ environment: settings.env,
40
+ release: `sdk-typescript@${settings.version}`,
41
+ transport: makeNodeTransport,
42
+ stackParser: Sentry.defaultStackParser,
43
+ // No integrations - we handle error capturing manually
44
+ integrations: [],
45
+ // Disable traces for the SDK client
46
+ tracesSampleRate: 0,
47
+ // Filter errors before sending - only send SDK errors
48
+ beforeSend(event, hint) {
49
+ const error = hint.originalException;
50
+ if (error instanceof Error) {
51
+ if (!isFromSDK(error)) {
52
+ // Drop errors that don't originate from SDK
53
+ return null;
54
+ }
55
+ }
56
+ return event;
57
+ },
58
+ });
59
+ sentryClient.init();
60
+ // Set SDK-specific tags
61
+ const scope = new Sentry.Scope();
62
+ scope.setTag("blaxel.workspace", settings.workspace);
63
+ scope.setTag("blaxel.version", settings.version);
64
+ scope.setTag("blaxel.commit", settings.commit);
65
+ scope.setClient(sentryClient);
66
+ // Register process handlers for uncaught errors (Node.js only)
67
+ // Only register once to prevent memory leaks
68
+ if (typeof process !== "undefined" &&
69
+ typeof process.on === "function" &&
70
+ !handlersRegistered) {
71
+ handlersRegistered = true;
72
+ // For SIGTERM/SIGINT, flush before exit
73
+ const signalHandler = (signal) => {
74
+ flushSentry(500)
75
+ .catch(() => {
76
+ // Silently fail
77
+ })
78
+ .finally(() => {
79
+ process.exit(signal === "SIGTERM" ? 143 : 130);
80
+ });
81
+ };
82
+ // Uncaught exception handler - only capture SDK errors
83
+ const uncaughtExceptionHandler = (error) => {
84
+ if (isFromSDK(error)) {
85
+ captureException(error);
86
+ }
87
+ // Let the default Node.js behavior handle the process exit
88
+ };
89
+ // Unhandled rejection handler - only capture SDK errors
90
+ const unhandledRejectionHandler = (reason) => {
91
+ const error = reason instanceof Error ? reason : new Error(String(reason));
92
+ if (isFromSDK(error)) {
93
+ captureException(error);
94
+ }
95
+ };
96
+ process.on("SIGTERM", () => signalHandler("SIGTERM"));
97
+ process.on("SIGINT", () => signalHandler("SIGINT"));
98
+ process.on("uncaughtException", uncaughtExceptionHandler);
99
+ process.on("unhandledRejection", unhandledRejectionHandler);
100
+ // Intercept console.error to capture SDK errors that are caught and logged
101
+ const originalConsoleError = console.error;
102
+ console.error = function (...args) {
103
+ // Call the original console.error first
104
+ originalConsoleError.apply(console, args);
105
+ // Check if any argument is an Error from SDK and capture it
106
+ for (const arg of args) {
107
+ if (arg instanceof Error && isFromSDK(arg)) {
108
+ captureException(arg);
109
+ break; // Only capture the first SDK error to avoid duplicates
110
+ }
111
+ }
112
+ };
113
+ }
114
+ }
115
+ catch (error) {
116
+ // Silently fail - Sentry initialization should never break the SDK
117
+ if (settings.env !== "production") {
118
+ console.error("[Blaxel SDK] Error initializing Sentry:", error);
119
+ }
120
+ }
121
+ }
122
+ /**
123
+ * Capture an exception to the SDK's isolated Sentry client.
124
+ * Only errors originating from SDK code will be captured.
125
+ *
126
+ * @param error - The error to capture
127
+ */
128
+ function captureException(error) {
129
+ if (sentryClient === null) {
130
+ return;
131
+ }
132
+ // Double-check that error is from SDK (defense in depth)
133
+ if (!isFromSDK(error)) {
134
+ return;
135
+ }
136
+ try {
137
+ // Create a unique identifier for this exception to avoid duplicates
138
+ const errorKey = `${error.name}:${error.message}:${error.stack?.slice(0, 200)}`;
139
+ if (capturedExceptions.has(errorKey)) {
140
+ return;
141
+ }
142
+ capturedExceptions.add(errorKey);
143
+ // Clean up old exception keys to prevent memory leak
144
+ if (capturedExceptions.size > 1000) {
145
+ capturedExceptions.clear();
146
+ }
147
+ // Create a scope with SDK tags and capture the exception
148
+ const scope = new Sentry.Scope();
149
+ scope.setTag("blaxel.workspace", settings.workspace);
150
+ scope.setTag("blaxel.version", settings.version);
151
+ scope.setTag("blaxel.commit", settings.commit);
152
+ scope.setClient(sentryClient);
153
+ scope.captureException(error);
154
+ }
155
+ catch {
156
+ // Silently fail - error capturing should never break the SDK
157
+ }
158
+ }
159
+ /**
160
+ * Flush pending Sentry events.
161
+ * This should be called before the process exits to ensure all events are sent.
162
+ *
163
+ * @param timeout - Maximum time in milliseconds to wait for flush (default: 2000)
164
+ */
165
+ export async function flushSentry(timeout = 2000) {
166
+ if (sentryClient === null) {
167
+ return;
168
+ }
169
+ try {
170
+ await sentryClient.flush(timeout);
171
+ }
172
+ catch {
173
+ // Silently fail
174
+ }
175
+ }
176
+ /**
177
+ * Check if Sentry is initialized and available.
178
+ */
179
+ export function isSentryInitialized() {
180
+ return sentryClient !== null;
181
+ }
@@ -1,25 +1,9 @@
1
1
  import { authentication } from "../authentication/index.js";
2
2
  import { env } from "../common/env.js";
3
- // Function to get package version
4
- function getPackageVersion() {
5
- try {
6
- // Check if require is available (CommonJS environment)
7
- if (typeof require !== "undefined") {
8
- // Try to require package.json (Node.js only, gracefully fails in browser)
9
- // eslint-disable-next-line @typescript-eslint/no-require-imports
10
- const packageJson = {"version":"0.2.51-preview.125","commit":"3853140a51897f5f5d076412f419c105d7f968ab"};
11
- return packageJson.version || "unknown";
12
- }
13
- else {
14
- // ESM environment - return unknown
15
- return "unknown";
16
- }
17
- }
18
- catch {
19
- // Fallback for browser environments or if require fails
20
- return "unknown";
21
- }
22
- }
3
+ // Build info - these placeholders are replaced at build time by build:replace-imports
4
+ const BUILD_VERSION = "0.2.52-dev.8";
5
+ const BUILD_COMMIT = "fa33ac70c1091576d0ebc47218eed9f378d94a32";
6
+ const BUILD_SENTRY_DSN = "";
23
7
  // Function to get OS and architecture
24
8
  function getOsArch() {
25
9
  try {
@@ -52,30 +36,9 @@ function getOsArch() {
52
36
  }
53
37
  return "browser/unknown";
54
38
  }
55
- // Function to get commit hash
56
- function getCommitHash() {
57
- try {
58
- // Check if require is available (CommonJS environment)
59
- if (typeof require !== "undefined") {
60
- // Try to require package.json and look for commit field (set during build)
61
- // eslint-disable-next-line @typescript-eslint/no-require-imports
62
- const packageJson = {"version":"0.2.51-preview.125","commit":"3853140a51897f5f5d076412f419c105d7f968ab"};
63
- // Check for commit in various possible locations
64
- const commit = packageJson.commit || packageJson.buildInfo?.commit;
65
- if (commit) {
66
- return commit.length > 7 ? commit.substring(0, 7) : commit;
67
- }
68
- }
69
- }
70
- catch {
71
- // Fallback for browser environments or if require fails
72
- }
73
- return "unknown";
74
- }
75
39
  class Settings {
76
40
  credentials;
77
41
  config;
78
- _version = null;
79
42
  constructor() {
80
43
  this.credentials = authentication();
81
44
  this.config = {
@@ -130,18 +93,21 @@ class Settings {
130
93
  return this.credentials.token;
131
94
  }
132
95
  get version() {
133
- if (this._version === null) {
134
- this._version = getPackageVersion();
135
- }
136
- return this._version;
96
+ return BUILD_VERSION || "unknown";
97
+ }
98
+ get commit() {
99
+ const commit = BUILD_COMMIT || "unknown";
100
+ return commit.length > 7 ? commit.substring(0, 7) : commit;
101
+ }
102
+ get sentryDsn() {
103
+ return BUILD_SENTRY_DSN || "";
137
104
  }
138
105
  get headers() {
139
106
  const osArch = getOsArch();
140
- const commitHash = getCommitHash();
141
107
  return {
142
108
  "x-blaxel-authorization": this.authorization,
143
109
  "x-blaxel-workspace": this.workspace || "",
144
- "User-Agent": `blaxel/sdk/typescript/${this.version} (${osArch}) blaxel/${commitHash}`,
110
+ "User-Agent": `blaxel/sdk/typescript/${this.version} (${osArch}) blaxel/${this.commit}`,
145
111
  };
146
112
  }
147
113
  get name() {
@@ -0,0 +1,3 @@
1
+ // This file is auto-generated during build. Do not edit manually.
2
+ export const PACKAGE_VERSION = "0.2.50";
3
+ export const PACKAGE_COMMIT = "4a74989dcb65a6ff8d826aed7976436c64554f6a";
@@ -164,6 +164,38 @@ export const getCodegenRerankingByPath = (options) => {
164
164
  ...options
165
165
  });
166
166
  };
167
+ /**
168
+ * Search for text content in files
169
+ * Searches for text content inside files using ripgrep. Returns matching lines with context.
170
+ */
171
+ export const getFilesystemContentSearchByPath = (options) => {
172
+ return (options.client ?? _heyApiClient).get({
173
+ security: [
174
+ {
175
+ scheme: 'bearer',
176
+ type: 'http'
177
+ }
178
+ ],
179
+ url: '/filesystem-content-search/{path}',
180
+ ...options
181
+ });
182
+ };
183
+ /**
184
+ * Find files and directories
185
+ * Finds files and directories using the find command.
186
+ */
187
+ export const getFilesystemFindByPath = (options) => {
188
+ return (options.client ?? _heyApiClient).get({
189
+ security: [
190
+ {
191
+ scheme: 'bearer',
192
+ type: 'http'
193
+ }
194
+ ],
195
+ url: '/filesystem-find/{path}',
196
+ ...options
197
+ });
198
+ };
167
199
  /**
168
200
  * List multipart uploads
169
201
  * List all active multipart uploads
@@ -273,6 +305,22 @@ export const postFilesystemMultipartInitiateByPath = (options) => {
273
305
  }
274
306
  });
275
307
  };
308
+ /**
309
+ * Fuzzy search for files and directories
310
+ * Performs fuzzy search on filesystem paths using fuzzy matching algorithm. Optimized alternative to find and grep commands.
311
+ */
312
+ export const getFilesystemSearchByPath = (options) => {
313
+ return (options.client ?? _heyApiClient).get({
314
+ security: [
315
+ {
316
+ scheme: 'bearer',
317
+ type: 'http'
318
+ }
319
+ ],
320
+ url: '/filesystem-search/{path}',
321
+ ...options
322
+ });
323
+ };
276
324
  /**
277
325
  * Delete file or directory
278
326
  * Delete a file or directory
@@ -325,6 +373,58 @@ export const putFilesystemByPath = (options) => {
325
373
  }
326
374
  });
327
375
  };
376
+ /**
377
+ * Delete directory tree
378
+ * Delete a directory tree recursively
379
+ */
380
+ export const deleteFilesystemTreeByPath = (options) => {
381
+ return (options.client ?? _heyApiClient).delete({
382
+ security: [
383
+ {
384
+ scheme: 'bearer',
385
+ type: 'http'
386
+ }
387
+ ],
388
+ url: '/filesystem/tree/{path}',
389
+ ...options
390
+ });
391
+ };
392
+ /**
393
+ * Get directory tree
394
+ * Get a recursive directory tree structure starting from the specified path
395
+ */
396
+ export const getFilesystemTreeByPath = (options) => {
397
+ return (options.client ?? _heyApiClient).get({
398
+ security: [
399
+ {
400
+ scheme: 'bearer',
401
+ type: 'http'
402
+ }
403
+ ],
404
+ url: '/filesystem/tree/{path}',
405
+ ...options
406
+ });
407
+ };
408
+ /**
409
+ * Create or update directory tree
410
+ * Create or update multiple files within a directory tree structure
411
+ */
412
+ export const putFilesystemTreeByPath = (options) => {
413
+ return (options.client ?? _heyApiClient).put({
414
+ security: [
415
+ {
416
+ scheme: 'bearer',
417
+ type: 'http'
418
+ }
419
+ ],
420
+ url: '/filesystem/tree/{path}',
421
+ ...options,
422
+ headers: {
423
+ 'Content-Type': 'application/json',
424
+ ...options?.headers
425
+ }
426
+ });
427
+ };
328
428
  /**
329
429
  * Stop monitoring ports for a process
330
430
  * Stop monitoring for new ports opened by a process
@@ -509,3 +609,19 @@ export const getWatchFilesystemByPath = (options) => {
509
609
  ...options
510
610
  });
511
611
  };
612
+ /**
613
+ * WebSocket endpoint
614
+ * WebSocket endpoint for all sandbox operations
615
+ */
616
+ export const getWs = (options) => {
617
+ return (options?.client ?? _heyApiClient).get({
618
+ security: [
619
+ {
620
+ scheme: 'bearer',
621
+ type: 'http'
622
+ }
623
+ ],
624
+ url: '/ws',
625
+ ...options
626
+ });
627
+ };
@@ -1,7 +1,7 @@
1
- import { settings } from "../../common/settings.js";
2
1
  import { fs } from "../../common/node.js";
2
+ import { settings } from "../../common/settings.js";
3
3
  import { SandboxAction } from "../action.js";
4
- import { deleteFilesystemByPath, getFilesystemByPath, getWatchFilesystemByPath, putFilesystemByPath, postFilesystemMultipartInitiateByPath, putFilesystemMultipartByUploadIdPart, postFilesystemMultipartByUploadIdComplete, deleteFilesystemMultipartByUploadIdAbort } from "../client/index.js";
4
+ import { deleteFilesystemByPath, deleteFilesystemMultipartByUploadIdAbort, getFilesystemByPath, getFilesystemContentSearchByPath, getFilesystemFindByPath, getFilesystemSearchByPath, getWatchFilesystemByPath, postFilesystemMultipartByUploadIdComplete, postFilesystemMultipartInitiateByPath, putFilesystemByPath, putFilesystemMultipartByUploadIdPart } from "../client/index.js";
5
5
  // Multipart upload constants
6
6
  const MULTIPART_THRESHOLD = 5 * 1024 * 1024; // 5MB
7
7
  const CHUNK_SIZE = 5 * 1024 * 1024; // 5MB per part
@@ -196,6 +196,86 @@ export class SandboxFileSystem extends SandboxAction {
196
196
  }
197
197
  return data;
198
198
  }
199
+ async search(query, path = "/", options) {
200
+ const formattedPath = this.formatPath(path);
201
+ const queryParams = {};
202
+ if (options?.maxResults !== undefined) {
203
+ queryParams.maxResults = options.maxResults;
204
+ }
205
+ if (options?.patterns && options.patterns.length > 0) {
206
+ queryParams.patterns = options.patterns.join(',');
207
+ }
208
+ if (options?.excludeDirs && options.excludeDirs.length > 0) {
209
+ queryParams.excludeDirs = options.excludeDirs.join(',');
210
+ }
211
+ if (options?.excludeHidden !== undefined) {
212
+ queryParams.excludeHidden = options.excludeHidden;
213
+ }
214
+ const result = await getFilesystemSearchByPath({
215
+ path: { path: formattedPath },
216
+ query: queryParams,
217
+ baseUrl: this.url,
218
+ client: this.client,
219
+ });
220
+ this.handleResponseError(result.response, result.data, result.error);
221
+ return result.data;
222
+ }
223
+ async find(path, options) {
224
+ const formattedPath = this.formatPath(path);
225
+ const queryParams = {};
226
+ if (options?.type) {
227
+ queryParams.type = options.type;
228
+ }
229
+ if (options?.patterns && options.patterns.length > 0) {
230
+ queryParams.patterns = options.patterns.join(',');
231
+ }
232
+ if (options?.maxResults !== undefined) {
233
+ queryParams.maxResults = options.maxResults;
234
+ }
235
+ if (options?.excludeDirs && options.excludeDirs.length > 0) {
236
+ queryParams.excludeDirs = options.excludeDirs.join(',');
237
+ }
238
+ if (options?.excludeHidden !== undefined) {
239
+ queryParams.excludeHidden = options.excludeHidden;
240
+ }
241
+ const result = await getFilesystemFindByPath({
242
+ path: { path: formattedPath },
243
+ query: queryParams,
244
+ baseUrl: this.url,
245
+ client: this.client,
246
+ });
247
+ this.handleResponseError(result.response, result.data, result.error);
248
+ return result.data;
249
+ }
250
+ async grep(query, path = "/", options) {
251
+ const formattedPath = this.formatPath(path);
252
+ const queryParams = {
253
+ query,
254
+ };
255
+ if (options?.caseSensitive !== undefined) {
256
+ queryParams.caseSensitive = options.caseSensitive;
257
+ }
258
+ if (options?.contextLines !== undefined) {
259
+ queryParams.contextLines = options.contextLines;
260
+ }
261
+ if (options?.maxResults !== undefined) {
262
+ queryParams.maxResults = options.maxResults;
263
+ }
264
+ if (options?.filePattern) {
265
+ queryParams.filePattern = options.filePattern;
266
+ }
267
+ if (options?.excludeDirs && options.excludeDirs.length > 0) {
268
+ queryParams.excludeDirs = options.excludeDirs.join(',');
269
+ }
270
+ const result = await getFilesystemContentSearchByPath({
271
+ path: { path: formattedPath },
272
+ query: queryParams,
273
+ baseUrl: this.url,
274
+ client: this.client,
275
+ });
276
+ this.handleResponseError(result.response, result.data, result.error);
277
+ return result.data;
278
+ }
199
279
  async cp(source, destination, { maxWait = 180000 } = {}) {
200
280
  let process = await this.process.exec({
201
281
  command: `cp -r ${source} ${destination}`,