@blaxel/core 0.2.55-preview.17 → 0.2.56-dev.23

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 (33) hide show
  1. package/dist/cjs/.tsbuildinfo +1 -1
  2. package/dist/cjs/client/sdk.gen.js +2 -36
  3. package/dist/cjs/common/sentry.js +227 -131
  4. package/dist/cjs/common/settings.js +3 -3
  5. package/dist/cjs/common/version.js +6 -0
  6. package/dist/cjs/types/client/sdk.gen.d.ts +1 -11
  7. package/dist/cjs/types/client/types.gen.d.ts +0 -48
  8. package/dist/cjs/types/common/sentry.d.ts +1 -3
  9. package/dist/cjs/types/common/version.d.ts +2 -0
  10. package/dist/cjs/types/sandbox/client/sdk.gen.d.ts +3 -3
  11. package/dist/cjs-browser/.tsbuildinfo +1 -1
  12. package/dist/cjs-browser/client/sdk.gen.js +2 -36
  13. package/dist/cjs-browser/common/sentry-browser.js +27 -0
  14. package/dist/cjs-browser/common/sentry.js +306 -11
  15. package/dist/cjs-browser/common/settings.js +3 -3
  16. package/dist/cjs-browser/common/version.js +6 -0
  17. package/dist/cjs-browser/types/client/sdk.gen.d.ts +1 -11
  18. package/dist/cjs-browser/types/client/types.gen.d.ts +0 -48
  19. package/dist/cjs-browser/types/common/sentry.d.ts +1 -3
  20. package/dist/cjs-browser/types/common/version.d.ts +2 -0
  21. package/dist/cjs-browser/types/sandbox/client/sdk.gen.d.ts +3 -3
  22. package/dist/esm/.tsbuildinfo +1 -1
  23. package/dist/esm/client/sdk.gen.js +0 -32
  24. package/dist/esm/common/sentry.js +227 -98
  25. package/dist/esm/common/settings.js +3 -3
  26. package/dist/esm/common/version.js +3 -0
  27. package/dist/esm-browser/.tsbuildinfo +1 -1
  28. package/dist/esm-browser/client/sdk.gen.js +0 -32
  29. package/dist/esm-browser/common/sentry-browser.js +22 -0
  30. package/dist/esm-browser/common/sentry.js +306 -11
  31. package/dist/esm-browser/common/settings.js +3 -3
  32. package/dist/esm-browser/common/version.js +3 -0
  33. package/package.json +2 -4
@@ -1206,38 +1206,6 @@ export const deleteSandboxPreviewToken = (options) => {
1206
1206
  ...options
1207
1207
  });
1208
1208
  };
