@ash-cloud/ash-ai 0.1.13 → 0.1.16

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
@@ -4205,6 +4205,50 @@ VERCEL_EOF`);
4205
4205
  }
4206
4206
  });
4207
4207
 
4208
+ // src/runtime/providers/firecracker/types.ts
4209
+ var init_types3 = __esm({
4210
+ "src/runtime/providers/firecracker/types.ts"() {
4211
+ }
4212
+ });
4213
+
4214
+ // src/runtime/providers/firecracker/image-manager.ts
4215
+ var init_image_manager = __esm({
4216
+ "src/runtime/providers/firecracker/image-manager.ts"() {
4217
+ }
4218
+ });
4219
+
4220
+ // src/runtime/providers/firecracker/network-manager.ts
4221
+ var init_network_manager = __esm({
4222
+ "src/runtime/providers/firecracker/network-manager.ts"() {
4223
+ }
4224
+ });
4225
+
4226
+ // src/runtime/providers/firecracker/ssh-executor.ts
4227
+ var init_ssh_executor = __esm({
4228
+ "src/runtime/providers/firecracker/ssh-executor.ts"() {
4229
+ }
4230
+ });
4231
+
4232
+ // src/runtime/providers/firecracker/vm-manager.ts
4233
+ var init_vm_manager = __esm({
4234
+ "src/runtime/providers/firecracker/vm-manager.ts"() {
4235
+ init_types3();
4236
+ }
4237
+ });
4238
+
4239
+ // src/runtime/providers/firecracker.ts
4240
+ var init_firecracker = __esm({
4241
+ "src/runtime/providers/firecracker.ts"() {
4242
+ init_types2();
4243
+ init_types3();
4244
+ init_image_manager();
4245
+ init_network_manager();
4246
+ init_ssh_executor();
4247
+ init_vm_manager();
4248
+ init_types3();
4249
+ }
4250
+ });
4251
+
4208
4252
  // src/runtime/providers/index.ts
4209
4253
  var init_providers = __esm({
4210
4254
  "src/runtime/providers/index.ts"() {
@@ -4216,6 +4260,7 @@ var init_providers = __esm({
4216
4260
  init_fly();
4217
4261
  init_daytona();
4218
4262
  init_vercel();
4263
+ init_firecracker();
4219
4264
  init_local();
4220
4265
  init_modal();
4221
4266
  init_e2b();
@@ -4223,6 +4268,7 @@ var init_providers = __esm({
4223
4268
  init_fly();
4224
4269
  init_daytona();
4225
4270
  init_vercel();
4271
+ init_firecracker();
4226
4272
  }
4227
4273
  });
4228
4274
 
@@ -5261,6 +5307,23 @@ function isSandboxRunning(sessionId) {
5261
5307
  const cached = sandboxCache.get(sessionId);
5262
5308
  return cached !== void 0 && !cached.isExpired;
5263
5309
  }
5310
+ function getCachedSandbox(sessionId) {
5311
+ const cached = sandboxCache.get(sessionId);
5312
+ if (!cached || cached.isExpired) {
5313
+ return null;
5314
+ }
5315
+ cached.lastUsedAt = Date.now();
5316
+ return {
5317
+ sandbox: cached.sandbox,
5318
+ sandboxId: cached.sandbox.sandboxId,
5319
+ sdkInstalled: cached.sdkInstalled,
5320
+ startupScriptRan: cached.startupScriptRan,
5321
+ startupScriptHash: cached.startupScriptHash,
5322
+ isNew: false,
5323
+ configFileUrl: cached.configFileUrl,
5324
+ configInstalledAt: cached.configInstalledAt
5325
+ };
5326
+ }
5264
5327
  async function writeFileToSandbox(sessionId, path15, content) {
5265
5328
  const cached = sandboxCache.get(sessionId);
5266
5329
  if (!cached) {
@@ -5329,6 +5392,54 @@ async function readFileFromSandbox(sessionId, path15) {
5329
5392
  };
5330
5393
  }
5331
5394
  }
5395
+ async function executeCommandInSandbox(sessionId, command, options) {
5396
+ const cached = sandboxCache.get(sessionId);
5397
+ if (!cached) {
5398
+ return { success: false, error: "No active sandbox for session" };
5399
+ }
5400
+ if (cached.isExpired) {
5401
+ return { success: false, error: "Sandbox has expired" };
5402
+ }
5403
+ const startTime = Date.now();
5404
+ try {
5405
+ const sandbox = cached.sandbox;
5406
+ let fullCommand = command;
5407
+ if (options?.cwd) {
5408
+ fullCommand = `cd ${JSON.stringify(options.cwd)} && ${command}`;
5409
+ }
5410
+ const result = await sandbox.runCommand({
5411
+ cmd: "bash",
5412
+ args: ["-c", fullCommand],
5413
+ env: options?.env
5414
+ });
5415
+ const stdout = await result.stdout();
5416
+ const stderr = await result.stderr();
5417
+ const durationMs = Date.now() - startTime;
5418
+ cached.lastUsedAt = Date.now();
5419
+ return {
5420
+ success: result.exitCode === 0,
5421
+ exitCode: result.exitCode,
5422
+ stdout,
5423
+ stderr,
5424
+ durationMs
5425
+ };
5426
+ } catch (error) {
5427
+ const durationMs = Date.now() - startTime;
5428
+ if (isSandboxExpiredError(error)) {
5429
+ cached.isExpired = true;
5430
+ return {
5431
+ success: false,
5432
+ error: "Sandbox has expired",
5433
+ durationMs
5434
+ };
5435
+ }
5436
+ return {
5437
+ success: false,
5438
+ error: error instanceof Error ? error.message : "Unknown error",
5439
+ durationMs
5440
+ };
5441
+ }
5442
+ }
5332
5443
  async function listFilesInSandbox(sessionId, path15) {
5333
5444
  const cached = sandboxCache.get(sessionId);
5334
5445
  if (!cached) {
@@ -5808,19 +5919,7 @@ function getFileWatcherManager() {
5808
5919
  function createFileWatcherManager() {
5809
5920
  return new FileWatcherManager();
5810
5921
  }
5811
- function createRemoteFileWatcher(options) {
5812
- return new RemoteSandboxFileWatcher(options);
5813
- }
5814
- function getRemoteFileWatcherManager() {
5815
- if (!globalRemoteWatcherManager) {
5816
- globalRemoteWatcherManager = new RemoteFileWatcherManager();
5817
- }
5818
- return globalRemoteWatcherManager;
5819
- }
5820
- function createRemoteFileWatcherManager() {
5821
- return new RemoteFileWatcherManager();
5822
- }
5823
- var SandboxFileWatcher, FileWatcherManager, globalWatcherManager, RemoteSandboxFileWatcher, RemoteFileWatcherManager, globalRemoteWatcherManager;
5922
+ var SandboxFileWatcher, FileWatcherManager, globalWatcherManager;
5824
5923
  var init_sandbox_file_watcher = __esm({
5825
5924
  "src/runtime/sandbox-file-watcher.ts"() {
5826
5925
  SandboxFileWatcher = class {
@@ -5846,7 +5945,18 @@ var init_sandbox_file_watcher = __esm({
5846
5945
  this.watchPath = options.watchPath;
5847
5946
  this.debounceMs = options.debounceMs ?? 300;
5848
5947
  this.patterns = options.patterns ?? ["**/*"];
5849
- this.ignored = options.ignored ?? ["**/node_modules/**", "**/.git/**", "**/*.log"];
5948
+ this.ignored = options.ignored ?? [
5949
+ "**/node_modules/**",
5950
+ "**/.git/**",
5951
+ "**/*.log",
5952
+ // Temporary files from atomic saves and editors
5953
+ "**/*.tmp",
5954
+ "**/*.tmp.*",
5955
+ "**/*~",
5956
+ "**/*.swp",
5957
+ "**/*.swo",
5958
+ "**/.DS_Store"
5959
+ ];
5850
5960
  this.emitInitialEvents = options.emitInitialEvents ?? false;
5851
5961
  this.followSymlinks = options.followSymlinks ?? false;
5852
5962
  this.usePolling = options.usePolling ?? false;
@@ -6062,214 +6172,343 @@ var init_sandbox_file_watcher = __esm({
6062
6172
  }
6063
6173
  };
6064
6174
  globalWatcherManager = null;
6065
- RemoteSandboxFileWatcher = class {
6175
+ }
6176
+ });
6177
+
6178
+ // src/runtime/in-sandbox-watcher.ts
6179
+ function createInSandboxWatcher(options) {
6180
+ return new InSandboxWatcher(options);
6181
+ }
6182
+ function getInSandboxWatcherManager() {
6183
+ if (!globalInSandboxManager) {
6184
+ globalInSandboxManager = new InSandboxWatcherManager();
6185
+ }
6186
+ return globalInSandboxManager;
6187
+ }
6188
+ function createInSandboxWatcherManager() {
6189
+ return new InSandboxWatcherManager();
6190
+ }
6191
+ var WATCHER_SCRIPT, InSandboxWatcher, InSandboxWatcherManager, globalInSandboxManager;
6192
+ var init_in_sandbox_watcher = __esm({
6193
+ "src/runtime/in-sandbox-watcher.ts"() {
6194
+ init_vercel_sandbox_executor();
6195
+ WATCHER_SCRIPT = `
6196
+ const fs = require('fs');
6197
+ const path = require('path');
6198
+
6199
+ const watchPath = process.argv[2] || '.';
6200
+ const ignoredDirs = new Set(['node_modules', '.git', '.cache', '__pycache__']);
6201
+
6202
+ // Track all watchers for cleanup
6203
+ const watchers = new Map();
6204
+
6205
+ // Debounce map to coalesce rapid changes
6206
+ const pending = new Map();
6207
+ const DEBOUNCE_MS = 100;
6208
+
6209
+ function emit(type, filePath) {
6210
+ const event = {
6211
+ type,
6212
+ path: filePath,
6213
+ timestamp: Date.now()
6214
+ };
6215
+ console.log(JSON.stringify(event));
6216
+ }
6217
+
6218
+ function shouldIgnore(name) {
6219
+ // Ignore hidden files/dirs (starting with .)
6220
+ if (name.startsWith('.')) return true;
6221
+
6222
+ // Ignore known directories
6223
+ if (ignoredDirs.has(name)) return true;
6224
+
6225
+ // Ignore temporary files from atomic saves and editors:
6226
+ // - filename.tmp (ends with .tmp)
6227
+ // - filename.tmp.123456789 (has .tmp. in middle - atomic write pattern)
6228
+ // - filename~ (editor backup files)
6229
+ // - filename.swp / filename.swo (Vim swap files)
6230
+ if (name.endsWith('.tmp')) return true;
6231
+ if (name.includes('.tmp.')) return true;
6232
+ if (name.endsWith('~')) return true;
6233
+ if (name.endsWith('.swp') || name.endsWith('.swo')) return true;
6234
+
6235
+ return false;
6236
+ }
6237
+
6238
+ function watchDir(dir) {
6239
+ try {
6240
+ const watcher = fs.watch(dir, { persistent: true }, (eventType, filename) => {
6241
+ if (!filename || shouldIgnore(filename)) return;
6242
+
6243
+ const fullPath = path.join(dir, filename);
6244
+ const key = fullPath;
6245
+
6246
+ // Debounce
6247
+ if (pending.has(key)) {
6248
+ clearTimeout(pending.get(key));
6249
+ }
6250
+
6251
+ pending.set(key, setTimeout(() => {
6252
+ pending.delete(key);
6253
+
6254
+ fs.stat(fullPath, (err, stats) => {
6255
+ if (err) {
6256
+ if (err.code === 'ENOENT') {
6257
+ emit('unlink', fullPath);
6258
+ // Stop watching if it was a directory
6259
+ if (watchers.has(fullPath)) {
6260
+ watchers.get(fullPath).close();
6261
+ watchers.delete(fullPath);
6262
+ }
6263
+ }
6264
+ } else {
6265
+ const type = eventType === 'rename' ? 'add' : 'change';
6266
+ emit(type, fullPath);
6267
+
6268
+ // If it's a new directory, start watching it
6269
+ if (stats.isDirectory() && !watchers.has(fullPath)) {
6270
+ watchDir(fullPath);
6271
+ }
6272
+ }
6273
+ });
6274
+ }, DEBOUNCE_MS));
6275
+ });
6276
+
6277
+ watchers.set(dir, watcher);
6278
+
6279
+ // Watch subdirectories
6280
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
6281
+ for (const entry of entries) {
6282
+ if (entry.isDirectory() && !shouldIgnore(entry.name)) {
6283
+ watchDir(path.join(dir, entry.name));
6284
+ }
6285
+ }
6286
+ } catch (err) {
6287
+ // Directory may not exist or be inaccessible
6288
+ console.error(JSON.stringify({ error: err.message, dir }));
6289
+ }
6290
+ }
6291
+
6292
+ // Start watching
6293
+ watchDir(watchPath);
6294
+
6295
+ // Keep alive
6296
+ process.on('SIGTERM', () => {
6297
+ for (const watcher of watchers.values()) {
6298
+ watcher.close();
6299
+ }
6300
+ process.exit(0);
6301
+ });
6302
+
6303
+ // Heartbeat to indicate we're running
6304
+ setInterval(() => {
6305
+ console.log(JSON.stringify({ heartbeat: true, timestamp: Date.now() }));
6306
+ }, 5000);
6307
+
6308
+ console.log(JSON.stringify({ started: true, path: watchPath }));
6309
+ `;
6310
+ InSandboxWatcher = class {
6066
6311
  sessionId;
6067
- sandboxOps;
6068
- basePath;
6069
- pollIntervalMs;
6070
- ignored;
6071
- pollTimer = null;
6072
- previousFiles = /* @__PURE__ */ new Map();
6312
+ watchPath;
6313
+ outputPollIntervalMs;
6314
+ sandboxState = null;
6315
+ outputPollTimer = null;
6073
6316
  subscribers = /* @__PURE__ */ new Set();
6074
- isWatching = false;
6317
+ isRunning = false;
6075
6318
  startedAt;
6076
- lastPollAt;
6077
- pollCount = 0;
6319
+ lastHeartbeat;
6320
+ lastOutputPosition = 0;
6078
6321
  onError;
6322
+ onReady;
6079
6323
  constructor(options) {
6080
6324
  this.sessionId = options.sessionId;
6081
- this.sandboxOps = options.sandboxOps;
6082
- this.basePath = options.basePath;
6083
- this.pollIntervalMs = options.pollIntervalMs ?? 2e3;
6084
- this.ignored = options.ignored ?? ["**/node_modules/**", "**/.git/**"];
6325
+ this.watchPath = options.watchPath;
6326
+ this.outputPollIntervalMs = options.outputPollIntervalMs ?? 1e3;
6085
6327
  this.onError = options.onError;
6328
+ this.onReady = options.onReady;
6086
6329
  if (options.onFileChange) {
6087
6330
  this.subscribers.add(options.onFileChange);
6088
6331
  }
6089
6332
  }
6090
6333
  /**
6091
- * Start polling for file changes
6334
+ * Start the watcher process inside the sandbox
6092
6335
  */
6093
6336
  async start() {
6094
- if (this.isWatching) {
6095
- console.warn(`[REMOTE_WATCHER] Already watching session ${this.sessionId}`);
6337
+ if (this.isRunning) {
6338
+ console.warn(`[IN_SANDBOX_WATCHER] Already running for session ${this.sessionId}`);
6096
6339
  return;
6097
6340
  }
6098
- if (!this.sandboxOps.isSandboxRunning(this.sessionId)) {
6099
- throw new Error(`Sandbox is not running for session ${this.sessionId}`);
6100
- }
6101
- await this.scan(true);
6102
- this.pollTimer = setInterval(async () => {
6103
- try {
6104
- await this.scan(false);
6105
- } catch (error) {
6106
- console.error(`[REMOTE_WATCHER] Poll error for session ${this.sessionId}:`, error);
6107
- if (this.onError && error instanceof Error) {
6108
- this.onError(error);
6109
- }
6341
+ try {
6342
+ this.sandboxState = getCachedSandbox(this.sessionId);
6343
+ if (!this.sandboxState) {
6344
+ throw new Error(`No active sandbox found for session ${this.sessionId}. Sandbox must be created before starting file watcher.`);
6110
6345
  }
6111
- }, this.pollIntervalMs);
6112
- this.isWatching = true;
6113
- this.startedAt = /* @__PURE__ */ new Date();
6114
- console.log(`[REMOTE_WATCHER] Started watching session ${this.sessionId} at ${this.basePath}`);
6115
- }
6116
- /**
6117
- * Stop polling and cleanup
6118
- */
6119
- async stop() {
6120
- if (!this.isWatching) {
6121
- return;
6122
- }
6123
- if (this.pollTimer) {
6124
- clearInterval(this.pollTimer);
6125
- this.pollTimer = null;
6346
+ const { sandbox } = this.sandboxState;
6347
+ const scriptPath = "/tmp/.file-watcher.js";
6348
+ const outputPath = "/tmp/.file-watcher-output.log";
6349
+ const writeScriptCmd = `cat > ${scriptPath} << 'WATCHER_EOF'
6350
+ ${WATCHER_SCRIPT}
6351
+ WATCHER_EOF`;
6352
+ await sandbox.runCommand({
6353
+ cmd: "sh",
6354
+ args: ["-c", writeScriptCmd]
6355
+ });
6356
+ const startCmd = `nohup node ${scriptPath} "${this.watchPath}" > ${outputPath} 2>&1 &`;
6357
+ await sandbox.runCommand({
6358
+ cmd: "sh",
6359
+ args: ["-c", startCmd]
6360
+ });
6361
+ console.log(`[IN_SANDBOX_WATCHER] Started watcher in sandbox for ${this.watchPath}`);
6362
+ this.isRunning = true;
6363
+ this.startedAt = /* @__PURE__ */ new Date();
6364
+ this.outputPollTimer = setInterval(async () => {
6365
+ try {
6366
+ await this.pollOutput(outputPath);
6367
+ } catch (error) {
6368
+ console.error("[IN_SANDBOX_WATCHER] Error polling output:", error);
6369
+ if (this.onError && error instanceof Error) {
6370
+ this.onError(error);
6371
+ }
6372
+ }
6373
+ }, this.outputPollIntervalMs);
6374
+ setTimeout(() => {
6375
+ this.pollOutput(outputPath).catch(console.error);
6376
+ }, 500);
6377
+ } catch (error) {
6378
+ console.error(`[IN_SANDBOX_WATCHER] Failed to start watcher:`, error);
6379
+ throw error;
6126
6380
  }
6127
- this.isWatching = false;
6128
- this.previousFiles.clear();
6129
- console.log(`[REMOTE_WATCHER] Stopped watching session ${this.sessionId}`);
6130
6381
  }
6131
6382
  /**
6132
- * Subscribe to file change events
6383
+ * Poll the output file for new events
6133
6384
  */
6134
- subscribe(callback) {
6135
- this.subscribers.add(callback);
6136
- return () => this.subscribers.delete(callback);
6137
- }
6138
- /**
6139
- * Remove a subscriber
6140
- */
6141
- unsubscribe(callback) {
6142
- this.subscribers.delete(callback);
6143
- }
6144
- /**
6145
- * Check if watcher is active
6146
- */
6147
- isActive() {
6148
- return this.isWatching;
6149
- }
6150
- /**
6151
- * Get watcher status
6152
- */
6153
- getStatus() {
6154
- return {
6155
- sessionId: this.sessionId,
6156
- watchPath: this.basePath,
6157
- isWatching: this.isWatching,
6158
- watchedFileCount: this.previousFiles.size,
6159
- pendingEventCount: 0,
6160
- startedAt: this.startedAt,
6161
- lastPollAt: this.lastPollAt,
6162
- pollCount: this.pollCount
6163
- };
6385
+ async pollOutput(outputPath) {
6386
+ if (!this.sandboxState?.sandbox) return;
6387
+ try {
6388
+ const result = await this.sandboxState.sandbox.runCommand({
6389
+ cmd: "sh",
6390
+ args: ["-c", `tail -c +${this.lastOutputPosition + 1} ${outputPath} 2>/dev/null || true`]
6391
+ });
6392
+ const output = await result.stdout();
6393
+ if (output && output.trim()) {
6394
+ const sizeResult = await this.sandboxState.sandbox.runCommand({
6395
+ cmd: "sh",
6396
+ args: ["-c", `stat -c%s ${outputPath} 2>/dev/null || echo 0`]
6397
+ });
6398
+ const sizeStr = await sizeResult.stdout();
6399
+ this.lastOutputPosition = parseInt(sizeStr.trim(), 10) || 0;
6400
+ this.processOutput(output);
6401
+ }
6402
+ } catch {
6403
+ }
6164
6404
  }
6165
6405
  /**
6166
- * Force an immediate scan (useful for testing or manual refresh)
6406
+ * Process output from the watcher script
6167
6407
  */
6168
- async forceScan() {
6169
- await this.scan(false);
6408
+ processOutput(stdout) {
6409
+ const lines = stdout.split("\n").filter(Boolean);
6410
+ for (const line of lines) {
6411
+ try {
6412
+ const data = JSON.parse(line);
6413
+ if (data.started) {
6414
+ console.log(`[IN_SANDBOX_WATCHER] Watcher started for ${data.path}`);
6415
+ if (this.onReady) {
6416
+ this.onReady();
6417
+ }
6418
+ } else if (data.heartbeat) {
6419
+ this.lastHeartbeat = new Date(data.timestamp);
6420
+ } else if (data.error) {
6421
+ console.warn(`[IN_SANDBOX_WATCHER] Error in sandbox:`, data.error);
6422
+ } else if (data.type && data.path) {
6423
+ this.emitEvent({
6424
+ type: data.type,
6425
+ relativePath: data.path.replace(/^\.\//, ""),
6426
+ absolutePath: data.path,
6427
+ basePath: this.watchPath,
6428
+ sessionId: this.sessionId,
6429
+ timestamp: new Date(data.timestamp)
6430
+ });
6431
+ }
6432
+ } catch {
6433
+ }
6434
+ }
6170
6435
  }
6171
6436
  /**
6172
- * Scan the sandbox for file changes
6437
+ * Stop the watcher process
6173
6438
  */
6174
- async scan(isInitial) {
6175
- if (!this.sandboxOps.isSandboxRunning(this.sessionId)) {
6176
- console.warn(`[REMOTE_WATCHER] Sandbox stopped for session ${this.sessionId}`);
6177
- await this.stop();
6439
+ async stop() {
6440
+ if (!this.isRunning) {
6178
6441
  return;
6179
6442
  }
6180
- const listResult = await this.sandboxOps.listFiles(this.sessionId, this.basePath);
6181
- if (!listResult.success || !listResult.files) {
6182
- throw new Error(listResult.error ?? "Failed to list files in sandbox");
6183
- }
6184
- const currentFiles = /* @__PURE__ */ new Map();
6185
- for (const filePath of listResult.files) {
6186
- if (this.shouldIgnore(filePath)) {
6187
- continue;
6188
- }
6189
- currentFiles.set(filePath, { path: filePath });
6190
- }
6191
- this.lastPollAt = /* @__PURE__ */ new Date();
6192
- this.pollCount++;
6193
- if (isInitial) {
6194
- this.previousFiles = currentFiles;
6195
- return;
6443
+ if (this.outputPollTimer) {
6444
+ clearInterval(this.outputPollTimer);
6445
+ this.outputPollTimer = null;
6196
6446
  }
6197
- const changes = [];
6198
- for (const [filePath, info] of currentFiles) {
6199
- const previous = this.previousFiles.get(filePath);
6200
- if (!previous) {
6201
- changes.push({
6202
- type: "add",
6203
- relativePath: filePath,
6204
- absolutePath: `${this.basePath}/${filePath}`,
6205
- basePath: this.basePath,
6206
- sessionId: this.sessionId,
6207
- fileSize: info.size,
6208
- timestamp: /* @__PURE__ */ new Date()
6447
+ try {
6448
+ if (this.sandboxState?.sandbox) {
6449
+ await this.sandboxState.sandbox.runCommand({
6450
+ cmd: "sh",
6451
+ args: ["-c", "pkill -f file-watcher.js 2>/dev/null || true"]
6209
6452
  });
6210
- }
6211
- }
6212
- for (const [filePath] of this.previousFiles) {
6213
- if (!currentFiles.has(filePath)) {
6214
- changes.push({
6215
- type: "unlink",
6216
- relativePath: filePath,
6217
- absolutePath: `${this.basePath}/${filePath}`,
6218
- basePath: this.basePath,
6219
- sessionId: this.sessionId,
6220
- timestamp: /* @__PURE__ */ new Date()
6453
+ await this.sandboxState.sandbox.runCommand({
6454
+ cmd: "sh",
6455
+ args: ["-c", "rm -f /tmp/.file-watcher.js /tmp/.file-watcher-output.log"]
6221
6456
  });
6222
6457
  }
6458
+ } catch {
6223
6459
  }
6224
- this.previousFiles = currentFiles;
6225
- for (const event of changes) {
6226
- await this.emitEvent(event);
6227
- }
6460
+ this.isRunning = false;
6461
+ this.sandboxState = null;
6462
+ this.lastOutputPosition = 0;
6463
+ console.log(`[IN_SANDBOX_WATCHER] Stopped watcher for session ${this.sessionId}`);
6228
6464
  }
6229
6465
  /**
6230
- * Check if a path should be ignored
6466
+ * Subscribe to file change events
6231
6467
  */
6232
- shouldIgnore(filePath) {
6233
- for (const pattern of this.ignored) {
6234
- if (this.matchesGlob(filePath, pattern)) {
6235
- return true;
6236
- }
6237
- }
6238
- return false;
6468
+ subscribe(callback) {
6469
+ this.subscribers.add(callback);
6470
+ return () => this.subscribers.delete(callback);
6239
6471
  }
6240
6472
  /**
6241
- * Simple glob matching (supports ** and *)
6473
+ * Check if watcher is running
6242
6474
  */
6243
- matchesGlob(filePath, pattern) {
6244
- const regexPattern = pattern.replace(/\*\*/g, "{{GLOBSTAR}}").replace(/\*/g, "[^/]*").replace(/{{GLOBSTAR}}/g, ".*").replace(/\//g, "\\/");
6245
- const regex = new RegExp(`^${regexPattern}$`);
6246
- return regex.test(filePath);
6475
+ isActive() {
6476
+ return this.isRunning;
6247
6477
  }
6248
6478
  /**
6249
- * Emit a file change event to all subscribers
6479
+ * Get watcher status
6480
+ */
6481
+ getStatus() {
6482
+ return {
6483
+ sessionId: this.sessionId,
6484
+ watchPath: this.watchPath,
6485
+ isRunning: this.isRunning,
6486
+ startedAt: this.startedAt,
6487
+ lastHeartbeat: this.lastHeartbeat
6488
+ };
6489
+ }
6490
+ /**
6491
+ * Emit event to all subscribers
6250
6492
  */
6251
6493
  async emitEvent(event) {
6252
6494
  for (const callback of this.subscribers) {
6253
6495
  try {
6254
6496
  await callback(event);
6255
6497
  } catch (error) {
6256
- console.error("[REMOTE_WATCHER] Error in subscriber callback:", error);
6498
+ console.error("[IN_SANDBOX_WATCHER] Error in subscriber callback:", error);
6257
6499
  }
6258
6500
  }
6259
6501
  }
6260
6502
  };
6261
- RemoteFileWatcherManager = class {
6503
+ InSandboxWatcherManager = class {
6262
6504
  watchers = /* @__PURE__ */ new Map();
6263
6505
  /**
6264
- * Start watching a session's sandbox
6506
+ * Start watching a sandbox
6265
6507
  */
6266
6508
  async startWatching(options) {
6267
6509
  const { sessionId } = options;
6268
- const existing = this.watchers.get(sessionId);
6269
- if (existing) {
6270
- await existing.stop();
6271
- }
6272
- const watcher = new RemoteSandboxFileWatcher(options);
6510
+ await this.stopWatching(sessionId);
6511
+ const watcher = new InSandboxWatcher(options);
6273
6512
  await watcher.start();
6274
6513
  this.watchers.set(sessionId, watcher);
6275
6514
  return watcher;
@@ -6285,17 +6524,16 @@ var init_sandbox_file_watcher = __esm({
6285
6524
  }
6286
6525
  }
6287
6526
  /**
6288
- * Get a watcher for a session
6527
+ * Get watcher for a session
6289
6528
  */
6290
6529
  getWatcher(sessionId) {
6291
6530
  return this.watchers.get(sessionId);
6292
6531
  }
6293
6532
  /**
6294
- * Check if a session is being watched
6533
+ * Check if watching
6295
6534
  */
6296
6535
  isWatching(sessionId) {
6297
- const watcher = this.watchers.get(sessionId);
6298
- return watcher?.isActive() ?? false;
6536
+ return this.watchers.get(sessionId)?.isActive() ?? false;
6299
6537
  }
6300
6538
  /**
6301
6539
  * Stop all watchers
@@ -6306,7 +6544,7 @@ var init_sandbox_file_watcher = __esm({
6306
6544
  this.watchers.clear();
6307
6545
  }
6308
6546
  };
6309
- globalRemoteWatcherManager = null;
6547
+ globalInSandboxManager = null;
6310
6548
  }
6311
6549
  });
6312
6550
  function extractErrorMessage(error) {
@@ -6355,6 +6593,7 @@ var SandboxFileSync;
6355
6593
  var init_sandbox_file_sync = __esm({
6356
6594
  "src/runtime/sandbox-file-sync.ts"() {
6357
6595
  init_sandbox_file_watcher();
6596
+ init_in_sandbox_watcher();
6358
6597
  init_types();
6359
6598
  SandboxFileSync = class {
6360
6599
  fileStore;
@@ -6365,7 +6604,7 @@ var init_sandbox_file_sync = __esm({
6365
6604
  eventStorage;
6366
6605
  webhookConfig;
6367
6606
  // Watcher management
6368
- remoteWatchers = /* @__PURE__ */ new Map();
6607
+ inSandboxWatchers = /* @__PURE__ */ new Map();
6369
6608
  localWatchers = /* @__PURE__ */ new Map();
6370
6609
  fileChangeSubscribers = /* @__PURE__ */ new Set();
6371
6610
  // Sequence number cache per session (for event storage)
@@ -7156,34 +7395,27 @@ var init_sandbox_file_sync = __esm({
7156
7395
  this.localWatchers.set(sessionId, watcher);
7157
7396
  console.log(`[FILE_SYNC] Started local file watching for session ${sessionId} at ${opts.localPath}`);
7158
7397
  } else {
7159
- if (!this.sandboxOps) {
7160
- throw new Error("Sandbox operations not configured. Call setSandboxOperations first.");
7161
- }
7162
- const watcher = new RemoteSandboxFileWatcher({
7398
+ const watcher = new InSandboxWatcher({
7163
7399
  sessionId,
7164
- sandboxOps: this.sandboxOps,
7165
- basePath: watchPath,
7166
- // Use watchPath instead of sandboxBasePath
7167
- pollIntervalMs: opts.pollIntervalMs ?? 2e3,
7168
- ignored: opts.ignored ?? ["**/node_modules/**", "**/.git/**"],
7400
+ watchPath,
7169
7401
  onFileChange: handleFileChange,
7170
7402
  onError: (error) => {
7171
- console.error(`[FILE_SYNC] Remote watcher error for session ${sessionId}:`, error);
7403
+ console.error(`[FILE_SYNC] In-sandbox watcher error for session ${sessionId}:`, error);
7172
7404
  }
7173
7405
  });
7174
7406
  await watcher.start();
7175
- this.remoteWatchers.set(sessionId, watcher);
7176
- console.log(`[FILE_SYNC] Started remote file watching for session ${sessionId} at path: ${watchPath}`);
7407
+ this.inSandboxWatchers.set(sessionId, watcher);
7408
+ console.log(`[FILE_SYNC] Started in-sandbox file watching for session ${sessionId} at path: ${watchPath}`);
7177
7409
  }
7178
7410
  }
7179
7411
  /**
7180
7412
  * Stop watching a session's sandbox
7181
7413
  */
7182
7414
  async stopWatching(sessionId) {
7183
- const remoteWatcher = this.remoteWatchers.get(sessionId);
7184
- if (remoteWatcher) {
7185
- await remoteWatcher.stop();
7186
- this.remoteWatchers.delete(sessionId);
7415
+ const inSandboxWatcher = this.inSandboxWatchers.get(sessionId);
7416
+ if (inSandboxWatcher) {
7417
+ await inSandboxWatcher.stop();
7418
+ this.inSandboxWatchers.delete(sessionId);
7187
7419
  }
7188
7420
  const localWatcher = this.localWatchers.get(sessionId);
7189
7421
  if (localWatcher) {
@@ -7195,7 +7427,7 @@ var init_sandbox_file_sync = __esm({
7195
7427
  * Check if a session is being watched
7196
7428
  */
7197
7429
  isWatching(sessionId) {
7198
- return this.remoteWatchers.has(sessionId) || this.localWatchers.has(sessionId);
7430
+ return this.inSandboxWatchers.has(sessionId) || this.localWatchers.has(sessionId);
7199
7431
  }
7200
7432
  /**
7201
7433
  * Subscribe to file change events across all watched sessions.
@@ -7229,10 +7461,10 @@ var init_sandbox_file_sync = __esm({
7229
7461
  * Stop all watchers and cleanup
7230
7462
  */
7231
7463
  async stopAllWatching() {
7232
- const remotePromises = Array.from(this.remoteWatchers.values()).map((w) => w.stop());
7464
+ const inSandboxPromises = Array.from(this.inSandboxWatchers.values()).map((w) => w.stop());
7233
7465
  const localPromises = Array.from(this.localWatchers.values()).map((w) => w.stop());
7234
- await Promise.all([...remotePromises, ...localPromises]);
7235
- this.remoteWatchers.clear();
7466
+ await Promise.all([...inSandboxPromises, ...localPromises]);
7467
+ this.inSandboxWatchers.clear();
7236
7468
  this.localWatchers.clear();
7237
7469
  }
7238
7470
  /**
@@ -7240,8 +7472,8 @@ var init_sandbox_file_sync = __esm({
7240
7472
  */
7241
7473
  getWatchingStatus() {
7242
7474
  const statuses = [];
7243
- for (const [sessionId, watcher] of this.remoteWatchers) {
7244
- statuses.push({ sessionId, type: "remote", isActive: watcher.isActive() });
7475
+ for (const [sessionId, watcher] of this.inSandboxWatchers) {
7476
+ statuses.push({ sessionId, type: "in-sandbox", isActive: watcher.isActive() });
7245
7477
  }
7246
7478
  for (const [sessionId, watcher] of this.localWatchers) {
7247
7479
  statuses.push({ sessionId, type: "local", isActive: watcher.isActive() });
@@ -7252,364 +7484,6 @@ var init_sandbox_file_sync = __esm({
7252
7484
  }
7253
7485
  });
7254
7486
 
7255
- // src/runtime/in-sandbox-watcher.ts
7256
- function createInSandboxWatcher(options) {
7257
- return new InSandboxWatcher(options);
7258
- }
7259
- function getInSandboxWatcherManager() {
7260
- if (!globalInSandboxManager) {
7261
- globalInSandboxManager = new InSandboxWatcherManager();
7262
- }
7263
- return globalInSandboxManager;
7264
- }
7265
- function createInSandboxWatcherManager() {
7266
- return new InSandboxWatcherManager();
7267
- }
7268
- var WATCHER_SCRIPT, InSandboxWatcher, InSandboxWatcherManager, globalInSandboxManager;
7269
- var init_in_sandbox_watcher = __esm({
7270
- "src/runtime/in-sandbox-watcher.ts"() {
7271
- init_vercel_sandbox_executor();
7272
- WATCHER_SCRIPT = `
7273
- const fs = require('fs');
7274
- const path = require('path');
7275
-
7276
- const watchPath = process.argv[2] || '.';
7277
- const ignored = new Set(['node_modules', '.git', '.cache', '__pycache__']);
7278
-
7279
- // Track all watchers for cleanup
7280
- const watchers = new Map();
7281
-
7282
- // Debounce map to coalesce rapid changes
7283
- const pending = new Map();
7284
- const DEBOUNCE_MS = 100;
7285
-
7286
- function emit(type, filePath) {
7287
- const event = {
7288
- type,
7289
- path: filePath,
7290
- timestamp: Date.now()
7291
- };
7292
- console.log(JSON.stringify(event));
7293
- }
7294
-
7295
- function shouldIgnore(name) {
7296
- return ignored.has(name) || name.startsWith('.');
7297
- }
7298
-
7299
- function watchDir(dir) {
7300
- try {
7301
- const watcher = fs.watch(dir, { persistent: true }, (eventType, filename) => {
7302
- if (!filename || shouldIgnore(filename)) return;
7303
-
7304
- const fullPath = path.join(dir, filename);
7305
- const key = fullPath;
7306
-
7307
- // Debounce
7308
- if (pending.has(key)) {
7309
- clearTimeout(pending.get(key));
7310
- }
7311
-
7312
- pending.set(key, setTimeout(() => {
7313
- pending.delete(key);
7314
-
7315
- fs.stat(fullPath, (err, stats) => {
7316
- if (err) {
7317
- if (err.code === 'ENOENT') {
7318
- emit('unlink', fullPath);
7319
- // Stop watching if it was a directory
7320
- if (watchers.has(fullPath)) {
7321
- watchers.get(fullPath).close();
7322
- watchers.delete(fullPath);
7323
- }
7324
- }
7325
- } else {
7326
- const type = eventType === 'rename' ? 'add' : 'change';
7327
- emit(type, fullPath);
7328
-
7329
- // If it's a new directory, start watching it
7330
- if (stats.isDirectory() && !watchers.has(fullPath)) {
7331
- watchDir(fullPath);
7332
- }
7333
- }
7334
- });
7335
- }, DEBOUNCE_MS));
7336
- });
7337
-
7338
- watchers.set(dir, watcher);
7339
-
7340
- // Watch subdirectories
7341
- const entries = fs.readdirSync(dir, { withFileTypes: true });
7342
- for (const entry of entries) {
7343
- if (entry.isDirectory() && !shouldIgnore(entry.name)) {
7344
- watchDir(path.join(dir, entry.name));
7345
- }
7346
- }
7347
- } catch (err) {
7348
- // Directory may not exist or be inaccessible
7349
- console.error(JSON.stringify({ error: err.message, dir }));
7350
- }
7351
- }
7352
-
7353
- // Start watching
7354
- watchDir(watchPath);
7355
-
7356
- // Keep alive
7357
- process.on('SIGTERM', () => {
7358
- for (const watcher of watchers.values()) {
7359
- watcher.close();
7360
- }
7361
- process.exit(0);
7362
- });
7363
-
7364
- // Heartbeat to indicate we're running
7365
- setInterval(() => {
7366
- console.log(JSON.stringify({ heartbeat: true, timestamp: Date.now() }));
7367
- }, 5000);
7368
-
7369
- console.log(JSON.stringify({ started: true, path: watchPath }));
7370
- `;
7371
- InSandboxWatcher = class {
7372
- sessionId;
7373
- watchPath;
7374
- outputPollIntervalMs;
7375
- sandboxState = null;
7376
- outputPollTimer = null;
7377
- subscribers = /* @__PURE__ */ new Set();
7378
- isRunning = false;
7379
- startedAt;
7380
- lastHeartbeat;
7381
- lastOutputPosition = 0;
7382
- onError;
7383
- onReady;
7384
- constructor(options) {
7385
- this.sessionId = options.sessionId;
7386
- this.watchPath = options.watchPath;
7387
- this.outputPollIntervalMs = options.outputPollIntervalMs ?? 1e3;
7388
- this.onError = options.onError;
7389
- this.onReady = options.onReady;
7390
- if (options.onFileChange) {
7391
- this.subscribers.add(options.onFileChange);
7392
- }
7393
- }
7394
- /**
7395
- * Start the watcher process inside the sandbox
7396
- */
7397
- async start() {
7398
- if (this.isRunning) {
7399
- console.warn(`[IN_SANDBOX_WATCHER] Already running for session ${this.sessionId}`);
7400
- return;
7401
- }
7402
- try {
7403
- this.sandboxState = await getOrCreateSandbox({
7404
- sessionId: this.sessionId,
7405
- runtime: "node22",
7406
- timeout: 600
7407
- });
7408
- const { sandbox } = this.sandboxState;
7409
- const scriptPath = "/tmp/.file-watcher.js";
7410
- const outputPath = "/tmp/.file-watcher-output.log";
7411
- const writeScriptCmd = `cat > ${scriptPath} << 'WATCHER_EOF'
7412
- ${WATCHER_SCRIPT}
7413
- WATCHER_EOF`;
7414
- await sandbox.runCommand({
7415
- cmd: "sh",
7416
- args: ["-c", writeScriptCmd]
7417
- });
7418
- const startCmd = `nohup node ${scriptPath} "${this.watchPath}" > ${outputPath} 2>&1 &`;
7419
- await sandbox.runCommand({
7420
- cmd: "sh",
7421
- args: ["-c", startCmd]
7422
- });
7423
- console.log(`[IN_SANDBOX_WATCHER] Started watcher in sandbox for ${this.watchPath}`);
7424
- this.isRunning = true;
7425
- this.startedAt = /* @__PURE__ */ new Date();
7426
- this.outputPollTimer = setInterval(async () => {
7427
- try {
7428
- await this.pollOutput(outputPath);
7429
- } catch (error) {
7430
- console.error("[IN_SANDBOX_WATCHER] Error polling output:", error);
7431
- if (this.onError && error instanceof Error) {
7432
- this.onError(error);
7433
- }
7434
- }
7435
- }, this.outputPollIntervalMs);
7436
- setTimeout(() => {
7437
- this.pollOutput(outputPath).catch(console.error);
7438
- }, 500);
7439
- } catch (error) {
7440
- console.error(`[IN_SANDBOX_WATCHER] Failed to start watcher:`, error);
7441
- throw error;
7442
- }
7443
- }
7444
- /**
7445
- * Poll the output file for new events
7446
- */
7447
- async pollOutput(outputPath) {
7448
- if (!this.sandboxState?.sandbox) return;
7449
- try {
7450
- const result = await this.sandboxState.sandbox.runCommand({
7451
- cmd: "sh",
7452
- args: ["-c", `tail -c +${this.lastOutputPosition + 1} ${outputPath} 2>/dev/null || true`]
7453
- });
7454
- const output = await result.stdout();
7455
- if (output && output.trim()) {
7456
- const sizeResult = await this.sandboxState.sandbox.runCommand({
7457
- cmd: "sh",
7458
- args: ["-c", `stat -c%s ${outputPath} 2>/dev/null || echo 0`]
7459
- });
7460
- const sizeStr = await sizeResult.stdout();
7461
- this.lastOutputPosition = parseInt(sizeStr.trim(), 10) || 0;
7462
- this.processOutput(output);
7463
- }
7464
- } catch {
7465
- }
7466
- }
7467
- /**
7468
- * Process output from the watcher script
7469
- */
7470
- processOutput(stdout) {
7471
- const lines = stdout.split("\n").filter(Boolean);
7472
- for (const line of lines) {
7473
- try {
7474
- const data = JSON.parse(line);
7475
- if (data.started) {
7476
- console.log(`[IN_SANDBOX_WATCHER] Watcher started for ${data.path}`);
7477
- if (this.onReady) {
7478
- this.onReady();
7479
- }
7480
- } else if (data.heartbeat) {
7481
- this.lastHeartbeat = new Date(data.timestamp);
7482
- } else if (data.error) {
7483
- console.warn(`[IN_SANDBOX_WATCHER] Error in sandbox:`, data.error);
7484
- } else if (data.type && data.path) {
7485
- this.emitEvent({
7486
- type: data.type,
7487
- relativePath: data.path.replace(/^\.\//, ""),
7488
- absolutePath: data.path,
7489
- basePath: this.watchPath,
7490
- sessionId: this.sessionId,
7491
- timestamp: new Date(data.timestamp)
7492
- });
7493
- }
7494
- } catch {
7495
- }
7496
- }
7497
- }
7498
- /**
7499
- * Stop the watcher process
7500
- */
7501
- async stop() {
7502
- if (!this.isRunning) {
7503
- return;
7504
- }
7505
- if (this.outputPollTimer) {
7506
- clearInterval(this.outputPollTimer);
7507
- this.outputPollTimer = null;
7508
- }
7509
- try {
7510
- if (this.sandboxState?.sandbox) {
7511
- await this.sandboxState.sandbox.runCommand({
7512
- cmd: "sh",
7513
- args: ["-c", "pkill -f file-watcher.js 2>/dev/null || true"]
7514
- });
7515
- await this.sandboxState.sandbox.runCommand({
7516
- cmd: "sh",
7517
- args: ["-c", "rm -f /tmp/.file-watcher.js /tmp/.file-watcher-output.log"]
7518
- });
7519
- }
7520
- } catch {
7521
- }
7522
- this.isRunning = false;
7523
- this.sandboxState = null;
7524
- this.lastOutputPosition = 0;
7525
- console.log(`[IN_SANDBOX_WATCHER] Stopped watcher for session ${this.sessionId}`);
7526
- }
7527
- /**
7528
- * Subscribe to file change events
7529
- */
7530
- subscribe(callback) {
7531
- this.subscribers.add(callback);
7532
- return () => this.subscribers.delete(callback);
7533
- }
7534
- /**
7535
- * Check if watcher is running
7536
- */
7537
- isActive() {
7538
- return this.isRunning;
7539
- }
7540
- /**
7541
- * Get watcher status
7542
- */
7543
- getStatus() {
7544
- return {
7545
- sessionId: this.sessionId,
7546
- watchPath: this.watchPath,
7547
- isRunning: this.isRunning,
7548
- startedAt: this.startedAt,
7549
- lastHeartbeat: this.lastHeartbeat
7550
- };
7551
- }
7552
- /**
7553
- * Emit event to all subscribers
7554
- */
7555
- async emitEvent(event) {
7556
- for (const callback of this.subscribers) {
7557
- try {
7558
- await callback(event);
7559
- } catch (error) {
7560
- console.error("[IN_SANDBOX_WATCHER] Error in subscriber callback:", error);
7561
- }
7562
- }
7563
- }
7564
- };
7565
- InSandboxWatcherManager = class {
7566
- watchers = /* @__PURE__ */ new Map();
7567
- /**
7568
- * Start watching a sandbox
7569
- */
7570
- async startWatching(options) {
7571
- const { sessionId } = options;
7572
- await this.stopWatching(sessionId);
7573
- const watcher = new InSandboxWatcher(options);
7574
- await watcher.start();
7575
- this.watchers.set(sessionId, watcher);
7576
- return watcher;
7577
- }
7578
- /**
7579
- * Stop watching a session
7580
- */
7581
- async stopWatching(sessionId) {
7582
- const watcher = this.watchers.get(sessionId);
7583
- if (watcher) {
7584
- await watcher.stop();
7585
- this.watchers.delete(sessionId);
7586
- }
7587
- }
7588
- /**
7589
- * Get watcher for a session
7590
- */
7591
- getWatcher(sessionId) {
7592
- return this.watchers.get(sessionId);
7593
- }
7594
- /**
7595
- * Check if watching
7596
- */
7597
- isWatching(sessionId) {
7598
- return this.watchers.get(sessionId)?.isActive() ?? false;
7599
- }
7600
- /**
7601
- * Stop all watchers
7602
- */
7603
- async stopAll() {
7604
- const promises = Array.from(this.watchers.values()).map((w) => w.stop());
7605
- await Promise.all(promises);
7606
- this.watchers.clear();
7607
- }
7608
- };
7609
- globalInSandboxManager = null;
7610
- }
7611
- });
7612
-
7613
7487
  // src/runtime/index.ts
7614
7488
  function generateDockerCommand(config) {
7615
7489
  const args = ["docker", "run"];
@@ -8042,7 +7916,7 @@ var init_credentials = __esm({
8042
7916
  }
8043
7917
  });
8044
7918
  var gitHubSkillSourceSchema, localSkillSourceSchema, skillSourceSchema, skillConfigSchema, fileEntrySchema;
8045
- var init_types3 = __esm({
7919
+ var init_types4 = __esm({
8046
7920
  "src/skills/types.ts"() {
8047
7921
  gitHubSkillSourceSchema = z.object({
8048
7922
  type: z.literal("github"),
@@ -8586,7 +8460,7 @@ var init_manager2 = __esm({
8586
8460
  // src/skills/index.ts
8587
8461
  var init_skills = __esm({
8588
8462
  "src/skills/index.ts"() {
8589
- init_types3();
8463
+ init_types4();
8590
8464
  init_local_provider();
8591
8465
  init_github_provider();
8592
8466
  init_manager2();
@@ -18106,7 +17980,7 @@ var init_storage3 = __esm({
18106
17980
  }
18107
17981
  if (options.filePath) {
18108
17982
  query = query.or(
18109
- `event_data->>filePath.eq.${options.filePath},and(category.eq.tool,tool_name.in.(Read,Write,Edit),event_data->input->>file_path.eq.${options.filePath})`
17983
+ `event_data->>filePath.eq.${options.filePath},event_data->>canonicalPath.eq.${options.filePath},and(category.eq.tool,tool_name.in.(Read,Write,Edit),event_data->input->>file_path.eq.${options.filePath})`
18110
17984
  );
18111
17985
  }
18112
17986
  const ascending = options.order !== "desc";
@@ -18990,6 +18864,6 @@ var init_src = __esm({
18990
18864
  });
18991
18865
  init_src();
18992
18866
 
18993
- export { AVAILABLE_MODELS, AgentConfigSchema, AgentError, AgentHarness, AgentStatus, AshCloud, AshCloudApiError, AshCloudClient, AttachmentConfigSchema, AttachmentStorage, ClaudeSdkClient, CloudSandbox, CloudStorage, ConfigBuilder, ConfigError, CredentialManager, DEFAULT_MODELS, DEFAULT_SANDBOX_PROVIDER_CONFIG, EventCategory, FileWatcherManager, GCSBundleStore, GeminiCliClient, GitHubFileProvider, HarnessConfigSchema, HarnessError, HarnessErrorCode, HarnessEventEmitter, InSandboxWatcher, InSandboxWatcherManager, LocalBundleStore, LocalFileProvider, LocalSandbox, McpConfigBuilder, McpPresets, McpServers, MemoryBundleStore, MemoryCredentialStorage, MemoryQueueStorage, MemoryRateLimitStore, MemoryStorage, MessageRole, NotFoundError, PostgresQueueStorage, PostgresStorage, ProviderSandbox, QueueItemStatus, QueueProcessor, RemoteFileWatcherManager, RemoteSandboxFileWatcher, RuntimeConfigBuilder, RuntimePresets, S3BundleStore, S3FileStore, SENSITIVE_PATHS, SandboxFileSync, SandboxFileWatcher, SandboxGitRepo, SandboxLogger, SandboxPool, ServerConfigSchema, SessionError, SessionManager, SessionStatus, SkillCatalog, SkillManager, StorageConfigSchema, StorageError, StreamEventType, SupabaseBundleStore, SupabaseStorage, ToolCallProcessor, ToolError, ValidationError, Workspace, WorkspaceManager, attachmentSchema, attachmentToDataUrl, checkSecurityConfig, claudeClient, cleanupAllSandboxes, configureMcp, configureRuntime, convertClaudeMessage, createAgentsRouter, createAshCloud, createBackendExecutor, createCloudSandbox, createConfig, createCredentialManager, createOpenAPIServer as createDocumentedServer, createE2BSandbox, createEventHandler, createEventMiddlewareChain, createFileWatcher, createFileWatcherManager, createGCSBundleStore, createGeminiExecutor, createGitHubFileProvider, createGitRepo, createHarnessServer, createInSandboxWatcher, createInSandboxWatcherManager, createLocalBundleStore, createLocalFileProvider, createLocalSandbox, createLogger, createMemoryBundleStore, createMinioBundleStore, createMinioFileStore, createModalSandbox, createAgentsRouter2 as createOpenAPIAgentsRouter, createOpenAPIServer, createSessionsRouter2 as createOpenAPISessionsRouter, createSkillsRouter2 as createOpenAPISkillsRouter, createProviderSandbox, createQueueProcessor, createQueueRouter, createR2BundleStore, createR2FileStore, createRemoteFileWatcher, createRemoteFileWatcherManager, createS3BundleStore, createS3FileStore, createSandboxFileOperations, createSandboxFileSync, createSandboxLogger, createSandboxOptions, createSessionWorkspace, createSessionsRouter, createSkillCatalog, createSkillManager, createSupabaseBundleStore, createSupabaseBundleStoreFromEnv, createToolCall, createToolCallProcessor, createVercelSandbox, createVercelSandboxExecutor, createWorkspace, createWorkspaceHooks, createWorkspaceManager, dataUrlToBuffer, defineAgent, defineConfig, ensureSandboxPoolInitialized, env, envOptional, extractTextContent, extractTextFromMessage, fileEntrySchema, formatToolName, generateDockerCommand, generateMcpServerPackage, generateMcpServers, generateProxyEnv, generateToolSummary, getActionIcon, getActionLabel, getAllHeartbeatStatuses, getApiKeyEnvVar, getDefaultModel, getFileWatcherManager, getHeartbeatStatus, getInSandboxWatcherManager, getOrCreateSandbox, getRemoteFileWatcherManager, getSandboxCacheStats, getSandboxPool, getWorkspaceManager, gitHubSkillSourceSchema, globalEventEmitter, hasErrorCode, hashStartupScript, httpMcpWithAuth, initializeSandboxPool, introspectMcpServer, invalidateSandbox, isCommandRunAction, isDocumentMimeType, isErrorEntry, isFileEditAction, isFileReadAction, isFileWriteAction, isGenericToolAction, isGlobAction, isHarnessError, isHttpMcpConfig, isImageMimeType, isMcpToolAction, isSandboxExpiredError, isSandboxRunning, isSearchAction, isSensitivePath, isStdioMcpConfig, isTodoWriteAction, isToolCallEntry, isValidModel, isWebFetchAction, isWebSearchAction, listFilesInSandbox, loadConfig, loadGitHubSkill, loadGitHubSkills, loadWorkspaceState, localSkillSourceSchema, log, mapClaudeOptionsToGemini, mapToolToActionType, markConfigInstalled, markSdkInstalled, markStartupScriptRan, mcpAuthToHeaders, messageContentSchema, messageSchema, needsStartupScriptRerun, normalizeGitHubConfigs, normalizeMcpServers, normalizeMessages, normalizeToolResult, onHeartbeat, schemas_exports as openApiSchemas, parseCommandResult, parseGitHubUrl, parseMcpToolName, processStreamEvents, rateLimit, rateLimiters, readFileFromSandbox, rekeySessionId, releaseSandbox, requestLogger, saveWorkspaceState, schema_exports as schema, sessionSchema, shouldUseSandbox, shutdownSandboxPool, skillConfigSchema, skillSourceSchema, sseMcpWithAuth, startServer, updateToolCallWithResult, writeFileToSandbox };
18867
+ export { AVAILABLE_MODELS, AgentConfigSchema, AgentError, AgentHarness, AgentStatus, AshCloud, AshCloudApiError, AshCloudClient, AttachmentConfigSchema, AttachmentStorage, ClaudeSdkClient, CloudSandbox, CloudStorage, ConfigBuilder, ConfigError, CredentialManager, DEFAULT_MODELS, DEFAULT_SANDBOX_PROVIDER_CONFIG, EventCategory, FileWatcherManager, GCSBundleStore, GeminiCliClient, GitHubFileProvider, HarnessConfigSchema, HarnessError, HarnessErrorCode, HarnessEventEmitter, InSandboxWatcher, InSandboxWatcherManager, LocalBundleStore, LocalFileProvider, LocalSandbox, McpConfigBuilder, McpPresets, McpServers, MemoryBundleStore, MemoryCredentialStorage, MemoryQueueStorage, MemoryRateLimitStore, MemoryStorage, MessageRole, NotFoundError, PostgresQueueStorage, PostgresStorage, ProviderSandbox, QueueItemStatus, QueueProcessor, RuntimeConfigBuilder, RuntimePresets, S3BundleStore, S3FileStore, SENSITIVE_PATHS, SandboxFileSync, SandboxFileWatcher, SandboxGitRepo, SandboxLogger, SandboxPool, ServerConfigSchema, SessionError, SessionManager, SessionStatus, SkillCatalog, SkillManager, StorageConfigSchema, StorageError, StreamEventType, SupabaseBundleStore, SupabaseStorage, ToolCallProcessor, ToolError, ValidationError, Workspace, WorkspaceManager, attachmentSchema, attachmentToDataUrl, checkSecurityConfig, claudeClient, cleanupAllSandboxes, configureMcp, configureRuntime, convertClaudeMessage, createAgentsRouter, createAshCloud, createBackendExecutor, createCloudSandbox, createConfig, createCredentialManager, createOpenAPIServer as createDocumentedServer, createE2BSandbox, createEventHandler, createEventMiddlewareChain, createFileWatcher, createFileWatcherManager, createGCSBundleStore, createGeminiExecutor, createGitHubFileProvider, createGitRepo, createHarnessServer, createInSandboxWatcher, createInSandboxWatcherManager, createLocalBundleStore, createLocalFileProvider, createLocalSandbox, createLogger, createMemoryBundleStore, createMinioBundleStore, createMinioFileStore, createModalSandbox, createAgentsRouter2 as createOpenAPIAgentsRouter, createOpenAPIServer, createSessionsRouter2 as createOpenAPISessionsRouter, createSkillsRouter2 as createOpenAPISkillsRouter, createProviderSandbox, createQueueProcessor, createQueueRouter, createR2BundleStore, createR2FileStore, createS3BundleStore, createS3FileStore, createSandboxFileOperations, createSandboxFileSync, createSandboxLogger, createSandboxOptions, createSessionWorkspace, createSessionsRouter, createSkillCatalog, createSkillManager, createSupabaseBundleStore, createSupabaseBundleStoreFromEnv, createToolCall, createToolCallProcessor, createVercelSandbox, createVercelSandboxExecutor, createWorkspace, createWorkspaceHooks, createWorkspaceManager, dataUrlToBuffer, defineAgent, defineConfig, ensureSandboxPoolInitialized, env, envOptional, executeCommandInSandbox, extractTextContent, extractTextFromMessage, fileEntrySchema, formatToolName, generateDockerCommand, generateMcpServerPackage, generateMcpServers, generateProxyEnv, generateToolSummary, getActionIcon, getActionLabel, getAllHeartbeatStatuses, getApiKeyEnvVar, getCachedSandbox, getDefaultModel, getFileWatcherManager, getHeartbeatStatus, getInSandboxWatcherManager, getOrCreateSandbox, getSandboxCacheStats, getSandboxPool, getWorkspaceManager, gitHubSkillSourceSchema, globalEventEmitter, hasErrorCode, hashStartupScript, httpMcpWithAuth, initializeSandboxPool, introspectMcpServer, invalidateSandbox, isCommandRunAction, isDocumentMimeType, isErrorEntry, isFileEditAction, isFileReadAction, isFileWriteAction, isGenericToolAction, isGlobAction, isHarnessError, isHttpMcpConfig, isImageMimeType, isMcpToolAction, isSandboxExpiredError, isSandboxRunning, isSearchAction, isSensitivePath, isStdioMcpConfig, isTodoWriteAction, isToolCallEntry, isValidModel, isWebFetchAction, isWebSearchAction, listFilesInSandbox, loadConfig, loadGitHubSkill, loadGitHubSkills, loadWorkspaceState, localSkillSourceSchema, log, mapClaudeOptionsToGemini, mapToolToActionType, markConfigInstalled, markSdkInstalled, markStartupScriptRan, mcpAuthToHeaders, messageContentSchema, messageSchema, needsStartupScriptRerun, normalizeGitHubConfigs, normalizeMcpServers, normalizeMessages, normalizeToolResult, onHeartbeat, schemas_exports as openApiSchemas, parseCommandResult, parseGitHubUrl, parseMcpToolName, processStreamEvents, rateLimit, rateLimiters, readFileFromSandbox, rekeySessionId, releaseSandbox, requestLogger, saveWorkspaceState, schema_exports as schema, sessionSchema, shouldUseSandbox, shutdownSandboxPool, skillConfigSchema, skillSourceSchema, sseMcpWithAuth, startServer, updateToolCallWithResult, writeFileToSandbox };
18994
18868
  //# sourceMappingURL=index.js.map
18995
18869
  //# sourceMappingURL=index.js.map