@blaxel/core 0.2.67 → 0.2.68-dev.94

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.
@@ -203,23 +203,16 @@ function initSentry() {
203
203
  process.exit(signal === "SIGTERM" ? 143 : 130);
204
204
  });
205
205
  };
206
- // Uncaught exception handler - only capture SDK errors
207
- const uncaughtExceptionHandler = (error) => {
208
- if (isFromSDK(error)) {
209
- captureException(error);
210
- }
211
- };
212
- // Unhandled rejection handler - only capture SDK errors
213
- const unhandledRejectionHandler = (reason) => {
214
- const error = reason instanceof Error ? reason : new Error(String(reason));
206
+ // Monitor uncaught exceptions to capture SDK errors without
207
+ // preventing Node.js default crash behavior (print + exit).
208
+ const uncaughtExceptionMonitorHandler = (error) => {
215
209
  if (isFromSDK(error)) {
216
210
  captureException(error);
217
211
  }
218
212
  };
219
213
  process.on("SIGTERM", () => signalHandler("SIGTERM"));
220
214
  process.on("SIGINT", () => signalHandler("SIGINT"));
221
- process.on("uncaughtException", uncaughtExceptionHandler);
222
- process.on("unhandledRejection", unhandledRejectionHandler);
215
+ process.on("uncaughtExceptionMonitor", uncaughtExceptionMonitorHandler);
223
216
  // Intercept console.error to capture SDK errors that are caught and logged
224
217
  const originalConsoleError = console.error;
225
218
  console.error = function (...args) {
@@ -9,8 +9,8 @@ const index_js_1 = require("../authentication/index.js");
9
9
  const env_js_1 = require("../common/env.js");
10
10
  const node_js_1 = require("../common/node.js");
11
11
  // Build info - these placeholders are replaced at build time by build:replace-imports
12
- const BUILD_VERSION = "0.2.67";
13
- const BUILD_COMMIT = "3a64eedabba6c905c7dbba66fd6e8c036afdc3dd";
12
+ const BUILD_VERSION = "0.2.68-dev.94";
13
+ const BUILD_COMMIT = "14ccbafeb7ce8418b80f9cf18cc629ce055e6151";
14
14
  const BUILD_SENTRY_DSN = "https://fd5e60e1c9820e1eef5ccebb84a07127@o4508714045276160.ingest.us.sentry.io/4510465864564736";
15
15
  // Cache for config.yaml tracking value
16
16
  let configTrackingValue = null;
@@ -121,6 +121,206 @@ class ImageInstance {
121
121
  }
122
122
  return new ImageInstance(newContext);
123
123
  }
124
+ pipInstall(...args) {
125
+ let options = {};
126
+ let packages;
127
+ if (args.length > 0 && typeof args[0] === "object") {
128
+ options = args[0];
129
+ packages = args.slice(1);
130
+ }
131
+ else {
132
+ packages = args;
133
+ }
134
+ if (packages.length === 0)
135
+ return this;
136
+ const opts = [];
137
+ if (options.findLinks)
138
+ opts.push(`--find-links ${options.findLinks}`);
139
+ if (options.indexUrl)
140
+ opts.push(`--index-url ${options.indexUrl}`);
141
+ if (options.extraIndexUrl)
142
+ opts.push(`--extra-index-url ${options.extraIndexUrl}`);
143
+ if (options.pre)
144
+ opts.push("--pre");
145
+ if (options.extraOptions)
146
+ opts.push(options.extraOptions);
147
+ const cmd = ["pip install", ...opts, ...packages].join(" ").replace(/\s+/g, " ").trim();
148
+ return this.runCommands(cmd);
149
+ }
150
+ aptInstall(...args) {
151
+ let options = {};
152
+ let packages;
153
+ if (args.length > 0 && typeof args[0] === "object") {
154
+ options = args[0];
155
+ packages = args.slice(1);
156
+ }
157
+ else {
158
+ packages = args;
159
+ }
160
+ if (packages.length === 0)
161
+ return this;
162
+ const update = options.update ?? true;
163
+ const clean = options.clean ?? true;
164
+ const parts = [];
165
+ if (update)
166
+ parts.push("apt-get update");
167
+ parts.push(`apt-get install -y --no-install-recommends ${packages.join(" ")}`);
168
+ if (clean)
169
+ parts.push("rm -rf /var/lib/apt/lists/*");
170
+ return this.runCommands(parts.join(" && "));
171
+ }
172
+ apkAdd(...args) {
173
+ let options = {};
174
+ let packages;
175
+ if (args.length > 0 && typeof args[0] === "object") {
176
+ options = args[0];
177
+ packages = args.slice(1);
178
+ }
179
+ else {
180
+ packages = args;
181
+ }
182
+ if (packages.length === 0)
183
+ return this;
184
+ const noCache = options.noCache ?? true;
185
+ const update = options.update ?? true;
186
+ const clean = options.clean ?? true;
187
+ const pkgs = packages.join(" ");
188
+ if (noCache) {
189
+ return this.runCommands(`apk add --no-cache ${pkgs}`);
190
+ }
191
+ const parts = [];
192
+ if (update)
193
+ parts.push("apk update");
194
+ parts.push(`apk add ${pkgs}`);
195
+ if (clean)
196
+ parts.push("rm -rf /var/cache/apk/*");
197
+ return this.runCommands(parts.join(" && "));
198
+ }
199
+ npmInstall(...args) {
200
+ let options = {};
201
+ let packages;
202
+ if (args.length > 0 && typeof args[0] === "object") {
203
+ options = args[0];
204
+ packages = args.slice(1);
205
+ }
206
+ else {
207
+ packages = args;
208
+ }
209
+ const pm = (options.packageManager ?? "npm").toLowerCase();
210
+ const g = options.globalInstall ?? false;
211
+ const d = options.saveDev ?? false;
212
+ const pkgs = packages.join(" ");
213
+ let cmd;
214
+ if (!packages.length) {
215
+ // Install from lockfile/package.json
216
+ const installCmds = {
217
+ npm: "npm install",
218
+ yarn: "yarn install",
219
+ pnpm: "pnpm install",
220
+ bun: "bun install",
221
+ };
222
+ cmd = installCmds[pm];
223
+ if (!cmd)
224
+ throw new Error(`Invalid package manager: ${pm}. Must be one of npm, yarn, pnpm, bun`);
225
+ }
226
+ else {
227
+ const addCmds = {
228
+ npm: `npm install ${g ? "-g " : ""}${d ? "--save-dev " : ""}${pkgs}`,
229
+ yarn: `yarn ${g ? "global add" : "add"} ${d && !g ? "--dev " : ""}${pkgs}`,
230
+ pnpm: `pnpm add ${g ? "-g " : ""}${d ? "-D " : ""}${pkgs}`,
231
+ bun: `bun add ${g ? "-g " : ""}${d ? "-d " : ""}${pkgs}`,
232
+ };
233
+ cmd = addCmds[pm];
234
+ if (!cmd)
235
+ throw new Error(`Invalid package manager: ${pm}. Must be one of npm, yarn, pnpm, bun`);
236
+ }
237
+ return this.runCommands(cmd.replace(/\s+/g, " ").trim());
238
+ }
239
+ gemInstall(...args) {
240
+ let options = {};
241
+ let packages;
242
+ if (args.length > 0 && typeof args[0] === "object") {
243
+ options = args[0];
244
+ packages = args.slice(1);
245
+ }
246
+ else {
247
+ packages = args;
248
+ }
249
+ if (packages.length === 0)
250
+ return this;
251
+ const noDoc = options.noDocument ?? true;
252
+ const cmd = `gem install ${noDoc ? "--no-document " : ""}${packages.join(" ")}`.replace(/\s+/g, " ").trim();
253
+ return this.runCommands(cmd);
254
+ }
255
+ cargoInstall(...args) {
256
+ let options = {};
257
+ let packages;
258
+ if (args.length > 0 && typeof args[0] === "object") {
259
+ options = args[0];
260
+ packages = args.slice(1);
261
+ }
262
+ else {
263
+ packages = args;
264
+ }
265
+ if (packages.length === 0)
266
+ return this;
267
+ const cmd = `cargo install ${options.locked ? "--locked " : ""}${packages.join(" ")}`.replace(/\s+/g, " ").trim();
268
+ return this.runCommands(cmd);
269
+ }
270
+ /**
271
+ * Install Go packages.
272
+ */
273
+ goInstall(...packages) {
274
+ if (packages.length === 0)
275
+ return this;
276
+ const commands = packages.map((pkg) => `go install ${pkg}`);
277
+ return this.runCommands(commands.join(" && "));
278
+ }
279
+ composerInstall(...args) {
280
+ let options = {};
281
+ let packages;
282
+ if (args.length > 0 && typeof args[0] === "object") {
283
+ options = args[0];
284
+ packages = args.slice(1);
285
+ }
286
+ else {
287
+ packages = args;
288
+ }
289
+ const flags = `${options.noDev ? "--no-dev " : ""}${options.optimizeAutoloader ? "--optimize-autoloader " : ""}`;
290
+ let cmd;
291
+ if (packages.length > 0) {
292
+ cmd = `composer require ${flags}${packages.join(" ")}`;
293
+ }
294
+ else {
295
+ cmd = `composer install ${flags}`;
296
+ }
297
+ return this.runCommands(cmd.replace(/\s+/g, " ").trim());
298
+ }
299
+ uvInstall(...args) {
300
+ let options = {};
301
+ let packages;
302
+ if (args.length > 0 && typeof args[0] === "object") {
303
+ options = args[0];
304
+ packages = args.slice(1);
305
+ }
306
+ else {
307
+ packages = args;
308
+ }
309
+ if (packages.length === 0)
310
+ return this;
311
+ const system = options.system ?? true;
312
+ const cmd = `uv pip install ${system ? "--system " : ""}${options.upgrade ? "--upgrade " : ""}${packages.join(" ")}`.replace(/\s+/g, " ").trim();
313
+ return this.runCommands(cmd);
314
+ }
315
+ /**
316
+ * Install Python CLI applications using pipx.
317
+ */
318
+ pipxInstall(...packages) {
319
+ if (packages.length === 0)
320
+ return this;
321
+ const commands = packages.map((pkg) => `pipx install ${pkg}`);
322
+ return this.runCommands(commands.join(" && "));
323
+ }
124
324
  /**
125
325
  * Set environment variables.
126
326
  *
@@ -102,6 +102,7 @@ class McpTool {
102
102
  throw err;
103
103
  }
104
104
  logger_js_1.logger.debug(`MCP:${this.name}:Connecting to fallback`);
105
+ this.transportName = undefined;
105
106
  this.transport = await this.getTransport(this.fallbackUrl);
106
107
  await this.client.connect(this.transport);
107
108
  logger_js_1.logger.debug(`MCP:${this.name}:Connected to fallback`);
@@ -28,6 +28,41 @@ export interface ImageBuildOptions {
28
28
  onStatusChange?: (status: string) => void;
29
29
  sandboxVersion?: string;
30
30
  }
31
+ export interface PipInstallOptions {
32
+ findLinks?: string;
33
+ indexUrl?: string;
34
+ extraIndexUrl?: string;
35
+ pre?: boolean;
36
+ extraOptions?: string;
37
+ }
38
+ export interface AptInstallOptions {
39
+ update?: boolean;
40
+ clean?: boolean;
41
+ }
42
+ export interface ApkAddOptions {
43
+ update?: boolean;
44
+ noCache?: boolean;
45
+ clean?: boolean;
46
+ }
47
+ export interface NpmInstallOptions {
48
+ packageManager?: "npm" | "yarn" | "pnpm" | "bun";
49
+ globalInstall?: boolean;
50
+ saveDev?: boolean;
51
+ }
52
+ export interface GemInstallOptions {
53
+ noDocument?: boolean;
54
+ }
55
+ export interface CargoInstallOptions {
56
+ locked?: boolean;
57
+ }
58
+ export interface ComposerInstallOptions {
59
+ noDev?: boolean;
60
+ optimizeAutoloader?: boolean;
61
+ }
62
+ export interface UvInstallOptions {
63
+ system?: boolean;
64
+ upgrade?: boolean;
65
+ }
31
66
  /**
32
67
  * A fluent builder for creating sandbox images programmatically.
33
68
  *
@@ -75,6 +110,54 @@ export declare class ImageInstance {
75
110
  * @returns A new Image instance with the commands added
76
111
  */
77
112
  runCommands(...commands: string[]): ImageInstance;
113
+ /**
114
+ * Install Python packages using pip.
115
+ */
116
+ pipInstall(...packages: string[]): ImageInstance;
117
+ pipInstall(options: PipInstallOptions, ...packages: string[]): ImageInstance;
118
+ /**
119
+ * Install packages using apt-get (Debian/Ubuntu).
120
+ */
121
+ aptInstall(...packages: string[]): ImageInstance;
122
+ aptInstall(options: AptInstallOptions, ...packages: string[]): ImageInstance;
123
+ /**
124
+ * Install packages using apk (Alpine Linux).
125
+ */
126
+ apkAdd(...packages: string[]): ImageInstance;
127
+ apkAdd(options: ApkAddOptions, ...packages: string[]): ImageInstance;
128
+ /**
129
+ * Install Node.js packages using npm, yarn, pnpm, or bun.
130
+ */
131
+ npmInstall(...packages: string[]): ImageInstance;
132
+ npmInstall(options: NpmInstallOptions, ...packages: string[]): ImageInstance;
133
+ /**
134
+ * Install Ruby gems.
135
+ */
136
+ gemInstall(...packages: string[]): ImageInstance;
137
+ gemInstall(options: GemInstallOptions, ...packages: string[]): ImageInstance;
138
+ /**
139
+ * Install Rust packages using cargo.
140
+ */
141
+ cargoInstall(...packages: string[]): ImageInstance;
142
+ cargoInstall(options: CargoInstallOptions, ...packages: string[]): ImageInstance;
143
+ /**
144
+ * Install Go packages.
145
+ */
146
+ goInstall(...packages: string[]): ImageInstance;
147
+ /**
148
+ * Install PHP packages using Composer.
149
+ */
150
+ composerInstall(...packages: string[]): ImageInstance;
151
+ composerInstall(options: ComposerInstallOptions, ...packages: string[]): ImageInstance;
152
+ /**
153
+ * Install Python packages using uv (fast Python package installer).
154
+ */
155
+ uvInstall(...packages: string[]): ImageInstance;
156
+ uvInstall(options: UvInstallOptions, ...packages: string[]): ImageInstance;
157
+ /**
158
+ * Install Python CLI applications using pipx.
159
+ */
160
+ pipxInstall(...packages: string[]): ImageInstance;
78
161
  /**
79
162
  * Set environment variables.
80
163
  *
@@ -1 +1 @@
1
- export { ImageInstance, ImageBuildContext, ImageBuildOptions, LocalFile, SANDBOX_API_IMAGE, SANDBOX_API_PATH, } from "./image.js";
1
+ export { ImageInstance, ImageBuildContext, ImageBuildOptions, LocalFile, SANDBOX_API_IMAGE, SANDBOX_API_PATH, PipInstallOptions, AptInstallOptions, ApkAddOptions, NpmInstallOptions, GemInstallOptions, CargoInstallOptions, ComposerInstallOptions, UvInstallOptions, } from "./image.js";
@@ -137,9 +137,16 @@ export type ProcessRequest = {
137
137
  env?: {
138
138
  [key: string]: string;
139
139
  };
140
+ /**
141
+ * Disable scale-to-zero while process runs. Default timeout is 600s (10 minutes). Set timeout to 0 for infinite.
142
+ */
143
+ keepAlive?: boolean;
140
144
  maxRestarts?: number;
141
145
  name?: string;
142
146
  restartOnFailure?: boolean;
147
+ /**
148
+ * Timeout in seconds. When keepAlive is true, defaults to 600s (10 minutes). Set to 0 for infinite (no auto-kill).
149
+ */
143
150
  timeout?: number;
144
151
  waitForCompletion?: boolean;
145
152
  waitForPorts?: Array<number>;
@@ -149,6 +156,10 @@ export type ProcessResponse = {
149
156
  command: string;
150
157
  completedAt: string;
151
158
  exitCode: number;
159
+ /**
160
+ * Whether scale-to-zero is disabled for this process
161
+ */
162
+ keepAlive?: boolean;
152
163
  logs: string;
153
164
  maxRestarts?: number;
154
165
  name: string;