1209
- /**
1210
- * Start Sandbox
1211
- * Starts a Sandbox by name.
1212
- */
1213
- export const startSandbox = (options) => {
1214
- return (options.client ?? _heyApiClient).put({
1215
- security: [
1216
- {
1217
- scheme: 'bearer',
1218
- type: 'http'
1219
- }
1220
- ],
1221
- url: '/sandboxes/{sandboxName}/start',
1222
- ...options
1223
- });
1224
- };
1225
- /**
1226
- * Stop Sandbox
1227
- * Stops a Sandbox by name.
1228
- */
1229
- export const stopSandbox = (options) => {
1230
- return (options.client ?? _heyApiClient).put({
1231
- security: [
1232
- {
1233
- scheme: 'bearer',
1234
- type: 'http'
1235
- }
1236
- ],
1237
- url: '/sandboxes/{sandboxName}/stop',
1238
- ...options
1239
- });
1240
- };
1241
1209
  /**
1242
1210
  * Get workspace service accounts
1243
1211
  * Returns a list of all service accounts in the workspace.
@@ -0,0 +1,22 @@
1
+ /* eslint-disable */
2
+ // Browser/Edge-compatible exports for Sentry
3
+ // In browser/edge environments, @sentry/node is not available
4
+ // All functions are no-ops
5
+ /**
6
+ * Initialize Sentry - no-op in browser/edge environments.
7
+ */
8
+ export function initSentry() {
9
+ // No-op in browser/edge environments
10
+ }
11
+ /**
12
+ * Flush pending Sentry events - no-op in browser/edge environments.
13
+ */
14
+ export async function flushSentry(_timeout = 2000) {
15
+ // No-op in browser/edge environments
16
+ }
17
+ /**
18
+ * Check if Sentry is initialized - always returns false in browser/edge environments.
19
+ */
20
+ export function isSentryInitialized() {
21
+ return false;
22
+ }
@@ -1,22 +1,317 @@
1
- /* eslint-disable */
2
- // Browser/Edge-compatible exports for Sentry
3
- // In browser/edge environments, @sentry/node is not available
4
- // All functions are no-ops
1
+ import { settings } from "./settings.js";
2
+ // Lightweight Sentry client using fetch - only captures SDK errors
3
+ let sentryInitialized = false;
4
+ const capturedExceptions = new Set();
5
+ let handlersRegistered = false;
6
+ // Parsed DSN components
7
+ let sentryConfig = null;
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
+ ];
5
16
  /**
6
- * Initialize Sentry - no-op in browser/edge environments.
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
+ * Parse a Sentry DSN into its components.
26
+ * DSN format: https://{public_key}@{host}/{project_id}
27
+ */
28
+ function parseDsn(dsn) {
29
+ try {
30
+ const url = new URL(dsn);
31
+ const publicKey = url.username;
32
+ const host = url.host;
33
+ const projectId = url.pathname.slice(1); // Remove leading slash
34
+ if (!publicKey || !host || !projectId) {
35
+ return null;
36
+ }
37
+ return { publicKey, host, projectId };
38
+ }
39
+ catch {
40
+ return null;
41
+ }
42
+ }
43
+ /**
44
+ * Generate a UUID v4
45
+ */
46
+ function generateEventId() {
47
+ return "xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx".replace(/[xy]/g, (c) => {
48
+ const r = (Math.random() * 16) | 0;
49
+ const v = c === "x" ? r : (r & 0x3) | 0x8;
50
+ return v.toString(16);
51
+ });
52
+ }
53
+ /**
54
+ * Convert an Error to a Sentry event payload.
55
+ */
56
+ function errorToSentryEvent(error) {
57
+ const frames = parseStackTrace(error.stack || "");
58
+ return {
59
+ event_id: generateEventId(),
60
+ timestamp: Date.now() / 1000,
61
+ platform: "javascript",
62
+ level: "error",
63
+ environment: settings.env,
64
+ release: `sdk-typescript@${settings.version}`,
65
+ tags: {
66
+ "blaxel.workspace": settings.workspace,
67
+ "blaxel.version": settings.version,
68
+ "blaxel.commit": settings.commit,
69
+ },
70
+ exception: {
71
+ values: [
72
+ {
73
+ type: error.name,
74
+ value: error.message,
75
+ stacktrace: {
76
+ frames,
77
+ },
78
+ },
79
+ ],
80
+ },
81
+ };
82
+ }
83
+ /**
84
+ * Parse a stack trace string into Sentry-compatible frames.
85
+ */
86
+ function parseStackTrace(stack) {
87
+ const lines = stack.split("\n").slice(1); // Skip first line (error message)
88
+ const frames = [];
89
+ for (const line of lines) {
90
+ // Match patterns like "at functionName (filename:line:col)" or "at filename:line:col"
91
+ const match = line.match(/at\s+(?:(.+?)\s+\()?(.+?):(\d+):(\d+)\)?/);
92
+ if (match) {
93
+ frames.unshift({
94
+ function: match[1] || "<anonymous>",
95
+ filename: match[2],
96
+ lineno: parseInt(match[3], 10),
97
+ colno: parseInt(match[4], 10),
98
+ });
99
+ }
100
+ }
101
+ return frames;
102
+ }
103
+ /**
104
+ * Send an event to Sentry using fetch.
105
+ */
106
+ async function sendToSentry(event) {
107
+ if (!sentryConfig)
108
+ return;
109
+ const { publicKey, host, projectId } = sentryConfig;
110
+ const envelopeUrl = `https://${host}/api/${projectId}/envelope/`;
111
+ // Create envelope header
112
+ const envelopeHeader = JSON.stringify({
113
+ event_id: event.event_id,
114
+ sent_at: new Date().toISOString(),
115
+ dsn: `https://${publicKey}@${host}/${projectId}`,
116
+ });
117
+ // Create item header
118
+ const itemHeader = JSON.stringify({
119
+ type: "event",
120
+ content_type: "application/json",
121
+ });
122
+ // Create envelope body
123
+ const envelope = `${envelopeHeader}\n${itemHeader}\n${JSON.stringify(event)}`;
124
+ try {
125
+ await fetch(envelopeUrl, {
126
+ method: "POST",
127
+ headers: {
128
+ "Content-Type": "application/x-sentry-envelope",
129
+ "X-Sentry-Auth": `Sentry sentry_version=7, sentry_client=blaxel-sdk/${settings.version}, sentry_key=${publicKey}`,
130
+ },
131
+ body: envelope,
132
+ });
133
+ }
134
+ catch {
135
+ // Silently fail - error reporting should never break the SDK
136
+ }
137
+ }
138
+ // Queue for pending events
139
+ const pendingEvents = [];
140
+ let flushPromise = null;
141
+ /**
142
+ * Register browser/edge environment error handlers.
143
+ * Separated to isolate dynamic globalThis access.
144
+ */
145
+ function registerBrowserHandlers() {
146
+ const g = globalThis;
147
+ if (g && typeof g.addEventListener === "function") {
148
+ g.addEventListener("error", (event) => {
149
+ const e = event;
150
+ if (e.error instanceof Error && isFromSDK(e.error)) {
151
+ captureException(e.error);
152
+ }
153
+ });
154
+ g.addEventListener("unhandledrejection", (event) => {
155
+ const e = event;
156
+ const error = e.reason instanceof Error ? e.reason : new Error(String(e.reason));
157
+ if (isFromSDK(error)) {
158
+ captureException(error);
159
+ }
160
+ });
161
+ }
162
+ }
163
+ /**
164
+ * Initialize the lightweight Sentry client for SDK error tracking.
7
165
  */
8
166
  export function initSentry() {
9
- // No-op in browser/edge environments
167
+ try {
168
+ // Check if tracking is disabled
169
+ if (!settings.tracking) {
170
+ return;
171
+ }
172
+ const dsn = settings.sentryDsn;
173
+ if (!dsn) {
174
+ return;
175
+ }
176
+ // Parse DSN
177
+ sentryConfig = parseDsn(dsn);
178
+ if (!sentryConfig) {
179
+ return;
180
+ }
181
+ // Only allow dev/prod environments
182
+ if (settings.env !== "dev" && settings.env !== "prod") {
183
+ return;
184
+ }
185
+ sentryInitialized = true;
186
+ // Register error handlers only once
187
+ if (!handlersRegistered) {
188
+ handlersRegistered = true;
189
+ // Node.js specific handlers
190
+ if (typeof process !== "undefined" && typeof process.on === "function") {
191
+ // For SIGTERM/SIGINT, flush before exit
192
+ const signalHandler = (signal) => {
193
+ flushSentry(500)
194
+ .catch(() => {
195
+ // Silently fail
196
+ })
197
+ .finally(() => {
198
+ process.exit(signal === "SIGTERM" ? 143 : 130);
199
+ });
200
+ };
201
+ // Uncaught exception handler - only capture SDK errors
202
+ const uncaughtExceptionHandler = (error) => {
203
+ if (isFromSDK(error)) {
204
+ captureException(error);
205
+ }
206
+ };
207
+ // Unhandled rejection handler - only capture SDK errors
208
+ const unhandledRejectionHandler = (reason) => {
209
+ const error = reason instanceof Error ? reason : new Error(String(reason));
210
+ if (isFromSDK(error)) {
211
+ captureException(error);
212
+ }
213
+ };
214
+ process.on("SIGTERM", () => signalHandler("SIGTERM"));
215
+ process.on("SIGINT", () => signalHandler("SIGINT"));
216
+ process.on("uncaughtException", uncaughtExceptionHandler);
217
+ process.on("unhandledRejection", unhandledRejectionHandler);
218
+ // Intercept console.error to capture SDK errors that are caught and logged
219
+ const originalConsoleError = console.error;
220
+ console.error = function (...args) {
221
+ originalConsoleError.apply(console, args);
222
+ for (const arg of args) {
223
+ if (arg instanceof Error && isFromSDK(arg)) {
224
+ captureException(arg);
225
+ break;
226
+ }
227
+ }
228
+ };
229
+ }
230
+ else {
231
+ // Browser/Edge environment handlers
232
+ registerBrowserHandlers();
233
+ }
234
+ }
235
+ }
236
+ catch (error) {
237
+ // Silently fail - Sentry initialization should never break the SDK
238
+ if (settings.env !== "production") {
239
+ console.error("[Blaxel SDK] Error initializing Sentry:", error);
240
+ }
241
+ }
242
+ }
243
+ /**
244
+ * Capture an exception to Sentry.
245
+ * Only errors originating from SDK code will be captured.
246
+ *
247
+ * @param error - The error to capture
248
+ */
249
+ function captureException(error) {
250
+ if (!sentryInitialized || !sentryConfig) {
251
+ return;
252
+ }
253
+ // Double-check that error is from SDK (defense in depth)
254
+ if (!isFromSDK(error)) {
255
+ return;
256
+ }
257
+ try {
258
+ // Create a unique identifier for this exception to avoid duplicates
259
+ const errorKey = `${error.name}:${error.message}:${error.stack?.slice(0, 200)}`;
260
+ if (capturedExceptions.has(errorKey)) {
261
+ return;
262
+ }
263
+ capturedExceptions.add(errorKey);
264
+ // Clean up old exception keys to prevent memory leak
265
+ if (capturedExceptions.size > 1000) {
266
+ capturedExceptions.clear();
267
+ }
268
+ // Convert error to Sentry event and queue it
269
+ const event = errorToSentryEvent(error);
270
+ pendingEvents.push(event);
271
+ // Send immediately (fire and forget)
272
+ sendToSentry(event).catch(() => {
273
+ // Silently fail
274
+ });
275
+ }
276
+ catch {
277
+ // Silently fail - error capturing should never break the SDK
278
+ }
10
279
  }
11
280
  /**
12
- * Flush pending Sentry events - no-op in browser/edge environments.
281
+ * Flush pending Sentry events.
282
+ * This should be called before the process exits to ensure all events are sent.
283
+ *
284
+ * @param timeout - Maximum time in milliseconds to wait for flush (default: 2000)
13
285
  */
14
- export async function flushSentry(_timeout = 2000) {
15
- // No-op in browser/edge environments
286
+ export async function flushSentry(timeout = 2000) {
287
+ if (!sentryInitialized || pendingEvents.length === 0) {
288
+ return;
289
+ }
290
+ // If already flushing, wait for it
291
+ if (flushPromise) {
292
+ await flushPromise;
293
+ return;
294
+ }
295
+ try {
296
+ // Send all pending events
297
+ const eventsToSend = [...pendingEvents];
298
+ pendingEvents.length = 0;
299
+ flushPromise = Promise.race([
300
+ Promise.all(eventsToSend.map((event) => sendToSentry(event))).then(() => { }),
301
+ new Promise((resolve) => setTimeout(resolve, timeout)),
302
+ ]);
303
+ await flushPromise;
304
+ }
305
+ catch {
306
+ // Silently fail
307
+ }
308
+ finally {
309
+ flushPromise = null;
310
+ }
16
311
  }
17
312
  /**
18
- * Check if Sentry is initialized - always returns false in browser/edge environments.
313
+ * Check if Sentry is initialized and available.
19
314
  */
20
315
  export function isSentryInitialized() {
21
- return false;
316
+ return sentryInitialized;
22
317
  }
@@ -3,9 +3,9 @@ import { authentication } from "../authentication/index.js";
3
3
  import { env } from "../common/env.js";
4
4
  import { fs, os, path } from "../common/node.js";
5
5
  // Build info - these placeholders are replaced at build time by build:replace-imports
6
- const BUILD_VERSION = "0.2.55-preview.17";
7
- const BUILD_COMMIT = "1efcf3565af2e54805e7526888bebaf2347c5886";
8
- const BUILD_SENTRY_DSN = "https://fd5e60e1c9820e1eef5ccebb84a07127@o4508714045276160.ingest.us.sentry.io/4510465864564736";
6
+ const BUILD_VERSION = "0.2.56-dev.23";
7
+ const BUILD_COMMIT = "d54548dc9e764e57728f9eda7721d5e50f11573a";
8
+ const BUILD_SENTRY_DSN = "";
9
9
  // Cache for config.yaml tracking value
10
10
  let configTrackingValue = null;
11
11
  let configTrackingLoaded = false;
@@ -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";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blaxel/core",
3
- "version": "0.2.55-preview.17",
3
+ "version": "0.2.56-dev.23",
4
4
  "description": "Blaxel Core SDK for TypeScript",
5
5
  "license": "MIT",
6
6
  "author": "Blaxel, INC (https://blaxel.ai)",
@@ -53,6 +53,7 @@
53
53
  "dependencies": {
54
54
  "@hey-api/client-fetch": "^0.10.0",
55
55
  "@modelcontextprotocol/sdk": "^1.20.0",
56
+ "@sentry/node": "^10.27.0",
56
57
  "axios": "^1.9.0",
57
58
  "dotenv": "^16.5.0",
58
59
  "form-data": "^4.0.2",
@@ -63,9 +64,6 @@
63
64
  "yaml": "^2.7.1",
64
65
  "zod": "^3.24.3"
65
66
  },
66
- "optionalDependencies": {
67
- "@sentry/node": "^10.27.0"
68
- },
69
67
  "devDependencies": {
70
68
  "@eslint/js": "^9.26.0",
71
69
  "@testing-library/dom": "^9.3.0",